为了方便调用暂停、继续的方法。要将speech的功能写成一个类。直接附上代码:
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Speech.Synthesis; 5 using System.Text; 6 using System.Speech; 7 8 namespace WindowsFormsApplication1 9 { 10 public class TextToSpeak 11 { 12 //想要实现暂停等功能,要调用朗读时使用的SpeechSynthesizer对象 13 SpeechSynthesizer speech = new SpeechSynthesizer(); 14 15 /// <summary> 16 /// 朗读 17 /// </summary> 18 /// <param name="text">文本</param> 19 /// <param name="rate">语速</param> 20 public void Speak(string text, int rate) 21 { 22 speech.Rate = rate; 23 speech.Speak(text); 24 speech.Dispose(); 25 } 26 27 /// <summary> 28 /// 朗读 29 /// </summary> 30 /// <param name="text">文本</param> 31 /// <param name="rate">语速</param> 32 /// <param name="gender">性别</param> 33 public void Speak(string text, int rate, string gender) 34 { 35 36 speech.Rate = rate; 37 try 38 { 39 if (gender.ToLower() == "male") 40 { 41 speech.SelectVoice("VW Paul"); 42 } 43 else if (gender.ToLower() == "female") 44 { 45 speech.SelectVoice("VW Kate"); 46 } 47 48 } 49 //这个异常是语音库未安装 50 catch (ArgumentException) 51 { 52 53 throw; 54 } 55 finally 56 { 57 speech.Speak(text); 58 speech.Dispose(); 59 } 60 } 61 62 /// <summary> 63 /// 保存音频文件 64 /// </summary> 65 /// <param name="path">路径</param> 66 /// <param name="text">文本</param> 67 /// <param name="rate">语速</param> 68 /// <param name="gender">性别,可为null</param> 69 public void SaveWaveFile(string path, string text, int rate, string gender) 70 { 71 speech.Rate = rate; 72 try 73 { 74 if (gender.ToLower() == "male") 75 { 76 speech.SelectVoice("VW Paul"); 77 } 78 else if (gender.ToLower() == "female") 79 { 80 speech.SelectVoice("VW Kate"); 81 } 82 83 } 84 catch (ArgumentException) 85 { 86 87 throw; 88 } 89 finally 90 { 91 speech.SetOutputToWaveFile(path); 92 speech.Speak(text); 93 speech.SetOutputToNull(); 94 } 95 } 96 97 public void SpeakPause() 98 { 99 speech.Pause(); 100 } 101 102 public void SpeakResume() 103 { 104 speech.Resume(); 105 } 106 107 public void SpeakStop() 108 { 109 speech.Dispose(); 110 } 111 } 112 }
我使用的是winfrom实现这个类的。一开始想都没想直接给按钮加上click事件,调用TextToSpeak类的Speak方法,给另一个按钮添加SpeakPause功能。运行时复制了好几段英文,发现窗体出现假死,但是依然有声音输出,这叫我怎么暂停嘛,有点小凌乱。想想这情况应该类似于多线程,不要笑话我,winfrom没怎么弄过,之前一直搞的时asp.net。在网上搜了下进度条的实现方法,最后定下来使用backgroundWorker,不因为别的,就是看着别人写的比较方便~~~
简单介绍下backgroundWorker吧。它就在工具栏里躺着。它有好几个方法。
1. 这个就是后台运行的进程 backgroundWorker1_DoWork(objectsender,DoWorkeventArgs e)。在这里就放extToSpeak类的Speak方法。它用backgroundWorker1.RunWokerAsync(参数,可不加)来调用。所以就把这个方法放到播放按钮的click事件里咯。
2.backgroundWorker1_ProgressChanged这个是运行时可以执行的方法。用backgroundWorker1.ReportProgress(int)调用。
3.backgroundWorker1_RunWorkerCompleted这个是进程结束时执行的。
具体的请看:http://www.cnblogs.com/inforasc/archive/2009/10/12/1582110.html
我是直接在winfrom里放了个richtextbox,用来写入要读的英文。一开始我想当然在backgroundWorker1_DoWork(objectsender,DoWorkeventArgs e)里的speak中,直接把richtextbox.text的值传进去,但运行时没有一点反应。一开始不懂哪错了,一点一点的试。后台代码不好调哇,又不能直接调试到代码,只能用个提示语句来帮忙了。最后才发现是卡在richtextbox.text,它读取不到这个值。好像是啥原因的~~~但为啥我那个语速的插件值能读到呢,就因为它是int型么。。那怎么办呢,只能在click事件里调用时传参啦。我有两个参数,一个是text一个是性别,那就string数组了。
上代码:
1 _ttSpeak = new TextToSpeak(); 2 string[] parameter = { richTextBox1.Text, cbbsex.Text }; 3 backgroundWorker1.RunWorkerAsync(parameter);
细心的小伙伴应该发现了_ttSpeak = new TextToSpeak(),这个实例化语句怪怪的。其实和TextToSpeak类似,都是把实例化的类对象声明为成员变量。为啥这里要重新实例化呢,一开始我也没注意。运行程序时,第二次点朗读按钮时没反应了。原来是第一次运行时已经把Synthesis的资源释放了。所以要重新实例化一个,即重写成员变量。
之后想要使用暂停、继续功能就很方便了。
1 _ttSpeak.SpeakPause();
_ttSpeak.SpeakResume();
还有个注意点,在执行朗读功能是要把朗读按钮禁用,否则在执行时再click就会报错哦,等运行结束后再启用。
就是把启用的方法写在backgroundWorker1_RunWorkerCompleted里就行啦~~~