网上虽然有很多语音识别的教程,但是很多是却少一些部分,笔者在综合了几篇之后,做成功了语音识别,下面是教程。
网上的语音识别分成几种,把语音识别消息放入队列中的是一种,笔者认为这个效率比较高,所以用这个。
本文以加在对话框中为例,XXXdlg XXX.h
第一,安装speech sdk 貌似虽然大家用的都是老版本,但是微软最新的是speech sdk 11.在win7以后的系统可以用,C++的程序写法还是和老的5.1一样用。
第二,在工程中设置。
项目->属性->配置属性->C/C++ 附加包含目录,输入以下(注意你自己安装在哪里就是 哪里)
"D:\Program Files\Microsoft SDKs\Speech\v11.0\Include"
"X:\XXX\Microsoft SDKs\Speech\v11.0\Include"
(X:\XXX是你的安装目录)
项目->属性->配置属性->链接库 ,输入以下
"D:\Program Files\Microsoft SDKs\Speech\v11.0\Lib"
"D:\Program Files\Microsoft SDKs\Speech\v11.0\Lib"
(X:\XXX是你的安装目录)
(D:\Program Files\Microsoft SDKs\Speech\v11.0\前面为你装的speech的目录,具体的自己调整,很坑爹的是好像没有配置这一项,能用,反而加了这个,语音合成出事了,不加是因为在系统默认的include目录下已经包含了头文件,至于版本问题,好像v11和5.3都尝试过,不知道起作用的是哪个版本)
第三,添加自定义消息 和消息映射 还有头文件
如果想在全部应用语音识别 在stdafx.h 里面加 #include "sphelper.h" 或者单独在.h里面加
#include "sphelper.h"
在XXXDlg.h的开头加入消息自定义const int WM_RECORD=WM_USER+100;
如下
#pragma once
const int WM_RECORD=WM_USER+100;
与此同时,同在头文件声明自定义消息响应函数,和其他消息响应函数放一起就好了。
afx_msg LRESULT OnRecord(WPARAM wParam,LPARAM lParam);
public:
CComPtr<ISpRecognizer>m_pSREngine;// 语音识别引擎(recognition)的接口。
CComPtr<ISpRecoContext>m_pSRContext;// 识别引擎上下文(context)的接口。
CComPtr<ISpRecoGrammar>m_pSRGrammar;// 识别文法(grammar)的接口。
CComPtr<ISpStream>m_pInputStream;// 流()的接口。
CComPtr<ISpObjectToken>m_pToken;// 语音特征的(token)接口。
CComPtr<ISpAudio>m_pAudio;// 音频(Audio)的接口。(用来保存原来默认的输入流)
ULONGLONG ullGrammerID ;
在XXXDlg.cpp 加入消息和消息响应函数的映射 ON_MESSAGE(WM_RECORD,OnRecord),如下所示
BEGIN_MESSAGE_MAP(CMSsimDlg, CDialog)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_MESSAGE(WM_RECORD,OnRecord)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
第四,编写XML文件,并放在响应目录下面,XML怎么编写网上很多,大家自己搜一下
第五,在对话框的 OnInitDialog()函数中,加入以下代码,初始化语音识别的设置。
OnInitDialog()函数:(类视图-》dlg类右击属性,右边重写标签页选择相应函数。)
// TODO: 在此添加额外的初始化代码CoInitialize(NULL);HRESULT hr;hr=m_pSREngine.CoCreateInstance ( CLSID_SpInprocRecognizer );if(FAILED(hr)){MessageBox(L"m_pSREngine.CoCreateInstance");}/*else{MessageBox(L"success");}*/hr = m_pSREngine->CreateRecoContext ( &m_pSRContext );//建立上下文if(FAILED(hr)){MessageBox(L" m_pSREngine->CreateRecoContext ");}/*else{MessageBox(L"success");}*///这里是设置事件HWND hwnd=GetSafeHwnd();hr=m_pSRContext->SetNotifyWindowMessage(hwnd,WM_RECORD,0,0);if(FAILED(hr)){MessageBox(L"SetNotifyWindowMessage");}/*else{MessageBox(L"success");}*/hr=m_pSRContext->SetInterest(SPFEI(SPEI_RECOGNITION),SPFEI(SPEI_RECOGNITION));//这里是设置默认的音频输入hr = SpCreateDefaultObjectFromCategoryId(SPCAT_AUDIOIN, &m_pAudio);m_pSREngine->SetInput(m_pAudio,true);//这里是加载默认的语法规则ullGrammerID = 1000;hr=m_pSRContext->CreateGrammar(ullGrammerID,&m_pSRGrammar);if(FAILED(hr)){MessageBox(L"CreateGrammar");}/*else{MessageBox(L"success");}*/WCHAR wszXMLFile[20]=L"";MultiByteToWideChar(CP_ACP, 0,(LPCSTR)"res\\main.xml" , -1, wszXMLFile, 256); //这里修改XML的目录hr=m_pSRGrammar->LoadCmdFromFile(wszXMLFile,SPLO_DYNAMIC);if(FAILED(hr)){MessageBox(L"LoadCmdFromFile");}/*else{MessageBox(L"success");}*///开启语音识别m_pSRGrammar->SetRuleState( NULL,NULL,SPRS_ACTIVE );hr=m_pSREngine->SetRecoState(SPRST_ACTIVE);if(FAILED(hr)){MessageBox(L"SetRecoState");}/*else{MessageBox(L"success");}*/
第五,编写消息映射的函数。
LRESULT CtestSpeechDlg::OnRecord(WPARAM wParam,LPARAM lParam){USES_CONVERSION; CSpEvent event; //MessageBox(L"onrecord");if(m_pSRContext){while(event.GetFrom(m_pSRContext)==S_OK){switch (event.eEventId) { case SPEI_RECOGNITION: { //识别出了语音输入 //m_bGotReco = TRUE; static const WCHAR wszUnrecognized[] = L"<Unrecognized>"; CSpDynamicString dstrText; 取得识别结果 if (FAILED(event.RecoResult()->GetText(SP_GETWHOLEPHRASE, SP_GETWHOLEPHRASE, TRUE ,&dstrText, NULL))) { dstrText = wszUnrecognized; } BSTR SRout; dstrText.CopyToBSTR(&SRout); CString Recstring; Recstring.Empty(); Recstring = SRout; //这里开始处理语音识别的消息。MessageBox(Recstring);} break; } }}return NULL;
}
六:出错提示
LoadCmdFromFile是文件加载的问题,看看路径有木有问题,还有xml文件的那个编码写得不对也是不行的。
有能力修改转码问题的同学我就不说了,如果没有的话,出现问题可以点击,项目-》属性-》配置属性-》常规-》项目默认-》字符集-》unicode
嗯
原文出处:http://blog.csdn.net/artemisrj/article/details/8723095
有人私信问我一个问题,我匿名帖全文了。
“微软MFC下做speech sdk语音识别,消息响应的版本”我按你发布的做了调试,基本成功了,可以加载我自己写的xml语法文件进行识别。
可是只能在打开vc的情况下编译通过后运行才可以进行识别,当我单独的打开Debug中生成的可执行程序时,总是提示LoadCmdFromFile出错!!然后的情况是可以进入界面,但是语音识别是无法进行识别的。
也就是说在单独运行生成的可执行程序时,初始化到LoadCMDFromFile这里就出错了无法加载了!!
这个困扰我有一段时间了 ,不知道你遇到这个情况没有,有没有解决方案!!
对于这个程序,当初也是因为大创项目而做的,也没有怎么精雕细琢,做得很粗糙,但愿能够对大家有用
最后有个传送门,是关于对话框切换的
http://blog.csdn.net/artemisrj/article/details/8896360
mxl范例:
http://download.csdn.net/detail/artemisrj/5830307
参考资料:《基于Microsoft Speech SDK的语音程序的设计与实现》骆家伟 2009年5月(有些语法出错了)
《基于Speech SDK的机器人语音交互系统》陈景帅,周风余2010年3月 (代码并不全)
网上一份封装在类里面的,感觉很乱,还有一个版本是SRC类的,那个曾经被人用来写在定时器里面,那种用法效率极低