Windows 语音识别编程

网友投稿 951 2022-09-16

Windows 语音识别编程

Windows 语音识别编程

语音类

1)在构造语音类之前,必须先设置好工程环境:

a、从微软官方网站-windows speech sdk并安装,然后在Visual Studio 6.0中进行相关设置,在Project Setings选项的C++选项卡的“分类:预处理器”添加“,__WIN32_DCOM”(为预先初始化COM组件成功);

b、将预处理头文件选项选中“自动使用预补偿页眉”;

c、在常规选项卡中选择“实用MFC静态连接库”;

入图:(一)

2)封装语音类

由于采用面向对象的编程理念,借助UML(Unified Modeling Language统一建模语言)构造CSPEECH语音类如下

CSPEECH类

+ void InitSR(); //初始化语音

+void RecoEvent();//识别命令函数

+BOOL b_initSR;

+BOOL b_Cmd_Grammar;

//3个语音接口

+CComPtr m_cpRecocontxt;

+CComPtr m_cpRecoGrammar;

+CComPtr m_cpRecoEngine;

然后开始添加语音类,需要注意的是在定义语音类的头文件中,包含〈sphelper.h〉并且自定义语音识别消息和类型

#define GID_CMD_GR 333333

#define WM_RECOEVENT WM_USER+102

剩下来就是对cpp文件的函数initSR()和RecoEvent()补充函数体

3)具体见下面代码

(1)void CSpeech::initSR()

{

HRESULT hr=S_OK;

hr=m_cpRecoEngine.CoCreateInstance(CLSID_SpInprocRecognizer);//创建识别引擎COM实例

if(SUCCEEDED(hr))

{

hr =m_cpRecoEngine->CreateRecoContext(&m_cpRecoCtxt );//创建识别上下文

}

else

MessageBox(hWnd,"error1","error",S_OK);

if(SUCCEEDED(hr))

{

hr = m_cpRecoCtxt->SetNotifyWindowMessage(hWnd, WM_RECOEVENT, 0, 0 );

}//消息机制设置,使计算机时刻监听语音消息

else

MessageBox(hWnd,"error2","error",S_OK);

if (SUCCEEDED(hr))

{

ULONGLONG ullMyEvents = SPFEI(SPEI_RECOGNITION) | SPFEI(SPEI_HYPOTHESIS);

hr = m_cpRecoCtxt->SetInterest(ullMyEvents, ullMyEvents);

}

else

MessageBox(hWnd,"error3","error",S_OK);

//设置默认的音频

CComPtr m_cpAudio;

hr=SpCreateDefaultObjectFromCategoryId(SPCAT_AUDIOIN,&m_cpAudio);//建立默认的音频输入对象

hr=m_cpRecoEngine->SetInput(m_cpAudio,TRUE);//设置识别引擎输入源

hr=m_cpRecoCtxt->CreateGrammar(GID_CMD_GR,&m_cpCmdGrammar);//创建命令语法

b_Cmd_Grammar=TRUE;

if(FAILED(hr))

{

MessageBox(hWnd,"error 4","error",S_OK);

}

hr=m_cpCmdGrammar->LoadCmdFromResource(NULL,MAKEINTRESOURCEW(IDR_CMDCTRL),L"SRGRAMMAR",MAKELANGID(LANG_NEUTRAL,SUBLANG_NEUTRAL), SPLO_DYNAMIC);//加载命令语法文件

if(FAILED(hr))

{

MessageBox(hWnd,"error5","error",S_OK);

}

b_initSR=TRUE;

}

(2)BOOL CSpeech::RecoEvent()

