windows下利用微软的SpeechSDK实现语音控制

语音识别是当前研究的热点,我们可以利用微软的语音识别引擎来进行二次开发。首先需要安装微软的SpeechSDK,安装完成后配置项目的包含目录和库目录,这些都不是重点,不会的可以去百度。然后就可以写代码了,码农嘛,还是看代码有感觉。

源文件<Demo.cpp>

#include <Windows.h>
#include <atlstr.h>
#include <sphelper.h>
#include <sapi.h>
#include <comutil.h>
#include <string.h>

#pragma comment(lib,"sapi.lib")
#ifdef _UNICODE
#pragma   comment(lib,   "comsuppw.lib")  //_com_util::ConvertBSTRToString
#else
#pragma   comment(lib,   "comsupp.lib")  //_com_util::ConvertBSTRToString
#endif

#define GID_CMD_GR 333333
#define WM_RECOEVENT WM_USER+1

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);

TCHAR szAppName[] = TEXT("语音控制Demo");
BOOL b_initSR;
BOOL b_Cmd_Grammar;
CComPtr<ISpRecoContext> m_cpRecoCtxt;//语音识别程序接口
CComPtr<ISpRecoGrammar> m_cpCmdGramma;//识别语法
CComPtr<ISpRecognizer> m_cpRecoEngine; //语音识别引擎
int speak(wchar_t *str);

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,PSTR szCmdLine,int iCmdShow)
{
	HWND hwnd;
	MSG msg;
	WNDCLASS wndclass;

	//窗口类结构体初始化值
	wndclass.cbClsExtra = 0;
	wndclass.cbWndExtra = 0;
	wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
	wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
	wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
	wndclass.hInstance = hInstance;
	wndclass.lpfnWndProc = WndProc;
	wndclass.lpszClassName = szAppName;
	wndclass.lpszMenuName = NULL;
	wndclass.style = CS_HREDRAW|CS_VREDRAW;

	//注册窗口类
	if(!RegisterClass(&wndclass))
	{
		//失败后提示并返回
		MessageBox(NULL,TEXT("This program requires Windows NT!"),szAppName,MB_ICONERROR);
		return 0;
	}

	//创建窗口
	hwnd = CreateWindow(szAppName,
						TEXT("语音识别"),
						WS_OVERLAPPEDWINDOW,
						CW_USEDEFAULT,
						CW_USEDEFAULT,
						CW_USEDEFAULT,
						CW_USEDEFAULT,
						NULL,
						NULL,
						hInstance,
						NULL);
	
	//显示窗口
	ShowWindow(hwnd,iCmdShow);
	UpdateWindow(hwnd);

	//进入消息循环
	while(GetMessage(&msg,NULL,0,0))
	{
		TranslateMessage(&msg);//翻译消息
		DispatchMessage(&msg);//分发消息
	}
	return msg.wParam;
}

