更新,vad鉴权没加
authorp15692025051 <846603105@qq.com>
Mon, 23 Jun 2025 02:14:55 +0000 (10:14 +0800)
committerp15692025051 <846603105@qq.com>
Mon, 23 Jun 2025 02:14:55 +0000 (10:14 +0800)
18 files changed:
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/CMakeLists.txt
2.code/aicos/app/AI_AMP_2_5/bk_dev.c [new file with mode: 0644]
2.code/aicos/app/AI_AMP_2_5/bk_dev.h [new file with mode: 0644]
2.code/aicos/app/AI_AMP_2_5/bk_key.c
2.code/aicos/app/AI_AMP_2_5/bk_opus_coder.c [new file with mode: 0644]
2.code/aicos/app/AI_AMP_2_5/bk_opus_coder.h [new file with mode: 0644]
2.code/aicos/app/AI_AMP_2_5/bk_websocket.c
2.code/aicos/app/AI_AMP_2_5/bk_websocket.h
2.code/aicos/app/AI_AMP_2_5/imsl_vad.h
2.code/aicos/app/AI_AMP_2_5/libimslnn.a
2.code/aicos/app/AI_AMP_2_5/libimslvad.a
2.code/aicos/app/AI_AMP_2_5/opus/guixin/aic_ogg.h [new file with mode: 0644]
2.code/aicos/app/AI_AMP_2_5/opus/guixin/libogg.a [new file with mode: 0644]
2.code/aicos/app/AI_AMP_2_5/opus/guixin/libogg_dsp.a [new file with mode: 0644]
2.code/aicos/app/AI_AMP_2_5/opus/guixin/opus_test.c [new file with mode: 0644]
2.code/aicos/app/AI_AMP_2_5/opus/opus.zip [new file with mode: 0644]

index a511aeb..6f76250 100644 (file)
@@ -1,7 +1,7 @@
 
 
 #define AIC_THIS_FILE    0x888888
-#define SUPPORT_OPUS 1
+
 #include <aic_errno.h>
 #include <aic_init.h>
 #include <aic_osa_ex.h>
@@ -22,7 +22,9 @@
 #include <gpio_inc.h>
 #if SUPPORT_OPUS 
 #include "opus/guixin/opus_interface.h"
+
 #endif
+#include "bk_opus_coder.h"
 #include "dev_authentication.h"
 #include "imsl_vad.h"
 #include "imsl_kws.h"
 #include "power_supply.h"
 #include "sysoff.h"
 #include "app_msg.h"
+#include "aic_ogg.h"
+#include "efuse.h"
 // #include "opus/include/opus.h"
 u8 current_card_id = 0;
 u8 VC_TTS_PLAY_EVENT = 0;
 typedef enum
 {
-    inbound_attributes_format_PCM,
-    inbound_attributes_format_OPUS,
-}inbound_attributes_format_type;
-inbound_attributes_format_type inbound_attributes_format = inbound_attributes_format_PCM;
+    attributes_format_PCM,
+    attributes_format_OPUS,
+}attributes_format_type;
+attributes_format_type inbound_attributes_format = attributes_format_PCM;
+attributes_format_type outbound_attributes_format = attributes_format_OPUS;
 #define  OPUS_ENCODER_PACK_MS 60  //多少ms一帧数据
-#define OPUS_PERIOD_MS OPUS_PERIOD_60_MS
-#define OPUS_RB_LEN OPUS_ENCODER_PACK_MS*32*10//10贞数据
-bk_ring_buf_t *OPUS_rb_data = NULL;
+
+
+int send_opus_data(char *PCM_data,int data_len);
 AI_AMP_2_5_cfg vc_cfg;
+volatile char AI_VC_stata = 0;//VC是否在运行
 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 IS_KWS 0
 #define IS_VAD 1
 
-#define VAD_RB_LEN 64*1024
+#define VAD_RB_LEN 32*1024
 bk_ring_buf_t *VAD_rb_data = NULL;
 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:长按录音模式
+//char vc_cfg.VC_mode = 0;//0:短按连续问答模式 1:长按录音模式
 #define ai_VC_task_priority 35
 static aos_thread_id AI_AMP_task_id = 0;
 static aos_queue_ptr AI_AMP_task_queue = NULL;
@@ -97,17 +103,16 @@ static aos_timer_ptr sys_10S_timer = NULL;
 static int login_timer_count = 0;
 static int power_off_count = 60*6*24;
 
-// OpusEncoder *opus_encoder_h = NULL;
-// OpusDecoder *opus_decoder_h = NULL;
 static void play_file_stop(void);
 
-static struct opus_enc_init_param *opus_encoder_h = NULL;
-static struct opus_dec_init_param  *opus_decoder_h = NULL;
+int get_AI_key_longstate(void);
+
 static void AI_VC_send_satrt(void);
 static aos_status AI_VC_send_data(char *data,u32 len,u8 AIC_WEBSOCKET_OPCODE);
 VC_state_type VC_state = VC_State_None;
+static u8 uid[50];
+static int uid_len =0;
 
-static void AI_VC_put_play_data(char *data,u32 len);//音频数据入队播放
 //关闭录音
 void VC_record_End(void);
 //打开录音
@@ -130,6 +135,7 @@ int bk_get_imei(char *imei)
     strcpy(imei,vc_cfg.dev_imei);
     return 0;
 }
+#if (BK_LOG_CFG==BK_LOG_UART)
 int bk_printf(const char *format, ...)
 {
     int ret=0;
@@ -153,6 +159,35 @@ int bk_printf(const char *format, ...)
     aic_free(out);
        return ret;
 }
+#elif (BK_LOG_CFG ==  BK_LOG_USB)
+int bk_printf(const char *format, ...)
+{
+    int ret=0;
+    int bk_printf_count = 10*1024;
+       va_list args;
+       char *out = NULL;
+    out = aic_zalloc(bk_printf_count);
+    if(!out)
+    {
+        app_logi("bk_printf ERROR!!!!!\r\n");
+        return 0;
+    }
+       va_start( args, format );
+    ret = vsnprintf(out, bk_printf_count, format, args);
+    memcpy(out+ret,"\r\n",2);
+    ret+=2;
+    uart_write(ai_uart_handle,out, ret);
+    app_logi("[BK]%s",out);
+    //aos_sleep(100);
+       va_end( args );
+    aic_free(out);
+       return ret;
+}
+#else
+int bk_printf(const char *format, ...)
+{
+}
+#endif
 //用于定时器打印
 int bk_msg_printf(const char *format, ...)
 {
@@ -191,6 +226,10 @@ void bk_print_hex(u8 *data,int data_len)
     {
         tmp_len = snprintf(tmp,sizeof(tmp),"%02X ",data[i]);
         uart_write(ai_uart_handle,tmp, tmp_len);
+        if((i+1)%16 ==0)
+        {
+            uart_write(ai_uart_handle,"\r\n", 2);
+        }
     }
     uart_write(ai_uart_handle,"\r\n", 2);
 }
@@ -231,7 +270,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_ADS;//奥德赛
+    vc_cfg.dev_type = DEV_JSWM;//金山完美
     //strcpy(vc_cfg.server_ip,"amp.raisound.com");//服务器地址
     strcpy(vc_cfg.server_ip,"115.190.94.208:22080");//服务器地址
     vc_cfg.VC_mode =0;//对话模式
@@ -244,7 +284,7 @@ void reset_VC_cfg(void)
     vc_cfg.is_KWS = IS_KWS;//=1打开本地语言打断
     vc_cfg.speech_rate = 0;//语速配置
     vc_cfg.vad_silence = 200;//vad断句时间 ms
-    vc_cfg.VC_TTS_volume = 50;//音量
+    vc_cfg.VC_TTS_volume = 80;//音量
 }
 int init_VC_cfg(void)
 {
@@ -337,6 +377,33 @@ int check_text(char *text,int ret_str_len)
             goto RET;
         }
     }
