zoukankan      html  css  js  c++  java
  • Windows 语音识别编程

    转载:http://blog.csdn.net/yincheng01/article/details/3584630

    语音类 
      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文件可通过以记事本形式打开编辑。具体如下: 
      ---

    向上走

    向下走

    停下来

    跑步

    识别

    语音

    还原

    文件

    踢球 

  • 相关阅读:
    javaWeb快速入门
    SpringBoot的json序列化及时间序列化处理
    Springboot整合Mybatis 之分页插件使用
    springboot全局异常处理
    接口统一参数格式封装方法参数传递工具类
    基于AOP注解实现业务功能的动态配置
    sss
    sss
    sss
    sss
  • 原文地址:https://www.cnblogs.com/ldjhust/p/3191560.html
Copyright © 2011-2022 走看看