/*
*消息回调函数,由操作系统调用
*/
LRESULT CALLBACK WndProc(HWND hwnd, UINT message,WPARAM wParam,LPARAM lParam)
{
	HDC hdc;
	PAINTSTRUCT ps;

	switch(message)
	{
	case WM_CREATE:
		{	
			//初始化COM端口
			::CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);
			//创建识别上下文接口
			HRESULT hr = m_cpRecoEngine.CoCreateInstance(CLSID_SpSharedRecognizer);
			if(SUCCEEDED(hr))
			{
				hr = m_cpRecoEngine->CreateRecoContext(&m_cpRecoCtxt);
			}
			else
			{
				MessageBox(hwnd,TEXT("引擎实例化出错"),TEXT("提示"),S_OK);
			}
			//设置识别消息,使计算机时刻监听语音消息
			if(SUCCEEDED(hr))
			{
				hr = m_cpRecoCtxt->SetNotifyWindowMessage(hwnd,WM_RECOEVENT,0,0);
			}
			else
			{
				MessageBox(hwnd,TEXT("创建上下文接口出错"),TEXT("提示"),S_OK);
			}
			//设置我们感兴趣的事件
			if(SUCCEEDED(hr))
			{
				ULONGLONG ullMyEvents = SPFEI(SPEI_SOUND_START)|SPFEI(SPEI_RECOGNITION)|SPFEI(SPEI_SOUND_END);
				hr = m_cpRecoCtxt->SetInterest(ullMyEvents,ullMyEvents);
			}
			else
			{
				MessageBox(hwnd,TEXT("设置识别消息出错"),TEXT("提示"),S_OK);
			}
			//创建语法规则
			b_Cmd_Grammar = TRUE;
			if(FAILED(hr))
			{
				MessageBox(hwnd,TEXT("创建语法规则出错"),TEXT("提示"),S_OK);
			}
			hr = m_cpRecoCtxt->CreateGrammar(GID_CMD_GR,&m_cpCmdGramma);
			hr = m_cpCmdGramma->LoadCmdFromFile(L"cmd.xml",SPLO_DYNAMIC);
			if(FAILED(hr))
			{
				MessageBox(hwnd,TEXT("配置文件打开出错"),TEXT("提示"),S_OK);
			}
			b_initSR = TRUE;
			//在开始识别时,激活语法进行识别
			hr = m_cpCmdGramma->SetRuleState(NULL,NULL,SPRS_ACTIVE);
			break;
		}
	case WM_RECOEVENT:
		{
			RECT rect;
			GetClientRect(hwnd,&rect);
			hdc = GetDC(hwnd);
			USES_CONVERSION;
			CSpEvent event;
			while(event.GetFrom(m_cpRecoCtxt)==S_OK)
			{
				switch(event.eEventId)
				{
				case SPEI_RECOGNITION:
					{
						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);
						char * lpszText2 = _com_util::ConvertBSTRToString(SRout);
						if(b_Cmd_Grammar)
						{
							//MessageBoxA(0,lpszText2,"内容",0);
							if(strcmp("腾讯QQ",lpszText2)==0)
							{
								//MessageBox(0,TEXT("计算机"),TEXT("内容"),0);
								speak(L"好的");
								//打开QQ.exe
								ShellExecuteA(NULL,"open","D:\\QQ\\QQProtect\\Bin\\QQProtect.exe",0,0,1);
							}
							if(strcmp("确定",lpszText2)==0)
							{
								//按下回车键
								keybd_event(VK_RETURN,0,0,0);
								keybd_event(VK_RETURN,0,KEYEVENTF_KEYUP,0);
							}
							if(strcmp("音乐",lpszText2)==0)
							{		
								speak(L"好的");
								//调用系统程序wmplayer.exe播放音乐
								ShellExecuteA(NULL,"open","\"C:\\Program Files (x86)\\Windows Media Player\\wmplayer.exe\"","C:\\Users\\KYT\\Desktop\\123.mp3",0,0);
							}
						}
					}
				}
			}
			break;
		}
	case WM_PAINT:
		hdc = BeginPaint(hwnd,&ps);
		EndPaint(hwnd,&ps);
		break;
	case WM_DESTROY:
		PostQuitMessage(0);
		break;
	}
	return DefWindowProc(hwnd,message,wParam,lParam);
}

#pragma comment(lib,"ole32.lib")//CoInitialize CoCreateInstance 需要调用ole32.dll

/*
*语音合成函数,朗读字符串str
*/
int speak(wchar_t *str)
{
	ISpVoice * pVoice = NULL;
	::CoInitialize(NULL);
	//获得ISpVoice接口
	long hr = CoCreateInstance(CLSID_SpVoice,NULL,CLSCTX_ALL,IID_ISpVoice,(void **)&pVoice);
	hr = pVoice->Speak(str,0,NULL);
	pVoice->Release();
	pVoice = NULL;
	//千万不要忘记
	::CoUninitialize();
	return TRUE;
}

只有源文件还不行,程序中还用到一个XML格式的语音配置文件cmd.xml。如果是利用编译器调试程序,cmd.xml需要和源代码同目录;发布程序以后,cmd.xml就得放到程序可执行文件所在的目录下了。总之,程序必须访问到cmd.xml文件,方便起见,可以在两个目录下都放一个cmd.xml文件。

配置文件<cmd.xml>

<?xml version="1.0" encoding="utf-8"?>
<GRAMMAR LANGID="804">
 <DEFINE>
    <ID NAME="CMD" VAL="10"/>
    </DEFINE>
  <RULE NAME="COMMAND" ID="CMD" TOPLEVEL="ACTIVE">
   <L>
    <P>腾讯QQ</P>
    <P>确定</P>
    <P>音乐</P>
    </L>
   </RULE>
</GRAMMAR>

到这里,一个简单的语音控制程序Demo就算完成了,你对它说:“腾迅QQ”,它就打开了一个QQ,你说:“确定”,默认的QQ账号就自己登陆了。你还可以说:“音乐”,于是一首曼妙的音乐响起(为什么看不见播放器呢,因为在代码
ShellExecuteA(NULL,"open","\"C:\\Program Files (x86)\\Windows Media Player\\wmplayer.exe\"","C:\\Users\\KYT\\Desktop\\123.mp3",0,0);

 设置了wmplayer.exe隐藏执行,想要关闭,嘻嘻,请打开任务管理器。另外,一定要设置你电脑上的音乐路径,不然你懂得)。 

语音识别是不是挺有意思的,发挥你的想象,去震精别人吧。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值