C#英文語音合成與中文語音識別技術(shù)
C#英文語音合成與中文語音識別技術(shù)的實現(xiàn),先安裝微軟的Speech Application SDK(SASDK),它的***版本是 SAPI 5.1 他能夠識別中、日、英三種語言,你可以在這里下載:http://www.microsoft.com/speech/download/sdk51/,需要安裝這兩個文件Speech SDK 5.1和5.1 Language Pack,其中5.1 Language Pack可以選擇安裝支持的語言。
安裝好以后,我們就可以開始進行語音程序的開發(fā)了,當然,在這之前我們需要把SAPI.dll通過如下圖所示添加到引用中
下面我們設(shè)計一個能夠朗讀中英文混合語言的類:
我們將用單例模式實現(xiàn)該類,類的代碼如下,我們將詳細解釋:
- public class Speach
- {
- private static Speach _Instance = null ;
- private SpeechLib.SpVoiceClass voice =null;
- private Speach()
- {
- BuildSpeach() ;
- }
- public static Speach instance()
- {
- if (_Instance == null)
- _Instance = new Speach() ;
- return _Instance ;
- }
- private void SetChinaVoice()
- {
- voice.Voice = voice.GetVoices(string.Empty,string.Empty).Item(0) ;
- }
- private void SetEnglishVoice()
- {
- voice.Voice = voice.GetVoices(string.Empty,string.Empty).Item(1) ;
- }
- private void SpeakChina(string strSpeak)
- {
- SetChinaVoice() ;
- Speak(strSpeak) ;
- }
- private void SpeakEnglishi(string strSpeak)
- {
- SetEnglishVoice() ;
- Speak(strSpeak) ;
- }
- public void AnalyseSpeak(string strSpeak)
- {
- int iCbeg = 0 ;
- int iEbeg = 0 ;
- bool IsChina = true ;
- for(int i=0;i
- {
- char chr = strSpeak[i] ;
- if (IsChina)
- {
- if (chr<=122&&chr>=65)
- {
- int iLen = i - iCbeg ;
- string strValue = strSpeak.Substring(iCbeg,iLen) ;
- SpeakChina(strValue) ;
- iEbeg = i ;
- IsChina = false ;
- }
- }
- else
- {
- if (chr>122||chr<65)
- {
- int iLen = i - iEbeg ;
- string strValue = strSpeak.Substring(iEbeg,iLen) ;
- this.SpeakEnglishi(strValue) ;
- iCbeg = i ;
- IsChina = true ;
- }
- }
- }//end for
- if (IsChina)
- {
- int iLen = strSpeak.Length - iCbeg ;
- string strValue = strSpeak.Substring(iCbeg,iLen) ;
- SpeakChina(strValue) ;
- }
- else
- {
- int iLen = strSpeak.Length - iEbeg ;
- string strValue = strSpeak.Substring(iEbeg,iLen) ;
- SpeakEnglishi(strValue) ;
- }
- }
- private void BuildSpeach()
- {
- if (voice == null)
- voice = new SpVoiceClass() ;
- }
- public int Volume
- {
- get
- {
- return voice.Volume ;
- }
- set
- {
- voice.SetVolume((ushort)(value)) ;
- }
- }
- public int Rate
- {
- get
- {
- return voice.Rate ;
- }
- set
- {
- voice.SetRate(value) ;
- }
- }
- private void Speak(string strSpeack)
- {
- try
- {
- voice.Speak(strSpeack,SpeechVoiceSpeakFlags.SVSFlagsAsync) ;
- }
- catch(Exception err)
- {
- throw(new Exception("發(fā)生一個錯誤:"+err.Message)) ;
- }
- }
- public void Stop()
- {
- voice.Speak(string.Empty,SpeechLib.SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak) ;
- }
- public void Pause()
- {
- voice.Pause() ;
- }
- public void Continue()
- {
- voice.Resume() ;
- }
- }//end class
- 在 private SpeechLib.SpVoiceClass voice =null;這里,我們定義個一個用來發(fā)音的類,并且在第一次調(diào)用該類時,對它用BuildSpeach方法進行了初始化。
- 我們還定義了兩個屬性Volume和Rate,能夠設(shè)置音量和語速。
- 我們知道,SpVoiceClass 有一個Speak方法,我們發(fā)音主要就是給他傳遞一個字符串,它負責(zé)讀出該字符串,如下所示。
- private void Speak(string strSpeack)
- {
- try
- {
- voice.Speak(strSpeack,SpeechVoiceSpeakFlags.SVSFlagsAsync) ;
- }
- catch(Exception err)
- {
- throw(new Exception("發(fā)生一個錯誤:"+err.Message)) ;
- }
- }
其中SpeechVoiceSpeakFlags.SVSFlagsAsync表示異步發(fā)音。
但是,這個方法本身并不知道你給的字符串是什么語言,所以需要我們它這個字符串用什么語言讀出。SpVoiceClass 類的Voice 屬性就是用來設(shè)置語種的,我們可以通過SpVoiceClass 的GetVoices方法得到所有的語種列表,然后在根據(jù)參數(shù)選擇相應(yīng)的語種,比如設(shè)置語種為漢語如下所示:
- private void SetChinaVoice()
- {
- voicevoice.Voice = voice.GetVoices(string.Empty,string.Empty).Item(0) ;
- }
0表示是漢用,1234都表示英語,就是口音不同。
這樣,我們就設(shè)置了語種,如果結(jié)合發(fā)音方法,我們就可以設(shè)計出一個只發(fā)漢語語音的方法
- private void SpeakChina(string strSpeak)
- {
- SetChinaVoice() ;
- Speak(strSpeak) ;
- }
只發(fā)英語語音的方法也是類似的,上面程序里有。
對于一段中英文混合的語言,我們讓程序讀出混合語音的方法就是:編程把這段語言的中英文分開,對于中文調(diào)用SpeakChina方法,英文調(diào)用SpeakEnglishi方法;至于怎樣判斷一個字符是英文還是中文,我采用的是判斷asc碼的方法,具體的類方法是通過AnalyseSpeak實現(xiàn)的。
這樣,對于一段中英文混合文字,我們只需把它作為參數(shù)傳遞給AnalyseSpeak就可以了,他能夠完成中英文的混合發(fā)音。
當然,對于發(fā)音的暫定、繼續(xù)、停止等操作,上面也給出了簡單的方法調(diào)用,很容易明白。
下面簡單介紹一下C#英文、中文語音識別的方法:
先把該語音識別的類源代碼貼在下面,然后再做說明:
- public class SpRecognition
- {
- private static SpRecognition _Instance = null ;
- private SpeechLib.ISpeechRecoGrammar isrg ;
- private SpeechLib.SpSharedRecoContextClass ssrContex =null;
- private System.Windows.Forms.Control cDisplay ;
- private SpRecognition()
- {
- ssrContex = new SpSharedRecoContextClass() ;
- isrg = ssrContex.CreateGrammar(1) ;
- SpeechLib._ISpeechRecoContextEvents_RecognitionEventHandler recHandle =
- new _ISpeechRecoContextEvents_RecognitionEventHandler(ContexRecognition) ;
- ssrContex.Recognition += recHandle ;
- }
- public void BeginRec(Control tbResult)
- {
- isrg.DictationSetState(SpeechRuleState.SGDSActive) ;
- cDisplay = tbResult ;
- }
- public static SpRecognition instance()
- {
- if (_Instance == null)
- _Instance = new SpRecognition() ;
- return _Instance ;
- }
- public void CloseRec()
- {
- isrg.DictationSetState(SpeechRuleState.SGDSInactive) ;
- }
- private void ContexRecognition(int iIndex,object obj,SpeechLib.SpeechRecognitionType type,SpeechLib.ISpeechRecoResult result)
- {
- cDisplay.Text += result.PhraseInfo.GetText(0,-1,true) ;
- }
- }
我們定義了ssrContex 和isrg為語音識別的上下文和語法,通過設(shè)置isrg的DictationSetState方法,我們可以開始或結(jié)束識別,在上面的程序中是BeginRec和CloseRec方法。cDisplay 是我們用來輸出識別結(jié)果的地方,為了能夠在大部分控件上都可以顯示結(jié)果,我用了一個Control 類來定義它。當然,每次語音識別后都會觸發(fā)ISpeechRecoContextEvents_RecognitionEventHandler 事件,我們定義了一個這樣的方法ContexRecognition來響應(yīng)事件,并且在這個方法里輸出識別結(jié)果。
這樣,C#英文和中文語音處理的一些最基本的問題就有了一個簡單的解決方法,當然,這種方法還有很多不完善的地方,希望大家多提出批評意見,共同提高。
【編輯推薦】