1. 程式人生 > >使用微軟Speech SDK 5.1(SAPI 5.1)語音開發包介紹

使用微軟Speech SDK 5.1(SAPI 5.1)語音開發包介紹

微軟語音識別分兩種模式:文字識別模式和命令識別模式.此兩種模式的主要區別,主要在於識別過程中使用的匹配字典不同.前者使用的是通用字典,特點是內容多,覆蓋的詞彙量大,字典由sdk提供.適用於沒有預定目標的隨機聽寫之類的應用.同時因為詞彙量大直接導致識別的精度降低,識別速度較慢.後者的字典需要 開發者自己編寫,就是你們所說的xml檔案.xml檔案作為一種資料儲存的方式,有一定的格式,定義了sdk需要確定的一些標籤,和用以匹配的詞彙.這種方式由開發者定義詞彙的數量,大大降低匹配過程中需要檢索的詞彙量,提高了識別速度.同時因為侯選項極少,所以一般不會識別錯誤.其缺點也是明顯的:詞彙量小,只有預先輸入字典的詞彙可以被識別出來,所以一般用來作為常用命令的識別,方便使用者操作,代替選單命令等. 


利用微軟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函式即可。 

至此最簡單的識別就完成了。