C#中調(diào)用SAPI實現(xiàn)語音合成的2種方法
我們都知道現(xiàn)在的語音合成TTS是可以通過微軟的SAPI實現(xiàn)的,好處我就不多說了,方便而已,因為在微軟的操作系統(tǒng)里面就自帶了這個玩意,主要的方式有兩種:
1、使用COM組件技術(shù),不管是C++,C#,Delphi都能玩的轉(zhuǎn),開發(fā)出來的東西在XP和WIN7都能跑。(要引入SpeechLib,好像在項目上點引用,然后選到系統(tǒng)COM吧,好久沒弄,記不清楚了)
2、使用WIN7的windows api,其實最終還是調(diào)用了SAPI,所以開發(fā)出來的東西就只能在WIN7上面跑。
其實不管是哪一種,都是調(diào)用SAPI,可能后一種代碼比較簡單,使用已經(jīng)安裝的TTS引擎,現(xiàn)在一般用NeoSpeech,這個就不解釋了,太強大了這個發(fā)音。。。
COM組件技術(shù):
public class Speach { private static Speach _Instance = null ; private SpeechLib.SpVoiceClass voice =null; //SAPI5.1 private SpeechLib.SpVoice voice = null;//SAPI 5.4 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<strSpeak.Length;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,能夠設置音量和語速。
我們知道,SpVoiceClass 有一個Speak方法,我們發(fā)音主要就是給他傳遞一個字符串,它負責讀出該字符串,如下所示。
private void Speak(string strSpeack) { try { voice.Speak(strSpeack,SpeechVoiceSpeakFlags.SVSFlagsAsync) ; } catch(Exception err) { throw(new Exception("發(fā)生一個錯誤:"+err.Message)) ; } }
第二種使用.NET類庫和系統(tǒng)API的代碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Speech.Synthesis; using System.Speech; namespace StudyBeta { public class SRead { public SpeechSynthesizer synth; //語音合成對象 public SRead() { synth = new SpeechSynthesizer(); } public SRead(int m, int n) { //使用 synth 設置朗讀音量 [范圍 0 ~ 100] synth.Volume = m; //使用 synth 設置朗讀頻率 [范圍 -10 ~ 10] synth.Rate = n; } public void SpeakChina(string ggg) { //SpVoice Voice = new SpVoice(); synth.SelectVoice("Microsoft Lili"); //Voice.Speak(ggg, SpFlags); synth.SpeakAsync(ggg); //String speechPeople = synth.Voice; //使用 synth 設置朗讀音量 [范圍 0 ~ 100] // synth.Volume = 80; //使用 synth 設置朗讀頻率 [范圍 -10 ~ 10] // synth.Rate = 0; //使用synth 合成 wav 音頻文件: //synth.SetOutputToWaveFile(string path); } public void SpeakEnglish(string ggg) { //SpVoice Voice = new SpVoice(); synth.SelectVoice("VW Julie"); synth.Speak(ggg); //ggg為要合成的內(nèi)容 } public int m { get { return synth.Volume; } set { synth.Volume = value; } } public int n { get { return synth.Rate; } set { synth.Rate = value; } } }