+    if(strstr(text,"切换"))
+    {
+        if(strstr(text,"对话模式") || strstr(text,"兑换模式"))
+        {
+            vc_cfg.VC_mode+=1;
+            if(vc_cfg.VC_mode > 2)
+                vc_cfg.VC_mode = 0;
+            bk_printf("切换对话模式:vc_cfg.VC_mode :%d",vc_cfg.VC_mode );
+            if(vc_cfg.VC_mode == 0)
+            {
+                AI_AMP_MSG_put("已切换到连续对话模式。",strlen("已切换到连续对话模式。"),VC_TTS_PLAY);
+                
+            }else if(vc_cfg.VC_mode == 1)
+            {
+                AI_AMP_MSG_put("已切换到单对话模式。长按按钮说话,说完松开即可。",strlen("已切换到单对话模式。长按按钮说话,说完松开即可。"),VC_TTS_PLAY);
+                
+            }else
+            {
+                AI_AMP_MSG_put("已切换到按键打断模式。我说话的时候需要短按按钮打断。",strlen("已切换到按键打断模式。我说话的时候需要短按按钮打断。"),VC_TTS_PLAY);
+            }
+            is_save_VC_cfg = 1;
+            ret = 0;
+            goto RET;
+        }
+        
+    }
+
     if(strstr(text,"查询"))
     {
         if(strstr(text,"信号"))
@@ -622,8 +689,14 @@ static void AI_VC_send_satrt(void)
         cJSON_AddStringToObject(outbound_attributes, "provider", "volcengine");
     // 创建 outbound_attributes 下的 cfg 对象
     cJSON *outbound_cfg = cJSON_CreateObject();
-    cJSON_AddStringToObject(outbound_cfg, "format", "pcm");
-    cJSON_AddNumberToObject(outbound_cfg, "sample_rate", 16000);
+    if(outbound_attributes_format == attributes_format_OPUS)
+    {
+        cJSON_AddStringToObject(outbound_cfg, "format", "ogg_opus");
+        cJSON_AddNumberToObject(outbound_cfg, "compression_rate", 20);
+    }
+    else
+        cJSON_AddStringToObject(outbound_cfg, "format", "pcm");
+    cJSON_AddNumberToObject(outbound_cfg, "sample_rate", vc_cfg.VC_play_samplerate);
     cJSON_AddNumberToObject(outbound_cfg, "bit_rate", 16);
     cJSON_AddNumberToObject(outbound_cfg, "channel", 1);
     cJSON_AddNumberToObject(outbound_cfg, "volume", 100);
@@ -644,7 +717,7 @@ static void AI_VC_send_satrt(void)
     // 创建 inbound_attributes 对象
     cJSON *inbound_attributes = cJSON_CreateObject();
     cJSON_AddStringToObject(inbound_attributes, "provider", "volcengine");
-    if(VC_mode == 0 && vc_cfg.is_VAD == 0)//连续对话模式
+    if(vc_cfg.VC_mode == 0 && vc_cfg.is_VAD == 0)//连续对话模式,开在线vad
         cJSON_AddBoolToObject(inbound_attributes, "disable_vad", 0);
     else
         cJSON_AddBoolToObject(inbound_attributes, "disable_vad", 1);
@@ -667,7 +740,7 @@ static void AI_VC_send_satrt(void)
 
     // 创建 inbound_attributes 下的 cfg 对象
     cJSON *inbound_cfg = cJSON_CreateObject();
-    if(inbound_attributes_format == inbound_attributes_format_OPUS)
+    if(inbound_attributes_format == attributes_format_OPUS)
     {
         cJSON_AddStringToObject(inbound_cfg, "codec", "opus");
         cJSON_AddStringToObject(inbound_cfg, "format", "pcm");
@@ -675,7 +748,7 @@ static void AI_VC_send_satrt(void)
     else
         cJSON_AddStringToObject(inbound_cfg, "format", "pcm");
 
-    cJSON_AddNumberToObject(inbound_cfg, "sample_rate", 16000);
+    cJSON_AddNumberToObject(inbound_cfg, "sample_rate", vc_cfg.VC_record_samplerate);
     cJSON_AddNumberToObject(inbound_cfg, "bit_rate", 16);
     cJSON_AddNumberToObject(inbound_cfg, "channel", 1);
     cJSON_AddBoolToObject(inbound_cfg, "enable_punctuation", 1);
@@ -852,10 +925,30 @@ static void AI_VC_send_task(void *thread_input)//websocket 发送线程
             if(AI_client_VC && AI_VC_send_queue_data.data)
             {
                 VC_pingping_timerout = 4;
-                
+                if(inbound_attributes_format == attributes_format_OPUS&& AI_VC_send_queue_data.AIC_WEBSOCKET_OPCODE ==AIC_WEBSOCKET_OPCODE_BINARY_FRAME )//转码opus
+                {
+                    char *opus_data = aic_malloc(OPUS_ENCODER_PACK_MS*16); 
+                    if(opus_data)
+                    {
+                        ret = opus_encode_data(AI_VC_send_queue_data.data,AI_VC_send_queue_data.len,OPUS_ENCODER_PACK_MS*32,opus_data,OPUS_ENCODER_PACK_MS*16);
+                        bk_printf("opus_encode_data1:len:%d",ret);
+                        if(ret >0)
+                        {
+                            AI_VC_send_queue_data.len = ret;
+                            ret = send_websocket_message(AI_client_VC,opus_data,ret,(WebSocketMessageType)AI_VC_send_queue_data.AIC_WEBSOCKET_OPCODE);
+                        }
+                        
+                        aic_free(opus_data);
+                    }
+                    else
+                    {
+                        bk_printf("opus_data malloc error!");
+                    }
+                }else
                 {
                     ret = send_websocket_message(AI_client_VC,AI_VC_send_queue_data.data,AI_VC_send_queue_data.len,
                         (WebSocketMessageType)AI_VC_send_queue_data.AIC_WEBSOCKET_OPCODE);
+                    //bk_printf("AI_VC_send_task:send str!");
                 }
                 
                 if(AI_VC_send_queue_data.AIC_WEBSOCKET_OPCODE ==AIC_WEBSOCKET_OPCODE_TEXT_FRAME )
@@ -864,8 +957,8 @@ static void AI_VC_send_task(void *thread_input)//websocket 发送线程
                 {
                     bk_printf("send ret=%d,len=%d",ret,AI_VC_send_queue_data.len);
                 }
-                    
-                aic_free(AI_VC_send_queue_data.data);
+                if(AI_VC_send_queue_data.data)    
+                    aic_free(AI_VC_send_queue_data.data);
             }else
             {
                 bk_printf("AI_VC_send ERROR:close_websocket_client = %d",AI_client_VC);
@@ -932,16 +1025,18 @@ static void AI_VC_read_task(void *thread_input)//websocket 读线程
                         }else
                         {
                             
-                            if(VC_mode == 1)//长按模式,或者本地vad模式
+                            if(vc_cfg.VC_mode == 1)//长按模式
                             {
                                 AI_VC_send_audio_create();
-                            }else if(VC_mode == 0 )//连续对话模式
+                            }else if(vc_cfg.VC_mode == 0 )//连续对话模式
+                                VC_state = VC_State_Listening;
+                            else if(vc_cfg.VC_mode == 2 )//连续对话模式,按键打断
                                 VC_state = VC_State_Listening;
                                 
                         }
                     }else if(strstr(recv_buff,"\"asr.started\""))//asr开始
                     {
-                        if(VC_mode == 1 || vc_cfg.is_VAD ==1)//长按模式
+                        if(vc_cfg.VC_mode == 1 || vc_cfg.is_VAD ==1)//长按模式,或开机本地vad模式
                             VC_state = VC_State_SpeechIng;
                     }else if(strstr(recv_buff,"\"asr.result\""))
                     {
@@ -963,16 +1058,17 @@ static void AI_VC_read_task(void *thread_input)//websocket 读线程
                             }
                             
                             
-                            int ret = check_text(str_tmp,str_tmp_len) ;
-                            //识别到有命令词,退出
-                            if(ret == 0)
-                                break;
+                            
                         }
                     }else if(strstr(recv_buff,"\"asr.completed\""))//asr结束
                     {
                         VC_state = VC_State_ASR_End;
                         if(AI_ASR_str && AI_ASR_str_tmp)
                         {
+                            int ret = check_text(AI_ASR_str_tmp,strlen(AI_ASR_str_tmp)) ;
+                            //识别到有命令词,退出
+                            if(ret == 0)
+                                break;
                             if(VAD_time_count <= VAD_TIMEOUT )//时间间隔短,认为是一次对话,拼接内容
                             {
                                 
@@ -1018,7 +1114,7 @@ static void AI_VC_read_task(void *thread_input)//websocket 读线程
                     }
                     else if(strstr(recv_buff,"\"completed\""))//结束
                     {
-                        VC_state = VC_State_End;//VC_State_Listening;
+                        VC_state = VC_State_End;//
                         
                         //AI_AMP_MSG_put(0,0,VC_RECORD_START);//打开录音
                     }else if(strstr(recv_buff,"\"event\":\"failed\""))//扣子报错
@@ -1040,10 +1136,16 @@ static void AI_VC_read_task(void *thread_input)//websocket 读线程
                 {
                     
                     
-                    //bk_printf("read BIN  status:%d,code:%d!!!!!!",status,code);
+                    bk_printf("read BIN  status:%d,code:%d!!!!!!",status,code);
+                    if(outbound_attributes_format == attributes_format_OPUS)
+                    {
+                        ogg_opus_decode_data(recv_buff,status);
+                    }else
+                    {
+                        AI_VC_put_play_data(recv_buff,status);//
+                        play_data_len+=status;
+                    }
                     
-                    AI_VC_put_play_data(recv_buff,status);//音频调试1
-                    play_data_len+=status;
                     
                 }
             }else// if(status == -1)//报错,关闭连接
@@ -1077,47 +1179,8 @@ static void AI_VC_read_task(void *thread_input)//websocket 读线程
     AI_VC_read_task_flag=3;
 }
 
-u8 opus_remain_buf[OPUS_ENCODER_PACK_MS*32];
-u32 opus_remain_len = 0;
-u8 opus_data[OPUS_ENCODER_PACK_MS*16];
-void send_opus_end(void)
-{
-    opus_remain_len = 0;
-}
-//
-void send_opus_data(char *PCM_data,int data_len)
-{
-    #if SUPPORT_OPUS 
-    int ret;
-
-    //struct opus_dec_param dec_inparam;
-    struct opus_enc_param enc_inparam;
-
-    if(opus_remain_len+data_len>=32*OPUS_ENCODER_PACK_MS)//够一帧数据
-    {
-        memcpy(opus_remain_buf+opus_remain_len,PCM_data,32*OPUS_ENCODER_PACK_MS-opus_remain_len);
-        bk_printf("send_opus_data:cpy1:偏移:%d,长度:%d",opus_remain_len,32*OPUS_ENCODER_PACK_MS-opus_remain_len);
-        enc_inparam.input = (int16_t*)(opus_remain_buf);//PCM数据
-        enc_inparam.input_size = 32*OPUS_ENCODER_PACK_MS;
-        enc_inparam.output = (int8_t*)opus_data;
-        enc_inparam.outbuffer_size = OPUS_ENCODER_PACK_MS*16;
-        ret = aic_opus_encode(&enc_inparam);
-        //enc_inparam.output_len_array[0];//长度
-        AI_VC_send_data(opus_data,enc_inparam.output_len_array[0],AIC_WEBSOCKET_OPCODE_BINARY_FRAME);//够一帧,发送数据
-        bk_printf("send_opus_data:send:data_len = %d",enc_inparam.output_len_array[0]);
-        memcpy(opus_remain_buf,PCM_data+32*OPUS_ENCODER_PACK_MS-opus_remain_len,data_len-32*OPUS_ENCODER_PACK_MS-opus_remain_len);
-        bk_printf("send_opus_data:cpy2:偏移:%d,长度:%d",32*OPUS_ENCODER_PACK_MS-opus_remain_len,data_len-32*OPUS_ENCODER_PACK_MS-opus_remain_len);
-        opus_remain_len = data_len-32*OPUS_ENCODER_PACK_MS-opus_remain_len;
-    }else
-    {
-        memcpy(opus_remain_buf+opus_remain_len,PCM_data,data_len);//缓存数据,等待够一帧数据
-        bk_printf("send_opus_data:cpy3:偏移:%d,长度:%d",opus_remain_len,data_len);
-        opus_remain_len+=data_len;
-    }
-    
-    #endif
-    
-}
+
+
 u8 vrecord_buf[3500 + 4];
 static void AI_VC_record_task(void *thread_input)//录音线程
 {
@@ -1153,7 +1216,7 @@ static void AI_VC_record_task(void *thread_input)//录音线程
             vrecord_buf, 3200, 1010);
         // u32 timer_ms = aos_get_tickcount();
         // bk_printf("%d:ret=%d",timer_ms,ret);
-        //bk_printf("AI_VC_record_task app_audio_read len = %d,VC_state = %d",ret,VC_state);
+        app_logi("AI_VC_record_task app_audio_read len = %d,VC_state = %d",ret,VC_state);
         if(ret<=0)
         {
             //bk_printf("AI_VC_record_task continue len = %d,VC_state = %d",ret,VC_state);
@@ -1161,11 +1224,16 @@ static void AI_VC_record_task(void *thread_input)//录音线程
             continue;
         }
         
