您的位置:首页 > 编程语言 > Go语言

MFC使用Google Speech API进行语音识别

2014-01-10 17:40 453 查看
这段时间需要做个语音识别的程序,由于时间和能力有限,所以不大可能自己做一个识别引擎,怎么办呢,当然是查看度娘了。

这才发现网上其实有很多的解决方案,最出名的莫过于APPLE SIRI 以及GOOGLE NOW这两个识别引擎,GOOGLE NIOW已经在自己的安卓手机上进行了无数次测试,怎么说呢,这识别率简直是爆表啊,就算不是标准普通话,就像我这种川普也是没有问题的;少年你这么猛,你家人知道么


操作之前当然要去看看大神们的研究成果啦,我这里就不说原理了,大家转到这里去看看原帖点击打开链接找不到连接就看这里/article/10377501.html

这里由于楼主以前是搞通信的,所以文件采用amr格式,这东西好啊,压缩率高,专门用来传输人声的,效果很赞哦,关键是还能滤掉杂音,可以提高识别率(自我安慰)

废话说了这么多!上代码

int CGoogleNowDlg::PostGoogleAPI()
{
char sendata[65536]={0};
SOCKET sock = ::socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sock == INVALID_SOCKET)
return 0;
SOCKADDR_IN server;
server.sin_family = AF_INET;
server.sin_port = htons(80);
struct hostent *host_addr = gethostbyname("www.google.com");
if (host_addr == NULL)
return -1;
server.sin_addr.s_addr = *((int *) *host_addr->h_addr_list);
if (::connect(sock, (SOCKADDR *) &server, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
{
::closesocket(sock);
return 0;
}

char temp[64] = {0};

FILE *fp;
fp = fopen("Out.amr" , "rb");
fseek( fp , 0 , SEEK_END );
int file_size;
file_size = ftell( fp );
char * tmp;
fseek( fp , 0 , SEEK_SET);
tmp = (char *)malloc( file_size * sizeof( char ) );
memset(tmp, '\0', file_size);
int ret = fread( tmp , sizeof(char) , file_size , fp );
fclose(fp);

strcat(sendata, "POST /speech-api/v1/recognize?xjerr=1&client=chromium&lang=zh-CN&maxresults=1 HTTP/1.1\r\n");//请求行
strcat(sendata,"Accept: */*\r\n");
strcat(sendata,"Accept-Language: zh-cn\r\n");
strcat(sendata,"Accept-Encoding: gzip, deflate\r\n");
strcat(sendata,"User-Agent: Mozilla/5.0\r\n");
strcat(sendata,"Host: www.google.com\r\n");
strcat(sendata,"Pragma: no-cache\r\n");
sprintf(temp, "Content-Length: %d\r\n", file_size);
strcat(sendata,temp);
strcat(sendata, "Content-Disposition: form-data; name='file'; filename='a.amr'\r\n");
strcat(sendata, "Content-Type: audio/amr; rate=8000\r\n\r\n");//在http头后边有一空行,空行后边接着发送post数据

CString SendData;
SendData = sendata;
for (int i = 0; i<file_size; i++)
{
SendData+=tmp[i];
}
int cx = send(sock, SendData, SendData.GetLength(), 0);//发出socket请求

//接收数据
char szBuffer[1024] = {0};
CString recvData;
int flag = 1;
while (true)
{
int nRet = ::recv(sock, szBuffer, sizeof(szBuffer), 0);
recvData = szBuffer;
if (nRet == 0 || nRet == WSAECONNRESET)
{
AfxMessageBox("Connection Closed.\n");
break;
}
else if (nRet == SOCKET_ERROR)
{
AfxMessageBox("socket error\n");
break;
}
else
{
int str = recvData.Find('{');
int needNum = recvData.GetLength()-str-1;
recvData = recvData.Right(recvData.GetLength()-str-1);
FILE * fp = fopen("GoogleSpeechAPI.txt","wb");
fwrite(recvData,needNum,1,fp);
fclose(fp);
break;
}
}
::closesocket(sock);
return 0;
}


代码写得比较烂,大家将就看吧,其中有两个知识点,第一个就是如何用socket模拟http post ,关键点就是要构造http头结构,



这要严格按照这个结构组装,就不会出问题,在调试阶段,一定要查看返回值,如果出现400,表示你的结构有问题,出现200说明成功。

第二个问题就是,amr文件中含有大量NUL字符,这个字符表示文件结束,使用读取的时候一定要采用二进制方式读取,特别是在组装数据的过程中一定要强制性的组装所有字符,所以我采用一个个字符组装。不然会出现字符断掉的情况,返回值虽然为200但是最后并没有返回识别数据。

暂时就这样吧!有问题可以留言哦!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: