新增led前备份,已加5秒内重复触发vad打断,续写asr结果
authorp15692025051 <846603105@qq.com>
Tue, 3 Jun 2025 02:26:42 +0000 (10:26 +0800)
committerp15692025051 <846603105@qq.com>
Tue, 3 Jun 2025 02:26:42 +0000 (10:26 +0800)
2.code/aicos/app/AI_AMP_2_5/AI_AMP_2_5.c
2.code/aicos/app/AI_AMP_2_5/AI_AMP_2_5.h
2.code/aicos/app/AI_AMP_2_5/dev_authentication.c

index bb20303..a6dbc73 100644 (file)
@@ -30,7 +30,7 @@
 #include "sysoff.h"
 // #include "opus/include/opus.h"
 u8 current_card_id = 0;
-u8 Close_flag = 0;
+u8 VC_TTS_PLAY_EVENT = 0;
 typedef enum
 {
     inbound_attributes_format_PCM,
@@ -41,9 +41,12 @@ AI_AMP_2_5_cfg vc_cfg;
 volatile char app_audio_flag = 0;
 volatile char audio_stop_flag = 0;
 int32_t bk_audio_start_callback(void *p_param, uint32_t size);
-#define VAD_RB_LEN 16*1024
+#define VAD_RB_LEN 64*1024
 bk_ring_buf_t *VAD_rb_data = NULL;
-int VAD_status = 0;//VAD状态
+static u32 VAD_status = 0;//VAD状态
+static u32 VAD_time = 0;//缓存上一次VAD触发结束时间
+static int VAD_time_count = 0;//上一次VAD触发结束到下一次触发开始间隔时间,用来判断是否超时,没超时拼接上一次asr结果
+#define VAD_TIMEOUT 5000
 char VC_mode = 0;//0:短按连续问答模式 1:长按录音模式
 #define ai_VC_task_priority 35
 static aos_thread_id AI_AMP_task_id = 0;
@@ -75,6 +78,10 @@ static u32 close_timerout = 0;
 static u32 VC_pingping_timerout = 0;
 static u32 VC_END_play_timerout = 0;
 static char *AI_TTS_str = NULL;
+static char *AI_ASR_str = NULL;
+#define AI_ASR_STR_MAX_LEN 1024*2
+static char *AI_ASR_str_tmp = NULL;
+#define AI_ASR_STR_MAX_TMP_LEN 1024
 static aos_timer_ptr AI_VC_1S_timer = NULL;
 // OpusEncoder *opus_encoder_h = NULL;
 // OpusDecoder *opus_decoder_h = NULL;
@@ -208,8 +215,8 @@ void reset_VC_cfg(void)
 {
     vc_cfg.start_flag = 0xaaaa;
     vc_cfg.end_flag = 0xaaaa;
-    vc_cfg.dev_type = DEV_FX1_H;//产品
-    //vc_cfg.dev_type = DEV_ADS;//奥德赛
+    //vc_cfg.dev_type = DEV_FX1_H;//产品
+    vc_cfg.dev_type = DEV_ADS;//奥德赛
     //strcpy(vc_cfg.server_ip,"amp.raisound.com");//服务器地址
     strcpy(vc_cfg.server_ip,"115.190.94.208:22080");//服务器地址
     vc_cfg.VC_mode =0;//对话模式
@@ -239,7 +246,8 @@ int init_VC_cfg(void)
             bk_printf("init_VC_cfg:获取配置正常。vc_cfg.VC_TTS_volume:%d",vc_cfg.VC_TTS_volume);
         }else if(vc_cfg.start_flag == 0xaaaa && vc_cfg.end_flag != 0xaaaa)//结构体新增参数
         {
-
+            bk_printf("init_VC_cfg:新增配置");
+            reset_VC_cfg();
         }else //if(vc_cfg.start_flag != 0xaaaa && vc_cfg.end_flag != 0xaaaa)//m没有配置,要初始化配置
         {
             bk_printf("init_VC_cfg:没有配置");
@@ -447,7 +455,22 @@ int check_text(char *text,int ret_str_len)
     }
     if(ret_str_len<16 && (strstr(text,"关机") ))
     {
-        AI_AMP_MSG_put(tmp_data,tmp_data_len,POWER_OFF);
+        tmp_data_len = snprintf(tmp_data,sizeof(tmp_data),"正在关机。");
+        AI_AMP_MSG_put(tmp_data,tmp_data_len,VC_TTS_PLAY_POWER_OFF);
+    }
+    if(ret_str_len<16 && (strstr(text,"重启") ))
+    {
+        tmp_data_len = snprintf(tmp_data,sizeof(tmp_data),"正在重启。");
+        AI_AMP_MSG_put(tmp_data,tmp_data_len,VC_TTS_PLAY_RESET);
+    }
+    if(ret_str_len<24 && (strstr(text,"恢复出厂") ))
+    {
+        reset_VC_cfg();
+        tmp_data_len = snprintf(tmp_data,sizeof(tmp_data),"恢复出厂成功,即将重启。");
+        AI_AMP_MSG_put(tmp_data,tmp_data_len,VC_TTS_PLAY_RESET);
+        is_save_VC_cfg = 1;
+        ret = 0;
+        goto RET;
     }
 RET:
     if(is_save_VC_cfg == 1)
@@ -507,7 +530,13 @@ static void AI_VC_send_satrt(void)
     cJSON *payload = cJSON_CreateObject();
     cJSON_AddStringToObject(payload, "device_id", vc_cfg.dev_imei);
     cJSON_AddStringToObject(payload, "user_agent", "AudioClient/1.0");
-
+    if(AI_ASR_str && VAD_time_count !=0 && VAD_time_count <= VAD_TIMEOUT )//时间间隔短,认为是一次对话,加上上一次内容
+    {
+        if(strlen(AI_ASR_str)>0)
+            cJSON_AddStringToObject(payload, "previous_result_text",AI_ASR_str);
+        bk_printf("上次asr内容追加:%s",AI_ASR_str);
+         
+    }
     // 创建 dialog_attributes 对象
     cJSON *dialog_attributes = cJSON_CreateObject();
     if(vc_cfg.dev_type == DEV_ADS)
@@ -838,18 +867,6 @@ static void AI_VC_send_task(void *thread_input)//websocket 发送线程
                                 opus_count += enc_inparam.output_len_array[i];
                         }
                         bk_printf("opus data send:opus_count=%d",opus_count);