-        if(vc_cfg.is_VAD == 1)//VAD逻辑:先判断有没有有效数据,触发了有效数据才发送
+        if((vc_cfg.VC_mode == 0 || vc_cfg.VC_mode == 2)&& vc_cfg.is_VAD == 1)//VAD逻辑:先判断有没有有效数据,触发了有效数据才发送
         {
+            if(vc_cfg.VC_mode == 2 &&  VC_state > VC_State_SpeechEnd )//按钮打断模式,tts播放时禁止打断,不输入语音
+                continue;
             // 每次获得语音后调用, 语音长度最好小于100ms
             // wave为u8*或void*指针时需要 / 2
+            //int vad_test_time = aos_get_tickcount();
+            //bk_printf("run_vad vad_test_time:%d,data_len:%d",vad_test_time,ret);
             run_vad((int16_t *)vrecord_buf, ret / 2);
+            //bk_printf("run_vad 用时:%d",aos_get_tickcount()-vad_test_time);
             vad_status_t = vad_detect(); 
             //bk_printf("VAD:vad_status_t:%d",vad_status_t);  
             audio_data(vrecord_buf,ret,23);
@@ -1176,6 +1244,14 @@ static void AI_VC_record_task(void *thread_input)//录音线程
                     //VAD_timeout = aos_get_tickcount()-VAD_time;
                     VAD_time = aos_get_tickcount();
                     bk_rb_clear(VAD_rb_data);
+                    if(inbound_attributes_format == attributes_format_OPUS)//填充更多数据,以免后面丢失
+                    {
+                        if(sizeof(vrecord_buf)>ret)
+                        {
+                            memset(vrecord_buf+ret,0,sizeof(vrecord_buf)-ret-1);
+                        }
+                        ret =  sizeof(vrecord_buf);
+                    }
                     AI_VC_put_record_data(vrecord_buf,ret);
                 }
                 VAD_status = 2;
@@ -1226,6 +1302,8 @@ static void AI_VC_record_task(void *thread_input)//录音线程
                         aic_free(vad_r_tmp);
                     VAD_status = 1;
                 }
+                
+
                 AI_VC_put_record_data(vrecord_buf,ret);
                 audio_data(vrecord_buf,ret,21);
                 if(vc_cfg.is_KWS)
@@ -1243,8 +1321,9 @@ static void AI_VC_record_task(void *thread_input)//录音线程
                 //bk_printf("VAD:检测到说话了"); 
             }else if(vad_status_t == 0 )//m没有说话
             {
+                
                 //把音频入队,缓存回溯数据
-                if(VAD_rb_data)
+                if(ret>0 && VAD_rb_data)
                 {
                     if(VAD_RB_LEN - bk_rb_data_len(VAD_rb_data) >= ret)//缓存够
                     {
@@ -1285,12 +1364,10 @@ static void AI_VC_record_task(void *thread_input)//录音线程
                         if(aos_recv_from_queue(AI_VC_record_tmp_queue,&AI_VC_play_record_data,AOS_NO_WAIT) == AOS_SUCCESS)//有有效录音数据
                         {
                             audio_data(AI_VC_play_record_data.data,AI_VC_play_record_data.len,22);
-                            if(inbound_attributes_format == inbound_attributes_format_OPUS)
-                            {
-                                send_opus_data(AI_VC_play_record_data.data,AI_VC_play_record_data.len);
-                            }else
-                                AI_VC_send_data(AI_VC_play_record_data.data,AI_VC_play_record_data.len,AIC_WEBSOCKET_OPCODE_BINARY_FRAME);
-                            aic_free(AI_VC_play_record_data.data);
+                            
+                            AI_VC_send_data(AI_VC_play_record_data.data,AI_VC_play_record_data.len,AIC_WEBSOCKET_OPCODE_BINARY_FRAME);
+                            if(AI_VC_play_record_data.data)
+                                aic_free(AI_VC_play_record_data.data);
                         }else
                             break;
                     }
@@ -1320,8 +1397,8 @@ static void AI_VC_record_task(void *thread_input)//录音线程
                     bk_printf("VAD:发送停止音频"); 
                     bk_printf("VAD:vad_status_t:%d",vad_status_t); 
                     vad_end_flag = 0;
-                    if(inbound_attributes_format == inbound_attributes_format_OPUS)
-                        send_opus_end();
+                    if(inbound_attributes_format == attributes_format_OPUS)
+                        opus_clean();
                 }
                 
             }
@@ -1341,7 +1418,8 @@ static void AI_VC_record_task(void *thread_input)//录音线程
             AI_VC_put_record_data(vrecord_buf,ret);
         }
        //else if(VC_state >= VC_State_Listening && VC_state<VC_State_TTSStart)//正常录音
-        else if(VC_state >= VC_State_Listening )//正常录音
+        else if((vc_cfg.VC_mode == 0 && VC_state >= VC_State_Listening) ||   //连续对话模式
+                ((vc_cfg.VC_mode == 1  || vc_cfg.VC_mode == 2 )&& VC_state >= VC_State_SpeechIng  && VC_state < VC_State_SpeechEnd ))//长按对话模式,TTS过程不录音
         {
             char count_t = 200;
             while(count_t--)
@@ -1349,11 +1427,15 @@ static void AI_VC_record_task(void *thread_input)//录音线程
                 if(aos_recv_from_queue(AI_VC_record_tmp_queue,&AI_VC_play_record_data,AOS_NO_WAIT) == AOS_SUCCESS)//有录音数据
                 {
                     AI_VC_send_data(AI_VC_play_record_data.data,AI_VC_play_record_data.len,AIC_WEBSOCKET_OPCODE_BINARY_FRAME);
-                    aic_free(AI_VC_play_record_data.data);
+                    if(AI_VC_play_record_data.data)
+                        aic_free(AI_VC_play_record_data.data);
                 }else
                  break;
             }
             AI_VC_send_data(vrecord_buf,ret,AIC_WEBSOCKET_OPCODE_BINARY_FRAME);
+
+            if(vc_cfg.VC_mode == 1 && get_AI_key_longstate() == 0)//长按模式,按键释放后停止发送数据
+                AI_VC_send_audio_completed();
             //bk_printf("AI_VC_record_task send_data len = %d",ret);
         }else
         {
@@ -1362,7 +1444,8 @@ static void AI_VC_record_task(void *thread_input)//录音线程
             {
                 if(aos_recv_from_queue(AI_VC_record_tmp_queue,&AI_VC_play_record_data,AOS_NO_WAIT) == AOS_SUCCESS)//有录音数据
                 {
-                    aic_free(AI_VC_play_record_data.data);
+                    if(AI_VC_play_record_data.data)
+                        aic_free(AI_VC_play_record_data.data);
                 }else
                  break;
             }
@@ -1402,7 +1485,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(play_data_len>8*1024 &&VC_Play_flag ==1 && AI_VC_play_queue )
+        if((play_data_len>8*1024 || outbound_attributes_format == attributes_format_OPUS)&&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)
@@ -1419,8 +1502,8 @@ static void AI_VC_play_task(void *thread_input)//音频播放线程
                     }
                         
     
-
-                    aic_free(AI_VC_play_queue_data.data);
+                    if(AI_VC_play_queue_data.data)
+                        aic_free(AI_VC_play_queue_data.data);
                     if(VC_state == VC_State_End)
                     {
                         u32 count_tmp = 0;
@@ -1489,7 +1572,11 @@ static int websocket_connect_VC(void)
             dev_authentication_MSG_put(NULL,0,AUT_LOGIN);
             return - 1;
         }
-        url_len =snprintf(url,511,"ws://%s/vc/chat?is_auth=1&dt=%s",vc_cfg.server_ip,get_token());
+        if(vc_cfg.dev_type == DEV_JSWM)
+            url_len =snprintf(url,511,"ws://%s/vc/agent?is_auth=1&dt=%s",vc_cfg.server_ip,get_token());
+        else
+            url_len =snprintf(url,511,"ws://%s/vc/chat?is_auth=1&dt=%s",vc_cfg.server_ip,get_token());
+        
         url[url_len] = 0;
         bk_printf("连接服务器 url:%s",url);
         AI_client_VC = init_websocket_client(url,NULL);
@@ -1635,8 +1722,7 @@ int play_audio_file(char *file_name)
 {
     bk_printf("play_audio_file:%s",file_name);
     AI_AMP_MSG_put(file_name,strlen(file_name)+1,PLAY_AUDIO_FILE);
-    
-        
+
     return 0;
 }
 volatile char app_audio_play_file_stop_flag = 0;
@@ -1741,9 +1827,11 @@ static int play_file_stream_data_event(char *file_name)
         return -1;
     return 0;
 }
