夏俊杰,楊青,趙剛
(1.四川大學四川成都610064;2.成都中醫藥大學四川成都611130)
在設計問診系統時,使用Authorware開發工具進行開發,并且使用語音識別技術模擬醫生問的過程。語音識別采用微軟的語音開發包。微軟語音開發包中語音識別引擎是以COM為基礎構成的組件[1],但在Authorware中不能直接調用,而Authorware中使用控件是非常方便的。因此將語音識別接口編寫成控件的形式,然后在Authorware中調用。這樣就避免了編寫語音識別的程序,減少編程的代碼量,提高開發效率。文中就以語音識別組件為例來說明如何將COM組件轉化成控件。
COM組件和控件有一定的相似之處,都是基于COM原理[2]。COM組件和ActiveX控件都是模塊程序供其它程序調用。如圖1所示,COM組件的數據成員和控件中的方法類似;消息和事件類似。對于控件中的屬性則可能與組件中數據成員和函數成員都相關,需根據情況而定。它們之間可以相互轉化。

圖1 COM組件和activex控件的對比Fig.1 Comparison of COMcomponent and ActiveX control
語音識別組件轉化成控件的流程如圖2所示。由于組件接口比較多,調用起來不方便,因此先將組件接口封裝成一個C++類,這樣只要調用C++的幾個函數成員和數據成員就能調用引擎接口,使用比較方便。然后用VC設計一個語音識別控件。通過調用C++類的函數成員、數據成員和消息,在控件中添加相應的屬性、方法和事件。對于控件中的方法可以調用類中的函數成員。對于控件中的事件可類中的消息關聯起來。這樣就可完成語音識別控件的設計。

圖2 設計流程Fig.2 Process of designing
SAPI的語音識別引擎SR提供了語音識別功能的一系列函數,封裝在多個接口中。實現語音識別功能,主要使用ISpRecognizer、ISpRecoContext、ISpRecoGrammer等接口。Isp-Recognizer主要用于語音識別,將語音信號識別轉換成文本信息。IspRecoContext主要用于發送和接受消息。IspRecoGrammer主要用于加載語法規則。實現語音識別步驟為[3]:
1)初始化COM
2)建立IspRecognizer對象,通常建立COM對象有2種方法,一種是使用COM庫函數建立對象,使用CoCreateInstance()函數。另一種是使用智能指針建立COM對象,這種方法較常用。以建立IspRecognizer對象為例來說明。使用CcomPtr<IspRecognizer>m_pReco建立一個智能指針對象m_pReco,然后CcomPtr類中CoCreateInstance()函數創建IspRecognizer對象,即m_pReco.CoCreateInstance(…),然后就可使用m_pReco指針調用IspRecognizer接口中函數了。
3)創建IspRecoContext對象,設置消息的發送和接受。通過IspRecoContex接口中的SetNotifyWindowMessage()函數將消息傳遞到指定的窗口。并且調用其中的SetInterest()函數指定需要的某類特定消息。
4)建立IspRecoGrammer對象,加載語法規則。用Load Dictation()函數設置語音輸入方式進行識別。
5)調用IspRecognizer接口函數,比如停止識別、暫停識別、語音訓練、麥克風設置等。
為了調用方便,將語音識別接口寫成一個類CMyReco,類中包括了語音識別接口的所有功能。
class CMyReco{
……
BOOL Initialize(HWND hWnd=NULL,BOOL bIsShared=TRUE);//初始化函數
BOOL Start();//開始識別
BOOL Stop();//停止識別
//獲取識別出的文本
void GetRecoText(WCHAR**ppszCoMemText,ULONG ulStart=0,ULONG nlCount=-1);
CComPtr<ISpRecognizer>m_pREng;//創建智能指針
CComPtr<ISpRecoContext>m_pRecoCtxt;//創建智能指針
CComPtr<ISpRecoGrammar>m_pDictationGrammar;//創建智能指針
}
初始化函數將各種對象接口都建立了。初始化后就可以調用其他的如暫停、開始等函數。
控件一般有方法、屬性和事件3個組成成分[4]。將語音識別接口函數中的開始、停止、麥克風設置等函數作為控件中的方法;而識別出來的文本作為控件的屬性;通知用戶已產生文本的消息作為控件中的事件。下面說明制作語音識別控件的步驟:
1)利用VC++工具建立一個控件工程SREngine,將上面的CMyReco類文件加入到控件工程中。
2)初始化語音識別引擎
在CSREngineCtrl中添加WM_CREATE消息類型的消息響應函數OnCreate()。在該函數中實現語音識別初始化。
int CSREngineCtrl::OnCreate(LPCREATESTRUCT lpCreateStruct){
……..
m_SpeechReco.Initialize(this->GetSafeHwnd());
…….
}
其中m_SpeechReco是類CMyReco的對象。
3)添加方法
實現停止語音識別、開始語音識別、麥克風設置、是否語音識別引擎等功能可以使用控件的方法實現。例如,用類向導向程序代碼中添加方法SpStart。在CSREngineCtrl類的函數SpStart()中調用類CMyReco的Start()函數即可。在外部拖過要開始語音識別引擎,就可調用SpStart方法實現。其他功能的設計和開始語音識別功能的設計一樣。
4)添加屬性
為了獲取識別的結果,在控件中添加一個屬性用來保存識別出的文本。用類向導添加屬性SRtext,同時添加了GetSRtext()和SetSRtext()兩個函數。當外部程序讀屬性時,調用GetSRtext()函數。當設置屬性是調用SetSRtext()函數。因此,在GetSRtext函數中添加獲取語音識別結果的代碼。
BSTR CSREngineCtrl::GetSRtext(){
CString strResult;strResult=m_strText;
return strResult.AllocSysString();
}
其中m_strText是一個CString類的對象,保存語音識別引擎識別出來的字符串。對SetSRText函數不需加代碼。
5)添加事件
為了知道什么時候產生了識別出的文字,需要添加事件。用類向導添加事件SRResult,并且在CSREngineCtrl類中產生了FireSRResult()函數。在控件內部調用FireSRResult()函數,FireSRResult()函數調用FireEvent函數,從而對外部產生SRResult事件。另外當產生識別的文本時,語音識別引擎通過CMyReco類中自定義的消息WM_SREVENT進行通知。因此在CSREngineCtrl類中添加WM_SREVENT消息對應的消息響應函數OnSREvent()。在該函數中獲取識別出的文本,并調用FireSRResult()函數。
LRESULT CSREngineCtrl::OnSREvent(WPARAM,LPARAM){
WCHAR*pwzText;
m_SpeechReco.GetRecoText(&pwzText);
m_strText=CString(pwzText);
FireSRResult();
……
}
這樣當有文本被識別出來后,保存在m_strText中。然后調用FireSRResult()函數產生SRResult事件通知外部程序有識別出的文本,外部程序根據事件獲取SRtext屬性值,就可以獲取語音識別出來的文本。
最后編譯生成控件SREngine.ocx,那么在其他開發工具中就可調用了。
在Authorware中,使用“插入”菜單插入SREng控件。使用GetSpriteProperty()函數獲取SRtext屬性值,即獲取從語音中識別出的文本。用CallSprite函數設置語音識別控件的開始、暫停等功能[5]。用一個交互圖標進行對SRResult事件的響應,并對事件進行處理,即獲取SRtext屬性值,并顯示在文本框中。最后界面如圖3所示,輸入語音即可識別輸出文本。

