C#英文語(yǔ)音合成與中文語(yǔ)音識(shí)別技術(shù)
C#英文語(yǔ)音合成與中文語(yǔ)音識(shí)別技術(shù)的實(shí)現(xiàn),先安裝微軟的Speech Application SDK(SASDK),它的***版本是 SAPI 5.1 他能夠識(shí)別中、日、英三種語(yǔ)言,你可以在這里下載:http://www.microsoft.com/speech/download/sdk51/,需要安裝這兩個(gè)文件Speech SDK 5.1和5.1 Language Pack,其中5.1 Language Pack可以選擇安裝支持的語(yǔ)言。
安裝好以后,我們就可以開始進(jìn)行語(yǔ)音程序的開發(fā)了,當(dāng)然,在這之前我們需要把SAPI.dll通過如下圖所示添加到引用中
下面我們?cè)O(shè)計(jì)一個(gè)能夠朗讀中英文混合語(yǔ)言的類:
我們將用單例模式實(shí)現(xiàn)該類,類的代碼如下,我們將詳細(xì)解釋:
- 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ā)生一個(gè)錯(cuò)誤:"+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;這里,我們定義個(gè)一個(gè)用來發(fā)音的類,并且在第一次調(diào)用該類時(shí),對(duì)它用BuildSpeach方法進(jìn)行了初始化。
- 我們還定義了兩個(gè)屬性Volume和Rate,能夠設(shè)置音量和語(yǔ)速。
- 我們知道,SpVoiceClass 有一個(gè)Speak方法,我們發(fā)音主要就是給他傳遞一個(gè)字符串,它負(fù)責(zé)讀出該字符串,如下所示。
- private void Speak(string strSpeack)
- {
- try
- {
- voice.Speak(strSpeack,SpeechVoiceSpeakFlags.SVSFlagsAsync) ;
- }
- catch(Exception err)
- {
- throw(new Exception("發(fā)生一個(gè)錯(cuò)誤:"+err.Message)) ;
- }
- }
其中SpeechVoiceSpeakFlags.SVSFlagsAsync表示異步發(fā)音。
但是,這個(gè)方法本身并不知道你給的字符串是什么語(yǔ)言,所以需要我們它這個(gè)字符串用什么語(yǔ)言讀出。SpVoiceClass 類的Voice 屬性就是用來設(shè)置語(yǔ)種的,我們可以通過SpVoiceClass 的GetVoices方法得到所有的語(yǔ)種列表,然后在根據(jù)參數(shù)選擇相應(yīng)的語(yǔ)種,比如設(shè)置語(yǔ)種為漢語(yǔ)如下所示:
- private void SetChinaVoice()
- {
- voicevoice.Voice = voice.GetVoices(string.Empty,string.Empty).Item(0) ;
- }
0表示是漢用,1234都表示英語(yǔ),就是口音不同。
這樣,我們就設(shè)置了語(yǔ)種,如果結(jié)合發(fā)音方法,我們就可以設(shè)計(jì)出一個(gè)只發(fā)漢語(yǔ)語(yǔ)音的方法
- private void SpeakChina(string strSpeak)
- {
- SetChinaVoice() ;
- Speak(strSpeak) ;
- }
只發(fā)英語(yǔ)語(yǔ)音的方法也是類似的,上面程序里有。
對(duì)于一段中英文混合的語(yǔ)言,我們讓程序讀出混合語(yǔ)音的方法就是:編程把這段語(yǔ)言的中英文分開,對(duì)于中文調(diào)用SpeakChina方法,英文調(diào)用SpeakEnglishi方法;至于怎樣判斷一個(gè)字符是英文還是中文,我采用的是判斷asc碼的方法,具體的類方法是通過AnalyseSpeak實(shí)現(xiàn)的。
這樣,對(duì)于一段中英文混合文字,我們只需把它作為參數(shù)傳遞給AnalyseSpeak就可以了,他能夠完成中英文的混合發(fā)音。
當(dāng)然,對(duì)于發(fā)音的暫定、繼續(xù)、停止等操作,上面也給出了簡(jiǎn)單的方法調(diào)用,很容易明白。
下面簡(jiǎn)單介紹一下C#英文、中文語(yǔ)音識(shí)別的方法:
先把該語(yǔ)音識(shí)別的類源代碼貼在下面,然后再做說明:
- 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為語(yǔ)音識(shí)別的上下文和語(yǔ)法,通過設(shè)置isrg的DictationSetState方法,我們可以開始或結(jié)束識(shí)別,在上面的程序中是BeginRec和CloseRec方法。cDisplay 是我們用來輸出識(shí)別結(jié)果的地方,為了能夠在大部分控件上都可以顯示結(jié)果,我用了一個(gè)Control 類來定義它。當(dāng)然,每次語(yǔ)音識(shí)別后都會(huì)觸發(fā)ISpeechRecoContextEvents_RecognitionEventHandler 事件,我們定義了一個(gè)這樣的方法ContexRecognition來響應(yīng)事件,并且在這個(gè)方法里輸出識(shí)別結(jié)果。
這樣,C#英文和中文語(yǔ)音處理的一些最基本的問題就有了一個(gè)簡(jiǎn)單的解決方法,當(dāng)然,這種方法還有很多不完善的地方,希望大家多提出批評(píng)意見,共同提高。
【編輯推薦】