From: p15692025051 <846603105@qq.com> Date: Wed, 7 May 2025 03:57:40 +0000 (+0800) Subject: 新增 X-Git-Url: http://git.snicker.com.cn/?a=commitdiff_plain;h=47e092c4487a3ef17078fb9f92281e976f945729;p=mirrors%2FFX01.git 新增 --- diff --git a/2.code/aicos/app/AI_AMP_2_5/AI_AMP_2_5.c b/2.code/aicos/app/AI_AMP_2_5/AI_AMP_2_5.c index c0f1708..e8d54b7 100644 --- a/2.code/aicos/app/AI_AMP_2_5/AI_AMP_2_5.c +++ b/2.code/aicos/app/AI_AMP_2_5/AI_AMP_2_5.c @@ -17,6 +17,16 @@ #include "bk_websocket.h" #include "AI_AMP_2_5.h" #include "bk_key.h" +#include "opus/guixin/opus_interface.h" +#include "dev_authentication.h" +// #include "opus/include/opus.h" +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; +char 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; @@ -36,6 +46,11 @@ static u32 VC_pingping_timerout = 0; static u32 VC_END_play_timerout = 0; static char *AI_TTS_str = NULL; static aos_timer_ptr AI_VC_1S_timer = NULL; +// OpusEncoder *opus_encoder_h = NULL; +// OpusDecoder *opus_decoder_h = NULL; + +static struct opus_enc_init_param *opus_encoder_h = NULL; +static struct opus_dec_init_param *opus_decoder_h = NULL; 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; @@ -202,6 +217,7 @@ static void AI_client_VC_synthesis(char *str) free(json_str); cJSON_Delete(root); } +//开始事件 static void AI_VC_send_satrt(void) { // 创建根对象 @@ -210,7 +226,7 @@ static void AI_VC_send_satrt(void) // 创建 payload 对象 cJSON *payload = cJSON_CreateObject(); - cJSON_AddStringToObject(payload, "device_id", "125698745641"); + cJSON_AddStringToObject(payload, "device_id", "12569874564165"); cJSON_AddStringToObject(payload, "user_agent", "AudioClient/1.0"); // 创建 dialog_attributes 对象 @@ -263,7 +279,10 @@ static void AI_VC_send_satrt(void) // 创建 inbound_attributes 对象 cJSON *inbound_attributes = cJSON_CreateObject(); cJSON_AddStringToObject(inbound_attributes, "provider", "volcengine"); - cJSON_AddBoolToObject(inbound_attributes, "disable_vad", 0); + if(VC_mode == 0)//连续对话模式 + cJSON_AddBoolToObject(inbound_attributes, "disable_vad", 0); + else + cJSON_AddBoolToObject(inbound_attributes, "disable_vad", 1); cJSON_AddNumberToObject(inbound_attributes, "vad_silence", 500); // 创建 interrupt_options 对象 @@ -283,7 +302,14 @@ static void AI_VC_send_satrt(void) // 创建 inbound_attributes 下的 cfg 对象 cJSON *inbound_cfg = cJSON_CreateObject(); - cJSON_AddStringToObject(inbound_cfg, "format", "pcm"); + if(inbound_attributes_format == inbound_attributes_format_OPUS) + { + cJSON_AddStringToObject(inbound_cfg, "codec", "opus"); + //cJSON_AddStringToObject(inbound_cfg, "format", "pcm"); + } + else + cJSON_AddStringToObject(inbound_cfg, "format", "pcm"); + cJSON_AddNumberToObject(inbound_cfg, "sample_rate", 16000); cJSON_AddNumberToObject(inbound_cfg, "bit_rate", 16); cJSON_AddNumberToObject(inbound_cfg, "channel", 1); @@ -309,6 +335,78 @@ static void AI_VC_send_satrt(void) // 释放内存 cJSON_Delete(root); } +//Audio.Create 开始发送音频 +static void AI_VC_send_audio_create(void) +{ + // 创建根对象 + cJSON *root = cJSON_CreateObject(); + if (root == NULL) { + bk_printf("Failed to create root object.\n"); + return ; + } + + // 设置 "event" 字段 + cJSON_AddStringToObject(root, "event", "audio.create"); + + // 创建 "payload" 对象 + cJSON *payload = cJSON_CreateObject(); + if (payload == NULL) { + bk_printf("Failed to create payload object.\n"); + cJSON_Delete(root); + return ; + } + // 将 "payload" 对象添加到根对象中 + cJSON_AddItemToObject(root, "payload", payload); + + // 将 JSON 对象转换为字符串 + char *json_str = cJSON_Print(root); + if (json_str == NULL) { + bk_printf("Failed to print JSON object.\n"); + cJSON_Delete(root); + + } + AI_VC_send_data(json_str,strlen(json_str),AIC_WEBSOCKET_OPCODE_TEXT_FRAME);//发送数据 + + + // 释放内存 + free(json_str); + cJSON_Delete(root); +} +//Audio.Completed 结束发送音频 +static void AI_VC_send_audio_completed(void) +{ + // 创建根对象 + cJSON *root = cJSON_CreateObject(); + if (root == NULL) { + bk_printf("Failed to create root object.\n"); + return ; + } + + // 设置 "event" 字段 + cJSON_AddStringToObject(root, "event", "audio.completed"); + + // 创建 "payload" 对象 + cJSON *payload = cJSON_CreateObject(); + if (payload == NULL) { + bk_printf("Failed to create payload object.\n"); + cJSON_Delete(root); + return ; + } + // 将 "payload" 对象添加到根对象中 + cJSON_AddItemToObject(root, "payload", payload); + + // 将 JSON 对象转换为字符串 + char *json_str = cJSON_Print(root); + if (json_str == NULL) { + bk_printf("Failed to print JSON object.\n"); + cJSON_Delete(root); + + } + AI_VC_send_data(json_str,strlen(json_str),AIC_WEBSOCKET_OPCODE_TEXT_FRAME);//发送数据 + // 释放内存 + free(json_str); + cJSON_Delete(root); +} //TTS播放 static void VC_TTS_Play(const char *str) { @@ -342,7 +440,7 @@ static int websocket_connect_VC(void) "AI_VC_send", AI_VC_send_task, &AI_VC_send_task_id, - 4096u, + 1024*16, 0, NULL, ai_VC_task_priority, @@ -445,11 +543,13 @@ static aos_status AI_VC_send_data(char *data,u32 len,u8 AIC_WEBSOCKET_OPCODE) return AOS_SUCCESS; } +u16 opus_remain_buf[640]; +u32 opus_remain_size = 0; static void AI_VC_send_task(void *thread_input)//websocket 发送线程 { AI_VC_send_queue_t AI_VC_send_queue_data; bk_printf("AI_VC_send_task go......"); - + int ret = 0; while(1) { if(AI_VC_send_queue && aos_recv_from_queue(AI_VC_send_queue,&AI_VC_send_queue_data,AOS_WAIT_FOREVER) == AOS_SUCCESS) @@ -458,8 +558,76 @@ static void AI_VC_send_task(void *thread_input)//websocket 发送线程 if(AI_client_VC && AI_VC_send_queue_data.data) { VC_pingping_timerout = 5; - int 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); + if(AI_VC_send_queue_data.AIC_WEBSOCKET_OPCODE ==AIC_WEBSOCKET_OPCODE_BINARY_FRAME &&inbound_attributes_format == inbound_attributes_format_OPUS) + { + u8 *opus_data =aic_zalloc(AI_VC_send_queue_data.len); + u8 *pcm_data =aic_zalloc(opus_remain_size+AI_VC_send_queue_data.len); + struct opus_dec_param dec_inparam; + struct opus_enc_param enc_inparam; + u32 opus_count = 0; + u32 pcm_count = 0; + if(opus_remain_size)//有剩余数据,先复制剩余数据 + { + memcpy(pcm_data,opus_remain_buf,opus_remain_size); + } + memcpy(pcm_data+opus_remain_size,AI_VC_send_queue_data.data,AI_VC_send_queue_data.len); + pcm_count = opus_remain_size+AI_VC_send_queue_data.len; + opus_remain_size = 0; + if(opus_data) + { + enc_inparam.input = (int16_t*)(pcm_data);//PCM数据 + enc_inparam.input_size = pcm_count; + enc_inparam.output = (int8_t*)opus_data; + enc_inparam.outbuffer_size = AI_VC_send_queue_data.len; + ret = aic_opus_encode(&enc_inparam); + if(enc_inparam.consumed_size= VC_State_TTSStart)//要关闭播放声音 { @@ -917,10 +1095,12 @@ static void AI_VC_1S_timeout(void *param) VC_END_play_timerout --; if(VC_END_play_timerout<=0) { - //bk_msg_printf("VC_END_play_timerout1=%d",VC_END_play_timerout); - VC_state = VC_State_Listening;//重新开始了 + if(VC_mode == 0) + VC_state = VC_State_Listening;//重新开始了 + else + AI_AMP_MSG_put(0,0,VC_CLOSE); //AI_AMP_MSG_put(0,0,VC_RECORD_START);//开启录音 - //bk_msg_printf("VC_END_play_timerout2=%d",VC_END_play_timerout); + bk_msg_printf("VC_END_play_timerout=%d",VC_END_play_timerout); } } if(AI_VC_play_queue) @@ -937,20 +1117,27 @@ void AI_key_press(void) VC_state = VC_State_None; VC_record_Start() ; AI_VC_start(); + + } void AI_key_release(void) { + bk_printf("AI_key_release"); } void AI_key_long_press(void) { + AI_VC_Close(); bk_printf("AI_key_long_press"); } void pwk_key_release(void) { bk_printf("pwk_key_release"); - AI_VC_Close(); + if(VC_mode == 1)//长按模式 + AI_VC_send_audio_completed(); + } + void AI_VC_start(void) { int ret = 0; @@ -977,6 +1164,55 @@ void AI_VC_start(void) AOS_AUTO_ACTIVATE, AOS_BE_PERIOD); aic_assert(AI_VC_1S_timer); } + if(inbound_attributes_format == inbound_attributes_format_OPUS) + { + //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"); + return ; + } + opus_encoder_h->channel_cnt = 1; + opus_encoder_h->sample_rate = 16000; + opus_encoder_h->period_ms = OPUS_PERIOD_20_MS; + opus_encoder_h->bitrate = 16000; + ret = aic_opus_init_encoder(opus_encoder_h); + if (ret) + { + bk_printf("aic_opus_init_encoder error"); + return ; + } + //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"); + return; + } + opus_decoder_h->channel_cnt = 1; + opus_decoder_h->sample_rate = 16000; + ret = aic_opus_init_decoder(opus_decoder_h); + if (ret) + { + bk_printf("aic_opus_init_decoder error"); + return ; + } + + //opus_decoder_h = opus_decoder_create(16000, 1, &err); + } + } + + + VC_record_Start(); VC_Play_Start();//音频调试1 websocket_connect_VC();//音频调试1 @@ -1058,6 +1294,28 @@ void AI_VC_Close(void) AI_VC_1S_timer = NULL; } close_timerout = 0; + if(inbound_attributes_format == inbound_attributes_format_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; + } + } + app_audio_stop(APP_AUDIO_TYPE_STREAM_DUPLEX, NULL);//要在销毁线程之后 } aos_status AI_AMP_MSG_put(const char *data,u32 len,AI_AMP_MSG_Type MSG_Type) @@ -1101,6 +1359,7 @@ static void AI_AMP_2_5_task(void *thread_input)//做逻辑线程 bk_printf("AI_AMP_2_5_init 等待注网..... \n"); aos_sleep(1000); } + active_md5_sign_demo(); aic_network_enable_pdp_nic_capdump();//打开网络调试log char *tts_str = "你好!我是小瑞"; VC_TTS_Play(tts_str);//开启vc播放tts @@ -1181,6 +1440,8 @@ int AI_AMP_2_5_init(void) ai_uart_handle = uart_open(1); aic_assert(ai_uart_handle); + + /* change baudrate */ uart_set_baud_rate(ai_uart_handle, 921600); //创建AI_AMP_task队列 diff --git a/2.code/aicos/app/AI_AMP_2_5/CMakeLists.txt b/2.code/aicos/app/AI_AMP_2_5/CMakeLists.txt index d13ab5a..e7ef7c5 100644 --- a/2.code/aicos/app/AI_AMP_2_5/CMakeLists.txt +++ b/2.code/aicos/app/AI_AMP_2_5/CMakeLists.txt @@ -9,9 +9,77 @@ aic_library_sources_ifdef( ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/stream_play.c ${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 + + +) +#归芯原厂库opus库 +aic_library_import( + CONFIG_APP_AI_AMP_2_5 + ${AIC_SOURCE_ROOT}/app/AI_AMP_2_5/opus/guixin/libopus.a +) +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/ -) \ No newline at end of file +) diff --git a/2.code/aicos/app/AI_AMP_2_5/bk_key.c b/2.code/aicos/app/AI_AMP_2_5/bk_key.c index 363bc7a..7b9d59f 100644 --- a/2.code/aicos/app/AI_AMP_2_5/bk_key.c +++ b/2.code/aicos/app/AI_AMP_2_5/bk_key.c @@ -54,10 +54,11 @@ static int32_t bk_kpc_callback(void *p_param, uint32_t size) break; case KPC_KEY_EVENT_LONGKEY_RELEASE: - if (key_arr->key[i].key_value == 2) { - bk_printf("[2]AI_key_long_press"); - } - + if (key_arr->key[i].key_value == 0) {//AI键 + AI_AMP_MSG_put(0, 0, AI_KEY_RELEASE); + }else if(key_arr->key[i].key_value == 1) {//PWK键 + AI_AMP_MSG_put(0, 0, PWK_KEY_RELEASE); + } // bk_printf("[%d]AI_key_long_press",key_arr->key[i].key_value); diff --git a/2.code/aicos/app/AI_AMP_2_5/dev_authentication.c b/2.code/aicos/app/AI_AMP_2_5/dev_authentication.c new file mode 100644 index 0000000..2abe635 --- /dev/null +++ b/2.code/aicos/app/AI_AMP_2_5/dev_authentication.c @@ -0,0 +1,84 @@ +//设备鉴权 + +#define AIC_THIS_FILE 0x888899 +#include +#include +#include +#include +#include "app_msg.h" +#include "aic_net_pdp_mgr.h" +#include "aic_network_pcap.h" + +#include "cJSON.h" +#include +#include "aic_osa.h" +#include "AI_AMP_2_5.h" +#include "mbedtls/base64.h" +#include "mbedtls/md5.h" +static char * dev_key = "uKLrChwrxA1LklgBc3VwawYjUkbT3BgX" ; +static char * dev_pid = "cqxJZi5CNgzjS3mX21Zw"; +//激活用的md5签名 +static int active_md5_sign(const char *dev_id,const char *pid,const char *timestamp,const char *productSecret,char*md5_str) +{ + if(strlen(dev_id)>256) + return -1; + if(strlen(pid)>256) + return -2; + if(strlen(productSecret)>256) + return -3; + if(strlen(timestamp)>256) + return -4; + char md5_buf[16]={0}; + char *sign_buf = malloc(1024); + + if(!sign_buf) + return -10; + memset(sign_buf,0,1024); + int sign_len = 0; + strcpy(sign_buf,dev_id); + sign_len = strlen(sign_buf); + + strcpy(sign_buf+sign_len,pid); + sign_len = strlen(sign_buf); + + strcpy(sign_buf+sign_len,timestamp); + sign_len = strlen(sign_buf); + + strcpy(sign_buf+sign_len,productSecret); + sign_len = strlen(sign_buf); + bk_printf("sign_buf:%s",sign_buf); + + + mbedtls_md5_context ctx; + + // 初始化MD5上下文 + mbedtls_md5_init(&ctx); + + // 开始计算MD5哈希 + mbedtls_md5_starts(&ctx); + // 更新要计算哈希的数据 + mbedtls_md5_update(&ctx, (const unsigned char *)sign_buf, sign_len); + + // 完成哈希计算 + mbedtls_md5_finish(&ctx, md5_buf); + // 清理MD5上下文 + mbedtls_md5_free(&ctx); + for (int i = 0; i < 16; i++) { + sprintf(&md5_str[i * 2], "%02x", md5_buf[i]); + } + md5_str[32] = '\0'; + + free(sign_buf); + return 0; +} + +void active_md5_sign_demo(void) +{ + const char *dev_id ="1234567890";//imei号 + const char *timestamp = "1717752535000";//时间戳 + const char *pid = "Amg1HJ3dJkX3kLiLPNFg";//PID + const char *productSecret = "productSecret";//密钥 + char md5_buf[33]={0}; + active_md5_sign(dev_id,pid,timestamp,productSecret,md5_buf); + bk_printf("md5_buf:%s",md5_buf); +} \ No newline at end of file diff --git a/2.code/aicos/app/AI_AMP_2_5/dev_authentication.h b/2.code/aicos/app/AI_AMP_2_5/dev_authentication.h new file mode 100644 index 0000000..c600e06 --- /dev/null +++ b/2.code/aicos/app/AI_AMP_2_5/dev_authentication.h @@ -0,0 +1,6 @@ + +#ifndef __DEV_AUTHENTICATION_H__ +#define __DEV_AUTHENTICATION_H__ +void active_md5_sign_demo(void); + +#endif \ No newline at end of file