本文主要介紹如何使用微軟TTS語音引擎實現(xiàn)文本朗讀,以及生成wav格式的聲音文件。
1.語音引擎及語音庫的安裝 TTS(Text-To-Speech)是指文本語音的簡稱,即通過TTS引擎把文本轉(zhuǎn)化為語音輸出。 微軟TTS語音引擎提供了Windows Speech SDK開發(fā)包供編程者使用。Windows Speech SDK包含語音合成SS引擎和語音識別SR引擎兩種,語音合成引擎用于將文字轉(zhuǎn)換成語音輸出,語音識別引擎用于識別語音命令。 Windows Speech SDK可以在微軟的官網(wǎng)上免費下載,下載地址為:http://www.microsoft.com/download/en/details.aspx?id=10121 在該下載界面中,選擇下載SpeechSDK51.exe、SpeechSDK51LangPach.exe和sapi.chm 即可。其中,SpeechSDK51.exe是簡體中文語音引擎,SpeechSDK51LangPach.exe是中文男生語音庫,sapi.chm是SAPI(The Microsoft Speech API)幫助文檔。 下載完成后,先安裝語音引擎SpeechSDK51.exe,再安裝中文語音庫SpeechSDK51LangPach.exe。安裝完成后,可以依次點擊【開始】/【控制面板】/【語言】打開圖1所示的語言屬性對話框。在該對話框的“文字-語音轉(zhuǎn)換”標(biāo)簽頁下的“語音選擇”中能夠看到當(dāng)前系統(tǒng)安裝的全部可用的語音庫。 圖1 語言屬性對話框
2.ISpVoice接口的成員函數(shù) 文本朗讀的功能主要是通過使用ISpVoice接口的成員函數(shù)來實現(xiàn)的。該接口的常用成員函數(shù)有如下一些: (1)HRESULT Speak(LPCWSTR *pwcs, DWORD dwFlags, ULONG *pulStreamNumber); //朗讀文本 (2)HRESULT Pause ( void); //暫停朗讀 (3)HRESULT Resume ( void); //恢復(fù)朗讀 (4)HRESULT SetRate( long RateAdjust); //設(shè)置朗讀速度(取值范圍:-10到10) (5)HRESULT GetRate(long *pRateAdjust); //獲取朗讀速度 (6)HRESULT SetVoice(ISpObjectToken *pToken); //設(shè)置使用的語音庫 (7)HRESULT GetVoice(ISpObjectToken** ppToken); //獲取語音庫 (8)HRESULT SetVolume(USHORT usVolume); //設(shè)置音量(取值范圍:0到100) (9)HRESULT GetVolume(USHORT *pusVolume); //獲取音量 (10)HRESULT SetOutput(IUnknown *pUnkOutput,BOOL fAllowFormatChanges); //設(shè)置輸出 (11)HRESULT SpeakStream(IStream *pStream, DWORD dwFlags, ULONG *pulStreamNumber); //朗讀wav數(shù)據(jù)流
3.編程實例 了解了以上一些ISpVoice接口的成員函數(shù)之后,我們就可以開始編寫程序來實現(xiàn)文本朗讀,以及生成wav格式聲音文件的功能了。 3.1環(huán)境配置 首先,我們需要將Windows Speech SDK開發(fā)包的頭文件和庫文件所在路徑添加到編譯器中,具體方法如下(這里以VC++6.0為例): 依次點擊【工具】/【選項】,打開選項對話框,選擇【目錄】標(biāo)簽,在【路徑】中加入“C:\Program Files\Microsoft Speech SDK 5.1\Include”和“C:\Program Files\Microsoft Speech SDK 5.1\Lib\i386”。如圖2所示。 圖2 選項對話框 其次,還需要在工程中包含TTS語音引擎頭文件和庫文件,具體如下: 1 #include <sapi.h> //包含TTS語音引擎頭文件和庫文件 2 #include <sphelper.h> 3 #pragma comment(lib, "sapi.lib") 3.2枚舉語音庫 枚舉語音庫需要使用到SpEnumTokens()函數(shù),該函數(shù)原型如下: 1 inline HRESULT SpEnumTokens( 2 const WCHAR *pszCategoryId, 3 const WCHAR *pszReqAttribs, 4 const WCHAR *pszOptAttribs, 5 IEnumSpObjectTokens **ppEnum 6 ); 其中,參數(shù)ppEnum是IEnumSpObjectTokens類型的指針,用于存儲枚舉得到的所有語音Token。IEnumSpObjectTokens的成員函數(shù)GetCount()用于得到語音Token的總個數(shù),而成員函數(shù)Item()則用于得到具體的某一個語音Token。 如下的代碼示例如何枚舉得到的所有語音Token,并將得到的語音庫的名字添加到下拉組合框控件中,具體實現(xiàn)如下: 1 /* 2 * 函數(shù)功能 : 初始化語言包選擇組合框控件 3 * 備 注 : 4 * 作 者 : 博客園 依舊淡然 5 */ 6 void CTTSDemoDlg::InitVoicePackageSelComboxCtrl() 7 { 8 //初始化COM組件 9 if(FAILED(::CoInitialize(NULL))) 10 { 11 MessageBox("初始化COM組件失敗!", "提示", MB_OK|MB_ICONWARNING); 12 return; 13 } 14 15 //枚舉所有語音Token 16 if(SUCCEEDED(SpEnumTokens(SPCAT_VOICES, NULL, NULL, &m_pIEnumSpObjectTokens))) 17 { 18 //得到所有語音Token的個數(shù) 19 ULONG ulTokensNumber = 0; 20 m_pIEnumSpObjectTokens->GetCount(&ulTokensNumber); 21 22 //檢測該機器是否安裝有語音包 23 if(ulTokensNumber == 0) 24 { 25 MessageBox("該機器沒有安裝語音包!", "提示", MB_OK|MB_ICONWARNING); 26 return; 27 } 28 29 //將語音包的名字加入組合框控件 30 CString strVoicePackageName = _T(""); 31 CString strTokenPrefixText = _T("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Speech\\Voices\\Tokens\\"); 32 for(ULONG i=0; i<ulTokensNumber; i++) 33 { 34 m_pIEnumSpObjectTokens->Item(i, &m_pISpObjectToken); 35 WCHAR* pChar; 36 m_pISpObjectToken->GetId(&pChar); 37 strVoicePackageName = pChar; 38 strVoicePackageName.Delete(0, strTokenPrefixText.GetLength()); 39 m_ComboxVoiceSel.InsertString(i, strVoicePackageName); 40 } 41 42 //設(shè)置默認的語音包選擇 43 m_ComboxVoiceSel.SetCurSel(0); 44 } 45 } 通過以上的代碼可以看到,首先,我們通過調(diào)用CoInitialize()函數(shù)完成了對COM組件的初始化。然后,我們調(diào)用SpEnumTokens()函數(shù)得到了m_pIEnumSpObjectTokens對象,該對象存儲了枚舉得到的所有語音Token。緊接著,我們調(diào)用GetCount()函數(shù)得到個數(shù),并調(diào)用Item()函數(shù)得到具體的每一個語音Token對象m_pISpObjectToken。最后,我們通過調(diào)用m_pISpObjectToken對象的GetId()函數(shù)便能得到具體的某一個Token對象的ID,其形式為“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Speech\Voices\Tokens\XXXXX”,去掉其前綴便能得到具體的語音庫的名字了。 該實例運行效果如圖3所示,點擊“語音包選擇”組合框下拉箭頭,能夠看到與圖1中列出的語音包是一致的。 圖3 TTS示例運行效果 3.3文本朗讀 點擊圖3所示界面中的“開始朗讀”按鈕,能夠根據(jù)當(dāng)前所選擇的語音包以及設(shè)定的語速和音量,對朗讀內(nèi)容編輯框中的內(nèi)容進行朗讀。其具體實現(xiàn)方法如下: 1 /* 2 * 函數(shù)功能 : 點擊"開始朗讀"按鈕時,該函數(shù)被調(diào)用 3 * 備 注 : 4 * 作 者 : 博客園 依舊淡然 5 */ 6 void CTTSDemoDlg::OnButtonStartRead() 7 { 8 UpdateData(true); 9 10 //獲取ISpVoice接口 11 if(FAILED(CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_INPROC_SERVER, IID_ISpVoice, (void**)&m_pISpVoice))) 12 { 13 MessageBox("獲取ISpVoice接口失敗!", "提示", MB_OK|MB_ICONWARNING); 14 return; 15 } 16 17 //設(shè)置語言 18 m_pIEnumSpObjectTokens->Item(m_ComboxVoiceSel.GetCurSel(), &m_pISpObjectToken); 19 m_pISpVoice->SetVoice(m_pISpObjectToken); 20 21 //設(shè)置播放速度 22 m_pISpVoice->SetRate(m_SliderVoiceSpeed.GetPos() - 10); 23 24 //設(shè)置音量大小 25 m_pISpVoice->SetVolume(100 - m_SliderVoiceSize.GetPos()); 26 27 //檢測朗讀內(nèi)容是否為空 28 if(m_EditContent.IsEmpty()) 29 { 30 MessageBox("朗讀內(nèi)容不能為空!", "提示", MB_OK|MB_ICONWARNING); 31 return; 32 } 33 34 //開始進行朗讀 35 m_pISpVoice->Speak(m_EditContent.AllocSysString(), SPF_ASYNC, NULL); 36 } 在以上代碼中可以看到,使用了ISpVoice接口函數(shù)來完成語音庫的選擇、語速和音量大小的設(shè)定,以及通過調(diào)用Speak()函數(shù)進行文本朗讀。 3.4生成WAV格式的聲音文件 要將文本朗讀的聲音保存為WAV格式的聲音文件,主要是通過調(diào)用ISpVoice接口函數(shù)GetOutputStream()和SetOutput()來實現(xiàn)的。 以下的代碼段給出了實現(xiàn)該功能的示例: 1 //生成WAV文件 2 CComPtr<ISpStream> cpISpStream; 3 CComPtr<ISpStreamFormat> cpISpStreamFormat; 4 CSpStreamFormat spStreamFormat; 5 m_pISpVoice->GetOutputStream(&cpISpStreamFormat); 6 spStreamFormat.AssignFormat(cpISpStreamFormat); 7 HRESULT hResult = SPBindToFile("C:\\Documents and Settings\\Administrator\\桌面\\TEST\\test.wav", 8 SPFM_CREATE_ALWAYS, 9 &cpISpStream, 10 &spStreamFormat.FormatId(), 11 spStreamFormat.WaveFormatExPtr()); 12 if(SUCCEEDED(hResult)) 13 { 14 m_pISpVoice->SetOutput(cpISpStream, TRUE); 15 m_pISpVoice->Speak(m_EditContent.AllocSysString(), SPF_DEFAULT, NULL); 16 MessageBox("生成WAV文件成功!", "提示", MB_OK); 17 } 18 else 19 { 20 MessageBox("生成WAV文件失敗!", "提示", MB_OK|MB_ICONWARNING); 21 }
|
|
來自: goodwangLib > 《C#語音》