7 Commits
4 changed files with 104 additions and 45 deletions
@@ -187,6 +187,9 @@ static void key_thread_entry(void *parameter)
if(ql_rtos_get_systicks() - key_press_mic_time > KEY_LONG_PRESS_3S && power_down_status==0){ if(ql_rtos_get_systicks() - key_press_mic_time > KEY_LONG_PRESS_3S && power_down_status==0){
nfc_tx_click_count = 0; nfc_tx_click_count = 0;
power_down_status = 1; power_down_status = 1;
/* Shutdown audio must own the codec. Stop VAD and any
* interrupted TTS before queueing the power-off prompt. */
stop_player_func();
app_play_tips_file(10); app_play_tips_file(10);
power_down_status = 2; power_down_status = 2;
//ql_rtos_task_sleep_s(3); //ql_rtos_task_sleep_s(3);
@@ -34,6 +34,7 @@ const char *mp3_file[] ={
"volume_up_zh.mp3",//16 "volume_up_zh.mp3",//16
"volume_down_zh.mp3",//17 "volume_down_zh.mp3",//17
"ai_active_zh.mp3",//18 "ai_active_zh.mp3",//18
"barge_in_cute.mp3",//19 对话打断提示音
}; };
//http://banban.api.talkingq.com:8080/assets/roles/banban/tts_error.mp3 //http://banban.api.talkingq.com:8080/assets/roles/banban/tts_error.mp3
@@ -183,11 +184,13 @@ void app_file_check_download(void)
char filename_buff[64]={0x00}; char filename_buff[64]={0x00};
int ret = 0, cnt = 0; int ret = 0, cnt = 0;
for(index=1;index<19;index++){ for(index=1;index<20;index++){
if(index==4||index==5||index==6||index==7||index==8){ /* barge_in_cute.mp3 is shipped in customer_fs and is not hosted by the
continue; * legacy prompt download service. */
} if(index==4||index==5||index==6||index==7||index==8||index==19){
continue;
}
if(strlen(mp3_file[index])>0){ if(strlen(mp3_file[index])>0){
sprintf(filename_buff, "U:/%s", mp3_file[index]); sprintf(filename_buff, "U:/%s", mp3_file[index]);
@@ -203,14 +206,16 @@ down_loop:
} }
} }
void app_file_check_del(void) void app_file_check_del(void)
{ {
int index = 1; int index = 1;
char filename_buff[64]={0x00}; char filename_buff[64]={0x00};
for(index=1;index<19;index++){ for(index=1;index<20;index++){
if(index==4||index==5||index==6||index==7||index==8){ /* Keep the bundled barge-in prompt across app-only FOTA. Unlike the
* server-managed prompts, it cannot be restored by the downloader. */
if(index==4||index==5||index==6||index==7||index==8||index==19){
continue; continue;
} }
@@ -49,11 +49,14 @@ static uint8_t sender_buf[PCM_FRAME_LENGTH]={0};
static int16 mp3_buff[2*PCM_FRAME_LENGTH]; static int16 mp3_buff[2*PCM_FRAME_LENGTH];
static int16 *ppbuff=mp3_buff; static int16 *ppbuff=mp3_buff;
static int onmessage_status = -1; static int onmessage_status = -1;
volatile int tts_playing = 0; volatile int tts_playing = 0;
unsigned char wss_connect_start = 0; unsigned char wss_connect_start = 0;
static volatile int player_mq_couter = 0; static volatile int player_mq_couter = 0;
static unsigned char audio_in_task_cancel = 0; /* Set while a barge-in prompt bridges the old and new sessions. The old
* server response can still deliver URLs after its player queue was cleared. */
static volatile int barge_in_transition = 0;
static unsigned char audio_in_task_cancel = 0;
static unsigned char xiaoice_wss_connect_status = 0; static unsigned char xiaoice_wss_connect_status = 0;
static unsigned char wss_connect_counter = 0; static unsigned char wss_connect_counter = 0;
@@ -299,6 +302,14 @@ static void onmessage_text(rws_socket socket, const char *text, const unsigned i
return; return;
} }
/* The new session id is generated only when recording starts. Until
* then, every TTS message on this socket belongs to the interrupted
* session and must not be allowed to refill the cleared player queue. */
if (barge_in_transition) {
printf("drop stale websocket message during barge-in\r\n");
return;
}
// printf("message(txt), %d(byte): %s ", len, text); // printf("message(txt), %d(byte): %s ", len, text);
char url_buff[128]={0x00}; char url_buff[128]={0x00};
@@ -743,9 +754,12 @@ void generateSessionId(void)
#if 1 #if 1
void sendStartPacket(void) { void sendStartPacket(void) {
generateSessionId(); generateSessionId();
generateDeviceId(); /* sessionId now identifies the new conversation. Late URLs from the old
* conversation will fail the existing session-id check below. */
barge_in_transition = 0;
generateDeviceId();
gSequenceNumber = 0; gSequenceNumber = 0;
AudioPacket startPacket = {0}; AudioPacket startPacket = {0};
@@ -862,17 +876,23 @@ void sendRecordingAudioPacket(AudioPacket *packet) {
extern const char *mp3_file[]; extern const char *mp3_file[];
int app_play_tips_file(int index) int app_play_tips_file(int index)
{ {
int file_valid_check = 0; int file_valid_check = 0;
int access_ret = 0;
printf("xiaoice_play_index:%d\n", index);
printf("xiaoice_play_index:%d\n", index);
//正在录音过程中不允许播放
// if(xiaoice_get_tts_play_status() || get_start_mic_flag()==1) return -1; //正在录音过程中不允许播放
if(power_down_status!=1){ // if(xiaoice_get_tts_play_status() || get_start_mic_flag()==1) return -1;
if(vad_audio_is_recording() || tts_playing!=0 || fota_start==1 || power_down_status==2 || get_sleep_mode()==1) return -1; if(power_down_status!=1){
} if(vad_audio_is_recording() || tts_playing!=0 || fota_start==1 || power_down_status==2 || get_sleep_mode()==1) {
printf("tips blocked:index=%d vad=%d tts=%d fota=%d power=%d sleep=%d\r\n",
index, vad_audio_is_recording(), tts_playing, fota_start,
power_down_status, get_sleep_mode());
return -1;
}
}
char filename_buff[64]={0x00}; char filename_buff[64]={0x00};
@@ -881,15 +901,18 @@ int app_play_tips_file(int index)
if(index==0) { if(index==0) {
file_valid_check = 0; file_valid_check = 0;
}else{ }else{
if(ql_access(filename_buff, 0)==0){ access_ret = ql_access(filename_buff, 0);
file_valid_check = 1; if(access_ret==0){
}else{ file_valid_check = 1;
file_valid_check = 2; }else{
} printf("tips file missing:index=%d path=%s access=%d\r\n",
index, filename_buff, access_ret);
file_valid_check = 2;
}
} }
if(file_valid_check!=2){ if(file_valid_check!=2){
if(index==18){ if(index==18 || index==19){
add_file_to_play_player_queue(filename_buff, 2); add_file_to_play_player_queue(filename_buff, 2);
}else{ }else{
add_file_to_play_player_queue(filename_buff, 0); add_file_to_play_player_queue(filename_buff, 0);
@@ -1001,26 +1024,46 @@ void app_player_thread(void *arvg)
int tts_play_interrupt_func(void) int tts_play_interrupt_func(void)
{ {
int playback_interrupted = 0;
//如果在vad状态,则直接返回 //如果在vad状态,则直接返回
if(vad_audio_is_recording()||g_mic_working) return -1; if(vad_audio_is_recording()||g_mic_working) return -1;
g_mic_working = 1;//等待转为vad状态就清0 或者拾音超时 或者ws没有正常 g_mic_working = 1;//等待转为vad状态就清0 或者拾音超时 或者ws没有正常
xiaoice_close_all_audio(); /* Remember whether this key press is interrupting TTS. tts_playing == 2
* is only a cancellation signal for the old player; it must not leak into
* the next conversation, otherwise prompts and error audio are discarded. */
playback_interrupted = (tts_playing != 0 || player_mq_couter > 0);
barge_in_transition = playback_interrupted;
xiaoice_close_all_audio();
talkingq_ws_connect(); talkingq_ws_connect();
if(get_xiaoice_connected_status()!=2) { if(get_xiaoice_connected_status()!=2) {
g_mic_working = 0; /* Let the caller play its local network-error prompt. */
return -2; tts_play_status = 0;
} tts_playing = 0;
barge_in_transition = 0;
if(tts_playing==2){ g_mic_working = 0;
printf("vad_start_func0\n"); return -2;
vad_start_func();//如果是打断就不播报 }
if(playback_interrupted){
printf("barge_in_prompt\n");
/* The old player has finished consuming the cancellation state. */
tts_play_status = 0;
tts_playing = 0;
/* Use the same local-prompt flow as ai_active_zh.mp3. Queue type 2
* starts VAD after playback; fall back to VAD if the file is absent. */
if(app_play_tips_file(19) != 0){
vad_start_func();
}
}else{ }else{
app_play_tips_file(18); app_play_tips_file(18);
} }
return 0;
} }
void stop_player_func(void) void stop_player_func(void)
@@ -1028,6 +1071,7 @@ void stop_player_func(void)
vad_audio_stop_record(); vad_audio_stop_record();
xiaoice_close_all_audio(); xiaoice_close_all_audio();
tts_play_status = 0;
tts_playing = 0; tts_playing = 0;
} }
@@ -1194,9 +1238,16 @@ void xiaoice_close_all_audio(void)
timeout = hal_os_up_time_ms(); timeout = hal_os_up_time_ms();
while(tts_play_status&&tts_playing!=2){ /* The queue counter also includes the item currently owned by the
* player task. Wait for that item to observe tts_playing == 2 and
* finish cleanup before the cancellation state is reused/reset. */
while(player_mq_couter>0){
ql_rtos_task_sleep_ms(20); ql_rtos_task_sleep_ms(20);
if(hal_os_up_time_ms()-timeout>10000) break; if(hal_os_up_time_ms()-timeout>OTA_AUDIO_STOP_TIMEOUT_MS){
printf("wait player stop timeout, counter:%d\r\n",
player_mq_couter);
break;
}
} }
} }
#endif #endif
Binary file not shown.