-                        //测试:
-                        // memset(pcm_data,0,AI_VC_send_queue_data.len);
-                        // dec_inparam.input = opus_data;
-                        // dec_inparam.inputfrm_count = enc_inparam.ouputfrm_cnt;
-                        // memcpy(dec_inparam.input_len_array , enc_inparam.output_len_array, sizeof(dec_inparam.input_len_array));
-                        // dec_inparam.output = (int16_t*)pcm_data;
-                        // dec_inparam.outbuffer_size = AI_VC_send_queue_data.len;
-                        // ret = aic_opus_decode(&dec_inparam);
-                        // audio_data(pcm_data,dec_inparam.outputfrms_size,25);
-                        ////aos_sleep(10);
-                        //bk_printf("OPUS:inputfrm_count:%d,opus_remain_size:%d,pcm_len:%d,dec_pcm_len:%d,opus_count:%d",
-                        //    dec_inparam.inputfrm_count,opus_remain_size,AI_VC_send_queue_data.len,dec_inparam.outputfrms_size,opus_count);
                         if(opus_data)
                             aic_free(opus_data);
                         if(pcm_data)
@@ -870,7 +887,6 @@ static void AI_VC_send_task(void *thread_input)//websocket 发送线程
                     bk_printf("send ret=%d,len=%d,str=%s",ret,AI_VC_send_queue_data.len,AI_VC_send_queue_data.data);
                 else if(AI_VC_send_queue_data.AIC_WEBSOCKET_OPCODE ==AIC_WEBSOCKET_OPCODE_BINARY_FRAME )
                 {
-                    audio_data(AI_VC_send_queue_data.data,AI_VC_send_queue_data.len,21);
                     bk_printf("send ret=%d,len=%d",ret,AI_VC_send_queue_data.len);
                 }
                     
