if (memcpy_s(oggCtx->idHeader, HEADER_STRLEN, "OpusHead", HEADER_STRLEN) != 0) {
MEDIA_ERR_LOG("memcpy failed!");
+ MediaMemFree((void **)&oggCtx->idHeader);
return -1;
}
oggCtx->idHeader[0x8] = 0x01;
oggCtx->commentHeader = static_cast<unsigned char*>(MediaMemCalloc(OPUS_COMMENT_HEADER_LEN));
if (oggCtx->commentHeader == nullptr) {
MEDIA_ERR_LOG("malloc failed!");
+ MediaMemFree((void **)&oggCtx->idHeader);
return -1;
}
if (memcpy_s(oggCtx->commentHeader, HEADER_STRLEN, "OpusTags", HEADER_STRLEN) != 0) {
MEDIA_ERR_LOG("Opus idHeader memcpy failed!");
+ MediaMemFree((void **)&oggCtx->idHeader);
+ MediaMemFree((void **)&oggCtx->commentHeader);
return -1;
}
const char *vendor = "libogg-1.3.5";
if (memcpy_s(oggCtx->commentHeader + OPUS_OPUSTAGS_LEN, vendorLen, vendor, vendorLen) != 0) {
MEDIA_ERR_LOG("Opus commentHeader memcpy failed!");
+ MediaMemFree((void **)&oggCtx->idHeader);
+ MediaMemFree((void **)&oggCtx->commentHeader);
return -1;
}
return 0;
oggCtx->page = (ogg_page *)MediaMemCalloc(sizeof(ogg_page));
if (oggCtx->page == nullptr) {
MEDIA_ERR_LOG("malloc failed!");
+ MediaMemFree((void **)&oggCtx->packet);
return -1;
}
if (ogg_stream_init(&oggCtx->oggStream, oggCtx->serialno) != 0) {
MEDIA_ERR_LOG("ogg stream init failed");
+ MediaMemFree((void **)&oggCtx->packet);
+ MediaMemFree((void **)&oggCtx->page);
return -1;
}
if (AudioCapturerOggHeaderInit(oggCtx, channelCount, sampleRate) != 0) {
MEDIA_ERR_LOG("Header init failed!");
+ ogg_stream_clear(&oggCtx->oggStream);
+ MediaMemFree((void **)&oggCtx->packet);
+ MediaMemFree((void **)&oggCtx->page);
return -1;
}
// 如果队列写入失败,释放内存
free(cachedMsg.data);
}
+ } else if (cachedMsg.data != nullptr) {
+ // 防御性处理:如果data不为null但size为0,也应该释放
+ MEDIA_ERR_LOG("Invalid cached message: data not null but size is 0 or invalid");
+ free(cachedMsg.data);
}
} else {
MEDIA_ERR_LOG("Failed to read from file cache");
int32_t ret = RunAIVoice(context);
if (ret != 0) {
MEDIA_ERR_LOG("run AI voice failed");
+ // 清理已分配的资源(RunAIVoice中的InitAIVoiceResources可能已分配资源)
+ DeinitAIVoiceResources(context);
(void)ReleaseAudioFocus();
return;
}
struct VadConfig vad_config = {
.vad_log_level = 1, /* INFO 日志 */
.sil_threshold = 63, /* 静音阈值 */
- .energy_threshold = 10000, /* 能量阈值 */
+ .energy_threshold = 50000, /* 能量阈值 */
.min_speech_length = 240, /* 最短语音长度 (ms) */
.silence_detect_length = 300, /* 静音检测长度 (ms) */
.rule1_min_tailing_silence = 480, /* 规则1静音时间 (ms) */
audio_base64[0] = '\0';
} else {
// 正常音频数据,进行Base64编码
- size_t base64_size =audio_size*2; //((audio_size + 2) / 3) * 4 + 1;
+ size_t base64_size = audio_size * 2; //((audio_size + 2) / 3) * 4 + 1;
audio_base64 = (char*)malloc(base64_size);
if (!audio_base64) {
LN_WS_ERROR("Failed to allocate memory for base64 encoding\n");
- return -1;
- }
-
+ return -1;
+ }
+
size_t output_len = 0;
int ret_encode = mbedtls_base64_encode((unsigned char*)audio_base64, base64_size - 1, &output_len,
audio_data, audio_size);
if (ret_encode != 0) {
LN_WS_DEBUG("Base64 encoding failed: %d\n", ret_encode);
free(audio_base64);
- return -1;
+ return -1;
}
audio_base64[output_len] = '\0';
}
LN_WS_INFO("VAD cooldown active, ignoring start request\n");
return;
}
- #ifdef VAD_TEST
+ // #ifdef VAD_TEST
ln_ws_start_audio_chat(LN_AUDIO_CHAT_VOICE_CHAT_REQUEST);
- #endif
+ // #endif
}
else
if (status==2)
break;
}
- // 判断是否是最后一块
- bool is_last = (remaining <= chunk_size);
-
- // 发送数据
- LN_WS_DEBUG("Sending chunk: size=%u, remaining=%u, is_last=%d\n",
- chunk_size, remaining - chunk_size, is_last);
+ // 发送数据(所有块都标记为finished=false,因为这是缓存的历史数据)
+ LN_WS_DEBUG("Sending chunk: size=%u, remaining=%u\n",
+ chunk_size, remaining - chunk_size);
ret = ln_ws_send_audio_data(send_buffer, chunk_size, false);
ws_msg_info_t msg;
while (osMessageQueueGet(g_ws_msg_queue, &msg, NULL, 0) == osOK) {
// 原始消息数据不需要额外释放,因为存储在栈上
- HAISI_WS_DEBUG("Clearing queued message: %s\n", msg.raw_data);
- ws_msg_free(&msg);
+ HAISI_WS_DEBUG("Clearing queued message: %s\n", msg.raw_data);
+ ws_msg_free(&msg);
}
osMessageQueueDelete(g_ws_msg_queue);
}
g_ws_connected = WS_STATE_DISCONNECTED;
- // 删除消息队列
+ // 删除消息队列(先清理所有消息)
if (g_ws_msg_queue != NULL) {
+ // 队列中存储的是 ws_msg_info_t* 指针,需要先清理所有消息
+ ws_msg_info_t *msg;
+ while (osMessageQueueGet(g_ws_msg_queue, &msg, NULL, 0) == osOK) {
+ if (msg != NULL) {
+ HAISI_WS_DEBUG("Clearing queued message before stop\n");
+ ws_msg_free(msg); // 释放动态分配的消息结构体和raw_data
+ }
+ }
osMessageQueueDelete(g_ws_msg_queue);
g_ws_msg_queue = NULL;
}