-static void AI_VC_put_play_data(char *data,u32 len)
+void AI_VC_put_play_data(char *data,u32 len)
 {
     u32 count_tmp = 0;
+    if(len <= 0)
+        return ;
     while(1)
     {
         if(AI_VC_play_queue == NULL)
@@ -1790,7 +1878,8 @@ static void AI_VC_put_play_data(char *data,u32 len)
         
     return ;
 PUT_PLAY_ERROR:
-    aic_free(AI_VC_play_queue_data.data);
+    if(AI_VC_play_queue_data.data)
+        aic_free(AI_VC_play_queue_data.data);
 }
 
 //打开音频播放
@@ -1852,7 +1941,8 @@ void VC_Play_End(void)
 
 static void AI_VC_put_record_data(char *data,u32 len)
 {
-
+    if(len <= 0)
+        return ;
     AI_VC_audio_queue_t AI_VC_record_queue_data;
     AI_VC_record_queue_data.data = aic_malloc(len);
 
@@ -1879,7 +1969,8 @@ static void AI_VC_put_record_data(char *data,u32 len)
         
     return;
 PUT_RECORD_ERROR:
-    aic_free(AI_VC_record_queue_data.data);
+    if(AI_VC_record_queue_data.data)
+        aic_free(AI_VC_record_queue_data.data);
 
 }
 
@@ -1964,7 +2055,7 @@ static void AI_VC_1S_timeout(void *param)
         VC_END_play_timerout --;
         if(VC_END_play_timerout<=0)
         {
-            if(VC_mode == 0)
+            if(vc_cfg.VC_mode == 0 || vc_cfg.VC_mode == 2)
             {
                 if(VC_TTS_PLAY_EVENT == VC_TTS_PLAY_CLOSE)
                 {
@@ -1997,13 +2088,19 @@ static void AI_VC_1S_timeout(void *param)
     //     bk_msg_printf("AI_VC_send_queue:play_queue_count=%d",play_queue_count);
     // }
 }
+char AI_key_long_flag = 0;
 void AI_key_press(void)
 {
     static u64 timer_ms = 0;
 
     u64 timer_ms_tmp = aos_get_tickcount();
-    if(timer_ms_tmp-timer_ms<1000)//每次触发小于1000ms不响应
+    if(timer_ms_tmp-timer_ms<1000)//每次触发小于1000ms关闭对话
+    {
+        if(vc_cfg.VC_mode ==0 || vc_cfg.VC_mode == 2)//关闭服务
+            AI_VC_Close();
         return;
+    }
+        
     timer_ms = timer_ms_tmp;
     bk_printf("AI_key_press");
     AI_VC_Close();
@@ -2023,19 +2120,28 @@ void AI_key_press(void)
 }
 void AI_key_release(void)
 {
-    
+
+    if(vc_cfg.VC_mode ==1)
+    {
+        AI_AMP_MSG_put("请您按住按钮讲话,讲完松开即可。",strlen("请您按住按钮讲话,讲完松开即可。"),VC_TTS_PLAY);
+    }
     bk_printf("AI_key_release");
 }
 void AI_key_long_press(void)
 {
+    AI_key_long_flag = 1;
     bk_printf("AI_key_long_press");
 
 }
 void AI_key_long_release(void)
 {
+    AI_key_long_flag = 0;
     bk_printf("AI_key_long_release");
-    if(VC_mode == 1)//长按模式
-        AI_VC_send_audio_completed();
+    
+}
+int get_AI_key_longstate(void)
+{
+    return AI_key_long_flag;
 }
 void pwk_key_release(void)
 {
@@ -2097,7 +2203,7 @@ int AI_VC_start(void)
     app_audio_param_t param;
     param.channel = 1;
     param.format = ASTREAM_FORMAT_PCM;
-    param.sample_rate = 16000;
+    param.sample_rate = vc_cfg.VC_play_samplerate;
     param.flag = 0;
     param.bit_rate = 0;
     play_data_len = 0;
@@ -2136,65 +2242,14 @@ int AI_VC_start(void)
             AOS_AUTO_ACTIVATE, AOS_BE_PERIOD);
         aic_assert(AI_VC_1S_timer);
     }
-    if(inbound_attributes_format == inbound_attributes_format_OPUS)
+    if(inbound_attributes_format == attributes_format_OPUS ||outbound_attributes_format == attributes_format_OPUS)
     {
-        #if SUPPORT_OPUS 
-        bk_printf("opus_init start");
-        //int err;
-        if (opus_encoder_h == NULL)
-        {
-            opus_encoder_h = (opus_enc_init_param_t *)aic_zalloc(sizeof(opus_enc_init_param_t));
-            if(!opus_encoder_h)
-            {
-                bk_printf("opus_encoder_h alloc error");
-                ret = -1;
-                goto AI_VC_start_RET;
-            }
-            opus_encoder_h->channel_cnt = 1;
-            opus_encoder_h->sample_rate = 16000;
-            opus_encoder_h->period_ms = OPUS_PERIOD_MS;
-            opus_encoder_h->bitrate = 16000;
-            status = aic_opus_init_encoder(opus_encoder_h);
-            if (status)
-            {
-                bk_printf("aic_opus_init_encoder error");
-                ret = -1;
-                goto AI_VC_start_RET;
-            }
-            //opus_encoder_h = opus_encoder_create(16000, 1, OPUS_APPLICATION_VOIP, &err);
-
-        }
-            
-        if (opus_decoder_h == NULL)
-        {
-            
-            opus_decoder_h = (opus_dec_init_param_t *)aic_zalloc(sizeof(opus_dec_init_param_t));
-            if(!opus_decoder_h)
-            {
-                bk_printf("opus_decoder_h alloc error");
-                ret = -1;
-                goto AI_VC_start_RET;
-            }
-            opus_decoder_h->channel_cnt = 1;
-            opus_decoder_h->sample_rate = 16000;
-            status = aic_opus_init_decoder(opus_decoder_h);
-            if (status)
-            {
-                bk_printf("aic_opus_init_decoder error");
-                ret = -1;
-                goto AI_VC_start_RET;;
-            }
-               
-            //opus_decoder_h = opus_decoder_create(16000, 1, &err);
-        }
-        if(OPUS_rb_data == NULL)
-            OPUS_rb_data =  bk_rb_create(OPUS_RB_LEN);
-        if(!OPUS_rb_data )
+        if(opus_init()!= 0)
         {
-            bk_printf("OPUS_rb_data error!申请失败");
+            bk_printf("opus_init error!!!!!!!!!!!!!!!!!!!!!!!!");
+            ret = -1;
+            goto AI_VC_start_RET;
         }
-        bk_printf("opus_init end");
-        #endif
     }
     
         
@@ -2212,7 +2267,10 @@ int AI_VC_start(void)
         conf.rule2_min_tailing_silence = vc_cfg.vad_silence ;
         conf.rule3_min_tailing_silence = vc_cfg.vad_silence;
         conf.vad_log_level = 2;
-        init_vad(&conf);
+        int init_vad_ret = init_vad(&conf);
+        bk_printf("VAD init_vad:ret = %d",init_vad_ret);
+        bk_printf("VAD init_vad:ret = %d",init_vad_ret);
+        bk_printf("VAD init_vad:ret = %d",init_vad_ret);
         VAD_status = 0;
         //创建VAD回溯缓冲buf
         if(VAD_rb_data == NULL)
@@ -2255,7 +2313,8 @@ AI_VC_start_RET:
     {
         AI_VC_Close();
         play_audio_file("C:/xinhaoruo1.mp3");
-    }
+    }else
+        AI_VC_stata = 1;
     return ret;
 }
 char AI_VC_Close_lock = 0;
@@ -2271,23 +2330,7 @@ void AI_VC_Close(void)
     // 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时调用
-        free_vad();
-        
-        VAD_status = 0;
-        //删除VAD回溯缓冲buf
-        if(VAD_rb_data != NULL)
-        {
-            bk_rb_destroy(&VAD_rb_data);
-            VAD_rb_data= NULL;
-        }
-    }
-    if(vc_cfg.is_KWS == 1)
-    {
-        free_kws();
-    }
+    
     bk_printf("AI_VC_Close!!!!!!!!!!!!");
     
      //销毁录音线程
@@ -2409,35 +2452,28 @@ void AI_VC_Close(void)
         AI_VC_1S_timer = NULL;
     }
     close_timerout = 0;
-    if(inbound_attributes_format == inbound_attributes_format_OPUS)
-    {
-        #if SUPPORT_OPUS 
-        // if(opus_encoder_h)
-        //     opus_encoder_destroy(opus_encoder_h);
-        // opus_encoder_h =  NULL;
-        // if(opus_decoder_h)
-        //     opus_decoder_destroy(opus_decoder_h);
-        // opus_decoder_h = NULL;
-        if(aic_opus_deinit_encoder() == 0)
-        {
-            if(opus_encoder_h)
-                aic_free(opus_encoder_h);
-            opus_encoder_h =  NULL;
-        }
-        if(aic_opus_deinit_decoder() == 0)
-        {
-            if(opus_decoder_h)
-                aic_free(opus_decoder_h);
-            opus_decoder_h =  NULL;
-        }
-        if(OPUS_rb_data != NULL)
+    if(inbound_attributes_format == attributes_format_OPUS||outbound_attributes_format == attributes_format_OPUS)
+    {
+        opus_close();
+    }
+    bk_printf("app_audio_stop1");
+    if(vc_cfg.is_VAD == 1)
+    {
+        // 不使用或暂停使用VAD时调用
+        free_vad();
+        
+        VAD_status = 0;
+        //删除VAD回溯缓冲buf
+        if(VAD_rb_data != NULL)
         {
-            bk_rb_destroy(&OPUS_rb_data);
-            OPUS_rb_data= NULL;
+            bk_rb_destroy(&VAD_rb_data);
+            VAD_rb_data= NULL;
         }
-        #endif
     }
-    bk_printf("app_audio_stop1");
+    if(vc_cfg.is_KWS == 1)
+    {
+        free_kws();
+    }
     //app_logi("app_audio_stop1");
     if(app_audio_flag == 1)
     {
@@ -2465,7 +2501,7 @@ void AI_VC_Close(void)
         AI_ASR_str =NULL;
     }
     //app_logi("app_audio_stop2");
-
+    AI_VC_stata = 0;
     AI_VC_Close_lock = 0;
     
 }
@@ -2522,6 +2558,28 @@ static void sys_10S_timeout(void *param)
             
         }
     }
+    struct psy_info psy_info;
+    get_psy_info(&psy_info);
+    if(psy_info.bat_capacity> 15 &&psy_info.bat_capacity<=25 && AI_VC_stata == 0)
+    {
+        play_audio_file("C:/Low_power_warning.mp3");
+    }else if(psy_info.bat_capacity<=15)
+    {
+        // AI_AMP_MSG_put(NULL,0,VC_CLOSE);//关闭对话
+        // play_audio_file("C:/didianguanji.mp3");//播放低电关机
+        AI_AMP_MSG_put("C:/didianguanji.mp3",strlen("C:/didianguanji.mp3"),POWER_OFF);
+
+    }
+    // bk_printf("电量查询:psy_name:%s bat_vol:%d bat_cap:%d chg_status%d chg_type:%d bat_min_voltage:%d bat_max_voltage:%d\n",
+
+    //         psy_info.psy_name,
+    //         psy_info.bat_current_voltage,
+    //         psy_info.bat_capacity,
+    //         psy_info.bat_chg_status,
+    //         psy_info.bat_chg_type,
+    //         psy_info.bat_min_voltage,
+    //         psy_info.bat_max_voltage);
+    //tmp_data_len = snprintf(tmp_data,sizeof(tmp_data),"当前电量为百分之%d。",psy_info.bat_capacity);
 }
 
 static void AI_AMP_2_5_task(void *thread_input)//做逻辑线程
@@ -2535,39 +2593,6 @@ static void AI_AMP_2_5_task(void *thread_input)//做逻辑线程
     app_audio_set_master_volume(15*vc_cfg.VC_TTS_volume/100);
     play_audio_file_event("C:/R_POWER_1.mp3");
 
-    // volatile int32_t a = 1626;
-    // volatile int32_t b = 1536;
-    // volatile int32_t res = 0;
-    // int ai = 0;
-    // u32 time1 = aos_get_tickcount();
-    // for (ai = 0; ai < 245000; ai++) {
-    //     res += (a + ai) * (b + ai);
-    // }
-    // u32 time2 = aos_get_tickcount();
-    // bk_printf("run int32 takes : %d\n", time2 - time1);
-
-    // volatile int64_t a1 = 1626;
-    // volatile int64_t b1 = 1536;
-    // volatile int64_t res1 = 0;
-    // // int ai = 0;
-    // time1 = aos_get_tickcount();
-    // for (ai = 0; ai < 245000; ai++) {
-    //     res1 += (a1 + ai) * (b1 + ai);
-    // }
-    // time2 = aos_get_tickcount();
-    // bk_printf("run int64 takes : %d\n", time2 - time1);
-
-    // volatile float a2 = 1626.0f;
-    // volatile float b2 = 1536.0f;
-    // volatile float res2 = 0;
-    // // int ai = 0;
-    // time1 = aos_get_tickcount();
-    // for (ai = 0; ai < 245000; ai++) {
-    //     res2 += (a2 + ai) * (b2 + ai);
-    // }
-    // time2 = aos_get_tickcount();
-    // bk_printf("run float takes : %d\n", time2 - time1);
-
 
     while(count --)
     {
@@ -2579,6 +2604,10 @@ static void AI_AMP_2_5_task(void *thread_input)//做逻辑线程
         //audio_play_tone(3,500);//播放提示音,测试用
         aos_sleep(1000);
     }
+    bk_websocket_demo();
+    aic_get_uid(uid,&uid_len);
+    bk_printf("UID:%s",uid);
+    bk_printf("UID:%s",uid);
 
     current_card_id = aic_srv_tele_sim_get_current_card_sync();
     aic_srv_tele_radio_get_current_slot_imei_sync(vc_cfg.dev_imei);
@@ -2612,6 +2641,11 @@ static void AI_AMP_2_5_task(void *thread_input)//做逻辑线程
                 case POWER_OFF://关机
                     AI_VC_Close();
                     //播放关机提示音
+                    if(AI_AMP_msg.data)//有数据,播放本地文件
+                    {
+                        play_audio_file_event(AI_AMP_msg.data);
+                        aos_sleep(5);
+                    }
                     sysoff_shutdown();
                     break;
                 case POWER_RESET://重启
