语音识别 Windows 语音识别编程

来源:互联网 发布:上海浦东开发集团 知乎 编辑:程序博客网 时间:2024/04/29 22:10
语音类 
  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文件可通过以记事本形式打开编辑。具体如下: 
  ---

向上走

向下走

停下来

跑步

识别

语音

还原

文件

踢球

原创粉丝点击