diff --git a/ql-application/threadx/interface/custom_app/ws_talkingq.c b/ql-application/threadx/interface/custom_app/ws_talkingq.c index 65c1d41..f0bc864 100644 --- a/ql-application/threadx/interface/custom_app/ws_talkingq.c +++ b/ql-application/threadx/interface/custom_app/ws_talkingq.c @@ -21,6 +21,7 @@ #include "ql_ping.h" #include "ql_nw.h" #include "ql_atcmd.h" +#include "ql_platform.h" #include "layer3.h" #include "ql_uart.h" #include "hal_api.h" @@ -29,6 +30,8 @@ #define PCM_FRAME_LENGTH 1152 +#define CLOUD_TTS_ERROR_URL_FORMAT \ + "http://101.35.224.118:8080/assets/roles/banban/tts_error/tts_error%02u.mp3" static int g_sim_ready = 0; @@ -192,6 +195,56 @@ static void remove_underscores(char *str) { *dst = '\0'; // 添加字符串结束符 } +/* + * 将后台下发的任意角色对话超时音频 URL 改为 banban 角色的 HTTP 地址, + * 并在 tts_error00~tts_error09 中随机选择一条。 + */ +static int randomize_tts_error_url(char *url, size_t url_size) +{ + static uint32_t random_sequence = 0; + static unsigned int last_random_index = 10; + char *file_name; + uint32_t random_value; + unsigned int random_index; + int written; + + if(url == NULL || url_size == 0){ + return 0; + } + + file_name = strrchr(url, '/'); + file_name = (file_name == NULL) ? url : file_name + 1; + + if(strncmp(file_name, "tts_error", strlen("tts_error")) != 0 && + strncmp(file_name, "tts_err", strlen("tts_err")) != 0){ + return 0; + } + + /* + * 某些设备上硬件随机接口可能持续返回 0,因此混合伪随机数、系统 tick + * 和递增序列;若仍与上一次相同,则向后偏移,避免连续重复播放。 + */ + random_sequence++; + random_value = hal_os_get_rand(); + random_value ^= ql_pseudo_random_number(); + random_value ^= ql_rtos_get_systicks(); + random_value ^= random_sequence * 0x9E3779B9U; + random_index = random_value % 10; + if(random_index == last_random_index){ + random_index = (random_index + 1 + (random_sequence % 9)) % 10; + } + last_random_index = random_index; + + written = snprintf(url, url_size, CLOUD_TTS_ERROR_URL_FORMAT, random_index); + if(written < 0 || (size_t)written >= url_size){ + printf("random tts error url buffer too small\n"); + return -1; + } + + printf("random cloud tts error index:%02u, url:%s\n", random_index, url); + return 1; +} + void add_file_to_play_player_queue(char *path, int type) { ice_work_item *item = NULL; @@ -266,14 +319,32 @@ static void onmessage_text(rws_socket socket, const char *text, const unsigned i }else{//TTS_URL:audio_url wss_connect_start = 0; - char *ret_str1= strstr(text, "http:"); - char *ret_str2= strstr(text, ".mp3"); - int len = 0; + char *ret_str1 = strstr(text, "https://"); + char *ret_str2 = NULL; + size_t url_len = 0; + int is_tts_error_url = 0; + if(ret_str1 == NULL){ + ret_str1 = strstr(text, "http://"); + } + if(ret_str1 != NULL){ + ret_str2 = strstr(ret_str1, ".mp3"); + } if(ret_str1!=NULL && ret_str2!=NULL){ - - len = strlen(ret_str1)-strlen(ret_str2); - strncpy(url_buff, ret_str1, len); - sprintf(url_buff+len, "%s", ".mp3"); + + /* 提取完整的 HTTP/HTTPS MP3 URL,结尾额外包含“.mp3”四个字符 */ + url_len = (size_t)(ret_str2 - ret_str1) + strlen(".mp3"); + if(url_len >= sizeof(url_buff)){ + printf("audio url too long:%d\n", (int)url_len); + return; + } + memcpy(url_buff, ret_str1, url_len); + url_buff[url_len] = '\0'; + + /* 两个角色统一使用 banban 的 HTTP 随机超时提示音 */ + is_tts_error_url = randomize_tts_error_url(url_buff, sizeof(url_buff)); + if(is_tts_error_url < 0){ + return; + } memcpy(url_buff_bak, url_buff, strlen(url_buff)+1); @@ -292,7 +363,7 @@ static void onmessage_text(rws_socket socket, const char *text, const unsigned i tts_play_status = 2; } - if(strstr(url_buff, "tts_error")!=NULL || strstr(url_buff, "message_ok")!=NULL){ + if(is_tts_error_url == 1 || strstr(url_buff, "message_ok")!=NULL){ printf("tts_error or message_ok\n"); vad_set_speech_timeout_flag(1); }