基于树莓派的语音机器人
近年来语音识别发展迅速也带动了人工智能的发展。曾经渴望自己做一个机器人,但是无奈,心有余而力不足,经过多年的积累,小白的我也能用站着巨人的肩膀上玩下机器人了。
准备工作:树莓派,音频模块,stm32单片机,百度语音识别接口,喇叭。
整体思路:
1. 由于树莓派没有ADC模块,所以这里借助于stm32的ADC模块来实现将语音信号转换成数字信号,然后通过串口传输 到树莓派你中,树莓派你将数据组装成wave文件,便于语音识别。
2.通过http协议将组装的语音文件上传到百度语音识别平台进行识别。文档说明(免费调用)
3.根据识别结果做出相应的处理。
4.对于需要播放语音时,根据百度语音合成接口合成语音然后使用mplayer播放出来。mplayer安装参考博客
部分代码:
将音频转换成wave文件
#include#include #include #include #include #include #include #include #include #include"listen.h" //gcc-ouartuart.c-lwiringPi typedefstructWAV_FormatWAVHEADER; #defineMAX_LISTEN_SIZES1024*70//定义接收数据的大小 #definebty460800//串口的波特率 structlisten*listenUart() { intfd,file; charbuff,buff2; structlisten*liste=(structlisten*)malloc(sizeof(structlisten)); unsignedshortsize; unsignedshort*music,temp=0; unsignedshortmax=0,min=0; char*result=NULL;//存储最后的返回值 intindex=0,i=0; charstop=1; WAVHEADERwavHead; music=(unsignedshort*)malloc(MAX_LISTEN_SIZES*2); result=(char*)malloc(MAX_LISTEN_SIZES*2+sizeof(WAVHEADER)); if(wiringPiSetup()<0)returnNULL; if((fd=serialOpen("/dev/ttyAMA0",bty))<0) { returnNULL; printf("serialerr\n"); } //file=open("abc.wav",O_RDWR|O_CREAT); printf("oepnsuccess\n"); //serialPrintf(fd,"HelloWorld!!!"); //需要对音频信号作出处理,当大于或者阈值时开始统计,知道录制完成 intcountTotal=0; intcountNumber=1000;//统计个数 intcountMax=2860;//最大值 intcountMin=2840;//最小值 intstartCount=1; while(1) { if(index==MAX_LISTEN_SIZES) { break; } buff=serialGetchar(fd); buff2=serialGetchar(fd); if((buff2&0x0F0)!=0) { buff2=serialGetchar(fd); } else { size=buff2; size=size<<8; size=(size&0xFF00)|(buff&0xFF); music[index]=size; if(startCount==1) { countTotal=countTotal+size; if(index>=countNumber) { inttemp=countTotal/(countNumber+1); if(temp>countMax||temp max) { max=temp; } if(temp length=sizeof(WAVHEADER)+MAX_LISTEN_SIZES*2; liste->data=result; returnliste; }
将音频识别成文字
#include"convertText.h" staticBuffer*listen_buff2=NULL; size_tlisten_getData2(void*ptr,size_tsize,size_tnmemb,void*stream) { appendBuffer(listen_buff2,ptr,nmemb); returnnmemb; } intlistenText(char*result2) { listen_buff2=initBuffer(); structlisten*lsn=listenUart(); char*base; intfileLength=lsn->length; intresult=1; intbaseSize=(lsn->length/3)*4+(lsn->length%3)*2+1; base=(char*)malloc(baseSize); base64_encode(lsn->data,lsn->length,base); //发送请求 free(lsn->data); free(lsn); intcode=initToken(); if(code==1) { char*token=getToken(); ///开始创建json字符串 cJSON*root=cJSON_CreateObject(); cJSON_AddItemToObject(root,"format",cJSON_CreateString("wav")); cJSON_AddItemToObject(root,"rate",cJSON_CreateString("16000")); cJSON_AddItemToObject(root,"channel",cJSON_CreateString("1")); cJSON_AddItemToObject(root,"cuid",cJSON_CreateString("34-68-95-91-77-43")); cJSON_AddItemToObject(root,"token",cJSON_CreateString(token)); cJSON_AddItemToObject(root,"dev_pid",cJSON_CreateString("1537")); cJSON_AddItemToObject(root,"speech",cJSON_CreateString(base)); cJSON_AddItemToObject(root,"len",cJSON_CreateNumber(fileLength)); char*jsonParam=cJSON_PrintUnformatted(root); char*apiurl="http://vop.baidu.com/server_api"; CURL*curl; CURLcoderes; //ptr=curl_easy_escape(NULL,(char*)a,asize); curl=curl_easy_init(); structcurl_slist*headers=NULL; headers=curl_slist_append(headers,"Content-Type:application/json"); curl_easy_setopt(curl,CURLOPT_HTTPHEADER,headers); curl_easy_setopt(curl,CURLOPT_URL,apiurl); curl_easy_setopt(curl,CURLOPT_TIMEOUT,60); curl_easy_setopt(curl,CURLOPT_POST,1); //http://vop.baidu.com/server_api //CURLOPT_POSTFIELDS,CURLOPT_POSTFIELDSIZE curl_easy_setopt(curl,CURLOPT_POSTFIELDS,jsonParam); curl_easy_setopt(curl,CURLOPT_POSTFIELDSIZE,strlen(jsonParam)); curl_easy_setopt(curl,CURLOPT_WRITEFUNCTION,listen_getData2); curl_easy_setopt(curl,CURLOPT_FOLLOWLOCATION,1); res=curl_easy_perform(curl); curl_easy_cleanup(curl); cJSON_Delete(root); curl_slist_free_all(headers); free(token); free(jsonParam); if(res==CURLE_OK) { char*chars; char*tempresult=(char*)malloc(listen_buff2->length+1); memcpy(tempresult,listen_buff2->buff,listen_buff2->length); tempresult[listen_buff2->length]=0; cJSON*json; cJSON*item=NULL; cJSON*errCode; json=cJSON_Parse(tempresult); item=cJSON_GetObjectItem(json,"result"); errCode=cJSON_GetObjectItem(json,"err_no"); if(errCode->valueint!=0) { return-3; } chars=cJSON_GetArrayItem(item,0)->valuestring; strcpy(result2,chars); free(tempresult); cJSON_Delete(json); return0; } else { return-3; } } else { return-2; } return-1; }
主程序
#include#include #include"convertText.h" #include"mp3.h" #include"led.h" #include"say.h" //gcc-orobotrobot.omp3.oBuffer.obase64.otoken.ocJSON.olisten.oconvertText.oled.osay.o-lcurl-lm-lwiringPi-lmad voidsayChina(char*china) { intresp=initSay(china); printf("resp:%d\n",resp); if(resp==1) { inttte=playData("temp.mp3"); printf("tte:%d\n",tte); } } intmain() { chartext[100]={0}; sayChina("你好,我是小志,有什么可以为你服务"); while(1) { printf(";;;;;;;;"); intcode=listenText(text); if(code==0) { printf("result:%s\n",text); if(strstr(text,"播放音乐,")!=NULL||strstr(text,"打开音乐,")!=NULL) { sayChina("正在为你打开音乐"); musicPlayFile("mu.mp3"); } if(strstr(text,"打开灯,")!=NULL||strstr(text,"打开,")!=NULL) { sayChina("好的"); printf("正在打开"); ledOn(); } if(strstr(text,"关闭灯,")!=NULL||strstr(text,"关闭,")!=NULL||strstr(text,"完毕,")!=NULL) { sayChina("好的"); printf("正在关闭"); ledOff(); } if(strstr(text,"你叫什么")!=NULL||strstr(text,"你叫什么名字")!=NULL||strstr(text,"名字")!=NULL) { sayChina("我叫小志"); } if(strstr(text,"今天天气咋样")!=NULL||strstr(text,"天气")!=NULL) { sayChina("外面在下雨,有点冷"); } if(strstr(text,"中午好")!=NULL||strstr(text,"中午")!=NULL) { sayChina("好什么啊,我还没吃饭呢"); } if(strstr(text,"你多大了")!=NULL||strstr(text,"今年几岁")!=NULL||strstr(text,"几岁")!=NULL) { sayChina("我才出生,还没满月"); } } else { printf("error\n"); } } return0; }
这里只是贴出来部分程序,所有代码请查看 链接 希望能和大家一起交流下心得。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。