extern "C" {
#endif
+// #define USE_SILENCE_AUDIO_288
// #define USE_SILENCE_AUDIO_288
// 静音音频数据定义
// 默认使用1100字节版本,定义 USE_SILENCE_AUDIO_288 可切换到288字节版本
#ifdef USE_SILENCE_AUDIO_288
+#define USE_SILENCE_AUDIO
+
// 288字节版本(纯MP3数据帧,无ID3标签)
static const unsigned char silence_audio[288] = {
0xff, 0xf3, 0x88, 0xc4, 0x00, 0x44, 0xc0, 0x03, 0x48, 0x00, 0x00, 0x00,
task_cfg.create_queue_handle = CreateAIVoiceQueue; // 设置队列创建函数
task_cfg.attr.name = "AIVoiceThread";
- task_cfg.attr.priority = (osPriority_t)28; // 使用合适的优先级
+ task_cfg.attr.priority = (osPriority_t)(28+2); // 使用合适的优先级
task_cfg.attr.stack_size = 0x2000; // 8KB栈空间
task_cfg.func = AIVoiceThread;
task_cfg.use_mem = USE_EXTEND_MEM;
}
MediaMutexUnLock(g_aiVoiceContextMutex);
+ // static uint32_t last_delay_us = 1;
+ int32_t ret=0;
+ #ifndef TIME_TICKS_TEST
+ ret = AudioStreamOutStreamWrite(data, size);
+ #else
// 写入音频数据到输出流
- int32_t ret = AudioStreamOutStreamWrite(data, size);
+ uint32_t current_tick = osKernelGetTickCount();
+ printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx AudioStreamOutStreamWrite current_tick: %u\n", current_tick);
+ ret = AudioStreamOutStreamWrite(data, size);
+ // printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx last_delay_us==1\r\n");
+ current_tick = osKernelGetTickCount();
+ printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx AudioStreamOutStreamWrite end current_tick: %u\n", current_tick);
+ // last_delay_us=0;
+ #endif
if(g_aiVoiceContext->outputAudioFormat==MP3)
{
// 延迟时间(微秒)= (数据大小(字节)* 8 * 1000000) / 比特率(bps)
// 当比特率更高时,延迟时间更短
// 公式:延迟(微秒)= (size * 8 * 1000000) / bit_rate
- uint32_t delay_us = (uint32_t)((uint64_t)(size-(size/10*5)) * 8 * 1000000ULL / g_tts_audio_bit_rate);
+ uint32_t delay_us = (uint32_t)((uint64_t)(size-(size/10*7)) * 8 * 1000000ULL / g_tts_audio_bit_rate);
+ #ifdef TIME_TICKS_TEST
+ printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx delay_ms %d\r\n",(uint32_t)((uint64_t)(size) * 8 * 1000000ULL / g_tts_audio_bit_rate)/1000);
+
MEDIA_DEBUG_LOG("delay_us %d\r\n",delay_us);
+ #endif
+
+
// 确保延迟时间在合理范围内(最小10微秒)
if (delay_us < 20) {
usleep(delay_us-20);
if (ret != 0) {
retry_count++;
- // MEDIA_ERR_LOG("Failed to write audio data to output stream, ret=%d, retry %d/%d", ret, retry_count, MAX_RETRY_COUNT);
+ MEDIA_ERR_LOG("Failed to write audio data to output stream, ret=%d, retry %d/%d", ret, retry_count, MAX_RETRY_COUNT);
usleep(delay_us*retry_count/10*5);
goto AI_WRITE;
}
uint32_t g_last_binary_data_tick = 0; // 最后一次接收二进制数据的tick
// 音频数据最近缓存(环形缓冲区,仅保留最近数据)
-#define AUDIO_CACHE_BUFFER_SIZE (1024*3) // 8KB缓存
+#define AUDIO_CACHE_BUFFER_SIZE (72*6*5) // 8KB缓存
static uint8_t g_audio_cache_buffer[AUDIO_CACHE_BUFFER_SIZE];
static uint32_t g_audio_cache_pos = 0; // 当前写入位置
static uint32_t g_audio_cache_total = 0; // 总写入数据量
static uint32_t ln_ws_copy_from_ring_cache(uint32_t start_pos, uint32_t length, uint8_t* output);
static int ln_ws_send_cached_audio_data(void);
-
+#define TIME_TICKS_TEST 0
/* 握手成功回调:标记连接就绪 */
static void ln_ws_on_open(int client)
LN_WS_WARN("Invalid message\n");
}
LN_WS_DEBUG("on_message: %s\n", buf);
-
+#if TIME_TICKS_TEST
+ uint32_t current_tick = osKernelGetTickCount();
+ LN_WS_DEBUG("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx on_message current_tick: %u\n", current_tick);
+#endif
free(buf);
}
{
LN_WS_DEBUG("Audio data written successfully: %u bytes\n", size);
+#if TIME_TICKS_TEST
+ uint32_t current_tick = osKernelGetTickCount();
+ LN_WS_DEBUG("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx current_tick: %u\n", current_tick);
+#endif
+
+
// 更新最后一次音频写入tick
g_last_audio_write_tick = osKernelGetTickCount();
g_audio_playback_active = true;
LN_WS_ERROR("Failed to allocate memory for base64 encoding\n");
return -1;
}
-
+ memset(audio_base64, 0, base64_size);
+ // LN_WS_DEBUG("audio_data before encode: \n");
+ // for(int i = 0; i < 32; i++)
+ // {
+ // printf(" %02X",audio_data[i]);
+ // }
+ // LN_WS_DEBUG("audio_data end\n");
+
size_t output_len = 0;
int ret_encode = mbedtls_base64_encode((unsigned char*)audio_base64, base64_size - 1, &output_len,
audio_data, audio_size);
static void ai_binary_message_handler(const uint8_t *raw_data, uint32_t timestamp, uint32_t data_len)
{
LN_WS_INFO("Received binary message at %u, length: %d bytes\n", timestamp, data_len);
-
+
+#if TIME_TICKS_TEST
+ uint32_t current_tick = osKernelGetTickCount();
+ LN_WS_DEBUG("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx ai_binary_message_handler current_tick: %u\n", current_tick);
+#endif
// 收到二进制消息时,清除 ping 超时检测
if (g_ping_timeout_active) {
g_ping_timeout_active = false;
LN_WS_WARN("Chat ID not matched\n");
return;
}
+ if(false==is_chat_id_matched() && g_audio_playback_active==false && g_audio_chat_ctx.finish_state == LN_CHAT_SENT_END_NO_REPLY)
+ {
+ LN_WS_DEBUG("Chat ID not matched, setting chat ID matched\n");
+ set_chat_id_matched();
+ }
if (!raw_data || data_len == 0) {
LN_WS_ERROR("Invalid binary data parameters\n");
return;
}
- const size_t CHUNK_SIZE = 1024; // 1K 分块大小
+ const size_t CHUNK_SIZE = 1024*2; // 1K 分块大小
- if (data_len <= CHUNK_SIZE) {
+ if (data_len <= CHUNK_SIZE || (g_audio_playback_active==false && data_len<=1024*5)) {
// 数据小于等于1K,直接发送
LN_WS_DEBUG("Sending data directly (size: %d bytes)\n", data_len);
AI_SendAudioDataToQueue(raw_data, data_len);
remaining -= current_chunk_size;
}
+ LN_WS_DEBUG("All %d chunks sent successfully\n", chunk_count);
+ }
+
// 更新最后一次音频写入tick
// 如果音频播放从非活跃状态转为活跃状态,记录开始播放时间
- if (!g_audio_playback_active) {
- g_audio_playback_start_tick = osKernelGetTickCount();
- LN_WS_INFO("Audio playback started at tick: %u\n", g_audio_playback_start_tick);
-
- // 触发音频播放开始事件
- if (g_ws_message_callback != NULL) {
- g_ws_message_callback(NULL, WS_CMD_AUDIO_PLAYBACK_START);
- }
- extern bool a2dp_is_connect;
- if(a2dp_is_connect)
- {
- int ret = a2dp_src_start_playing(ln_bt_get_last_conned_device_Addr()); // 设置耳机的状态为播放
+ if (!g_audio_playback_active) {
+ g_audio_playback_start_tick = osKernelGetTickCount();
+ LN_WS_INFO("Audio playback started at tick: %u\n", g_audio_playback_start_tick);
+
+ // 触发音频播放开始事件
+ if (g_ws_message_callback != NULL) {
+ g_ws_message_callback(NULL, WS_CMD_AUDIO_PLAYBACK_START);
+ }
+ extern bool a2dp_is_connect;
+ if(a2dp_is_connect)
+ {
+ int ret = a2dp_src_start_playing(ln_bt_get_last_conned_device_Addr()); // 设置耳机的状态为播放
+
+ LN_WS_DEBUG("a2dp_src_start_playing %d \n", ret);
- LN_WS_DEBUG("a2dp_src_start_playing %d \n", ret);
-
- }
-
}
g_audio_playback_active = true;
-
-
- LN_WS_DEBUG("All %d chunks sent successfully\n", chunk_count);
}
}
LN_WS_INFO("Sending cached audio data: %u bytes (wrapped=%d, start_pos=%u)\n",
total_size, g_audio_cache_wrapped, start_pos);
- #define MAX_SEND_CHUNK_SIZE 512 // 每次最多发送4KB
+ #define MAX_SEND_CHUNK_SIZE 72*6 // 每次最多发送4KB
int ret = 0;
uint32_t remaining = total_size;