fix(audio): isolate NFC leave-message sessions
This commit is contained in:
@@ -299,9 +299,47 @@ void vad_leave_message(void)
|
|||||||
audio_packet_type = 4;
|
audio_packet_type = 4;
|
||||||
|
|
||||||
vad_leave_message_flag = 1;
|
vad_leave_message_flag = 1;
|
||||||
|
/* A previous conversation may still be parked in WAITING_COMMAND. NFC
|
||||||
|
* leave-message recording must enter IDLE first, otherwise g_triggered is
|
||||||
|
* left pending forever and its 10-second no-speech timer never starts. */
|
||||||
|
set_state(STATE_IDLE);
|
||||||
vad_audio_trigger_record();
|
vad_audio_trigger_record();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int vad_leave_message_is_active(void)
|
||||||
|
{
|
||||||
|
return vad_leave_message_flag != 0 || audio_packet_type == 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* The conversation key has priority over an unfinished NFC leave-message
|
||||||
|
* transaction. Clear every local latch before the normal conversation prompt
|
||||||
|
* is queued so that its recording can never inherit packetType=4. */
|
||||||
|
int vad_cancel_leave_message(void)
|
||||||
|
{
|
||||||
|
int was_active = vad_leave_message_is_active();
|
||||||
|
|
||||||
|
if (!was_active) return 0;
|
||||||
|
|
||||||
|
printf("cancel pending leave message\r\n");
|
||||||
|
vad_leave_message_flag = 0;
|
||||||
|
g_triggered = false;
|
||||||
|
audio_packet_type = 0;
|
||||||
|
no_speech_timeout = 0;
|
||||||
|
speech_detect_count = 0;
|
||||||
|
vad_preroll_next = 0;
|
||||||
|
vad_preroll_count = 0;
|
||||||
|
key_start_leave = 0;
|
||||||
|
|
||||||
|
if (vad_audio_is_recording()) {
|
||||||
|
set_state(STATE_IDLE);
|
||||||
|
vad_audio_stop_no_wait_resp();
|
||||||
|
} else {
|
||||||
|
set_state(STATE_IDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// 主处理函数 - 需要在循环中定期调用
|
// 主处理函数 - 需要在循环中定期调用
|
||||||
void vad_audio_process(void) {
|
void vad_audio_process(void) {
|
||||||
size_t bytes_read = 0;
|
size_t bytes_read = 0;
|
||||||
@@ -317,7 +355,6 @@ void vad_audio_process(void) {
|
|||||||
switch (g_state) {
|
switch (g_state) {
|
||||||
case STATE_IDLE:
|
case STATE_IDLE:
|
||||||
no_speech_timeout = 0;
|
no_speech_timeout = 0;
|
||||||
vad_leave_message_flag = 0;
|
|
||||||
speech_detect_count = 0; // 空闲时清零计数器
|
speech_detect_count = 0; // 空闲时清零计数器
|
||||||
vad_tts_playback_finished_status = 0;
|
vad_tts_playback_finished_status = 0;
|
||||||
|
|
||||||
@@ -449,13 +486,18 @@ void vad_audio_process(void) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case STATE_WAITING_COMMAND:
|
case STATE_WAITING_COMMAND:
|
||||||
if(vad_tts_playback_finished_status == 1) {
|
if(vad_tts_playback_finished_status == 1) {
|
||||||
|
int leave_message_finished = vad_leave_message_flag != 0;
|
||||||
printf("finished_status:%d, no_speech_timeout:%d\n", vad_tts_playback_finished_status, no_speech_timeout);
|
printf("finished_status:%d, no_speech_timeout:%d\n", vad_tts_playback_finished_status, no_speech_timeout);
|
||||||
set_state(STATE_IDLE);
|
set_state(STATE_IDLE);
|
||||||
ql_rtos_task_sleep_ms(50);
|
ql_rtos_task_sleep_ms(50);
|
||||||
if(no_speech_timeout == 0&&vad_leave_message_flag==0) {
|
if(no_speech_timeout == 0&&vad_leave_message_flag==0) {
|
||||||
vad_audio_trigger_record();
|
vad_audio_trigger_record();
|
||||||
}
|
}
|
||||||
|
if(leave_message_finished) {
|
||||||
|
vad_leave_message_flag = 0;
|
||||||
|
audio_packet_type = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
key_start_leave = 0;
|
key_start_leave = 0;
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ static volatile int player_mq_couter = 0;
|
|||||||
/* Set while a barge-in prompt bridges the old and new sessions. The old
|
/* 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. */
|
* server response can still deliver URLs after its player queue was cleared. */
|
||||||
static volatile int barge_in_transition = 0;
|
static volatile int barge_in_transition = 0;
|
||||||
static unsigned char audio_in_task_cancel = 0;
|
static volatile 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;
|
||||||
@@ -71,6 +71,8 @@ static unsigned char shine_init = 0;
|
|||||||
extern int fisrt_net_start;
|
extern int fisrt_net_start;
|
||||||
extern u8 power_down_status;
|
extern u8 power_down_status;
|
||||||
extern int aofei_mp3_player_get_result(void);
|
extern int aofei_mp3_player_get_result(void);
|
||||||
|
extern int vad_leave_message_is_active(void);
|
||||||
|
extern int vad_cancel_leave_message(void);
|
||||||
|
|
||||||
void sendAuthentication(void);
|
void sendAuthentication(void);
|
||||||
void vad_start_func(void);
|
void vad_start_func(void);
|
||||||
@@ -351,6 +353,7 @@ static void onmessage_text(rws_socket socket, const char *text, const unsigned i
|
|||||||
char *ret_str2 = NULL;
|
char *ret_str2 = NULL;
|
||||||
size_t url_len = 0;
|
size_t url_len = 0;
|
||||||
int is_tts_error_url = 0;
|
int is_tts_error_url = 0;
|
||||||
|
int is_message_ok_url = 0;
|
||||||
if(ret_str1 == NULL){
|
if(ret_str1 == NULL){
|
||||||
ret_str1 = strstr(text, "http://");
|
ret_str1 = strstr(text, "http://");
|
||||||
}
|
}
|
||||||
@@ -367,6 +370,14 @@ static void onmessage_text(rws_socket socket, const char *text, const unsigned i
|
|||||||
}
|
}
|
||||||
memcpy(url_buff, ret_str1, url_len);
|
memcpy(url_buff, ret_str1, url_len);
|
||||||
url_buff[url_len] = '\0';
|
url_buff[url_len] = '\0';
|
||||||
|
is_message_ok_url = strstr(url_buff, "message_ok") != NULL;
|
||||||
|
|
||||||
|
/* A cancelled NFC transaction may still have a response in flight.
|
||||||
|
* Never let that acknowledgement enter a normal conversation. */
|
||||||
|
if(is_message_ok_url && !vad_leave_message_is_active()){
|
||||||
|
printf("drop stale leave message ack\r\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* 两个角色统一使用 banban 的 HTTP 随机超时提示音 */
|
/* 两个角色统一使用 banban 的 HTTP 随机超时提示音 */
|
||||||
is_tts_error_url = randomize_tts_error_url(url_buff, sizeof(url_buff));
|
is_tts_error_url = randomize_tts_error_url(url_buff, sizeof(url_buff));
|
||||||
@@ -391,7 +402,7 @@ static void onmessage_text(rws_socket socket, const char *text, const unsigned i
|
|||||||
tts_play_status = 2;
|
tts_play_status = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(is_tts_error_url == 1 || strstr(url_buff, "message_ok")!=NULL){
|
if(is_tts_error_url == 1 || is_message_ok_url){
|
||||||
printf("tts_error or message_ok\n");
|
printf("tts_error or message_ok\n");
|
||||||
vad_set_speech_timeout_flag(1);
|
vad_set_speech_timeout_flag(1);
|
||||||
}
|
}
|
||||||
@@ -1061,6 +1072,29 @@ void app_player_thread(void *arvg)
|
|||||||
int tts_play_interrupt_func(void)
|
int tts_play_interrupt_func(void)
|
||||||
{
|
{
|
||||||
int playback_interrupted = 0;
|
int playback_interrupted = 0;
|
||||||
|
int leave_message_cancelled = 0;
|
||||||
|
|
||||||
|
/* A short press explicitly starts a normal conversation. Cancel an NFC
|
||||||
|
* leave-message before the generic "already recording" guard, otherwise a
|
||||||
|
* pending/recording leave-message can leak packetType=4 into this session. */
|
||||||
|
leave_message_cancelled = vad_cancel_leave_message();
|
||||||
|
if(leave_message_cancelled){
|
||||||
|
uint64_t cancel_start;
|
||||||
|
|
||||||
|
/* Let the sender task discard buffered PCM and its encoder without
|
||||||
|
* emitting END. Only then close the old leave-message socket. */
|
||||||
|
audio_in_task_cancel = 1;
|
||||||
|
ql_rtos_semaphore_release(sender_sem);
|
||||||
|
cancel_start = hal_os_up_time_ms();
|
||||||
|
while(audio_in_task_cancel &&
|
||||||
|
hal_os_up_time_ms() - cancel_start < OTA_AUDIO_STOP_TIMEOUT_MS){
|
||||||
|
ql_rtos_task_sleep_ms(20);
|
||||||
|
}
|
||||||
|
if(audio_in_task_cancel){
|
||||||
|
printf("wait leave message sender cancel timeout\r\n");
|
||||||
|
}
|
||||||
|
talkingq_ws_disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
//如果在vad状态,则直接返回
|
//如果在vad状态,则直接返回
|
||||||
if(vad_audio_is_recording()||g_mic_working) return -1;
|
if(vad_audio_is_recording()||g_mic_working) return -1;
|
||||||
@@ -1313,6 +1347,23 @@ void app_sender_thread(void *arvg)
|
|||||||
ql_rtos_semaphore_wait(sender_sem, 0xFFFFFFFF);
|
ql_rtos_semaphore_wait(sender_sem, 0xFFFFFFFF);
|
||||||
|
|
||||||
sender_loop:
|
sender_loop:
|
||||||
|
if(audio_in_task_cancel){
|
||||||
|
left = rb_get_space_used(ring_sender);
|
||||||
|
while(left > 0){
|
||||||
|
int discard_len = left > PCM_FRAME_LENGTH ? PCM_FRAME_LENGTH : left;
|
||||||
|
hal_os_rb_read(ring_sender, sender_buf, discard_len, 0);
|
||||||
|
left = rb_get_space_used(ring_sender);
|
||||||
|
}
|
||||||
|
if(shine_init != 0){
|
||||||
|
shine_close(sh_shine);
|
||||||
|
sh_shine = NULL;
|
||||||
|
shine_init = 0;
|
||||||
|
}
|
||||||
|
audio_packet_type = 0;
|
||||||
|
audio_in_task_cancel = 0;
|
||||||
|
printf("leave message sender cancelled\r\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(!app_get_data_call_net_status()) continue;
|
if(!app_get_data_call_net_status()) continue;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user