C#中调用SAPI实现语音合成的2种方法
程序员文章站
2022-06-14 17:22:38
我们都知道现在的语音合成tts是可以通过微软的sapi实现的,好处我就不多说了,方便而已,因为在微软的操作系统里面就自带了这个玩意,主要的方式有两种:
1、使用com组件...
我们都知道现在的语音合成tts是可以通过微软的sapi实现的,好处我就不多说了,方便而已,因为在微软的操作系统里面就自带了这个玩意,主要的方式有两种:
1、使用com组件技术,不管是c++,c#,delphi都能玩的转,开发出来的东西在xp和win7都能跑。(要引入speechlib,好像在项目上点引用,然后选到系统com吧,好久没弄,记不清楚了)
2、使用win7的windows api,其实最终还是调用了sapi,所以开发出来的东西就只能在win7上面跑。
其实不管是哪一种,都是调用sapi,可能后一种代码比较简单,使用已经安装的tts引擎,现在一般用neospeech,这个就不解释了,太强大了这个发音。。。
com组件技术:
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("发生一个错误:"+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;这里,我们定义个一个用来发音的类,并且在第一次调用该类时,对它用buildspeach方法进行了初始化。
我们还定义了两个属性volume和rate,能够设置音量和语速。
我们知道,spvoiceclass 有一个speak方法,我们发音主要就是给他传递一个字符串,它负责读出该字符串,如下所示。
private void speak(string strspeack) { try { voice.speak(strspeack,speechvoicespeakflags.svsflagsasync) ; } catch(exception err) { throw(new exception("发生一个错误:"+err.message)) ; } }
第二种使用.net类库和系统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为要合成的内容 } public int m { get { return synth.volume; } set { synth.volume = value; } } public int n { get { return synth.rate; } set { synth.rate = value; } } }