{

USES_CONVERSION;

CSpEvent event;

while(event.GetFrom(m_cpRecoCtxt)==S_OK)

{

switch(event.eEventId)

{

case SPEI_RECOGNITION:

{

static const WCHAR wszUnrecognized[]=L" ";

CSpDynamicString dstrText;

if(FAILED(event.RecoResult()->GetText(SP_GETWHOLEPHRASE,SP_GETWHOLEPHRASE,TRUE,&dstrText,NULL)))

{

dstrText=wszUnrecognized;

}

dstrText.CopyToBSTR(&SRout);

Recstring.Empty();

Recstring=SRout;

if(b_Cmd_Grammar)

{

if(Recstring=="左")

{

ISpVoice *pVoice=NULL;

if(FAILED(CoInitialize(NULL)))

{

MessageBox(hWnd,"Error to initialize COM","error",S_OK);

return FALSE;

}

HRESULT hr=CoCreateInstance(CLSID_SpVoice,NULL,CLSCTX_ALL,IID_ISpVoice,(void**)&pVoice);

if(SUCCEEDED(hr))

{

hr=pVoice->Speak(L"左转",0,NULL);

pVoice->Release();

pVoice=NULL;

}

CoUninitialize();

m_OpenGL->m_baiscobj->LEFT=1;

return TRUE ;

}

if(Recstring=="向下走")

{

ISpVoice *pVoice=NULL;

if(FAILED(CoInitialize(NULL)))

{

MessageBox(hWnd,"Error to initialize COM","error",S_OK);

return FALSE;

}

HRESULT hr=CoCreateInstance(CLSID_SpVoice,NULL,CLSCTX_ALL,IID_ISpVoice,(void**)&pVoice);

if(SUCCEEDED(hr))

{

hr=pVoice->Speak(L"开始后退",0,NULL);

pVoice->Release();

pVoice=NULL;

}

CoUninitialize();

m_OpenGL->m_baiscobj->BACK=1;

return TRUE ;

}

if(Recstring=="最小化")

{

ISpVoice *pVoice=NULL;

if(FAILED(CoInitialize(NULL)))

{

MessageBox(hWnd,"Error to initialize COM","error",S_OK);

return FALSE;

}

HRESULT hr=CoCreateInstance(CLSID_SpVoice,NULL,CLSCTX_ALL,IID_ISpVoice,(void**)&pVoice);

if(SUCCEEDED(hr))

{

hr=pVoice->Speak(L"最小化",0,NULL);

pVoice->Release();

pVoice=NULL;

}

CoUninitialize();

SendMessage(hWnd,WM_SYSCOMMAND, SC_MINIMIZE, MAKELPARAM(0, 0));

return TRUE;

}

if(Recstring=="右")

{

ISpVoice *pVoice=NULL;

if(FAILED(CoInitialize(NULL)))

{

MessageBox(hWnd,"Error to initialize COM","error",S_OK);

return FALSE;

}

HRESULT hr=CoCreateInstance(CLSID_SpVoice,NULL,CLSCTX_ALL,IID_ISpVoice,(void**)&pVoice);

if(SUCCEEDED(hr))

{

hr=pVoice->Speak(L"开始右转",0,NULL);

pVoice->Release();

pVoice=NULL;

}

CoUninitialize();

m_OpenGL->m_baiscobj->RIGHT=1;

return TRUE ;

}

if(Recstring=="停下来")

{

ISpVoice *pVoice=NULL;

if(FAILED(CoInitialize(NULL)))

{

MessageBox(hWnd,"Error to initialize COM","error",S_OK);

return FALSE;

}

HRESULT hr=CoCreateInstance(CLSID_SpVoice,NULL,CLSCTX_ALL,IID_ISpVoice,(void**)&pVoice);

if(SUCCEEDED(hr))

{

hr=pVoice->Speak(L"动作开始了",0,NULL);

pVoice->Release();

pVoice=NULL;

}

CoUninitialize();

m_OpenGL->m_baiscobj->Move=0;

m_OpenGL->m_baiscobj->BACK=0;

m_OpenGL->m_baiscobj->LEFT=0;

m_OpenGL->m_baiscobj->RIGHT=0;

return TRUE ;

}

if(Recstring=="跑步")

{

ISpVoice *pVoice=NULL;

if(FAILED(CoInitialize(NULL)))

{

MessageBox(hWnd,"Error to initialize COM","error",S_OK);

return FALSE;

}

HRESULT hr=CoCreateInstance(CLSID_SpVoice,NULL,CLSCTX_ALL,IID_ISpVoice,(void**)&pVoice);

if(SUCCEEDED(hr))

{

hr=pVoice->Speak(L"动作开始了",0,NULL);

pVoice->Release();

pVoice=NULL;

}

CoUninitialize();

m_OpenGL->m_baiscobj->Move=1;

return TRUE ;

}

if(Recstring=="退出")

{

m_OpenGL->CleanUp(); // 结束处理

PostQuitMessage(0);

return TRUE;

}

}

}

}

}return TRUE;

}