index dcbd798..9b115a2 100644 (file)
@@ -1,8 +1,17 @@
 #include "aic_osa.h"
+
+#define SUPPORT_OPUS 1
+#define  BK_LOG_NONE 0//不打印
+#define BK_LOG_UART 1//串口打印
+#define BK_LOG_USB 2//USB打印
+
+
+#define BK_LOG_CFG BK_LOG_UART
 typedef enum 
 {
     DEV_FX1_H,//玩具机芯
     DEV_ADS,//奥德赛
+    DEV_JSWM,
 } DEV_TYPE;
 typedef enum 
 {
@@ -118,4 +127,5 @@ int bk_msg_printf(const char *format, ...);
 aos_status AI_AMP_MSG_put(const char *data,u32 len,AI_AMP_MSG_Type MSG_Type);
 int bk_get_imei(char *imei);
 int save_VC_cfg(void);
-int play_audio_file(char *file_name);
\ No newline at end of file
+int play_audio_file(char *file_name);
+void AI_VC_put_play_data(char *data,u32 len);//音频数据入队播放
\ No newline at end of file
index c5e7682..0ed5dfa 100644 (file)
@@ -10,6 +10,7 @@ aic_library_sources_ifdef(
     ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/bk_websocket.c
     ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/bk_key.c
     ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/dev_authentication.c
+    ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/bk_opus_coder.c
 
 
 )
@@ -18,76 +19,27 @@ aic_library_include_directories_ifdef(
     CONFIG_APP_AI_AMP_2_5
     ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/guixin/
 )
-# # 官方opus库
-# file(GLOB SOURCES ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/src/src/*.c)
-# aic_library_sources_ifdef( 
-#     CONFIG_APP_AI_AMP_2_5
-#     ${SOURCES})
 
-# file(GLOB SOURCES ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/src/celt/*.c)
-# aic_library_sources_ifdef( 
-#     CONFIG_APP_AI_AMP_2_5
-#     ${SOURCES})
-# # file(GLOB SOURCES ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/src/celt/arm/*.c)
-# # aic_library_sources_ifdef( ${SOURCES})
-
-# file(GLOB SOURCES ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/src/silk/*.c)
-# aic_library_sources_ifdef(
-#     CONFIG_APP_AI_AMP_2_5
-#     ${SOURCES})
-# # file(GLOB SOURCES ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/src/silk/arm/*.c)
-# # aic_library_sources_ifdef( 
-# #     CONFIG_APP_AI_AMP_2_5
-# #      ${SOURCES})
-# # ##有问题
-# # file(GLOB SOURCES ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/src/silk/scky/*.c)
-# # aic_library_sources_ifdef( 
-# #     CONFIG_APP_AI_AMP_2_5
-# #     ${SOURCES})
-
-# file(GLOB SOURCES ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/src/silk/fixed/*.c)
-# aic_library_sources_ifdef( 
-#     CONFIG_APP_AI_AMP_2_5
-#     ${SOURCES})
-# #如果定义 FIXED_POINT,不能编译
-# # file(GLOB SOURCES ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/src/silk/float/*.c)
-# # aic_library_sources_ifdef( 
-# #     CONFIG_APP_AI_AMP_2_5
-# #     ${SOURCES})
-
-# #有问题
-# # file(GLOB SOURCES ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/src/silk/mips/*.c)
-# # aic_library_sources_ifdef( 
-# #     CONFIG_APP_AI_AMP_2_5
-# #     ${SOURCES})
-
-# # file(GLOB SOURCES ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/src/silk/tests/*.c)
-# # aic_library_sources_ifdef( 
-# #     CONFIG_APP_AI_AMP_2_5
-# #     ${SOURCES})
-# aic_library_include_directories_ifdef(
-#     CONFIG_APP_AI_AMP_2_5
-#     ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/src/
-#     ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/include/
-#     ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/src/celt/
-#     ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/src/silk/
-#     ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/src/silk/float/
-#     ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/src/silk/fixed/
-# )
 
 aic_library_include_directories_ifdef(
     CONFIG_APP_AI_AMP_2_5
     ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/
 )
+aic_library_import(APP_AI_AMP_2_5_OPUS
+    ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/guixin/libopus.a
+)
+aic_library_import(APP_AI_AMP_2_5_OGG
+    ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/guixin/libogg.a
+)
+# aic_library_import(APP_AI_AMP_2_5_OGG_DSP
+#     ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/guixin/libogg_dsp.a
+# )
+
 #
 aic_library_import(APP_AI_AMP_2_5_VAD
     ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/libimslvad.a
-    #${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/guixin/libopus.a
-)
-aic_library_import(APP_AI_AMP_2_5_OPUS
-    #${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/libimslvad.a
-    ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/guixin/libopus.a
 )
+
 aic_library_import(APP_AI_AMP_2_5_KWS
     ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/libimslkws.a
 )
diff --git a/2.code/aicos/app/AI_AMP_2_5/bk_dev.c b/2.code/aicos/app/AI_AMP_2_5/bk_dev.c
new file mode 100644 (file)
index 0000000..be08020
--- /dev/null
@@ -0,0 +1,105 @@
+
+#include "bk_dev.h"
+#include <aic_errno.h>
+#include <aic_init.h>
+#include <aic_osa_ex.h>
+#include <aos_thread.h>
+#include "app_msg.h"
+#include "aic_net_pdp_mgr.h"
+#include "aic_network_pcap.h"
+#include "aic_osa.h"
+#include <gpio_inc.h>
+static aos_thread_id bk_dev_task_id = 0;
+static aos_queue_ptr bk_dev_task_queue = NULL;
+
+//鉴权消息发送
+aos_status bk_dev_MSG_put(const char *data,u32 len,bk_dev_MSG_Type MSG_Type)
+{
+    bk_dev_MSG_queue_t bk_dev_MSG_queue_data = {0};
+    //bk_msg_printf("bk_dev_MSG_put1 MSG_Type:%d",MSG_Type);
+    if(len >0)
+    {
+        bk_dev_MSG_queue_data.data = aic_malloc(len+1);
+        memset(bk_dev_MSG_queue_data.data ,0,len+1);
+        if(!bk_dev_MSG_queue_data.data)
+        {
+            //bk_msg_printf("AI_VC_send_data aic_malloc ERROR!!!!!!!!!!");
+            return AOS_ERROR;
+        }
+        memcpy(bk_dev_MSG_queue_data.data,data,len);
+        bk_dev_MSG_queue_data.len=len;
+    }
+    
+    bk_dev_MSG_queue_data.MSG_Type=MSG_Type;
+    if(bk_dev_task_queue && AOS_SUCCESS!=aos_send_to_queue(bk_dev_task_queue,&bk_dev_MSG_queue_data,AOS_NO_WAIT))
+    {
+       if(!bk_dev_MSG_queue_data.data)
+            aic_free(bk_dev_MSG_queue_data.data);
+        return AOS_ERROR;
+    }
+    //bk_msg_printf("bk_dev_MSG_put2 MSG_Type:%d",MSG_Type);
+    return AOS_SUCCESS;
+}
+
+static void bk_dev_task(void *thread_input)//设备驱动控制线程
+{
+    bk_dev_MSG_queue_t bk_dev_msg = {0};
+    // ase_encrypt_demo();
+    // //dev_NTP();//获取时间
+    // aut_active();//激活
+    // aut_login();//登录
+    if(LOGIN_1H_timeout == NULL)
+    {
+        LOGIN_1H_timer = aos_create_timer("AI_VC_1S_timer",
+            LOGIN_1H_timeout, &LOGIN_1H_timer,
+            1000*60,
+            AOS_AUTO_ACTIVATE, AOS_BE_PERIOD);
+        aic_assert(LOGIN_1H_timer);
+    }
+
+    /**
+     * 原来已激活过了...AuthVo(password=rPbSCNTIVYWKso6I5+6l0KIbSiIembg3p10IEny2UVg=, deviceId=860132061481751, nonce=xiRqXDqkqGFodIiw)
+     */
+    while (1) {
+        if(bk_dev_task_queue)
+        {
+            aos_recv_from_queue(bk_dev_task_queue,&bk_dev_msg,AOS_WAIT_FOREVER) ;
+            switch (bk_dev_msg.MSG_Type)
+            {
+                case BK_OPEN_LED_RED://亮红灯
+                    
+                    break;
+                case BK_OPEN_LED_GREEN://亮绿灯
+                    
+                    break;
+                case BK_BK_OPEN_LED_BLUE://亮蓝灯
+                    
+                    break;
+            }
+            if(bk_dev_msg.data)
+                aic_free(bk_dev_msg.data);
+        }else
+        {
+            aos_sleep(10);
+        }
+    }
+}
+void bk_dev_init(void)
+{
+    //创建设备激活队列
+    if(bk_dev_task_queue == NULL)
+    {
+        bk_dev_task_queue = aos_create_queue("bk_dev_task_queue",
+            sizeof(bk_dev_MSG_queue_t),
+            200);
+    }
+    bk_dev_task_id = aos_create_thread(
+        "bk_dev_task",
+        bk_dev_task,
+        &bk_dev_task_id,
+        4096u,
+        0,
+        NULL,
+        35,
+        AOS_AUTO_START);
+}
\ No newline at end of file
diff --git a/2.code/aicos/app/AI_AMP_2_5/bk_dev.h b/2.code/aicos/app/AI_AMP_2_5/bk_dev.h
new file mode 100644 (file)
index 0000000..eefcf74
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef __BK_DEV_H__
+#define __BK_DEV_H__
+#include <gpio_inc.h>
+// 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 );//马达
+#define OPEN_LED GPIO_OUTPUT_LVL_HIGH
+#define CLOSE_LED GPIO_OUTPUT_LVL_LOW
+
+#define RED_LED GPIO_25
+#define GREEN_LED GPIO_30
+#define BLUE_LED GPIO_31
+
+typedef enum bk_dev_MSG
+{
+    BK_OPEN_LED_RED,//亮红灯
+    BK_OPEN_LED_GREEN,//亮绿灯
+    BK_BK_OPEN_LED_BLUE,//亮蓝灯
+    BK_CLOSE_LED //关闭所有灯
+} bk_dev_MSG_Type;
+typedef struct
+{
+    char *data;
+    u32 len;
+    bk_dev_MSG_Type MSG_Type;
+}bk_dev_MSG_queue_t;
+void bk_dev_init(void);
+#endif
index 08c566a..7e426c7 100644 (file)
@@ -27,7 +27,7 @@ static int32_t bk_kpc_callback(void *p_param, uint32_t size)
         return -1;
     }
 
