123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508 |
- #include "includes.h"
- #include "nwy_audio_api.h"
- #define THREAD_AUDIO_STACK_SIZE (1024*10)
- nwy_osiThread_t *learnRecThread=NULL;
- nwy_osiThread_t *learnPlyThread=NULL;
- unsigned char recPcm[320];
- bool recoderStatus=false;
- LEARN_REC_DEF learnAudio={NULL};
- typedef struct{
- unsigned short maxVolume;//最大音量
- float avSpeed;//录音平均语速
- int64_t time;//记录录音时长
- unsigned char charactorNum;//单词个数
- }LEARN_REC_RESULT_DEF;//录音结果
- LEARN_REC_RESULT_DEF recordResult;
- static void learnRecTask(void *param);
- static void processRecData(void);
- static int recordDataCb(unsigned char *pcm, unsigned int len);
- static void pcmVolProcess(unsigned char *pcm, unsigned int len);
- static void initRecResult(unsigned char charaNum){
- recordResult.maxVolume=0;
- recordResult.avSpeed=0;
- recordResult.time=nwy_get_ms();
- recordResult.charactorNum=charaNum;
- }
- static void recordResultMake(void){
- int64_t time;
- float tmp;
- time=nwy_get_ms();
- time = time-recordResult.time;
- if(time<1) time=1;//最小为1秒
- tmp=recordResult.charactorNum;
- recordResult.avSpeed = 1000*tmp/time;//单词/秒
- MSG_INFO(1, "Chara speed:%.1f,num:%d,t:%lldms", recordResult.avSpeed, recordResult.charactorNum,time);
- }
- /*获取本次录音过程中的最大音量值*/
- unsigned short learnGetRecordMaxVolume(void){
- //return (recordResult.maxVolume*LEV_NUM/0x7FFF);
- return recordResult.maxVolume;
- }
- #define SPEED_FACTOR 4
- /*获取本次录音的语速:单词/秒*/
- float learnGetRecordRecSpeed(void){
- float speedscore=getLearnSpeedParam()*recordResult.avSpeed*SPEED_FACTOR;
- if(speedscore>10) speedscore=10;
- return speedscore;
- }
- bool learnStartRecord(unsigned char charaNum){
- //初始化编码器
- #ifdef ENABLE_ENABLE_AMRNB
- if(AMRC_INIT_OK != wamr_encoder_init()){
- MSG_ERR(1, "wamr encoder init failed");
- goto R_END;
- }
- if(learnAudio.pcm==NULL) learnAudio.pcm=(unsigned char *)malloc((1+FRAME_PER_SIZE)*MAX_FRAMES_TOTAL);
- #endif
- #ifdef ENABLE_ENABLE_SPEEX
- int quality=FRAME_QULITY;
- int ret;
- learnAudio.speexCt = speex_encoder_init(speex_lib_get_mode(SPEEX_MODEID_NB));
- if(NULL==learnAudio.speexCt){
- MSG_ERR(1, "speex encoder init failed");
- goto R_END;
- }
- ret=speex_encoder_ctl(learnAudio.speexCt, SPEEX_SET_QUALITY, &quality);
- if(ret!=0){
- MSG_ERR(1, "speed encoder ctl failed");
- goto R_END;
- }
- speex_bits_init(&learnAudio.bits);
- if(learnAudio.pcm==NULL) learnAudio.pcm=(unsigned char *)malloc((FRAME_PER_SIZE)*MAX_FRAMES_TOTAL);
- #endif
- if(NULL==learnAudio.pcm){
- MSG_ERR(1, "recorder malloc buf failed");
- goto R_END;
- }
- MSG_INFO(1, "[mem malloc]%x",learnAudio.pcm);
- //创建线程去处理接收到的录音数据
- learnRecThread=nwy_create_thread("learnRecTask", learnRecTask, NULL, NWY_OSI_PRIORITY_NORMAL, THREAD_AUDIO_STACK_SIZE, 6);
- if(learnRecThread==NULL){
- MSG_ERR(1, "record rec thread err");
- goto R_END;
- }
- initRecResult(charaNum);
- if(NWY_SUCESS != nwy_audio_recorder_open(recordDataCb)){
- MSG_ERR(1, "recorder open failed");
- goto R_END;
- }
- if(NWY_SUCESS != nwy_audio_recorder_start()){
- MSG_ERR(1, "recorder start failed");
- nwy_audio_recorder_close();
- goto R_END;
- }
- appSleepCtl(ASLEEP_LEARN, 1);
- learnAudio.frameNum=0;
- learnAudio.frameSize=0;
- recoderStatus=true;
- return true;
- R_END:
- #ifdef ENABLE_ENABLE_AMRNB
- wamr_encoder_uninit();
- if(NULL != learnAudio.pcm){
- free(learnAudio.pcm);
- learnAudio.pcm=NULL;
- }
- #endif
- #ifdef ENABLE_ENABLE_SPEEX
- if(learnAudio.speexCt!=NULL){
- speex_encoder_destroy(learnAudio.speexCt);
- learnAudio.speexCt=NULL;
- }
- #endif
- if(NULL != learnRecThread){
- threadSendEvent(learnRecThread,OHPOC_EVENT_LEARN,0,NULL,NULL);//退出
- }
- }
- /*停止录音*/
- void learnStopRecord(void){
- if(recoderStatus==false) return;
- nwy_audio_recorder_stop();
- nwy_audio_recorder_close();
- recoderStatus=false;
- appSleepCtl(ASLEEP_LEARN, 0);
- recordResultMake();
- }
- /*录音接收处理线程*/
- static void learnRecTask(void *param){
- nwy_osiEvent_t event = {};
- MSG_INFO(1, "learnRecTask start");
- for(;;){
- nwy_wait_thead_event(nwy_get_current_thread(), &event,0);
- if(event.id==OHPOC_EVENT_LEARN){
- if(event.param1==0) break;
- else if(event.param1==1) processRecData();
- }
- }
- MSG_INFO(1, "learnRecTask exit");
- learnRecThread=NULL;
- nwy_exit_thread();
- }
- /*处理具体的录音数据*/
- static void processRecData(void){
- unsigned short outlen;
- unsigned int i;
- unsigned char *pcm=recPcm;
- pcmVolProcess(recPcm, 320);//计算平均音量
- #ifdef ENABLE_ENABLE_AMRNB
- unsigned char tbuf[100];
- int ret;
- ret=wamr_encoder_encode_frame((short *)pcm, 160, tbuf,sizeof(tbuf), &outlen, UMR122);
- if(AMRC_CODEC_SUCC != ret){
- MSG_WARN(1, "amrnb encode err");
- return 0;
- }
- if(outlen != FRAME_PER_SIZE){
- MSG_WARN(1, "amrnb encode size unfix:%d", outlen);
- return 0;
- }
- #endif
- #ifdef ENABLE_ENABLE_SPEEX
- #define T_FRAME_SIZE 160
- float input[T_FRAME_SIZE];
- short tmp;
- char tbuf[70];//不小于62
- for(i=0;i<T_FRAME_SIZE;i++){
- tmp=pcm[2*i+1];tmp <<= 8;
- tmp |= pcm[2*i];
- input[i]=tmp;
- }
- speex_bits_reset(&learnAudio.bits);
- speex_encode(learnAudio.speexCt, input, &learnAudio.bits);
- outlen=speex_bits_write(&learnAudio.bits, tbuf, sizeof(tbuf));
- #endif
- if(learnAudio.frameNum<MAX_FRAMES_TOTAL){
- if(learnAudio.frameNum==0) learnAudio.frameSize=outlen;
- #ifdef ENABLE_ENABLE_AMRNB
- i=learnAudio.frameNum*(1+FRAME_PER_SIZE);
- learnAudio.pcm[i++]=FRAME_PER_SIZE;
- #endif
- #ifdef ENABLE_ENABLE_SPEEX
- if(learnAudio.frameNum==0) learnAudio.pcm[0]=FRAME_PER_SIZE;//第一字节表示后面的音频帧长度(每帧)
- i=1+learnAudio.frameNum*(0+FRAME_PER_SIZE);
- #endif
- memcpy(learnAudio.pcm+i, tbuf, FRAME_PER_SIZE);
- if(++learnAudio.frameNum>=MAX_FRAMES_TOTAL){
- MSG_WARN(1, "record max buf, stop rec");
- learnRecSetStatus(LEARN_REC_OT);
- }
- }
- }
- //释放录音时的资源
- void learnRecordFree(void){
- if(NULL != learnRecThread){
- threadSendEvent(learnRecThread,OHPOC_EVENT_LEARN,0,NULL,NULL);//退出
- }
- #ifdef ENABLE_ENABLE_AMRNB
- wamr_encoder_uninit();
- #endif
- #ifdef ENABLE_ENABLE_SPEEX
- speex_encoder_destroy(learnAudio.speexCt);
- speex_bits_destroy(&learnAudio.bits);
- #endif
- }
- /*释放已申请的临时缓存空间*/
- void learnRecordBufRelease(void){
- if(learnAudio.pcm==NULL) return;
- MSG_INFO(1, "[mem free]%x",learnAudio.pcm);
- free(learnAudio.pcm);
- learnAudio.pcm=NULL;
- }
- /*录音回调,不能在里面做太多事件*/
- static int recordDataCb(unsigned char *pcm, unsigned int len){
- if(len != 320) return;
- memcpy(recPcm, pcm, len);
- if(NULL != learnRecThread)
- threadSendEvent(learnRecThread, OHPOC_EVENT_LEARN, 1, NULL, NULL);//通知线程处理数据
- return 0;
- }
- #ifdef SAVE_PCM_SD
- int sdFd=-1;
- void pcmFileOpen(void){
- int fd;
- char file[50];
- if(sdFd>0) return;
- snprintf(file, sizeof(file), "%s/pcm_low.rec", SD_TOKEN);
- fd = nwy_sdk_fopen(file, NWY_CREAT | NWY_RDWR|NWY_TRUNC);//清0式
- if(fd<0){
- MSG_INFO(1,"open failed");
- return;
- }
- sdFd=fd;
- MSG_INFO(1,"open ok");
- }
- void pcmFileClose(void){
- if(sdFd<0){
- MSG_INFO(1,"no need close");
- return;
- }
- nwy_sdk_fclose(sdFd);
- MSG_INFO(1,"close ok");
- sdFd=-1;
- }
- void pcmSaveData(unsigned char *pcm, int len){
- if(sdFd<0){
- MSG_INFO(1,"not open");
- return;
- }
- nwy_sdk_fwrite(sdFd, pcm, len);
- }
- #endif
- static void pcmVolProcess(unsigned char *pcm, unsigned int len){
- #ifdef SAVE_PCM_SD
- pcmSaveData(pcm,len);
- #else
- //对语音数据进行平均音量分析,分析方法为累加,并求平均值,静音时是为0的值
- #define VOL_SUM_FRAME 5
- #define VOL_SHORT_LEV (VOL_SUM_FRAME*160)
- short *ptr=(short *)pcm;
- int i;
- static unsigned short frameVolNum=0;
- unsigned int sum=0,tmp;
- static unsigned int pcmSum=0;
- //char info[60];
- if(len != 320) return;
- for(i=0;i<160;i++){
- tmp=abs(ptr[i]);
- pcmSum += tmp;
- }
- if(++frameVolNum>=VOL_SUM_FRAME){
- sum=pcmSum/VOL_SHORT_LEV;
- //snprintf(info, sizeof(info), "[0]{%d}",sum);
- //nwy_usb_serial_send(info, strlen(info));
- //MSG_INFO(1, "pcm:%lu,%lu", sum,pcmSum);
- sum *= (LEV_NUM-0);
- sum /=4000;//10000;
- //MSG_INFO(1,"===%d",sum);
- if(sum >(LEV_NUM-0)) sum = LEV_NUM-0;
- learnRecSetVol(sum);
- if(sum > recordResult.maxVolume){
- recordResult.maxVolume=sum;//计算每一帧的最大音量
- //MSG_INFO(1,"=======%d", sum);
- }
- pcmSum=0;
- frameVolNum=0;
- }
- #endif
- }
- static int player_cb(nwy_player_status state){
- MSG_INFO(1,"player_cb state=%d", state);
- if(0==state){//播放完毕了
- MSG_INFO(1,"pcm play finished");
- }
- }
- static void learnPlayStop(void){
- nwy_audio_player_stop();
- nwy_audio_player_close();
- }
- static bool learnPlayStart(void){
- if(NWY_SUCESS!=nwy_audio_player_open(player_cb)) return false;
- else return true;
- }
- void spkControl(bool status){
- if(true==status) sutPocStatus.spk=1;
- else sutPocStatus.spk=0;
- paControl(status);
- }
- LEARN_PLY_ENUM learnPlayStatus;
- static void learnPlyTask(void *param){
- unsigned char *pcmPtr;
- float output[T_FRAME_SIZE];
- short out[T_FRAME_SIZE];
- short tmp,i;
- unsigned char audioType;
- unsigned char vFileBuf[FRAME_PER_SIZE];
- unsigned int addr;
-
- MSG_INFO(1, "learnPlyTask start");
- appSleepCtl(ASLEEP_LEARN, 1);
- spkControl(true);
- audioType=learnAudio.playType;
- learnAudio.plyNum=0;
-
- if(audioType==0){//播放临时录音
- while(learnAudio.plyNum<learnAudio.frameNum){
- if(learnAudio.stopPlay==true) break;
- pcmPtr=learnAudio.pcm+1+learnAudio.plyNum*learnAudio.frameSize;
- //解码
- speex_bits_reset(&learnAudio.bits);
- speex_bits_read_from(&learnAudio.bits, pcmPtr, learnAudio.frameSize);
- speex_decode(learnAudio.speexCt, &learnAudio.bits, output);
- for(i=0;i<T_FRAME_SIZE;i++) out[i]=output[i];
- pcmPtr=(unsigned char *)out;
- //播放
- if(NWY_SUCESS != nwy_audio_player_play(pcmPtr, 320)){
- MSG_ERR(1, "frame 1 play error");
- learnPlayStatus=LEARN_PLY_FAILED;//播放出错
- break;
- }
- //播放完一帧
- learnAudio.plyNum++;
- }
- if(learnAudio.plyNum==learnAudio.frameNum) learnPlayStatus=LEARN_PLY_DONE;//播放成功,结束
- }else{//播放本地文件
- for(;;){
- if(learnAudio.fd<=0){
- MSG_ERR(1, "audio fd invalid");
- learnPlayStatus=LEARN_PLY_FAILED;
- break;
- }
- if(learnAudio.stopPlay==true) break;
- addr=4+1+learnAudio.plyNum*learnAudio.frameSize;
- nwy_sdk_fseek(learnAudio.fd, addr, NWY_SEEK_SET);
- nwy_sdk_fread(learnAudio.fd, vFileBuf, learnAudio.frameSize);
- //解码
- speex_bits_reset(&learnAudio.bits);
- speex_bits_read_from(&learnAudio.bits, vFileBuf, learnAudio.frameSize);
- speex_decode(learnAudio.speexCt, &learnAudio.bits, output);
- for(i=0;i<T_FRAME_SIZE;i++) out[i]=output[i];
- pcmPtr=(unsigned char *)out;
- //播放
- if(NWY_SUCESS != nwy_audio_player_play(pcmPtr, 320)){
- MSG_ERR(1, "frame 2 play error");
- learnPlayStatus=LEARN_PLY_FAILED;//播放出错
- break;
- }
- //播放完一帧
- if(++learnAudio.plyNum>=learnAudio.frameNum){
- learnPlayStatus=LEARN_PLY_DONE;//播放成功,结束
- break;
- }
- }
- }
- //释放资源
- learnPlayStop();
- if(learnAudio.speexCt!=NULL){
- speex_decoder_destroy(learnAudio.speexCt);
- speex_bits_destroy(&learnAudio.bits);
- learnAudio.speexCt=NULL;
- }
- if(learnAudio.fd>0){
- nwy_sdk_fclose(learnAudio.fd);
- learnAudio.fd=-1;
- }
- MSG_INFO(1, "learnPlyTask exit");
- learnPlyThread=NULL;
- spkControl(false);
- appSleepCtl(ASLEEP_LEARN, 0);
- nwy_exit_thread();
- }
- void learnPlayAudio(unsigned char type, const char *fname){
- char file[50];
- unsigned char size;
- int tmp=1;
- learnAudio.playType=type;
- if(NULL!=learnPlyThread){//使用线程播放吧
- MSG_INFO(1, "learnPlyTask is busy");
- return;
- }
- if(type != 0){//播放本地文件
- //只读方式打开文件
- snprintf(file, sizeof(file), "%s/%s.rec", SD_TOKEN, fname);
- learnAudio.fd=nwy_sdk_fopen(file, NWY_RDONLY);
- if(learnAudio.fd<0){
- MSG_ERR(1, "open %s.rec to play failed", fname);
- goto P_EXIT;
- }
- nwy_sdk_fread(learnAudio.fd, (unsigned char *)&learnAudio.frameNum, 4);
- nwy_sdk_fseek(learnAudio.fd, 4, NWY_SEEK_SET);
- nwy_sdk_fread(learnAudio.fd, &size, 1);
- learnAudio.frameSize=size;
- if(learnAudio.frameNum > MAX_FRAMES_TOTAL || learnAudio.frameSize != FRAME_PER_SIZE){
- MSG_ERR(1, "%s.rec header err:%d,%d", learnAudio.frameNum,learnAudio.frameSize);
- goto P_EXIT;
- }
- }
- //播放临时缓存中的语音/本地文件都需要初始化以下操作
- learnAudio.stopPlay=false;
- learnPlayStatus=LEARN_PLY_IDLE;
- //解码初始化
- learnAudio.speexCt=speex_decoder_init(speex_lib_get_mode(SPEEX_MODEID_NB));
- if(NULL==learnAudio.speexCt){
- MSG_ERR(1, "play decoder init failed");
- goto P_EXIT;
- }
- if(0!=speex_decoder_ctl(learnAudio.speexCt, SPEEX_SET_ENH, &tmp)){
- MSG_ERR(1, "player decoder ctl failed");
- goto P_EXIT;
- }
- speex_bits_init(&learnAudio.bits);
- //打开播放设备
- if(true!=learnPlayStart()){
- MSG_ERR(1, "play open failed");
- goto P_EXIT;
- }
- //申请线程
- learnPlyThread=nwy_create_thread("learnPlyTask", learnPlyTask, NULL, NWY_OSI_PRIORITY_NORMAL, THREAD_AUDIO_STACK_SIZE, 4);
- if(learnPlyThread==NULL){
- MSG_ERR(1, "play thread err");
- goto P_EXIT;
- }
- learnPlayStatus=LEARN_PLY_BUSY;
- MSG_INFO(1, "start play process ok");
- return;
- P_EXIT:
- MSG_INFO(1, "learnPlayAudio exit:%d",type);
- learnPlayStatus=LEARN_PLY_PRE_ERR;//播放准备失败
- if(learnAudio.speexCt != NULL){
- speex_decoder_destroy(learnAudio.speexCt);
- speex_bits_destroy(&learnAudio.bits);
- learnAudio.speexCt=NULL;
- }
- if(learnAudio.fd>0){
- nwy_sdk_fclose(learnAudio.fd);
- learnAudio.fd=-1;
- }
- if(learnPlyThread != NULL) learnPlayStop();
- }
- LEARN_PLY_ENUM learnPlyGetResult(void){return learnPlayStatus;}
- //获取当前播放的类型:0 播放的是临时录音 1 播放的是本地录音
- unsigned char learnGetAudioType(void){return learnAudio.playType;}
- void learnStopPlaying(void){
- learnAudio.stopPlay=true;
- }
- /*将临时语音保存到本地.rec文件中,覆盖式*/
- void recordSaveTmpToLocal(char *fileName){
- char file[50];
- int fd;
- unsigned int total;
-
- snprintf(file, sizeof(file), "%s/%s.rec", SD_TOKEN, fileName);
- fd = nwy_sdk_fopen(file, NWY_CREAT | NWY_RDWR|NWY_TRUNC);//清0式
- if(fd<0){
- MSG_WARN(1, "Save record file fopen failed,%s", fileName);
- return;
- }
- memcpy(file, (unsigned char *)&learnAudio.frameNum, 4);
- //memcpy(file+4, (unsigned char *)&learnAudio.frameSize, 2);
- nwy_sdk_fwrite(fd, file, 4);
- total=learnAudio.frameNum*learnAudio.frameSize+1;
- nwy_sdk_fwrite(fd, learnAudio.pcm, total);
- nwy_sdk_fclose(fd);
- MSG_INFO(1, "Save task %s:%d bytes done", fileName, total+4);
- }
- unsigned char *learnGetTmpAudioBuf(void){
- return learnAudio.pcm;
- }
- unsigned int learnGetTmpAudioLength(void){
- return learnAudio.frameNum*learnAudio.frameSize;
- }
|