@@ -928,7 +944,7 @@ static void AI_VC_read_task(void *thread_input)//websocket 读线程
                 if(code == WS_TEXT)//字符串
                 {
                     //bk_printf("AI_VC_read_task 3");
-                    bk_printf("read TEXT:status:%d,data:%s\n",status,recv_buff);
+                    bk_printf("read TEXT:status:%d,data:%s",status,recv_buff);
                     if(strstr(recv_buff,"\"started\""))//开始
                     {
                         
@@ -961,12 +977,47 @@ static void AI_VC_read_task(void *thread_input)//websocket 读线程
                             //bk_printf("content!!");
                             str_tmp += strlen("\"content\":\"");
                             int str_tmp_len = str_count(str_tmp,'\"');
-
+                            //存asr结果
+                            if(AI_ASR_str_tmp)
+                            {
+                                if(str_tmp_len>AI_ASR_STR_MAX_LEN-1)
+                                    str_tmp_len = AI_ASR_STR_MAX_LEN-1;
+                                memcpy(AI_ASR_str_tmp,str_tmp,str_tmp_len);
+                                AI_ASR_str_tmp[str_tmp_len] = 0;
+                            }
+                            
+                            
                             int ret = check_text(str_tmp,str_tmp_len) ;
                             //识别到有命令词,退出
                             if(ret == 0)
                                 break;
                         }
+                    }else if(strstr(recv_buff,"\"asr.completed\""))//asr结束
+                    {
+                        if(AI_ASR_str && AI_ASR_str_tmp)
+                        {
+                            if(VAD_time_count <= VAD_TIMEOUT )//时间间隔短,认为是一次对话,拼接内容
+                            {
+                                
+                                
+                                
+                                    if(strlen(AI_ASR_str) +strlen(AI_ASR_str_tmp)> AI_ASR_STR_MAX_LEN-1)//超出缓存长度,清零
+                                    {
+                                        memset(AI_ASR_str,0,AI_ASR_STR_MAX_LEN);
+                                        bk_printf("ASR内容超出缓存长度,清零缓存");
+
+                                    }
+                                    strncpy(AI_ASR_str+strlen(AI_ASR_str),AI_ASR_str_tmp,AI_ASR_STR_MAX_LEN -strlen(AI_ASR_str) );
+                                
+                                
+                                bk_printf("vad间隔时间短拼接asr结果:%s",AI_ASR_str);
+                                
+                            }else//超时,不用拼接
+                            {
+                                strncpy(AI_ASR_str,AI_ASR_str_tmp,AI_ASR_STR_MAX_LEN);
+                                bk_printf("vad间隔时间长,判断为两次对话:%s",AI_ASR_str);
+                            }
+                        }
                     }
                     else if(strstr(recv_buff,"\"vad.active\""))//vad触发
                     {
@@ -979,6 +1030,7 @@ static void AI_VC_read_task(void *thread_input)//websocket 读线程
                     else if(strstr(recv_buff,"\"tts.started\""))//tts开始
                     {
                         VC_state = VC_State_TTSStart;
+                        play_data_len = 0;
                         AI_AMP_MSG_put(0,0,VC_PLAY_START);//打开声音
                         
                     }else if(strstr(recv_buff,"\"tts.completed\""))//tts结束
@@ -997,17 +1049,7 @@ static void AI_VC_read_task(void *thread_input)//websocket 读线程
                 else if(code == WS_BINARY)//二进制
                 {
                     
-                    // for(int i = 0;i<4;i++)
-                    // {
-                    //     audio_data(recv_buff+status/4*i,status/4,24);
-                    //     //bk_printf("recv_buff len = %d",status/4);
-                    //     aos_sleep(1);
-                    // }
-                    // if(status%4)
-                    // {
-                    //     audio_data(recv_buff+status/4*4,status%4,24);
-                    //     aos_sleep(1);
-                    // }
+                    
                     //bk_printf("read BIN  status:%d,code:%d!!!!!!",status,code);
                     
                     AI_VC_put_play_data(recv_buff,status);//音频调试1
@@ -1030,7 +1072,7 @@ static void AI_VC_read_task(void *thread_input)//websocket 读线程
             aos_sleep(1);
         }else
         {
-            bk_printf("AI_VC_read_task:error AI_VC_client_websocket_handle=%d\n",AI_VC_client_websocket_handle);
+            bk_printf("AI_VC_read_task:error AI_VC_client_websocket_handle=%d",AI_VC_client_websocket_handle);
             break;
         }
         // bk_printf("AI_VC_read_task ..... \n");
@@ -1084,7 +1126,7 @@ static void AI_VC_record_task(void *thread_input)//录音线程
             aos_sleep(1);
             continue;
         }
