使用微軟Speech SDK 5.1(SAPI 5.1)語音開發包介紹
阿新 • • 發佈:2019-01-25
微軟語音識別分兩種模式:文字識別模式和命令識別模式.此兩種模式的主要區別,主要在於識別過程中使用的匹配字典不同.前者使用的是通用字典,特點是內容多,覆蓋的詞彙量大,字典由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函式即可。
至此最簡單的識別就完成了。
利用微軟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函式即可。
至此最簡單的識別就完成了。