Windows 系统调用.COM.微软语言引擎简单应用(C#) 本文主要讲述,如何调用微软的语言引擎... 应用场景 如看图识字软件等等....(我可不是作语言软件的、这个子是做着玩的)
涉及技术 动态调用Com对象(全反射、没有引用com ocx) 取得系统存在的各种语言引擎 使用引擎进行朗读 使用引擎进行保存声音
程序图列:
主要功能描述 实列变量等,构造函授等
取得所有的 识别对象模块集合,放入下拉框
代码
object _spVoiceCls = null; //保存朗读用的 SAPI.SpVoice
const int SpFlags = 1; //SpeechVoiceSpeakFlags.SVSFlagsAsyn
object _oISpeechObjectTokens = null; //保存 SAPI.ISpeechObjectTokens 就是系统有的语音引擎集合
int TokensCount = 0; // 语音引擎集合 数 DictionaryEntry[] _deTokens=null; //榜定下拉框用的
public MainForm() { InitializeComponent(); this.HandleDestroyed += new EventHandler(Form1_HandleDestroyed); }
private void Form1_Load(object sender, EventArgs e) {
InitSAPI(); }
系统事件:程序加载
取得所有的 识别对象模块集合,放入下拉框
代码
void InitSAPI() { //创建语音对象朗读用 _spVoiceCls = CreateComObject("SAPI.SpVoice");
if (_spVoiceCls == null) {
MessageBox.Show("您的系统没有,微软语音组件"); Application.Exit(); } else {//取得所有的 识别对象模块集合
_oISpeechObjectTokens = CallComMethod("GetVoices", _spVoiceCls); //取得SAPI.ISpeechObjectTokens //识别对象集合 Count; object r = GetComPropery("Count", _oISpeechObjectTokens); if (r is int) {
TokensCount = (int)r;
if (TokensCount > 0) { //取得全部语音识别对象模块,及名称,以被以后使用 _deTokens = new DictionaryEntry[TokensCount]; for (int i = 0; i < TokensCount; i++) { //从集合中取出单个 识别对象模块 object oSpObjectToken = CallComMethod("Item", _oISpeechObjectTokens, i); //返回 SAPI.SpObjectToken //取名称 string Description = CallComMethod("GetDescription", oSpObjectToken) as string; //放到 DictionaryEntry 对象中,key 是 识别对象模块,value 是名称 _deTokens= new DictionaryEntry(oSpObjectToken, Description);
} //邦定到 下拉框 cboxTokens.DisplayMember = "Value"; cboxTokens.ValueMember = "Key"; cboxTokens.DataSource = _deTokens; cboxTokens.SelectedIndex = 0; }
}
}
}
用户事件:朗读
朗读输入的文本信息
代码
private void btnSynthesis_Click(object sender, EventArgs e) { string msg = rTxtMsg.Text.Trim(); if (msg.Length != 0) {
if (_spVoiceCls != null) { //设置语言引擎 SetComProperty("Voice", _spVoiceCls, cboxTokens.SelectedValue); //调用Speak 函数,msg 是要播放的文本,1 是异步播放,因为是异步的 com 对象不立刻释放 CallComMethod("Speak", _spVoiceCls, msg, SpFlags);
} }
}
用户事件:保存声音
将输入的文本信息生成音频文件保存到文件
代码
private void Save() { string msg = rTxtMsg.Text.Trim(); if (msg.Length != 0) { using (SaveFileDialog sfd = new SaveFileDialog()) { sfd.Filter = "wav 文件 (*.wav)|*.wav"; sfd.RestoreDirectory = true; if (sfd.ShowDialog() == DialogResult.OK) { /* Enum SpeechStreamFileMode; SSFMOpenForRead = 0; SSFMOpenReadWrite = 1; SSFMCreate = 2; SSFMCreateForWrite = 3;
*/
int SpFileMode = 3;// SpeechStreamFileMode.SSFMCreateForWrite
object oSpFileStream = CreateComObject("SAPI.SpFileStream"); //创建 SAPI.SpFileStream
object oSpVoice = CreateComObject("SAPI.SpVoice"); //创建 SAPI.SpVoice
try { CallComMethod("Open", oSpFileStream, sfd.FileName, SpFileMode, false); //打开流 SetComProperty("Voice", oSpVoice, cboxTokens.SelectedValue); //设置 Voice 属性,让谁朗读 SetComProperty("AudioOutputStream", oSpVoice, oSpFileStream); //设置流
CallComMethod("Speak", oSpVoice, msg, SpFlags); //调用 Speak
CallComMethod("WaitUntilDone", oSpVoice, Timeout.Infinite); //等 CallComMethod("Close", oSpFileStream); //关闭流
MessageBox.Show("保存成功"); } finally { Marshal.ReleaseComObject(oSpVoice); Marshal.ReleaseComObject(oSpFileStream); }
}
} }
} private void btnSave_Click(object sender, EventArgs e) {
try { btnSave.Enabled = false; Save();
} catch (Exception ex) { MessageBox.Show(ex.Message); } finally { btnSave.Enabled = true; }
}
调用com组件,功能函数
自己写的一些帮助函数可以方便调用反射,要不太郁闷(如果是VB 就不用如此费尽了)
#region 调用com组件,功能通用函数 /// <summary> /// 设置属性 /// </summary> /// <param name="name"></param> /// <param name="o"></param> /// <param name="vlaue"></param> private static void SetComProperty(string name, object o, object vlaue) { Type t = o.GetType(); t.InvokeMember(name, BindingFlags.Instance | BindingFlags.SetProperty, null, o, new object[] { vlaue }); } /// <summary> /// 取得属性 /// </summary> /// <param name="name"></param> /// <param name="o"></param> /// <returns></returns> private static object GetComPropery(string name, object o) { Type t = o.GetType(); return t.InvokeMember(name, BindingFlags.Instance | BindingFlags.GetProperty, null, o, null); } /// <summary> /// 调用方法函授 /// </summary> /// <param name="name"></param> /// <param name="o"></param> /// <param name="parms"></param> /// <returns></returns> private static object CallComMethod(string name, object o, params object[] parms) { Type t = o.GetType();
return t.InvokeMember(name, BindingFlags.Instance | BindingFlags.InvokeMethod, null, o, parms); } /// <summary> /// 创建 com 对象 /// </summary> /// <param name="FromProgID"></param> /// <returns></returns> private static object CreateComObject(string FromProgID) { Type comType = Type.GetTypeFromProgID(FromProgID); object rVar = null; if (comType != null) rVar = System.Activator.CreateInstance(comType);
return rVar; } #endregion
释放com对象 很简单的就一行即可
代码 void Form1_HandleDestroyed(object sender, EventArgs e) { //释放com对象 Marshal.ReleaseComObject(_spVoiceCls);
}
说明 关于 SAPI 对象的具体情参考,msdn Microsoft Speech SDK 部分是英文的帮助(VS2003 和 VS2005 的都有,ms 网站上好像也有),我英文也不好没法翻译抱歉,我用的这些函数有的是在 ms 网站上看到的有的是自己用对象浏览器慢慢找的.... |