Windows 語音辨識編程

來源:互聯網
上載者:User
語音類
  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檔案可通過以記事本形式開啟編輯。具體如下:
  ---

向上走

向下走

停下來

跑步

識別

語音

還原

檔案

踢球

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.