-        audio_data(vrecord_buf,ret,23);
+        
         if(vc_cfg.is_VAD == 1)//VAD逻辑:先判断有没有有效数据,触发了有效数据才发送
         {
             
@@ -1093,37 +1135,48 @@ static void AI_VC_record_task(void *thread_input)//录音线程
             run_vad((int16_t *)vrecord_buf, ret / 2);
             vad_status_t = vad_detect(); 
             //bk_printf("VAD:vad_status_t:%d",vad_status_t);  
-            
-            if (vad_status_t == 2) {
+            audio_data(vrecord_buf,ret,23);
+            if (vad_status_t == 2) {//说话停止
                 vad_clear();
                 if(VAD_status == 1)//清空buff
                 {
+                    //VAD_timeout = aos_get_tickcount()-VAD_time;
+                    VAD_time = aos_get_tickcount();
                     bk_rb_clear(VAD_rb_data);
                     AI_VC_put_record_data(vrecord_buf,ret);
                 }
                 VAD_status = 2;
-                
+                audio_data(vrecord_buf,ret,21);
+                memset(vrecord_buf,0xff,sizeof(vrecord_buf));
+                audio_data(vrecord_buf,sizeof(vrecord_buf),21);
             }else if(vad_status_t == 1 )//检测到说话
             {
                 if(VAD_status ==0)//第一次检测到说话
                 {
+                    if(VAD_time !=0)
+                        VAD_time_count = aos_get_tickcount()-VAD_time;
                     
                     int rb_len_t = bk_rb_data_len(VAD_rb_data);
                     bk_printf("VAD:检测到说话了,回溯音频大小:%d,VC_state:%d",rb_len_t,VC_state); 
+                    unsigned char *vad_r_tmp =  aic_malloc(2560);
                     while(bk_rb_data_len(VAD_rb_data))//清空缓存数据
                     {
-                        unsigned char *vad_r_tmp =  aic_malloc(1280);
+                        
                         if(vad_r_tmp)
                         {
-                            unsigned int r_len =  bk_rb_read(VAD_rb_data,vad_r_tmp,1280);
+                            unsigned int r_len =  bk_rb_read(VAD_rb_data,vad_r_tmp,2560);
                             //AI_VC_send_data(vad_r_tmp,r_len,AIC_WEBSOCKET_OPCODE_BINARY_FRAME);//发送缓冲数据
                             AI_VC_put_record_data(vad_r_tmp,r_len);//入队缓冲数据
-                            aic_free(vad_r_tmp);
+                            audio_data(vad_r_tmp,r_len,21);
+                            
                         }
                     }
+                    if(vad_r_tmp)
+                        aic_free(vad_r_tmp);
                     VAD_status = 1;
                 }
                 AI_VC_put_record_data(vrecord_buf,ret);
+                audio_data(vrecord_buf,ret,21);
                 //bk_printf("VAD:检测到说话了"); 
             }else if(vad_status_t == 0 )//m没有说话
             {
@@ -1145,7 +1198,7 @@ static void AI_VC_record_task(void *thread_input)//录音线程
                         bk_rb_write(VAD_rb_data,vrecord_buf,ret);
                     }
                 }
-
+                VAD_status =0;
             }
             u32 count_tmp = 0;
             if(AI_VC_record_tmp_queue)
@@ -1267,7 +1320,7 @@ static void AI_VC_play_task(void *thread_input)//音频播放线程
         if(AI_VC_play_task_flag >=2)
             break;
         //app_logi("app_audio_write0!!\r\n");
