一個整合微軟語音識別技術與語音朗讀的類,基於Microsoft SpeechAPI5.1的開發
//////////////////////////////////////////////////////////1,生成動態連線庫時,要#define USE_SPEECH_DLL,// 並且#define LANE_SPEECH_EXPORTS//2,使用動態連線庫時,要#define USE_SPEECH_DLL//3,聲稱和使用靜態連線庫時,什麼都不需要//4,另外主程式中靜態連線庫要呼叫的方式裡要呼叫CoInitialize( NULL )和CoUninitialize(),// 動態連線庫就不用呼叫了。////////////////////////////////////////////////////////#ifndef LANE_SPEECH_H#define LANE_SPEECH_H
#include <windows.h>#define _ATL_APARTMENT_THREADED#include <atlbase.h>extern CComModule _Module; //You may derive a class from CComModule and use it. if you want to override something,but do not change the name of _Module#include <atlcom.h>#include <sphelper.h> //sapi需要的標頭檔案
//-----生成動態連線庫和靜態庫的處理----------------#ifdef USE_SPEECH_DLL //定義了USE_SPEECH_DLL,就按生成DLL,宣告匯出匯入類
#ifdef LANE_SPEECH_EXPORTS #define LANE_SPEECH_DLL __declspec(dllexport) #else #define LANE_SPEECH_DLL __declspec(dllimport) #endif
//這個警告我現在還沒鬧清楚是怎麼回事了,估計是DLL和com或atl有關 //暫時只能遮蔽掉它,在靜態庫裡就不會出現這個警告。 #pragma warning( disable : 4251 )
#else //沒定義USE_SPEECH_DLL,則不宣告匯出或匯入類(LANE_SPEECH_DLL就為空) #define LANE_SPEECH_DLL
#endif //USE_SPEECH_DLL
//***************************常量***********************
/////////公共常量-----------------const DWORD SP_CHINESE = 0x0000; //簡體中文.const DWORD SP_ENGLISH = 0x0001; //英語.
/////////CTTS常量-----------------const UINT WM_SPEAK = WM_USER + 4444; //觸發事件產生的訊息。
/////////SR常量-------------------const UINT WM_RECOEVENT = WM_USER + 3333; //觸發事件產生的訊息。const DWORD SR_INPROC = 0x0000; //獨享型別的SR.const DWORD SR_SHARE = 0x0001; //共享型別的SR.
//以下常量僅作例子用。#define VID_TopLevelRule 9000 //頂級規則ID#define VID_SubLevelRule1 9001 //子規則ID#define VID_SubLevelRule2 9002 //子規則ID#define VID_SubLevelRule3 9003 //子規則ID
//*************************類宣告************************
class CSR;////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CTTS////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class LANE_SPEECH_DLL CTTS{protected: HWND m_hWnd; // 關聯的視窗控制代碼。
CComPtr<ISpVoice> m_pVoice; // 聲音物件的指標。 CComPtr<ISpObjectToken> m_pToken; // token物件的指標。 CComPtr<ISpAudio> m_pAudio; // 音訊物件的指標。(用來儲存原來預設的輸入流) CComPtr<ISpStream> m_pOutputStream; // 輸出到檔案的流物件。
public://********************************初始化部分********************
//////////////////////////////////////////////////////////////////// //功能: 儲存與識別引擎關聯的視窗控制代碼。 //引數: hWnd:要關聯的視窗控制代碼。 //返回值: 無。 //////////////////////////////////////////////////////////////////// CTTS ( const HWND hWnd );
//////////////////////////////////////////////////////////////////// //功能: 釋放所有的物件。 //引數: 無。 //返回值: 無。 //////////////////////////////////////////////////////////////////// ~CTTS ();
//////////////////////////////////////////////////////////////////// //功能: 建立一個voice物件。設定要是別的語言種類,訊息,通知事件。 //引數: dwLanguage:要朗讀的語言種類,SP_CHINESE為中文, // SP_ENGLISH為英文。 //返回值: HRESULT型別。 //////////////////////////////////////////////////////////////////// HRESULT Create( const DWORD dwLanguage = SP_CHINESE );
//////////////////////////////////////////////////////////////////// //功能: 從一個SR引擎建立一個voice物件。設定要是別的語言種類,訊息, // 通知事件。 //引數: pSRContext:SR引擎的指標。dwLanguage:要朗讀的語言種類, // SP_CHINESE為中文,SP_ENGLISH為英文。 //返回值: HRESULT型別。 //////////////////////////////////////////////////////////////////// HRESULT Create ( const CSR * pSR, const DWORD dwLanguage = SP_CHINESE );
//********************************設定部分***************************************
//////////////////////////////////////////////////////////////////// //功能: 設定朗讀聲音的語言種類。 //引數: dwLanguage:語言種類。SP_CHINESE為中文,SP_ENGLISH為英文。 //返回值: HRESULT型別。 //////////////////////////////////////////////////////////////////// HRESULT SetLanguage ( const DWORD dwLanguage );
//////////////////////////////////////////////////////////////////// //功能: 設定要處理的的事件。 //引數: ullInterest:來自enum SPEVENTENUM,要用SPFEI()轉化為64bit的, // 設定多個事件用運算子" | "。 用SPFEI_ALL_SR_EVENTS表示全部事 // 件都會收到通知。 //返回值: HRESULT。 //////////////////////////////////////////////////////////////////// HRESULT SetInterest ( const ULONGLONG ullInterest );
//////////////////////////////////////////////////////////////////// //功能: 設定朗讀聲音的音量。 //引數: usVolume:音量數值應該從0到100 //返回值: 無。 //////////////////////////////////////////////////////////////////// void SetVolume ( USHORT usVolume );
//////////////////////////////////////////////////////////////////// //功能: 得到朗讀聲音的音量。 //引數: 無。 //返回值: 音量數值,應該從0到100。 //////////////////////////////////////////////////////////////////// USHORT GetVolume ( );
//////////////////////////////////////////////////////////////////// //功能: 設定朗讀聲音的音速。 //引數: RateAdjust:音速,引數範圍從-10到10。 //返回值: 無。 //////////////////////////////////////////////////////////////////// void SetRate ( LONG RateAdjust );
//////////////////////////////////////////////////////////////////// //功能: 得到朗讀聲音的音速。 //引數: 無。 //返回值: 音速,引數範圍從-10到10。 //////////////////////////////////////////////////////////////////// LONG GetRate ( );
//////////////////////////////////////////////////////////////////// //功能: 設定朗讀的聲音流到.wav檔案,如果不呼叫此函式則預設從音箱輸出。 //引數: pszFileName:.wav檔案的檔名。要用" L"" "轉換。 //返回值: HRESULT。 //////////////////////////////////////////////////////////////////// HRESULT SetOutputWithWav ( const WCHAR *pszFileName = L"TtsOut.wav");
//////////////////////////////////////////////////////////////////// //功能: 設定朗讀的聲音從音箱輸出。 //引數: 無。 //返回值: HRESULT。 //////////////////////////////////////////////////////////////////// HRESULT UnSetOutputWithWav ();
//**********************播放語音,文字到語音轉換部分*****************************
//////////////////////////////////////////////////////////////////// //功能: 停止朗讀。如果朗讀為同步方式,則不能停止。 //引數: pwcs:要朗讀的字串,需用" L"" "轉換,可以是包含xml標記 // 的字串。dwFlags:朗讀方式。SPF_ASYNC為非同步,SVSFDefault為同步, // SVSFIsXML為朗讀帶xml標記的文字。 //返回值: HRESULT。 //////////////////////////////////////////////////////////////////// HRESULT Speak ( const WCHAR *pwcs, const DWORD dwFlags = SPF_ASYNC );
//////////////////////////////////////////////////////////////////// //功能: 停止朗讀。如果朗讀為同步方式,則不能停止。 //引數: 無。 //返回值: 無。 //////////////////////////////////////////////////////////////////// void Stop ( );
//////////////////////////////////////////////////////////////////// //功能: 暫停朗讀。如果朗讀為同步方式,則不能暫停。 //引數: 無。 //返回值: 無。 //////////////////////////////////////////////////////////////////// void Pause ();
//////////////////////////////////////////////////////////////////// //功能: 從暫停的地方繼續朗讀。 //引數: 無。 //返回值: 無。 //////////////////////////////////////////////////////////////////// void Resume ();
//********************************處理事件部分***********************************
public: //////////////////////////////////////////////////////////////////// //功能: 處理髮生的事件。系統自動呼叫,不需要使用者自己處理。 //引數: 無。 //返回值: 無。 //////////////////////////////////////////////////////////////////// void ProcessTTSEvent ();
//////////////////////////////////////////////////////////////////// //功能: 為虛擬函式。當輸出流結束時要觸發的動作,需要在派生類過載。 //引數: 無。 //返回值: 無。 //////////////////////////////////////////////////////////////////// virtual void OnStreamStart ();
//////////////////////////////////////////////////////////////////// //功能: 為虛擬函式。當輸出流結束時要觸發的動作,需要在派生類過載。 //引數: 無。 //返回值: 無。 //////////////////////////////////////////////////////////////////// virtual void OnStreamEnd ();};
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CSR////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
class LANE_SPEECH_DLL CSR{
protected: HWND m_hWnd;
public: CComPtr<ISpRecognizer> m_pSREngine; // 語音識別引擎(recognition)的介面。 CComPtr<ISpRecoContext> m_pSRContext; // 識別引擎上下文(context)的介面。 CComPtr<ISpRecoGrammar> m_pSRGrammar; // 識別文法(grammar)的介面。 CComPtr<ISpStream> m_pInputStream; // 流()的介面。 CComPtr<ISpObjectToken> m_pToken; // 語音特徵的(token)介面。 CComPtr<ISpAudio> m_pAudio; // 音訊(Audio)的介面。(用來儲存原來預設的輸入流)public: static ULONGLONG ullGrammerID; // Grammer的識別符號, 64位無符號整型 每建立一個Grammar,加一。
protected://***************************輔助功能部分****************************************
//////////////////////////////////////////////////////////////////// //GrammarID加一,每個GrammerID必須不同。 //////////////////////////////////////////////////////////////////// static void UpdateGrammerID ( );
public: //////////////////////////////////////////////////////////////////// //功能: 友員。TTS中的從SR引擎中建立voice物件。 //引數: pSRContext:SR上下文物件的指標。 //返回值: HRESULT型別。 //////////////////////////////////////////////////////////////////// friend HRESULT CTTS::Create ( const CSR * pSR, const DWORD dwLanguage );
//****************************初始化部分*****************************************
//////////////////////////////////////////////////////////////////// //功能: 儲存與識別引擎關聯的視窗控制代碼,更新GrammarID。 //引數: hWnd:要關聯的視窗控制代碼。 //返回值: 無。 //////////////////////////////////////////////////////////////////// CSR ( HWND hWnd );
//////////////////////////////////////////////////////////////////// //功能: 釋放所有的物件。 //引數: 無。 //返回值: 無。 //////////////////////////////////////////////////////////////////// ~CSR ( );
//////////////////////////////////////////////////////////////////// //功能: 建立各個介面的物件。設定要是別的語言種類,訊息,通知事件, // 載入文法檔案。 //引數: SRType:識別引擎的型別,SR_INPROC為獨享型別,SR_SHARE共享型別。 // pwcGramFileName:文法檔案的檔名,要用" L"" "轉換為WCHAR型。 // dwLanguage:要是別的語言種類,SP_CHINESE為中文,SP_ENGLISH為英文。 //返回值: HRESULT型別。 //////////////////////////////////////////////////////////////////// HRESULT Create (const DWORD SRType, const WCHAR *pwcGramFileName = L"grammar.xml", const DWORD dwLanguage = SP_CHINESE );
//**********************************設定部分*************************************
//////////////////////////////////////////////////////////////////// //功能: 設定要處理的上下文接受的事件。 //引數: ullInterest:來自enum SPEVENTENUM,要用SPFEI()轉化為64bit的, // 設定多個事件用運算子" | "。 用SPFEI_ALL_SR_EVENTS表示全部事 // 件都會收到通知。 //返回值: HRESULT。 //////////////////////////////////////////////////////////////////// HRESULT SetInterest ( const ULONGLONG ullInterest );
//////////////////////////////////////////////////////////////////// //功能: 設定某個規則的狀態(啟用或者取消啟用)。 //引數: pszName:規則名,要用" L"" "轉換。bFlag:TRUE表示啟用, // FALSE表示取消啟用。 //返回值: HRESULT。 //////////////////////////////////////////////////////////////////// HRESULT SetRuleState ( const WCHAR *pszName, const BOOL bFlag );
//////////////////////////////////////////////////////////////////// //功能: 設定識別引擎從.wav檔案識別語音,如果不呼叫此函式則預設從麥克 // 風輸入。 //引數: pszFileName:.wav檔案的檔名。要用" L"" "轉換。 //返回值: HRESULT。 //////////////////////////////////////////////////////////////////// HRESULT SetInputWithWav ( const WCHAR *pszFileName = L"sr.wav" );
//////////////////////////////////////////////////////////////////// //功能: 取消從.wav檔案識別。恢復從麥克風識別。 //引數: 無。 //返回值: HRESULT。 //////////////////////////////////////////////////////////////////// HRESULT UnSetInputWithWav ( );
//***********************識別開始,結束,識別結果的處理**************************
//////////////////////////////////////////////////////////////////// //功能: 識別開始(將所有規則啟用)。 //引數: 無 //返回值: 無。 //////////////////////////////////////////////////////////////////// void StartRecognize ( );
//////////////////////////////////////////////////////////////////// //功能: 識別結束(將所有規則取消啟用)。 //引數: 無。 //返回值: 無。 //////////////////////////////////////////////////////////////////// void EndRecognize ( );
public: //////////////////////////////////////////////////////////////////// //功能: 處理髮生的事件。系統自動呼叫,不需要使用者自己處理。 //引數: 無。 //返回值: 無。 //////////////////////////////////////////////////////////////////// void ProcessRecoEvent ( );
protected: //////////////////////////////////////////////////////////////////// //功能: 識別成功時要呼叫的函式。系統自動呼叫,不需要使用者自己處理。 //引數: pPhrase:ISpPhrase型別。 //返回值: 無。 //////////////////////////////////////////////////////////////////// void OnRecoSuccess ( ISpPhrase *pPhrase );
public: //////////////////////////////////////////////////////////////////// //功能: 識別成功後,根據規則的ID決定動作。系統自動呼叫。虛擬函式, // 需要在派生類過載。規則ID必須以常量形式預先定義。 //引數: ulRuleID:頂級規則的ID。ulVal:子規則的ID。 //返回值: 無。 //////////////////////////////////////////////////////////////////// virtual void ExecuteCommand ( const ULONG ulRuleID, const ULONG ulVal );
//////////////////////////////////////////////////////////////////// //功能: 識別失敗時的動作,系統自動呼叫。虛擬函式,需要在派生類過載。 //引數: 無。 //返回值: 無。 //////////////////////////////////////////////////////////////////// virtual void OnRecoFail ();
//////////////////////////////////////////////////////////////////// //功能: 為虛擬函式。當輸入流開始時要觸發的動作,需要在派生類過載。 //引數: 無。 //返回值: 無。 //////////////////////////////////////////////////////////////////// virtual void OnStreamStart ();
//////////////////////////////////////////////////////////////////// //功能: 為虛擬函式。當輸入流結束時要觸發的動作,需要在派生類過載。 //引數: 無。 //返回值: 無。 //////////////////////////////////////////////////////////////////// virtual void OnStreamEnd ();
};
#endif //LANE_SPEECH_DLL_H
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////// 檔案:LaneSpeech.cpp// 功能:封裝的speech sdk5.1 的文字語音合成(TTS)和語音識別(SR)功能// 語音識別只支援命令模式,不支援連續模式// 作者:呂寶虹(Lane), msn: [email protected], qq: 3619908// 日期: 2004.10// 版本:1.2// //////////////////////////////////////////////////////////
#include "LaneSpeech.h"
//-----生成動態連線庫和靜態庫的處理----------------#ifdef USE_SPEECH_DLL //定義了USE_SPEECH_DLL,就按生成DLL,宣告匯出匯入類
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){ switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: CoInitialize(NULL); break; case DLL_THREAD_ATTACH: break; case DLL_THREAD_DETACH: break; case DLL_PROCESS_DETACH: CoUninitialize(); break; } return TRUE;}
#endif //USE_SPEECH_DLL
///////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////// //功能: 彈出一個資訊框。 //引數: lpText:是對話方塊資訊。lpCaption:對話方塊標題。 //返回值: 無。 //////////////////////////////////////////////////////////////////// inline void ShowError ( const LPCTSTR lpText = "ERROR", const LPCTSTR lpCaption = "ERROR" ) { ::MessageBox( NULL, lpText, lpCaption, MB_OK | MB_ICONERROR ); }
//////////////////////////////////////////////////////////////////// //功能: 檢查一個HRESULT型別的值,如果是錯誤的值則,彈出資訊框提示錯誤。 //引數: hr:要檢查的HRESULT的引用。 lpText:是對話方塊資訊。 // lpCaption:對話方塊標題。 //返回值: 有錯則為FALSE,沒錯則返回TRUE。 //////////////////////////////////////////////////////////////////// inline BOOL CheckHr ( const HRESULT &hr, const LPCTSTR lpText = "ERROR", const LPCTSTR lpCaption = "ERROR" ) { if ( FAILED( hr ) ) { ShowError ( lpText, lpCaption ); return FALSE; } return TRUE; }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CTTS////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////儲存關聯視窗控制代碼。初始化COM。////////////////////////////////////////////////////////////////////CTTS::CTTS ( const HWND hWnd ){ m_hWnd = hWnd; m_pVoice = NULL; m_pToken = NULL; m_pOutputStream = NULL; m_pAudio = NULL;}
//////////////////////////////////////////////////////////////////////釋放所有物件。////////////////////////////////////////////////////////////////////CTTS::~CTTS (){ if( m_pToken) { m_pToken.Release(); m_pToken = NULL; } if( m_pAudio ) { m_pAudio.Release(); m_pAudio = NULL; } if ( m_pOutputStream ) { m_pOutputStream.Release(); m_pOutputStream = NULL; } if( m_pVoice ) { m_pVoice.Release(); m_pVoice = NULL; }}
//////////////////////////////////////////////////////////////////////從SR的上下文中得到voice物件。此函式在CSR中被宣告一個友員。////////////////////////////////////////////////////////////////////HRESULT CTTS::Create( const CSR * pSR, const DWORD dwLanguage ){ HRESULT hr; hr = pSR->m_pSRContext->GetVoice ( &m_pVoice ); if ( !::CheckHr ( hr, "pSRContext->GetVoice()" ) ) { return hr; }
SetLanguage ( dwLanguage );
hr = SpCreateDefaultObjectFromCategoryId ( SPCAT_AUDIOIN, &m_pAudio );//建立一個預設音訊流 if ( !::CheckHr ( hr, "CreateDefaultObjectFodd()" ) ) { return hr; }
//SPEI_START_INPUT_STREAM表示輸出物件開始接受流輸出SPEI_START_INPUT_STREAM //SPEI_END_INPUT_STREAM 表示完成流輸出。 hr = m_pVoice->SetInterest( SPFEI( SPEI_START_INPUT_STREAM ) | SPFEI( SPEI_END_INPUT_STREAM ), SPFEI( SPEI_START_INPUT_STREAM ) | SPFEI( SPEI_END_INPUT_STREAM ) ); if ( !::CheckHr ( hr, "m_pVoice->SetInterest()" ) ) { return hr; }
//設定通知訊息 hr = m_pVoice->SetNotifyWindowMessage( m_hWnd, WM_SPEAK, 0, 0 ); if ( !::CheckHr ( hr, "m_pVoice->SetNotifyWindowMessage()" ) ) { return hr; }
return hr;}
//////////////////////////////////////////////////////////////////////單獨(相對於從SR的上下文中得到voice物件)建立一個voice物件。//並設定興趣,設定通知事件。////////////////////////////////////////////////////////////////////HRESULT CTTS::Create( const DWORD dwLanguage ){ HRESULT hr; hr = m_pVoice.CoCreateInstance ( CLSID_SpVoice ); if ( !::CheckHr ( hr, "m_pVoice.CoCreateInstance()" ) ) { return hr; }
SetLanguage ( dwLanguage );
hr = SpCreateDefaultObjectFromCategoryId ( SPCAT_AUDIOIN, &m_pAudio );//建立一個預設音訊流 if ( !::CheckHr ( hr, "CreateDefaultObjectFodd()" ) ) { return hr; }
//SPEI_START_INPUT_STREAM表示輸出物件開始接受流輸出SPEI_START_INPUT_STREAM //SPEI_END_INPUT_STREAM 表示完成流輸出。 hr = m_pVoice->SetInterest( SPFEI( SPEI_START_INPUT_STREAM ) | SPFEI( SPEI_END_INPUT_STREAM ), SPFEI( SPEI_START_INPUT_STREAM ) | SPFEI( SPEI_END_INPUT_STREAM ) ); if ( !::CheckHr ( hr, "m_pVoice->SetInterest()" ) ) { return hr; }
//設定通知訊息 hr = m_pVoice->SetNotifyWindowMessage( m_hWnd, WM_SPEAK, 0, 0 ); if ( !::CheckHr ( hr, "m_pVoice->SetNotifyWindowMessage()" ) ) { return hr; }
return hr;}
//////////////////////////////////////////////////////////////////////設定語言,預設的語言為中文。SP_CHINESE為中文,SP_ENGLISH為英文////////////////////////////////////////////////////////////////////HRESULT CTTS::SetLanguage ( const DWORD dwLanguage ){ HRESULT hr; switch ( dwLanguage ) { case SP_CHINESE: hr = SpFindBestToken( SPCAT_VOICES, L"language=804", NULL, &m_pToken ); if ( !::CheckHr ( hr, "SpFindBestToken()錯誤", "CTTS::SetLanguage" ) ) { return hr; } hr = m_pVoice->SetVoice( m_pToken ); if ( !::CheckHr ( hr, "SpFindBestToken()錯誤", "CTTS::SetLanguage" ) ) { return hr; } break;
case SP_ENGLISH: hr = SpFindBestToken( SPCAT_VOICES, L"language=409", NULL, &m_pToken ); if ( !::CheckHr ( hr, "SpFindBestToken()錯誤", "CTTS::SetLanguage" ) ) { return hr; } hr = m_pVoice->SetVoice( m_pToken ); if ( !::CheckHr ( hr, "SpFindBestToken()錯誤", "CTTS::SetLanguage" ) ) { return hr; } break; default: ::ShowError ( "設定中文請用SP_CHINESE,設定英文請用SP_ENGLISH", "CTTS::SetLanguage()引數錯誤" ); }
return hr;}
//////////////////////////////////////////////////////////////////////設定要處理的事件。////////////////////////////////////////////////////////////////////HRESULT CTTS::SetInterest ( const ULONGLONG ullInterest ){ HRESULT hr; // 設定pvoice感興趣的事件。 hr = m_pVoice->SetInterest( ullInterest, ullInterest ); if ( !::CheckHr ( hr, "m_pVoice->SetInterest()", "CTTS::SetInterest()" ) ) { return hr; } /*//設定通知訊息 hr = m_pVoice->SetNotifyWindowMessage( hWnd, WM_SPEAK, 0, 0 ); if ( !::CheckHr ( hr, "m_pVoice->SetNotifyWindowMessage()", "CTTS::SetInterest()" ) ) { return hr; }*/ return hr;}
//////////////////////////////////////////////////////////////////////設定朗讀音量。音量數值應該從0到100////////////////////////////////////////////////////////////////////void CTTS::SetVolume ( USHORT usVolume ){ if ( (usVolume > 100) || (usVolume<0) ) { ::ShowError ( "CTTS::SetVolume音量範圍應該從0到100" ); return; } m_pVoice->SetVolume( usVolume );}
//////////////////////////////////////////////////////////////////////取得音量的值。////////////////////////////////////////////////////////////////////USHORT CTTS::GetVolume ( ){ USHORT usVolume; m_pVoice->GetVolume ( &usVolume ); return usVolume;}
//////////////////////////////////////////////////////////////////////設定語速。引數範圍從-10到10////////////////////////////////////////////////////////////////////void CTTS::SetRate ( LONG RateAdjust ){ if ( (RateAdjust < -10) || (RateAdjust > 10) ) { ::ShowError ( "SetRate()設定的數值必須在 -10到10之間" ); return; } m_pVoice->SetRate ( RateAdjust );}
//////////////////////////////////////////////////////////////////////得到當前語速的數值。////////////////////////////////////////////////////////////////////LONG CTTS::GetRate ( ){ LONG RateAdjust; m_pVoice->GetRate( &RateAdjust ); return RateAdjust;}
//////////////////////////////////////////////////////////////////////設定朗讀的聲音流到.wav檔案,如果不呼叫此函式則預設從音箱輸出。//並設定要處理的事件,應該包含對流的開始和結束。在Create()中已經設定好了。////////////////////////////////////////////////////////////////////HRESULT CTTS::SetOutputWithWav ( const WCHAR *pszFileName ) //,LONG Format = PSF_22kHz16BitStereo){ HRESULT hr;
CSpStreamFormat sOutputFormat;
CComPtr<ISpStreamFormat> cpOldStream;
m_pVoice->GetOutputStream( &cpOldStream ); sOutputFormat.AssignFormat( SPSF_22kHz16BitStereo ); //sOutputFormat.AssignFormat(cpOldStream);
hr = SPBindToFile( pszFileName, SPFM_CREATE_ALWAYS, //SPFM_CREATE, //SPFM_OPEN_READWRITE, &m_pOutputStream, &sOutputFormat.FormatId(), sOutputFormat.WaveFormatExPtr() ); if ( !::CheckHr ( hr, "SPBindToFile" ) ) { return hr; }
hr = m_pVoice->SetOutput ( m_pOutputStream, TRUE ); if ( !::CheckHr ( hr, "m_pVoice->SetOutput()" ) ) { return hr; } return hr;}
//////////////////////////////////////////////////////////////////////設定朗讀的聲音從音箱輸出。////////////////////////////////////////////////////////////////////HRESULT CTTS::UnSetOutputWithWav (){ HRESULT hr; hr = m_pVoice->SetOutput ( m_pAudio, FALSE ); ::CheckHr ( hr, "UnSetOutputWithWav ()" ); m_pOutputStream->Close (); return hr;}
//////////////////////////////////////////////////////////////////////朗讀。dwFlags為SPF_ASYNC時,指非同步朗讀。SPF_DEFAULT為同步。//SPF_IS_XML指pwcs中包含xml標籤。按xml標籤的設定朗讀。////////////////////////////////////////////////////////////////////HRESULT CTTS::Speak ( const WCHAR *pwcs, const DWORD dwFlags ){ //WCHAR WTX[] = L"<VOICE REQUIRED=''NAME=Microsoft Mary''/>text to wave"; HRESULT hr; hr = m_pVoice->Speak ( pwcs, dwFlags, NULL); ::CheckHr ( hr, "CTTS::Speak" ); return hr;}
//////////////////////////////////////////////////////////////////////停止播放。Speak()為同步朗讀時不能停止。////////////////////////////////////////////////////////////////////void CTTS::Stop ( ){ m_pVoice->Speak ( NULL, SPF_ASYNC, NULL );}
//////////////////////////////////////////////////////////////////////暫停朗讀。////////////////////////////////////////////////////////////////////void CTTS::Pause (){ m_pVoice->Pause ();}
//////////////////////////////////////////////////////////////////////從暫停處繼續朗讀////////////////////////////////////////////////////////////////////void CTTS::Resume (){ m_pVoice->Resume ();}
//////////////////////////////////////////////////////////////////////從事件佇列取得事件並處理。根據相應的事件呼叫相應的函式。////////////////////////////////////////////////////////////////////void CTTS::ProcessTTSEvent (){ CSpEvent event; // 事件助手類
// 迴圈處理事件當事件佇列裡有事件的時候。 while ( event.GetFrom(m_pVoice) == S_OK ) { // 察看識別成功事件和識別失敗事件 switch (event.eEventId) { case SPEI_START_INPUT_STREAM: OnStreamStart (); break;
case SPEI_END_INPUT_STREAM: OnStreamEnd (); break;
case SPEI_VOICE_CHANGE: //OnVoiceChange (); break;
case SPEI_TTS_BOOKMARK: //OnBookMark (); break; case SPEI_WORD_BOUNDARY: //OnWordBoundAry (); break; } }}
//////////////////////////////////////////////////////////////////////流輸出到檔案開始時要觸發的事件。////////////////////////////////////////////////////////////////////void CTTS::OnStreamStart (){ ShowError ("朗讀開始");}
//////////////////////////////////////////////////////////////////////流輸出到檔案結束時要觸發的事件。////////////////////////////////////////////////////////////////////void CTTS::OnStreamEnd (){ ShowError ("朗讀完畢");}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CSR////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////儲存視窗控制代碼,初始化介面指標,呼叫UpdateGrammerID()。//如果要建立多個Grammar,Grammar必須不同。/////////////////////////////////////////////////////////CSR::CSR ( HWND hWnd ){ m_hWnd = hWnd; m_pSREngine = NULL; m_pSRContext = NULL; m_pSRGrammar = NULL; m_pInputStream = NULL; m_pToken = NULL; m_pAudio = NULL;
UpdateGrammerID ( );}
///////////////////////////////////////////////////////////更新GrammerID:GrammerID+1。為static函式。/////////////////////////////////////////////////////////void CSR::UpdateGrammerID ( ){ ullGrammerID ++;}
///////////////////////////////////////////////////////////建立引擎ISpRecognizer,設定識別語言。//建立引擎上下文ISpRecoContext,設定感興趣的事件及發生事件要通知視窗的訊息。//建立上下文的文法ISpRecoGrammar。從.xml檔案載入文法。/////////////////////////////////////////////////////////HRESULT CSR::Create ( const DWORD dwSRType, const WCHAR *pwcGramFileName, const DWORD dwLanguage ){ HRESULT hr = S_OK;
//容錯. if ( (dwSRType != SR_INPROC) && (dwSRType != SR_SHARE) ) { ::ShowError ( "指定要建立的SR型別錯誤,請用SR_INPROC或SR_SHARE呼叫" ); return 0x3333; } if ( (dwLanguage != SP_CHINESE) && (dwLanguage != SP_ENGLISH) ) { ::ShowError ( "請選擇要建立的SR的語言的種類:SP_CHINESE,SP_ENGLISH" ); return 0x3434; }
if ( dwSRType == SR_INPROC ) { //建立一個獨享的識別引擎,這裡必須呼叫SetInput() hr = m_pSREngine.CoCreateInstance ( CLSID_SpInprocRecognizer ); if ( !::CheckHr ( hr, "m_pSREngine.CoCreateInstance()" ) ) { return hr; }
hr = SpCreateDefaultObjectFromCategoryId ( SPCAT_AUDIOIN, &m_pAudio );//建立一個預設音訊流 if ( !::CheckHr ( hr, "CreateDefaultObjectFodd()" ) ) { return hr; }
hr = m_pSREngine->SetInput ( m_pAudio, TRUE );//為識別引擎設定音訊輸入 if ( !::CheckHr ( hr, "m_pSREngine->SetInput()" ) ) { return hr; } } else { hr = m_pSREngine.CoCreateInstance ( CLSID_SpSharedRecognizer );//建立一個共享的SR引擎。 if ( !::CheckHr ( hr, "m_pSREngine.CoCreateInstance()" ) ) { return hr; } }
//設定識別的語言。 if ( dwLanguage == SP_CHINESE ) { hr = SpFindBestToken ( SPCAT_RECOGNIZERS, L"language=804", NULL, &m_pToken ); } else { hr = SpFindBestToken ( SPCAT_RECOGNIZERS, L"language=409", NULL, &m_pToken ); } if ( !::CheckHr ( hr, "SpFindBestToken()" ) ) { return hr; } hr = m_pSREngine->SetRecognizer ( m_pToken ); if ( !::CheckHr ( hr, "m_pSREngine->SetRecognizerI()" ) ) { return hr; }
//為引擎建立一個上下文介面 hr = m_pSREngine->CreateRecoContext ( &m_pSRContext ); if ( !::CheckHr ( hr, "m_pSREngine->CreateRecoContext()" ) ) { return hr; }
//設定通知視窗的訊息 hr = m_pSRContext->SetNotifyWindowMessage ( m_hWnd, WM_RECOEVENT, 0, 0 ); if ( !::CheckHr ( hr, "m_pSRContext->SetNotifyWindowMessage()" ) ) { return hr; }
//設定興趣。 //hr = m_pSRContext->SetInterest ( SPFEI_ALL_SR_EVENTS, SPFEI_ALL_SR_EVENTS ); hr = m_pSRContext->SetInterest ( SPFEI( SPEI_RECOGNITION ) | SPFEI( SPEI_FALSE_RECOGNITION ), SPFEI( SPEI_RECOGNITION ) | SPFEI( SPEI_FALSE_RECOGNITION ) ); if ( !::CheckHr ( hr, "m_pSRContext->SetInterest()" ) ) { return hr; }
//建立一個Grammar hr = m_pSRContext->CreateGrammar ( ullGrammerID, &m_pSRGrammar ); if ( !::CheckHr ( hr, "m_pSRContext->CreateGrammar()" ) ) { return hr; }
//從檔案載入識別文法.檔名為WCHAR型別。 hr = m_pSRGrammar->LoadCmdFromFile ( pwcGramFileName, SPLO_DYNAMIC ); if ( !::CheckHr ( hr, "m_pSRGrammar->LoadCmdFromFile" ) ) { return hr; }
return hr;}
///////////////////////////////////////////////////////////釋放所有物件。/////////////////////////////////////////////////////////CSR::~CSR( ){ if ( m_pSRGrammar ) { m_pSRGrammar.Release(); m_pSRGrammar = NULL; } if ( m_pSRContext ) { m_pSRContext->SetNotifySink(NULL); m_pSRContext.Release(); m_pSRContext = NULL; } if ( m_pToken) { m_pToken.Release(); m_pToken = NULL; } if ( m_pAudio ) { m_pAudio.Release(); m_pAudio = NULL; } if ( m_pInputStream ) { m_pInputStream.Release(); m_pInputStream = NULL; } if ( m_pSREngine ) { m_pSREngine.Release(); m_pSREngine = NULL; }}
///////////////////////////////////////////////////////////設定要處理的事件。即上下文要捕捉的事件。//ullInterest 必須是用SPFEI()轉化每個事件,然後用"|"運算得來。//事件的型別是 enum SPEVENTENUM/////////////////////////////////////////////////////////HRESULT CSR::SetInterest ( const ULONGLONG ullInterest ){ HRESULT hr; hr = m_pSRContext->SetInterest ( ullInterest, ullInterest ); ::CheckHr ( hr, "CSR::SetInterest" );
//設定通知視窗的訊息 /*hr = m_pSRContext->SetNotifyWindowMessage ( m_hWnd, WM_RECOEVENT, 0, 0 ); if ( !::CheckHr ( hr, "m_pSRContext->SetNotifyWindowMessage()" ) ) { return hr; }*/ return hr;}
///////////////////////////////////////////////////////////啟用或者取消某個啟用規則。//m_pSRGrammar->SetRuleState的第三個引數為一個enum SPRULESTATE型別,//常用的為SPRS_INACTIVE,SPRS_ACTIVE。/////////////////////////////////////////////////////////HRESULT CSR::SetRuleState ( const WCHAR *pszName, const BOOL bFlag ){ HRESULT hr;
if ( bFlag ){ hr = m_pSRGrammar->SetRuleState ( pszName, NULL, SPRS_ACTIVE ); } else { hr = m_pSRGrammar->SetRuleState ( pszName, NULL, SPRS_INACTIVE ); } ::CheckHr ( hr, "CSR::SetRuleState()" );
return hr;}
///////////////////////////////////////////////////////////設定.wav檔案的聲音取樣格式要用到enum SPSTREAMFORMAT型別/////////////////////////////////////////////////////////HRESULT CSR::SetInputWithWav ( const WCHAR *pszFileName ){ HRESULT hr;
//取消規則啟用先 hr = m_pSRGrammar->SetRuleState ( NULL, NULL, SPRS_INACTIVE ); if ( !::CheckHr ( hr, "m_pSRGrammar->SetRuleState" ) ) { return hr; }
// 建立基本的sapi流物件。用SpBindToFile繫結到檔案 hr = m_pInputStream.CoCreateInstance(CLSID_SpStream); if ( !::CheckHr ( hr, "m_pInputStream.CoCreateInstance" ) ) { return hr; }
//建立WaveFormatEx結構,wav格式是22kHz, 16-bit, Stereo CSpStreamFormat sInputFormat; hr = sInputFormat.AssignFormat(SPSF_22kHz16BitStereo); if ( !::CheckHr ( hr, "sInputFormat.AssignFormat" ) ) { return hr; }
//用wav檔案pszFileName設定流物件,只讀 hr = m_pInputStream->BindToFile ( pszFileName, SPFM_OPEN_READONLY, &sInputFormat.FormatId(), sInputFormat.WaveFormatExPtr(), SPFEI_ALL_EVENTS ); if ( !::CheckHr ( hr, "m_pInputStream->BindToFile" ) ) { return hr; }
// 連線wav輸入到SR. hr = m_pSREngine->SetInput(m_pInputStream, TRUE); if ( !::CheckHr ( hr, "m_pSREngine->SetInput()" ) ) { return hr; }
//檢查 識別和流結束 事件 hr = m_pSRContext->SetInterest (SPFEI(SPEI_RECOGNITION) | SPFEI( SPEI_RECOGNITION ) | SPFEI(SPEI_END_SR_STREAM) | SPFEI(SPEI_START_SR_STREAM), SPFEI(SPEI_RECOGNITION) | SPFEI( SPEI_RECOGNITION ) | SPFEI(SPEI_END_SR_STREAM) | SPFEI(SPEI_START_SR_STREAM) );
//設定通知訊息。 hr = m_pSRContext->SetNotifyWindowMessage ( m_hWnd, WM_RECOEVENT, 0, 0 ); if ( !::CheckHr ( hr, "m_pSRContext->SetNotifyWindowMessage()" ) ) { return hr; }
return hr;}
///////////////////////////////////////////////////////////取消從.wav檔案識別,恢復從麥克風識別。/////////////////////////////////////////////////////////HRESULT CSR::UnSetInputWithWav ( ){ HRESULT hr;
//取消規則啟用先 hr = m_pSRGrammar->SetRuleState ( NULL, NULL, SPRS_INACTIVE ); if ( !::CheckHr ( hr, "m_pSRGrammar->SetRuleState" ) ) { return hr; }
hr = m_pSREngine->SetInput ( m_pAudio, TRUE );//為識別引擎設定音訊輸入 if ( !::CheckHr ( hr, "m_pSREngine->SetInput()" ) ) { return hr; }
//更新上下文 hr = m_pSRContext->GetRecognizer ( &m_pSREngine ); if ( !::CheckHr ( hr, "m_pSRContext->GetRecognizer()" ) ) { return hr; }
//設定通知視窗的訊息 hr = m_pSRContext->SetNotifyWindowMessage ( m_hWnd, WM_RECOEVENT, 0, 0 ); if ( !::CheckHr ( hr, "m_pSRContext->SetNotifyWindowMessage()" ) ) { return hr; }
//設定興趣。 hr = m_pSRContext->SetInterest ( SPFEI( SPEI_RECOGNITION ) | SPFEI( SPEI_FALSE_RECOGNITION ), SPFEI( SPEI_RECOGNITION ) | SPFEI( SPEI_FALSE_RECOGNITION ) ); if ( !::CheckHr ( hr, "m_pSRContext->SetInterest()" ) ) { return hr; }
//釋放流 hr = m_pInputStream->Close(); if ( !::CheckHr ( hr, "m_pInputStream->Close" ) ) { return hr; } //規則全部啟用。 hr = m_pSRGrammar->SetRuleState ( NULL, NULL, SPRS_INACTIVE ); if ( !::CheckHr ( hr, "m_pSRGrammar->SetRuleState" ) ) { return hr; }
return hr;}
///////////////////////////////////////////////////////////開始識別(啟用所有規則)。/////////////////////////////////////////////////////////void CSR::StartRecognize ( ){ HRESULT hr; //啟用文法規則,第一個NULL說明啟用全部規則。 hr = m_pSRGrammar->SetRuleState ( NULL, NULL, SPRS_ACTIVE ); ::CheckHr ( hr, "m_pSRGrammar->SetRuleState" );}
///////////////////////////////////////////////////////////識別結束(取消啟用所有規則)。/////////////////////////////////////////////////////////void CSR::EndRecognize ( ){ HRESULT hr; //取消啟用文法規則,第一個NULL說明取消啟用全部規則。 hr = m_pSRGrammar->SetRuleState ( NULL, NULL, SPRS_INACTIVE ); ::CheckHr ( hr, "m_pSRGrammar->SetRuleState" ); return ;}
///////////////////////////////////////////////////////////從事件佇列取得事件並處理。根據相應的事件呼叫相應的函式。/////////////////////////////////////////////////////////void CSR::ProcessRecoEvent( ){ CSpEvent event; // 事件助手類
// 迴圈處理事件當事件佇列裡有事件的時候。 while ( event.GetFrom(m_pSRContext) == S_OK ) { // 察看識別成功事件和識別失敗事件 switch (event.eEventId) { case SPEI_RECOGNITION: //識別成功 OnRecoSuccess ( event.RecoResult() ); break;
case SPEI_FALSE_RECOGNITION://識別失敗 OnRecoFail (); break;
case SPEI_START_SR_STREAM: OnStreamStart (); break;
case SPEI_END_SR_STREAM: OnStreamEnd (); break; } }}
///////////////////////////////////////////////////////////識別成功,把識別成功的短語的所屬的規則頂級ID和子規則的ID傳遞給//ExecuteCommand()。/////////////////////////////////////////////////////////void CSR::OnRecoSuccess ( ISpPhrase *pPhrase ){ SPPHRASE *pElements;
//得到短語元素,如果其中一個規則id (rule id )是我們在文法中指定的, //在switch中判斷出是哪一個命令被識別。 if (SUCCEEDED(pPhrase->GetPhrase(&pElements))) { ExecuteCommand ( pElements->Rule.ulId, pElements->pProperties->vValue.ulVal );
//釋放我們分配的pElements記憶體空間 ::CoTaskMemFree(pElements); }}
///////////////////////////////////////////////////////////根據識別的短語執行相應的動作。規則ID必須以常量形式預先定義。/////////////////////////////////////////////////////////void CSR::ExecuteCommand ( const ULONG ulRuleID, const ULONG ulVal ){ switch ( ulRuleID ) //Rule.ulID型別是: ULONG { case VID_TopLevelRule://這裡為頂級規則。 switch ( ulVal ) { case VID_SubLevelRule1://這裡為VID_TopLevelRule規則下的子規則。 ::ShowError ( "子規則1" ); break; case VID_SubLevelRule2: ::ShowError ( "子規則2" ); break; case VID_SubLevelRule3: ::ShowError ( "子規則3" ); break; } break;
default: break; }}
///////////////////////////////////////////////////////////識別失敗時觸發的動作。/////////////////////////////////////////////////////////void CSR::OnRecoFail ( ){ ::ShowError ( "識別失敗", "識別失敗" );}
///////////////////////////////////////////////////////////開始從檔案讀入流開始時要觸發的事件。/////////////////////////////////////////////////////////void CSR::OnStreamStart (){ //::ShowError("識別開始");}
///////////////////////////////////////////////////////////開始從檔案讀入流結束時要觸發的事件。/////////////////////////////////////////////////////////void CSR::OnStreamEnd (){ //::ShowError("識別結束");}
ULONGLONG CSR::ullGrammerID = 1000;
需要的留下Email,我給大家發