• C#WinForm调用COM实现语音功能


    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 网站上看到的有的是自己用对象浏览器慢慢找的....
  • 作者:wpf之家
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
  • 相关阅读:
    Spring 配置数据源的几种方式
    Java List 数据操作
    javascript 数组方法解析
    jQuery 获取页面元素的属性值
    表格列排序
    优秀资源的收集
    Java 集合介绍
    二进制、八进制、十进制、十六进制的转换
    Nginx配置
    Nginx安装
  • 原文地址:https://www.cnblogs.com/wpf123/p/2347494.html
Copyright © 2020-2023  润新知