-        if(VC_Play_flag ==1 && AI_VC_play_queue )
+        if(play_data_len>8*1024 &&VC_Play_flag ==1 && AI_VC_play_queue )
         {
             queue_ret = aos_recv_from_queue(AI_VC_play_queue,&AI_VC_play_queue_data,AOS_NO_WAIT);
             if( queue_ret== AOS_SUCCESS)
@@ -1696,12 +1749,19 @@ static void AI_VC_1S_timeout(void *param)
         {
             if(VC_mode == 0)
             {
-                if(Close_flag == 1)
+                if(VC_TTS_PLAY_EVENT == VC_TTS_PLAY_CLOSE)
                 {
-                    Close_flag = 0;
+                    VC_TTS_PLAY_EVENT = 0;
                     AI_AMP_MSG_put(0,0,VC_CLOSE);
-                }else
+                }else if (VC_TTS_PLAY_EVENT == VC_TTS_PLAY_POWER_OFF)
                 {
+                    AI_AMP_MSG_put(0,0,POWER_OFF);
+                }else if (VC_TTS_PLAY_EVENT == VC_TTS_PLAY_RESET)
+                {
+                    AI_AMP_MSG_put(0,0,POWER_RESET);
+                }
+                
+                else{
                     VAD_status = 0;
                     VC_state = VC_State_Listening;//重新开始了
                 }
@@ -1819,12 +1879,23 @@ void AI_VC_start(void)
         bk_printf("app_audio_start ret=%d",ret);
         app_logi("app_audio_start ret=%d",ret);
     }
-    // aic_gpio_output(GPIO_25,GPIO_OUTPUT_LVL_HIGH );//led
-    // aic_gpio_output(GPIO_30,GPIO_OUTPUT_LVL_HIGH );//led
-    // aic_gpio_output(GPIO_31,GPIO_OUTPUT_LVL_HIGH );//led
-    // aic_gpio_output(GPIO_GPO_8,GPIO_OUTPUT_LVL_HIGH );//马达
-    // aic_gpio_output(GPIO_GPO_1,GPIO_OUTPUT_LVL_LOW );//马达
-    // aic_gpio_output(GPIO_20,GPIO_OUTPUT_LVL_HIGH );//马达
+    VAD_time = 0;
+    VAD_time_count = 0;
+    if(AI_ASR_str_tmp == NULL)
+    {
+        AI_ASR_str_tmp = aic_zalloc(AI_ASR_STR_MAX_TMP_LEN);
+    }
+    if(AI_ASR_str == NULL)
+    {
+        AI_ASR_str = aic_zalloc(AI_ASR_STR_MAX_LEN);
+
+    }
+    aic_gpio_output(GPIO_25,GPIO_OUTPUT_LVL_HIGH );//led
+    aic_gpio_output(GPIO_30,GPIO_OUTPUT_LVL_HIGH );//led
+    aic_gpio_output(GPIO_31,GPIO_OUTPUT_LVL_HIGH );//led
+    aic_gpio_output(GPIO_GPO_8,GPIO_OUTPUT_LVL_HIGH );//马达
+    aic_gpio_output(GPIO_GPO_1,GPIO_OUTPUT_LVL_LOW );//马达
+    aic_gpio_output(GPIO_20,GPIO_OUTPUT_LVL_HIGH );//马达
     //app_audio_set_master_volume(8);
     // if (ret) {
     //     bk_printf("AI_VC_start app_audio_start error");
@@ -1919,12 +1990,12 @@ void AI_VC_start(void)
 void AI_VC_Close(void)
 {
     int count;
-    // aic_gpio_output(GPIO_25,GPIO_OUTPUT_LVL_LOW );
-    // aic_gpio_output(GPIO_30,GPIO_OUTPUT_LVL_LOW );
-    // aic_gpio_output(GPIO_31,GPIO_OUTPUT_LVL_LOW );
-    // aic_gpio_output(GPIO_GPO_8,GPIO_OUTPUT_LVL_LOW );
-    // aic_gpio_output(GPIO_GPO_1,GPIO_OUTPUT_LVL_LOW);
-    // aic_gpio_output(GPIO_20,GPIO_OUTPUT_LVL_LOW );
+    aic_gpio_output(GPIO_25,GPIO_OUTPUT_LVL_LOW );
+    aic_gpio_output(GPIO_30,GPIO_OUTPUT_LVL_LOW );
+    aic_gpio_output(GPIO_31,GPIO_OUTPUT_LVL_LOW );
+    aic_gpio_output(GPIO_GPO_8,GPIO_OUTPUT_LVL_LOW );
+    aic_gpio_output(GPIO_GPO_1,GPIO_OUTPUT_LVL_LOW);
+    aic_gpio_output(GPIO_20,GPIO_OUTPUT_LVL_LOW );
     if(vc_cfg.is_VAD == 1)
     {
         // 不使用或暂停使用VAD时调用
@@ -2092,7 +2163,16 @@ void AI_VC_Close(void)
         }
         bk_printf("app_audio_stop2 audio_count:%d",audio_count);
     }
-    
+    if(AI_ASR_str_tmp)
+    {
+        aic_free(AI_ASR_str_tmp);
+        AI_ASR_str_tmp =NULL;
+    }
+    if(AI_ASR_str)
+    {
+        aic_free(AI_ASR_str);
+        AI_ASR_str =NULL;
+    }
     //app_logi("app_audio_stop2");
     
     
@@ -2139,7 +2219,7 @@ static void AI_AMP_2_5_task(void *thread_input)//做逻辑线程
         if(pdp_activated == TRUE)
             break;
         bk_printf("AI_AMP_2_5_init 等待注网..... \n");
-        audio_play_tone(3,200);//播放提示音,测试用
+        audio_play_tone(count%10,500);//播放提示音,测试用
         aos_sleep(1000);
     }
 
