利用微軟Speech SDK 5.1在MFC中進行語音識別開發時的主要步驟

利用微軟Speech SDK 5.1在MFC中進行語音識別開發時的主要步驟,以Speech API 5.1+VC6爲例:

1、初始化COM端口
一般在CWinApp的子類中,調用CoInitializeEx函數進行COM初始化,代碼如下:
::CoInitializeEx(NULL,COINIT_APARTMENTTHREADED); // 初始化COM
注意:調用這個函數時,要在工程設置(project settings)->C/C++標籤,Category中選Preprocessor,在Preprocessor definitions:下的文本框中加上“,_WIN32_DCOM”。否則編譯不能通過。

2、創建識別引擎
微軟Speech SDK 5.1 支持兩種模式的:共享(Share)和獨享(InProc)。一般情況下可以使用共享型,大的服務型程序使用InProc。如下:
hr = m_cpRecognizer.CoCreateInstance(CLSID_SpSharedRecognizer);//Share
hr = m_cpRecognizer.CoCreateInstance(CLSID_SpInprocRecognizer);//InProc
如果是Share型,可直接進到步驟3;如果是InProc型,必須使用 ISpRecognizer::SetInput 設置語音輸入。如下:
CComPtr<ISpObjectToken> cpAudioToken;  //定義一個token
hr = SpGetDefaultTokenFromCategoryId(SPCAT_AUDIOIN, &cpAudioToken); //建立默認的音頻輸入對象
if (SUCCEEDED(hr)) { hr = m_cpRecognizer->SetInput(cpAudioToken, TRUE);}
或者:
CComPtr<ISpAudio> cpAudio;  //定義一個音頻對象
hr = SpCreateDefaultObjectFromCategoryId(SPCAT_AUDIOIN, &cpAudio);//建立默認的音頻輸入對象
hr = m_cpRecoEngine->SetInput(cpAudio, TRUE);//設置識別引擎輸入源

3、創建識別上下文接口
調用 ISpRecognizer::CreateRecoContext 創建識別上下文接口(ISpRecoContext),如下:
hr = m_cpRecoEngine->CreateRecoContext( &m_cpRecoCtxt );

4、設置識別消息
調用 SetNotifyWindowMessage 告訴Windows哪個是我們的識別消息,需要進行處理。如下:
hr = m_cpRecoCtxt->SetNotifyWindowMessage(m_hWnd, WM_RECOEVENT, 0, 0);
SetNotifyWindowMessage 定義在 ISpNotifySource 中。

5、設置我們感興趣的事件
其中最重要的事件是”SPEI_RECOGNITION“。參照 SPEVENTENUM。代碼如下:
const ULONGLONG ullInterest = SPFEI(SPEI_SOUND_START) | SPFEI(SPEI_SOUND_END) | SPFEI(SPEI_RECOGNITION) ;
hr = m_cpRecoCtxt->SetInterest(ullInterest, ullInterest);

6、創建語法規則
語法規則是識別的靈魂,必須要設置。分爲兩種,一種是聽說式(dictation),一種是命令式(command and control---C&C)。首先 利用ISpRecoContext::CreateGrammar 創建語法對象,然後加載不同的語法規則,如下:

//dictation
hr = m_cpRecoCtxt->CreateGrammar( GIDDICTATION, &m_cpDictationGrammar );
if  (SUCCEEDED(hr))
{
hr = m_cpDictationGrammar->LoadDictation(NULL, SPLO_STATIC);//加載詞典
}

//C&C
hr = m_cpRecoCtxt->CreateGrammar( GIDCMDCTRL, &m_cpCmdGrammar);
然後利用ISpRecoGrammar::LoadCmdxxx 加載語法,例如從CmdCtrl.xml中加載:
WCHAR wszXMLFile[20]=L"";
MultiByteToWideChar(CP_ACP, 0, (LPCSTR)"CmdCtrl.xml"  , -1, wszXMLFile, 256);//ANSI轉UNINCODE
hr = m_cpCmdGrammar->LoadCmdFromFile(wszXMLFile,SPLO_DYNAMIC); 
注意:C&C時,語法文件使用xml格式,參見Speech SDK 5.1 中的 Designing Grammar Rules。簡單例子:
<GRAMMAR LANGID="804"> 
   <DEFINE>
      <ID NAME="CMD" VAL="10"/>
   </DEFINE>
   <RULE NAME="COMMAND" ID="CMD" TOPLEVEL="ACTIVE">
     <L>
<p>你</P>
<p>我</p>
<p>他</p>
     </L>
   </RULE>
</GRAMMAR>
LANGI*="804"代表簡體中文,在<*>...</*>中增加命令。

7、在開始識別時,激活語法進行識別
hr = m_cpDictationGrammar->SetDictationState( SPRS_ACTIVE );//dictation
hr = m_cpCmdGrammar->SetRuleState( NULL,NULL,SPRS_ACTIVE );//C&C

8、獲取識別消息,進行處理
截獲識別消息(WM_RECOEVENT),然後處理。識別的結果放在CSpEvent的ISpRecoResult 中。如下:

USES_CONVERSION;
CSpEvent event;

switch (event.eEventId)
{
        case SPEI_RECOGNITION:
{
//識別出了語音輸入
m_bGotReco = TRUE;
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);

CString Recstring;
Recstring.Empty();
Recstring = SRout;

//進一步處理
......
}
break;
}

9、釋放創建的引擎、識別上下文對象、語法等。調用相應的Release函數即可。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章