圖3 語音識別控件測試Fig.3 Test of speech recognition control test
文中介紹了COM組件和ActiveX控件的轉化方法。通過一個語音識別的例子詳細說明轉化流程和方法。先將語音識別引擎接口封裝成一個C++類,這是方便對語音引擎接口的調用。然后添加控件的屬性、方法和事件設計控件。在控件方法和事件中,對類的函數成員或數據成員進行相應調用。最后,將控件在Authorware中運行得到較好效果。對于Authorware這樣的專用開發工具可以利用COM與其他應用程序進行通信[6-7],也可提高開發效率。
[1] Microsoft Corporation.Microsoft Speech SDK[EB/OL].(2009-3-3)[2012-4-20].http://download.microsoft.com/download/B/4/3/B4314928-7B71-4336-9DE7-6FA4CF00B 7B3/sapi.chm.
[2] 潘愛民.COM原理與應用[M].北京:清華大學出版社,1999.
[3] 史俊.語音數控機床的研究與實現[D].沈陽:沈陽航空工業學院,2007.
[4] 孫鑫,余安萍.VC++深入詳解[M].北京:電子工業出版社,2006.
[5] 孫偉.Authorware與Activex控件的高級通訊[J].集寧師專學報,2009,31(4):57-60.SUN Wei.A senior communication of authorware to the ActiveX control[J].Journal of Jining Teachers College,2009,31(4):57-60.
[6] 鄭楠,徐良賢.COM組件技術在多媒體軟件開發中的應用[J].計算機工程,2002,28(10):81-83.ZHENG Nan,XU Liang-xian.The application of COMin the development of mutimedia software[J].Computer Engineering,2002,28(10):81-83.
[7] Szyperski C.Component Software Beyond Object-oriented Programming[M].ACMPress,1998.