這篇文章將為大家詳細(xì)講解有關(guān)如何實(shí)現(xiàn)基于樹莓派的語音機(jī)器人,小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
創(chuàng)新互聯(lián)長期為超過千家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺(tái),與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為大城企業(yè)提供專業(yè)的網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站建設(shè),大城網(wǎng)站改版等技術(shù)服務(wù)。擁有10年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。
準(zhǔn)備工作:樹莓派,音頻模塊,stm32單片機(jī),百度語音識(shí)別接口,喇叭。
整體思路:
1. 由于樹莓派沒有ADC模塊,所以這里借助于stm32的ADC模塊來實(shí)現(xiàn)將語音信號(hào)轉(zhuǎn)換成數(shù)字信號(hào),然后通過串口傳 輸 到樹莓派你中,樹莓派你將數(shù)據(jù)組裝成wave文件,便于語音識(shí)別。
2. 通過http協(xié)議將組裝的語音文件上傳到百度語音識(shí)別平臺(tái)進(jìn)行識(shí)別。文檔說明(免費(fèi)調(diào)用)
3. 根據(jù)識(shí)別結(jié)果做出相應(yīng)的處理。
4. 對(duì)于需要播放語音時(shí),根據(jù)百度語音合成接口合成語音然后使用mplayer播放出來。mplayer安裝參考 博客
部分代碼:
將音頻轉(zhuǎn)換成wave文件
#include <stdio.h> #include <stdlib.h> #include <stdint.h> #include <wiringPi.h> #include <wiringSerial.h> #include <unistd.h> #include <fcntl.h> #include <sys/types.h> #include <sys/ioctl.h> #include "listen.h" //gcc -o uart uart.c -lwiringPi typedef struct WAV_Format WAVHEADER; #define MAX_LISTEN_SIZES 1024*70 //定義接收數(shù)據(jù)的大小 #define bty 460800//串口的波特率 struct listen*listenUart() { int fd,file; char buff,buff2; struct listen*liste=(struct listen*)malloc(sizeof(struct listen)); unsigned short size; unsigned short*music,temp=0; unsigned short max=0,min=0; char*result=NULL;//存儲(chǔ)最后的返回值 int index=0,i=0; char stop=1; WAVHEADER wavHead; music=(unsigned short*)malloc(MAX_LISTEN_SIZES*2); result=(char*)malloc(MAX_LISTEN_SIZES*2+sizeof(WAVHEADER)); if(wiringPiSetup() < 0)return NULL; if((fd = serialOpen ("/dev/ttyAMA0",bty))<0) { return NULL; printf("serial err\n"); } //file=open("abc.wav", O_RDWR|O_CREAT); printf("oepn success\n"); //serialPrintf(fd,"Hello World!!!"); //需要對(duì)音頻信號(hào)作出處理,當(dāng)大于或者閾值時(shí)開始統(tǒng)計(jì),知道錄制完成 int countTotal=0; int countNumber= 1000;//統(tǒng)計(jì)個(gè)數(shù) int countMax=2860;//最大值 int countMin=2840;//最小值 int startCount=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) { int temp=countTotal/(countNumber+1); if(temp>countMax||temp<countMin) { startCount=0; //開始錄音 printf(":::::%d\n",temp); index++; } else { printf("temp:%d\n",temp); index=0; } countTotal=0; } else { index++; } } else { index++; } } } serialClose(fd); printf("end\n"); //對(duì)音頻進(jìn)行放大處理 max=music[0]; min=music[0]; for(i=i;i<MAX_LISTEN_SIZES;i++){ temp=music[i]; if(temp>max) { max=temp; } if(temp<min) { min=temp; } } size=max-min; for(i=0;i<MAX_LISTEN_SIZES;i++) { music[i]=(unsigned short)((music[i]-min)*1.0*6000/size); } wavHead.ChunkID=0x46464952; /* "RIFF" */ wavHead.ChunkSize=sizeof(wavHead)+MAX_LISTEN_SIZES*2 -8; /* 36 + Subchunk2Size */ wavHead.Format=0x45564157; /* "WAVE" */ wavHead.Subchunk1ID=0x20746D66; /* "fmt " */ wavHead.Subchunk1Size=0x10; /* 16 for PCM */ wavHead.AudioFormat=0x01; /* PCM = 1*/ wavHead.NumChannels=0x01; /* Mono = 1, Stereo = 2, etc. */ wavHead.SampleRate=0x3E80; /* 8000, 44100, etc. */ wavHead.ByteRate=0x7D00; /* = SampleRate * NumChannels * BitsPerSample/8 */ wavHead.BlockAlign=0x02; /* = NumChannels * BitsPerSample/8 */ wavHead.BitsPerSample=0x10; /* 8bits, 16bits, etc. */ wavHead.Subchunk2ID=0x61746164; /* "data" */ wavHead.Subchunk2Size=MAX_LISTEN_SIZES*2; /* data size */ //返回?cái)?shù)據(jù)賦值 memcpy(result,(char*)&wavHead,sizeof(WAVHEADER)); memcpy(result+sizeof(WAVHEADER),(char*)music,MAX_LISTEN_SIZES*2); liste->length=sizeof(WAVHEADER)+MAX_LISTEN_SIZES*2; liste->data=result; return liste; }
將音頻識(shí)別成文字
#include "convertText.h" static Buffer *listen_buff2=NULL; size_t listen_getData2(void *ptr, size_t size, size_t nmemb, void *stream) { appendBuffer(listen_buff2,ptr,nmemb); return nmemb; } int listenText(char*result2) { listen_buff2=initBuffer(); struct listen*lsn=listenUart(); char*base; int fileLength=lsn->length; int result=1; int baseSize=(lsn->length/3)*4+(lsn->length%3)*2+1; base=(char*)malloc(baseSize); base64_encode(lsn->data,lsn->length,base); //發(fā)送請(qǐng)求 free(lsn->data); free(lsn); int code=initToken(); if(code==1) { char*token=getToken(); ///開始創(chuàng)建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; CURLcode res; // ptr = curl_easy_escape(NULL, (char *)a, asize); curl = curl_easy_init(); struct curl_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); return 0; } else { return -3; } } else { return -2; } return -1; }
主程序
#include<stdio.h> #include<string.h> #include "convertText.h" #include "mp3.h" #include "led.h" #include "say.h" //gcc -o robot robot.o mp3.o Buffer.o base64.o token.o cJSON.o listen.o convertText.o led.o say.o -lcurl -lm -lwiringPi -lmad void sayChina(char*china) { int resp=initSay(china); printf("resp:%d\n",resp); if(resp==1) { int tte=playData("temp.mp3"); printf("tte:%d\n",tte); } } int main() { char text[100]={0}; sayChina("你好,我是小志,有什么可以為你服務(wù)"); while(1) { printf(";;;;;;;;"); int code= 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,"關(guān)閉燈,")!=NULL||strstr(text,"關(guān)閉,")!=NULL||strstr(text,"完畢,")!=NULL) { sayChina("好的"); printf("正在關(guān)閉"); ledOff(); } if(strstr(text,"你叫什么")!=NULL||strstr(text,"你叫什么名字")!=NULL||strstr(text,"名字")!=NULL) { sayChina("我叫小志"); } if(strstr(text,"今天天氣咋樣")!=NULL||strstr(text,"天氣")!=NULL) { sayChina("外面在下雨,有點(diǎn)冷"); } if(strstr(text,"中午好")!=NULL||strstr(text,"中午")!=NULL) { sayChina("好什么啊,我還沒吃飯呢"); } if(strstr(text,"你多大了")!=NULL||strstr(text,"今年幾歲")!=NULL||strstr(text,"幾歲")!=NULL) { sayChina("我才出生,還沒滿月"); } } else { printf("error\n"); } } return 0; }
關(guān)于“如何實(shí)現(xiàn)基于樹莓派的語音機(jī)器人”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
當(dāng)前題目:如何實(shí)現(xiàn)基于樹莓派的語音機(jī)器人
當(dāng)前鏈接:http://jinyejixie.com/article46/iehihg.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)公司、App開發(fā)、標(biāo)簽優(yōu)化、App設(shè)計(jì)、網(wǎng)頁設(shè)計(jì)公司、電子商務(wù)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)