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

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

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

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

这里由于楼主以前是搞通信的,所以文件采用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但是最后并没有返回识别数据。

暂时就这样吧!有问题可以留言哦!

发布了6 篇原创文章 · 获赞 1 · 访问量 3469
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览