-    for (int i = 0; i < 5; i++) {
+    for (int i = 0; i < KPC_KEY_PRESSED_MAX_KEY_NUM; i++) {
         bk_printf("bk_kpc_callback key[%d].key_value=%d",i,key_arr->key[i].key_value);
         switch (key_arr->key[i].key_event) {
             case KPC_KEY_EVENT_PRESS://按下
diff --git a/2.code/aicos/app/AI_AMP_2_5/bk_opus_coder.c b/2.code/aicos/app/AI_AMP_2_5/bk_opus_coder.c
new file mode 100644 (file)
index 0000000..f245945
--- /dev/null
@@ -0,0 +1,360 @@
+//opus编解码应用
+#include <aic_errno.h>
+#include <aic_init.h>
+#include <aic_osa_ex.h>
+#include <aos_thread.h>
+#include "app_msg.h"
+#include "aic_net_pdp_mgr.h"
+#include "aic_network_pcap.h"
+#include "aic_websocket_client.h"
+#include "cJSON.h"
+#include <serial_inc.h>
+#include "aic_osa.h"
+#include "app_audio.h"
+#include "bk_ringbuf.h"
+#include "bk_websocket.h"
+#include "AI_AMP_2_5.h"
+#include "bk_key.h"
+#include "aic_srv_tele_sim.h"
+#include <gpio_inc.h>
+#if SUPPORT_OPUS 
+#include "opus/guixin/opus_interface.h"
+#endif
+#include "dev_authentication.h"
+#include "imsl_vad.h"
+#include "imsl_kws.h"
+#include "aic_srv_tele_ex.h"
+#include "power_supply.h"
+#include "sysoff.h"
+#include "app_msg.h"
+#include "aic_ogg.h"
+#define OPUS_PERIOD_MS OPUS_PERIOD_60_MS
+#define OPUS_ENCODER_RB_LEN 64*32*8//要2的次方
+bk_ring_buf_t *OPUS_encoder_rb_data = NULL;
+#define OPUS_DECODER_RB_LEN 16*1024//要2的次方
+bk_ring_buf_t *OPUS_decoder_rb_data = NULL;
+static struct opus_enc_init_param *opus_encoder_h = NULL;
+static struct opus_dec_init_param  *opus_decoder_h = NULL;
+int opus_init(void)
+{
+    #if SUPPORT_OPUS 
+    int status = 0;
+    int ret = -1;
+        bk_printf("opus_init start");
+        //int err;
+        if (opus_encoder_h == NULL)
+        {
+            opus_encoder_h = (opus_enc_init_param_t *)aic_zalloc(sizeof(opus_enc_init_param_t));
+            if(!opus_encoder_h)
+            {
+                bk_printf("opus_encoder_h alloc error");
+                ret = -1;
+                goto opus_init_RET;
+            }
+            opus_encoder_h->channel_cnt = 1;
+            opus_encoder_h->sample_rate = 16000;
+            opus_encoder_h->period_ms = OPUS_PERIOD_MS;
+            opus_encoder_h->bitrate = 16000;
+            status = aic_opus_init_encoder(opus_encoder_h);
+            if (status)
+            {
+                bk_printf("aic_opus_init_encoder error");
+                ret = -1;
+                goto opus_init_RET;
+            }
+            //opus_encoder_h = opus_encoder_create(16000, 1, OPUS_APPLICATION_VOIP, &err);
+        }
+            
+        if (opus_decoder_h == NULL)
+        {
+            
+            opus_decoder_h = (opus_dec_init_param_t *)aic_zalloc(sizeof(opus_dec_init_param_t));
+            if(!opus_decoder_h)
+            {
+                bk_printf("opus_decoder_h alloc error");
+                ret = -1;
+                goto opus_init_RET;
+            }
+            opus_decoder_h->channel_cnt = 1;
+            opus_decoder_h->sample_rate = 16000;
+            status = aic_opus_init_decoder(opus_decoder_h);
+            if (status)
+            {
+                bk_printf("aic_opus_init_decoder error");
+                ret = -1;
+                goto opus_init_RET;
+            }
+               
+            //opus_decoder_h = opus_decoder_create(16000, 1, &err);
+        }
+        if(OPUS_encoder_rb_data == NULL)
+            OPUS_encoder_rb_data =  bk_rb_create(OPUS_ENCODER_RB_LEN);
+        if(!OPUS_encoder_rb_data )
+        {
+            bk_printf("OPUS_encoder_rb_data error!申请失败");
+            ret = -1;
+            goto opus_init_RET;
+        }
+        if(OPUS_decoder_rb_data == NULL)
+            OPUS_decoder_rb_data =  bk_rb_create(OPUS_DECODER_RB_LEN);
+        if(!OPUS_decoder_rb_data )
+        {
+            bk_printf("OPUS_decoder_rb_data error!申请失败");
+            ret = -1;
+            goto opus_init_RET;
+        }
+
+        bk_printf("opus_init end");
+        return 0;
+        opus_init_RET:
+        if(opus_decoder_h )
+            aic_free(opus_decoder_h);
+        if(opus_encoder_h)
+            aic_free(opus_encoder_h);
+        return ret;
+        #endif
+}
+void opus_close(void)
+{
+    #if SUPPORT_OPUS 
+    if(aic_opus_deinit_encoder() == 0)
+    {
+       
+    }
+    if(opus_encoder_h)
+        aic_free(opus_encoder_h);
+    opus_encoder_h =  NULL;
+    if(aic_opus_deinit_decoder() == 0)
+    {
+        
+    }
+    if(opus_decoder_h)
+        aic_free(opus_decoder_h);
+    opus_decoder_h =  NULL;
+    if(OPUS_encoder_rb_data != NULL)
+    {
+        bk_rb_destroy(&OPUS_encoder_rb_data);
+        OPUS_encoder_rb_data= NULL;
+    }
+    if(OPUS_decoder_rb_data != NULL)
+    {
+        bk_rb_destroy(&OPUS_decoder_rb_data);
+        OPUS_decoder_rb_data= NULL;
+    }
+    
+    #endif
+}
+void opus_clean(void)
+{
+
+    if(OPUS_encoder_rb_data)
+    {
+        bk_rb_clear(OPUS_encoder_rb_data);
+    }
+}
+int opus_encode_data(char *PCM_data,int data_len,int one_pack_len,char *opus_data,int opus_data_max_len)
+{
+    int ret = 0;
+    #if SUPPORT_OPUS 
+    
+    //struct opus_dec_param dec_inparam;
+
+    struct opus_enc_param enc_inparam;
+    //OPUS_encoder_rb_data
+    if(OPUS_encoder_rb_data)
+    {
+        if(OPUS_ENCODER_RB_LEN - bk_rb_data_len(OPUS_encoder_rb_data) >= data_len)//缓存够
+        {
+            bk_rb_write(OPUS_encoder_rb_data,PCM_data,data_len);
+        }else//缓存太大,需要出队处理
+        {
+            return -1;
+            // unsigned char *OPUS_tmp =  aic_malloc(data_len);
+            // if(OPUS_tmp)
+            // {
+            //     bk_rb_read(OPUS_encoder_rb_data,OPUS_tmp,data_len);
+            //     aic_free(OPUS_tmp);
+            // }
+            // bk_printf("send_opus_data:缓存太大,先出队");
+            // bk_rb_write(OPUS_encoder_rb_data,PCM_data,data_len);
+        }
+        while(1)
+        {
+            if(bk_rb_data_len(OPUS_encoder_rb_data) < one_pack_len)//数据不够,退出
+            {
+                break;
+            }else
+            {
+                unsigned char *pcm_data =  aic_malloc(one_pack_len);
+                //unsigned char *opus_data =  aic_malloc(one_pack_len);
+                if(!pcm_data)
+                {
+                    bk_printf("opus_encode_data:alloc error!");
+                    
+                    if(pcm_data)
+                        aic_free(pcm_data); 
+                    return -1;
+                }
+                // int time_tmp = aos_get_tickcount();
+                // bk_printf("opus_encode_data:time = %d",time_tmp);
+                int pcm_len=bk_rb_read(OPUS_encoder_rb_data,pcm_data,one_pack_len);//解码数据
+                enc_inparam.input = (int16_t*)(pcm_data);//PCM数据
+                enc_inparam.input_size = pcm_len;
+                enc_inparam.output = (int8_t*)opus_data;
+                enc_inparam.outbuffer_size = opus_data_max_len;
+                ret = aic_opus_encode(&enc_inparam);
+                
+                //enc_inparam.output_len_array[0];//长度
+                //AI_VC_send_data(opus_data,enc_inparam.output_len_array[0],AIC_WEBSOCKET_OPCODE_BINARY_FRAME);//够一帧,发送数据
+                // ret = send_websocket_message(AI_client_VC,opus_data,enc_inparam.output_len_array[0],
+                //     AIC_WEBSOCKET_OPCODE_BINARY_FRAME);
+                
+                //bk_printf("opus_encode_data:data_len = %d 用时:%d MS",enc_inparam.output_len_array[0],aos_get_tickcount()-time_tmp);
+                aic_free(pcm_data);
+                
+                if(ret < 0)
+                    return -1;
+                ret = enc_inparam.output_len_array[0];
+            }
+        }
+    }
+    
+
+    #endif
+    return ret;
+}
+
+int ogg_opus_decode_data(char *in_ogg_data,int in_ogg_data_len)
+{
+    int data_count = 0;
+    int page_type;
+    int channel_cnt, sample_rate;
+    unsigned char* p_audio;
+    int frame_length;
+    struct opus_dec_param dec_inparam;
+    int ret = 0;
+    static char ogg_hend[27+256]  ={0};
+    static int ogg_hend_len = 0;
+    int seg_num =0;
+    //fread(page_buffer, 1, 27 + seg_num, fin);
+    if(!in_ogg_data)
+        return -2;
+    //fseek(fin, -1 * (27 + seg_num), SEEK_CUR);
+    //fread(page_buffer, 1, 27 + seg_num + seg_size, fin);
+    int seg_size;
+    #if SUPPORT_OPUS 
+    if(OPUS_decoder_rb_data)
+    {
+        if(OPUS_DECODER_RB_LEN - bk_rb_data_len(OPUS_decoder_rb_data) >= in_ogg_data_len)//缓存够
+        {
+            bk_rb_write(OPUS_decoder_rb_data,in_ogg_data,in_ogg_data_len);
+        }
+    }else
+    {
+        bk_printf("OPUS_decoder_rb_data error!!!!!");
+        return -1;
+    }
+    data_count = 0;
+    u64 timer_ms = aos_get_tickcount();
+    
+    while(1)
+    {
+
+        if(bk_rb_data_len(OPUS_decoder_rb_data) < 27)//不够一页数据
+        {
+            break;
+        }else
+        {
+            /**********1阶段判断头********** */
+            if(ogg_hend_len==0)//没有剩余的头数据
+            {
+                bk_rb_read(OPUS_decoder_rb_data,ogg_hend,27);
+                ogg_hend_len+=27;//读页头
+                
+            }
+            /**********2阶段判段数********** */
+            seg_num = ogg_get_segment_num(ogg_hend, 27);//读有多少段
+            //bk_printf("ogg段数:%d",seg_num);
+            if(ogg_hend_len < 27+seg_num)//没有段数据
+            {
+                if(bk_rb_data_len(OPUS_decoder_rb_data)< seg_num)//判断可读数据够不够
+                {
+                    bk_printf("算页大小数据不够,退出当前解包:seg_num %d",seg_num);
+                    break;
+                }
+                    
+                ogg_hend_len+=bk_rb_read(OPUS_decoder_rb_data,ogg_hend+27,seg_num);//读页的段数据
+            }
+            seg_size = ogg_calc_total_segment_data_size(ogg_hend, ogg_hend_len);//算这一页有多少数据
+            //bk_printf("整页数据大小:%d",seg_size);
+            /************3阶段读完整包****************** */
+            if(bk_rb_data_len(OPUS_decoder_rb_data)< seg_size)//判断可读数据够不够
+            {
+                    bk_printf("读整页数据大小不够,退出当前解包:seg_size %d,ogg_hend_len:%d",seg_size,ogg_hend_len);
+
+                    break;
+            }
+            char *ogg_buf = aic_malloc(27+seg_num+seg_size);
+            if(ogg_buf)
+            {   
+                memcpy(ogg_buf,ogg_hend,27+seg_num);
+                bk_rb_read(OPUS_decoder_rb_data,ogg_buf+27+seg_num,seg_size);//读一整页
+                ogg_hend_len = 0;//头部已读完,认为读完一整帧
+                page_type = ogg_check_opus_page_type(ogg_buf, &channel_cnt, &sample_rate);//获取数据类型,1是头,3是音频帧
+                if (1 == page_type) {
+                    bk_printf("ogg头:lchannel cnt = %d, sample rate = %d", channel_cnt, sample_rate);
+                }
+                else if (3 == page_type) {
+                    ogg_demux_context demux_context = { 0, 0 };
+                    while (1) {
+                        p_audio = ogg_get_next_audio_frame(ogg_buf, &demux_context, &frame_length);
+                        if (p_audio == NULL || frame_length == 0)
+                            break;
+                        //bk_printf("ogg解包:len:%d",frame_length);
+                        char *pcm_buf = aic_malloc(4096); 
+                        if(pcm_buf)
+                        {
+                            
+                            dec_inparam.input = p_audio;
+                            dec_inparam.inputfrm_count = 1;
+                            dec_inparam.input_len_array[0] = frame_length;
+                            //memcpy(dec_inparam.input_len_array , enc_inparam.output_len_array, sizeof(dec_inparam.input_len_array));
+                            dec_inparam.output = (int16_t *)pcm_buf;
+                            dec_inparam.outbuffer_size = 4096;
+                            ret = aic_opus_decode(&dec_inparam);
+                            
+                           // bk_printf("opus解码 result:%d,outsize:%d", ret,dec_inparam.outputfrms_size);
+                            if (ret == OPUS_RESULT_ERROR) {
+                                //bk_printf("opus解码  error:%d", ret);
+                                //bk_printf("ogg data:");
+                                bk_print_hex(ogg_buf,27+seg_num+seg_size);
+                                aic_free(pcm_buf);
+                                break;
+                            }
+                            AI_VC_put_play_data(pcm_buf,dec_inparam.outputfrms_size);//发送数据到音频队列
+                            //aos_sleep(1);
+                            aic_free(pcm_buf);
+                        }
+                        
+                    }
+                }else if(2 == page_type)//标签
+                {
+                    bk_printf("opus标签 :%s", ogg_buf+27+seg_num);
+                }
+                else
+                {
+                    bk_printf("ogg解析失败 :%d!!!!!!!!!!!!", page_type);
+                    aic_free(ogg_buf);
+                    break;
+                }
+                aic_free(ogg_buf);
+            }
+
+        }
+        
+        //aos_sleep(1);
+    }
+    bk_printf("ogg-opus解码 数据大小:%d,耗时:%d ms",in_ogg_data_len,aos_get_tickcount()-timer_ms );
+    #endif
+       return 0;
+}
\ No newline at end of file
diff --git a/2.code/aicos/app/AI_AMP_2_5/bk_opus_coder.h b/2.code/aicos/app/AI_AMP_2_5/bk_opus_coder.h
new file mode 100644 (file)
index 0000000..82eed1c
--- /dev/null
@@ -0,0 +1,8 @@
+#ifndef __BK_OPUS_CODER_H__
+#define __BK_OPUS_CODER_H__
+int opus_init(void);
+void opus_close(void);
+void opus_clean(void);
+int opus_encode_data(char *PCM_data,int data_len,int one_pack_len,char *opus_data,int opus_data_max_len);
+int ogg_opus_decode_data(char *in_ogg_data,int in_ogg_data_len);
+#endif
index 8b322cc..d78265d 100644 (file)
@@ -72,6 +72,7 @@ typedef struct {
     char *protocol;
     char *host;
     int port;
+    char port_str[7];
     char *path;
     char *query;
     int error;
@@ -150,6 +151,7 @@ BK_URL parse_url(const char *url) {
             aic_free(temp_url_t);
             return result;
         }
+        
         result.port = atoi(colon_port + 1);
         if (!result.port) {
             set_url_error(&result, "Invalid port number");
@@ -169,6 +171,8 @@ BK_URL parse_url(const char *url) {
             result.port = 443;
         }
     }
+    memset(result.port_str,0,sizeof(result.port_str));
+    snprintf(result.port_str,sizeof(result.port_str),"%d",result.port );
     temp_url = slash+1;
     //bk_printf("parse_url slash=%s\n",temp_url);
     // 解析路径和查询字符串
@@ -367,6 +371,8 @@ int send_handshake(WebSocketClient *client,const char *headers) {
 
 // 发送 WebSocket 消息
 int send_websocket_message(WebSocketClient *client, const unsigned char *message, size_t message_len, WebSocketMessageType type) {
+    if(!client)
+        return -1;
     unsigned char *frame=aic_zalloc(message_len + 50);
     int offset = 0;
     int ret = -1;
@@ -430,6 +436,8 @@ send_websocket_message_ERROR:
 int  receive_websocket_message(WebSocketClient *client, unsigned char *buf,int len,WebSocketMessageType *code) {
     //u64 timer_ms = aos_get_tickcount();
     //bk_printf("receive_websocket_message 1 timer_ms=%d\n",timer_ms);
+    if(!client )
+        return -1;
     unsigned char frame[20]={0};
     unsigned char masking_key[4];
     int bytes_received = 0;
@@ -679,24 +687,54 @@ WebSocketClient *init_websocket_client(const char *url, const char *headers) {
         bk_printf("init_websocket_client alloc error");
         goto client_ERROR;
     }
-
-    client->sockfd = socket(AF_INET, SOCK_STREAM, 0);
-    if (client->sockfd < 0) {
-        bk_printf("socket creation failed");
+    struct addrinfo hints, *addr_list, *cur;
+    hints.ai_family = AF_INET;
+    hints.ai_socktype =  SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
+    if( getaddrinfo( parsed_url.host, parsed_url.port_str, &hints, &addr_list ) != 0 )
+    //if( getaddrinfo( "www.baidu.com", "80", &hints, &addr_list ) != 0 )
+    {
+        bk_printf("init_websocket_client getaddrinfo error");
         goto client_ERROR;
     }
 
-   // bk_printf("init_websocket_client 3\n");
-    struct sockaddr_in server_addr;
-    server_addr.sin_family = AF_INET;
-    server_addr.sin_port = htons(parsed_url.port);
-    inet_pton(AF_INET, parsed_url.host, &server_addr.sin_addr);
+    for( cur = addr_list; cur != NULL; cur = cur->ai_next )
+    {
+        client->sockfd = (int) socket( cur->ai_family, cur->ai_socktype,
+                            cur->ai_protocol );
+        if( client->sockfd < 0 )
+        {
+            continue;
+        }
+
+        if( connect( client->sockfd , cur->ai_addr,  (int)cur->ai_addrlen ) == 0 )
+        {
+            
+            break;
+        }
 
-    if (connect(client->sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
-        bk_printf("connection failed");
-        close(client->sockfd);
+        close( client->sockfd  );
         goto client_ERROR;
+        bk_printf("init_websocket_client connect error");
     }
+    bk_printf("init_websocket_client connect ok,sockfd:%d",client->sockfd);
+//     client->sockfd = socket(AF_INET, SOCK_STREAM, 0);
+//     if (client->sockfd < 0) {
+//         bk_printf("socket creation failed");
+//         goto client_ERROR;
+//     }
+
+//    // bk_printf("init_websocket_client 3\n");
+//     struct sockaddr_in server_addr;
+//     server_addr.sin_family = AF_INET;
+//     server_addr.sin_port = htons(parsed_url.port);
+//     inet_pton(AF_INET, parsed_url.host, &server_addr.sin_addr);
+
+//     if (connect(client->sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
+//         bk_printf("connection failed");
+//         close(client->sockfd);
+//         goto client_ERROR;
+//     }
 
 
     strcpy(client->host, parsed_url.host);
@@ -740,17 +778,183 @@ void close_websocket_client(WebSocketClient *client) {
     }
     
 }
-
+int http_get_client(const char *url, const char *headers,const char *Content_Type,char* response,int response_len);
 int bk_websocket_demo(void) {
-    WebSocketClient *client;
-    client = init_websocket_client("ws://118.145.158.207:22086/vc/coze?is_auth=0",NULL);
-    if (client== NULL) {
-        return -1;
+    // WebSocketClient *client;
+    // client = init_websocket_client("ws://118.145.158.207:22086/vc/coze?is_auth=0",NULL);
+    // if (client== NULL) {
+    //     return -1;
+    // }
+    // close_websocket_client(client);
+    // aos_sleep(2);
+    // char *response =aic_zalloc(BUFFER_SIZE);
+    // //char *url = "http://dmp.raisound.com/sv/vad/auth/token?nonceStr=abc&sign=3470327e8eee163f00d5f54cc936d32595189b16d1e89c2b50155b80227c85d0&timestamp=1750406765243&token=9542143a532adc10ec6ee530cd1824d53b";
+    // char *url = "http://dmp.raisound.com/bz-mp-api/sv/vad/auth/token?nonceStr=abc&sign=3470327e8eee163f00d5f54cc936d32595189b16d1e89c2b50155b80227c85d0&timestamp=1750406765243&token=9542143a532adc10ec6ee530cd1824d53b";
+    // http_get_client(url,"bz-dt:9542143a532adc10ec6ee530cd1824d53b","application/x-www-form-urlencoded",response,BUFFER_SIZE);
+    // bk_printf("http GET data:%s",response);
+    // aic_free(response);
+    return 0;
+}
+    
+/************************http*********************************** */
+
+// WebSocket 客户端结构体
+typedef struct {
+    int sockfd;
+    char host[128];
+    char path[128];
+    char query[512];
+    int port;
+} httpClient;
+int send_http_get_handshake(httpClient *client,const char *headers,const char *Content_Type) {
+    char key[WEBSOCKET_KEY_LEN];
+    bk_printf("send_handshake1");
+    generate_websocket_key(key);
+    char accept_key[64];
+    int ret = 0;
+    generate_accept_key(key, accept_key);
+    bk_printf("send_handshake2");
+    char *request =aic_zalloc(BUFFER_SIZE);
+    if(headers!= NULL)
+    {
+        snprintf(request, BUFFER_SIZE,
+            "GET /%s?%s HTTP/1.1\r\n"
+            "Host: %s:%d\r\n"
+            "Content-Type: %s\r\n"
+            "Connection: close\r\n"
+            "%s\r\n"
+            "\r\n",
+            client->path,client->query ,client->host,client->port,Content_Type,headers);
+    }else
+    {
+        snprintf(request, BUFFER_SIZE,
+            "GET /%s?%s HTTP/1.1\r\n"
+            "Host: %s:%d\r\n"
+            "Content-Type: %s\r\n"
+            "Connection: close\r\n"
+            "\r\n",
+            client->path,client->query , client->host,client->port,Content_Type);
+    }
+    
+        bk_printf("send_handshake request:\r\n%s",request);
+    if (send(client->sockfd, request, strlen(request), 0) < 0) {
+        bk_printf("send handshake failed :sockfd:%d",client->sockfd);
+        
+        ret = -1;
     }
+    bk_printf("send_handshake3");
+    aic_free(request);
+    return ret;
+}
+//http get 客户端
+int http_get_client(const char *url, const char *headers,const char *Content_Type,char* response,int response_len) {
+    //bk_printf("init_websocket_client 1\n");
 
+    httpClient *client  =NULL;
+    BK_URL parsed_url = {0};
+    parsed_url = parse_url(url);//解析url
+    //bk_printf("url: %s", url);
+    if (parsed_url.error) {
+        bk_printf("Error: %s", parsed_url.error_message);
+        goto client_ERROR;
+    } else {
+        bk_printf("Protocol: %s", parsed_url.protocol);
+        bk_printf("Host: %s", parsed_url.host);
+        bk_printf("Port: %d", parsed_url.port);
+        bk_printf("Path: %s", parsed_url.path);
+        bk_printf("Query: %s", parsed_url.query);
+
+    }
+    client = aic_zalloc(sizeof(httpClient)) ;
+    if(!client)
+    {
+        bk_printf("http_get_client alloc error");
+        goto client_ERROR;
+    }
+    struct addrinfo hints, *addr_list, *cur;
+    hints.ai_family = AF_INET;
+    hints.ai_socktype =  SOCK_STREAM;
+    hints.ai_protocol = IPPROTO_TCP;
+    if( getaddrinfo( parsed_url.host, parsed_url.port_str, &hints, &addr_list ) != 0 )
+    //if( getaddrinfo( "www.baidu.com", "80", &hints, &addr_list ) != 0 )
+    {
+        bk_printf("getaddrinfo error");
+        goto client_ERROR;
+    }
+
+    for( cur = addr_list; cur != NULL; cur = cur->ai_next )
+    {
+        client->sockfd = (int) socket( cur->ai_family, cur->ai_socktype,
+                            cur->ai_protocol );
+        if( client->sockfd < 0 )
+        {
+            continue;
+        }
+
+        if( connect( client->sockfd , cur->ai_addr,  (int)cur->ai_addrlen ) == 0 )
+        {
+            
+            break;
+        }
+
+        close( client->sockfd  );
+        goto client_ERROR;
+        bk_printf("http_get_client connect error");
+    }
+    bk_printf("http_get_client connect ok,sockfd:%d",client->sockfd);
+//     client->sockfd = socket(AF_INET, SOCK_STREAM, 0);
+//     if (client->sockfd < 0) {
+//         bk_printf("socket creation failed");
+//         goto client_ERROR;
+//     }
+
+//    // bk_printf("init_websocket_client 3\n");
+//     struct sockaddr_in server_addr;
+//     server_addr.sin_family = AF_INET;
+//     server_addr.sin_port = htons(parsed_url.port);
+
+//     inet_pton(AF_INET, parsed_url.host, &server_addr.sin_addr);
     
+//     if (connect(client->sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
+//         bk_printf("connection failed");
+//         close(client->sockfd);
+//         goto client_ERROR;
+//     }
 
-    close_websocket_client(client);
-    return 0;
+
+    strcpy(client->host, parsed_url.host);
+    strcpy(client->path, parsed_url.path);
+    strcpy(client->query, parsed_url.query);
+    client->port = parsed_url.port;
+    if (send_http_get_handshake(client,headers,Content_Type) < 0) { //发送头
+        close(client->sockfd);
+        goto client_ERROR;
+    }
+
+
+    ssize_t bytes_received = recv(client->sockfd, response, response_len-1, 0);
+    if (bytes_received > 0) {
+        response[bytes_received] = '\0';
+        bk_printf("Received handshake response:\n%s\n", response);
+    }else
+    {
+        bk_printf("recv error bytes_received %d", recv);
+    }
+    // if(strstr(buffer,"HTTP/1.1 101") == NULL)
+    // {
+        
+    //     goto client_ERROR;
+    // }
+
+    free_url(parsed_url);
+    if(client)
+        aic_free(client);
+    return bytes_received;
+client_ERROR:
+
+    if(client)
+        aic_free(client);
+    free_url(parsed_url);
+    return -1;
 }
-    
\ No newline at end of file
+
index 5214e65..01d55ea 100644 (file)
@@ -32,5 +32,5 @@ int  receive_websocket_message(WebSocketClient *client, unsigned char *buf,int l
 
 // 发送 WebSocket 消息
 int send_websocket_message(WebSocketClient *client, const unsigned char *message, size_t message_len, WebSocketMessageType type) ;
-
+int bk_websocket_demo(void);
 #endif
index bde69af..8f36374 100644 (file)
@@ -21,7 +21,7 @@ struct VadConfig
     1  试用模式 (最长30分钟)
     2  授权模型 (授权失败  控制台会打印,同时转为试用模式)
 */
-int init_vad(struct VadConfig* conf);
+int init_vad(const struct VadConfig* conf);
 
 // 运行vad函数,data为16khz  16bit的pcm音频数据  
 // 注意data_len是int16_t的data_len,如果传入u8*或void* 数据data_len需要 / 2
index 399cedb..8ae85d5 100644 (file)
Binary files a/2.code/aicos/app/AI_AMP_2_5/libimslnn.a and b/2.code/aicos/app/AI_AMP_2_5/libimslnn.a differ
index 19fd159..692d6a4 100644 (file)
Binary files a/2.code/aicos/app/AI_AMP_2_5/libimslvad.a and b/2.code/aicos/app/AI_AMP_2_5/libimslvad.a differ
diff --git a/2.code/aicos/app/AI_AMP_2_5/opus/guixin/aic_ogg.h b/2.code/aicos/app/AI_AMP_2_5/opus/guixin/aic_ogg.h
new file mode 100644 (file)
index 0000000..94c4172
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef AIC_OGG_H
+#define AIC_OGG_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+       /*
+       p_page: page buffer pointer
+       length: length of the page buffer
+       return: segment entry nunber
+       */
+       int ogg_get_segment_num(unsigned char* p_page, int length);
+       /*
+       p_page: page buffer pointer
+       length: length of the page buffer
+       return: total length of the page
+       */
+       int ogg_calc_total_segment_data_size(unsigned char* p_page, int length);
+
+       typedef struct {
+               int index;//init to 0
+               int pre_total_len;//init to 0
+       } ogg_demux_context;
+
+       /*
+       p_page: page buffer pointer
+       p_ctx: init for every page
+       return : pointer to audio frame data, frame lehgth of this auido frame
+       */
+       //to reduce the latency, we can use this function to get the length of the next audio frame first and ignore the return
+       //buffer address. as soon as we get the data from network, send the data to opus decoder.
+       unsigned char* ogg_get_next_audio_frame(unsigned char* p_page, ogg_demux_context* p_ctx, int* frame_length);
+
+
+       //1: OpusHead, 2: OpusTags, 3: audio frame
+       //for OpusHead, return audio channel count and sample rate 
+       int ogg_check_opus_page_type(unsigned char* p_page, int* channel_cnt, int* sample_rate);
+
+
+
+       //buf length must >= 47+57
+       //return length of the page
+       int ogg_generate_opus_head_and_tags(unsigned char* p_buf, int buf_length, int channel_cnt, int sample_rate);
+
+
+       typedef struct {
+               int frame_length;//pcm samples per frame
+               int neg_buf_length;//the available buffer length to store header ahead of audio data pointer
+               unsigned int seq_num;//init to 0
+               unsigned long long granule_position;//init to 0
+       } ogg_mux_context;
+
+       /*
+       * p_buf: audio data pointer
+       * frame_num: audio frame number
+       * p_length: length of each audio frame
+       * last_flag: 0 if not last page
+       * return: length of page header
+       */
+       int ogg_generate_opus_audio_page(unsigned char* p_buf, short* p_length, int frame_num, ogg_mux_context* p_ctx, int last_flag);
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* AIC_OGG_H */
\ No newline at end of file
diff --git a/2.code/aicos/app/AI_AMP_2_5/opus/guixin/libogg.a b/2.code/aicos/app/AI_AMP_2_5/opus/guixin/libogg.a
new file mode 100644 (file)
index 0000000..58a72d3
Binary files /dev/null and b/2.code/aicos/app/AI_AMP_2_5/opus/guixin/libogg.a differ
diff --git a/2.code/aicos/app/AI_AMP_2_5/opus/guixin/libogg_dsp.a b/2.code/aicos/app/AI_AMP_2_5/opus/guixin/libogg_dsp.a
new file mode 100644 (file)
index 0000000..da299b1
Binary files /dev/null and b/2.code/aicos/app/AI_AMP_2_5/opus/guixin/libogg_dsp.a differ
diff --git a/2.code/aicos/app/AI_AMP_2_5/opus/guixin/opus_test.c b/2.code/aicos/app/AI_AMP_2_5/opus/guixin/opus_test.c
new file mode 100644 (file)
index 0000000..61d2564
--- /dev/null
@@ -0,0 +1,35 @@
+static u16 g_pcm[320] = {
+};
+static u8 g_bitstream[1500];
+
+int opus(int argc, char **argv)
+{
+    int ret = aic_opus_init_encoder(16000, 1);
+
+    if (ret) {
+        alog_error("init encoder failed");
+        return -1;
+    }
+    ret = aic_opus_init_decoder(16000, 1);
+    if (ret) {
+        alog_error("init decoder failed");
+        return -1;
+    }
+    /*input g_pcm, input sample:320, output:g_bitstream, ouput_buf size:1500
+      ret is ouput size of encoded data*/
+    ret = aic_opus_encode(g_pcm, 320, g_bitstream, 1500);
+    if (ret > 0) {
+        /*g_pcm: output pcm data
+          640: output buffer size
+          g_bitstream: input encoded data
+          ret input: the valid length for g_bitstrream
+          ret return value: the sample count of output pcm data*/
+        ret = aic_opus_decode(g_pcm, 640, g_bitstream, ret);
+    }
+
+
+    ret = aic_opus_deinit_encoder();
+    ret = aic_opus_deinit_decoder();
+
+    return 0;
+}
\ No newline at end of file
diff --git a/2.code/aicos/app/AI_AMP_2_5/opus/opus.zip b/2.code/aicos/app/AI_AMP_2_5/opus/opus.zip
new file mode 100644 (file)
index 0000000..537f055
Binary files /dev/null and b/2.code/aicos/app/AI_AMP_2_5/opus/opus.zip differ