@@ -2169,6 +2249,12 @@ static void AI_AMP_2_5_task(void *thread_input)//做逻辑线程
                     //播放关机提示音
                     sysoff_shutdown();
                     break;
+                case POWER_RESET://重启
+                    AI_VC_Close();
+                    //播放关机提示音
+                    sysoff_reset();
+                    break;
+                    
                 case VC_Cancel://打断
                     //发送打断
                     //AI_VC_send_cancel();//发送打断,发送完打断还有发开始音频
@@ -2207,12 +2293,25 @@ static void AI_AMP_2_5_task(void *thread_input)//做逻辑线程
                     if(AI_AMP_msg.data!=NULL)
                     {
                         VC_TTS_Play(AI_AMP_msg.data);
-                        Close_flag = 1;
+                        VC_TTS_PLAY_EVENT = VC_TTS_PLAY_CLOSE;
+                    }
+                    break;
+                case VC_TTS_PLAY_POWER_OFF://播放完关机
+                    if(AI_AMP_msg.data!=NULL)
+                    {
+                        VC_TTS_Play(AI_AMP_msg.data);
+                        VC_TTS_PLAY_EVENT = VC_TTS_PLAY_POWER_OFF;
+                    }
+                    break;
+                case VC_TTS_PLAY_RESET://播放完重启:
+                    if(AI_AMP_msg.data!=NULL)
+                    {
+                        VC_TTS_Play(AI_AMP_msg.data);
+                        VC_TTS_PLAY_EVENT = VC_TTS_PLAY_RESET;
                     }
-                        
-                    
                     break;
                     
+                    
                 case VC_CONNECT_ERROR://连接错误
                     AI_VC_Close();
                     if(AI_AMP_msg.data)
index 57a7ac4..b2e93d5 100644 (file)
@@ -43,6 +43,7 @@ extern AI_AMP_2_5_cfg vc_cfg;
 typedef enum AI_AMP_MSG
 {
     POWER_OFF,//关机
+    POWER_RESET,//重启
     VC_START,
     VC_PLAY_START,
     VC_PLAY_END,
@@ -51,6 +52,8 @@ typedef enum AI_AMP_MSG
     VC_Cancel,//打断取消
     VC_TTS_PLAY,
     VC_TTS_PLAY_CLOSE,//播放完关闭对话
+    VC_TTS_PLAY_RESET,//播放完重启
+    VC_TTS_PLAY_POWER_OFF,//播放完关机
     VC_CLOSE,
     VC_CONNECT_ERROR,
     AI_KEY_PRESS,//AI键按下
index 7e21ade..e47c368 100644 (file)
@@ -391,7 +391,7 @@ void aut_active(void)//设备激活
      // 创建JSON对象
      cJSON *root = cJSON_CreateObject();
      if (root == NULL) {
-        bk_printf(stderr, "Failed to create JSON object\n");
+        bk_printf( "Failed to create JSON object\n");
          return ;
      }
  
@@ -405,7 +405,7 @@ void aut_active(void)//设备激活
      // 生成JSON字符串
      char *json_string = cJSON_Print(root);
      if (json_string == NULL) {
-        bk_printf(stderr, "Failed to print JSON\n");
+        bk_printf("Failed to print JSON\n");
          cJSON_Delete(root);
          return ;
      }