#define AIC_THIS_FILE 0x888888
-#define SUPPORT_OPUS 1
+
#include <aic_errno.h>
#include <aic_init.h>
#include <aic_osa_ex.h>
#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;
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);
//打开录音
strcpy(imei,vc_cfg.dev_imei);
return 0;
}
+#if (BK_LOG_CFG==BK_LOG_UART)
int bk_printf(const char *format, ...)
{
int ret=0;
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, ...)
{
{
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);
}
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;//对话模式
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)
{
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,"信号"))
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);
// 创建 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);
// 创建 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");
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);
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 )
{
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);
}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\""))
{
}
- 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 )//时间间隔短,认为是一次对话,拼接内容
{
}
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\""))//扣子报错
{
- //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)//报错,关闭连接
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)//录音线程
{
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);
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);
//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;
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)
//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)//缓存够
{
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;
}
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();
}
}
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--)
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
{
{
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;
}
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)
}
-
- 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;
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);
{
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;
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)
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);
}
//打开音频播放
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);
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);
}
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)
{
// 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();
}
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)
{
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;
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
}
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)
{
AI_VC_Close();
play_audio_file("C:/xinhaoruo1.mp3");
- }
+ }else
+ AI_VC_stata = 1;
return ret;
}
char AI_VC_Close_lock = 0;
// 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!!!!!!!!!!!!");
//销毁录音线程
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)
{
AI_ASR_str =NULL;
}
//app_logi("app_audio_stop2");
-
+ AI_VC_stata = 0;
AI_VC_Close_lock = 0;
}
}
}
+ 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)//做逻辑线程
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 --)
{
//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);
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://重启
#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
{
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
${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
)
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
)
--- /dev/null
+
+#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
--- /dev/null
+#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
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://按下
--- /dev/null
+//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
--- /dev/null
+#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
char *protocol;
char *host;
int port;
+ char port_str[7];
char *path;
char *query;
int error;
aic_free(temp_url_t);
return result;
}
+
result.port = atoi(colon_port + 1);
if (!result.port) {
set_url_error(&result, "Invalid port number");
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);
// 解析路径和查询字符串
// 发送 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;
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;
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);
}
}
-
+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×tamp=1750406765243&token=9542143a532adc10ec6ee530cd1824d53b";
+ // char *url = "http://dmp.raisound.com/bz-mp-api/sv/vad/auth/token?nonceStr=abc&sign=3470327e8eee163f00d5f54cc936d32595189b16d1e89c2b50155b80227c85d0×tamp=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
+
// 发送 WebSocket 消息
int send_websocket_message(WebSocketClient *client, const unsigned char *message, size_t message_len, WebSocketMessageType type) ;
-
+int bk_websocket_demo(void);
#endif
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
--- /dev/null
+#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
--- /dev/null
+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