近年来语音识别发展迅速也带动了人工智能的发展。曾经渴望自己做一个机器人,但是无奈,心有余而力不足,经过多年的积累,小白的我也能用站着巨人的肩膀上玩下机器人了。
准备工作:树莓派,音频模块,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 -o uart uart.c -lwiringPi
typedef struct WAV_Format WAVHEADER;
#define MAX_LISTEN_SIZES 1024*70 //定义接收数据的大小
#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;//存储最后的返回值
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!!!");
//需要对音频信号作出处理,当大于或者阈值时开始统计,知道录制完成
int countTotal=0;
int countNumber= 1000;//统计个数
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||tempmax)
{
max=temp;
}
if(templength=sizeof(WAVHEADER)+MAX_LISTEN_SIZES*2;
liste->data=result;
return liste;
}
将音频识别成文字
#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);
//发送请求
free(lsn->data);
free(lsn);
int code=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;
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
#include
#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("你好,我是小志,有什么可以为你服务");
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,"关闭灯,")!=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");
}
}
return 0;
}
这里只是贴出来部分程序,所有代码请查看 https://gitee.com/telrobgit/robot 希望能和大家一起交流下心得,QQ:1140756409