要注意的是RecoEvent()必须能处理人物、摄像头的漫游,所以在人物、摄像机类的行为函数中添加了控制变量Move、BACK、LEFT、RIGHT;并附了初值1,当在行为函数中为1时行为函数体执行,所以也必须

#include "OpenGL.h"

#include "baiscobj.h"

其间我们借助于指针变量,巧妙的使语音能控制行为,却不影响动画的刷新,但不足的是由于opengl动画md2模型的不能导入成功,使踢球,跳木箱等功能函数没有完成,所以只要行为函数出来,可通过上述同样方法实现语音控制。

4)如何在winmain()函数中执行语音程序?

首先包含语音头文件〈sapi.h〉

接着(#define CSpeech speech)定义语音类对象

INT WINAPI WinMain(HINSTANCE hInst,HINSTANCE,LPSTR,INT )// WinMain程序入口

{

::CoInitializeEx(NULL,COINIT_APARTMENTTHREADED);//初始化COM

……

char cc[]="tml";

WNDCLASSEX wc = { sizeof(WNDCLASSEX), CS_CLASSDC, MsgProc, 0L, 0L,

GetModuleHandle(NULL), NULL, NULL, NULL, (LPCTSTR)IDR_MENU1,

cc, NULL };

RegisterClassEx( &wc );

m_OpenGL=new OpenGL();//

hWnd = CreateWindowEx(NULL,cc,"智能精灵键盘(↑进↓退→右←左UP仰DOWM俯)",

dwStyle|WS_CLIPCHILDREN|WS_CLIPSIBLINGS,nX,nY,Width, Height,NULL,NULL,hInst,NULL); // 创建窗口

ShowWindow( hWnd, SW_SHOWDEFAULT ); // 显示窗口

UpdateWindow( hWnd ); // 刷新窗口

speech.b_Cmd_Grammar=FALSE;

speech.initSR();

GameLoop(); // 进入消息循环

return 0;

}

通过speech.initSR(),执行语音的初始化,为了设置一个简单的语音识别开关,简单的添加一个任务栏,只有语音这一个菜单资源,然后利用消息机制,在消息处理函数里Switch(message)里添加:

case WM_COMMAND:

switch(LOWORD(wParam))

{

case IDM_SPEECH:speech.startcmd();

}

return 0;break;

即当单击语音菜单时,则使语音功能完全激活,下面是这个函数的实体:

void CSpeech::startcmd()

{

if(b_initSR)

{

HRESULT hr=m_cpCmdGrammar->SetRuleState(NULL,NULL,SPRS_ACTIVE);

ISpVoice *pVoice=NULL;

if(FAILED(CoInitialize(NULL)))

{

MessageBox(hWnd,"Error to initialize COM","error",S_OK);

return ;

}

hr=CoCreateInstance(CLSID_SpVoice,NULL,CLSCTX_ALL,IID_ISpVoice,(void**)&pVoice);

if(SUCCEEDED(hr))

{

hr=pVoice->Speak(L"语法已经激活",0,NULL);

pVoice->Release();

pVoice=NULL;

}

CoUninitialize();

}

}

5)在所有的工作完成之前,还必须先在项目工程下添加XML语法文件,通过initSR()中的LoadCmdFromResource()函数加载;XML文件可通过以记事本形式打开编辑。具体如下:

- - -

向上走

向下走

停下来

跑步

识别

语音

还原

文件

踢球

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:在WebApi 中使用AutoFac
下一篇:Windows API SHGetSpecialFolderPath的用法 ,获取特殊文件夹
相关文章

 发表评论

暂时没有评论,来抢沙发吧~