代码改变世界

SpeechLib 语音播报

2014-07-27 18:50  stoneniqiu  阅读(22724)  评论(15编辑  收藏  举报

    SpeechLib这的dll专门用来播放语音,能够识别英语、简体和繁体。并且可以播放声音文件,支持WAV格式,但不支持MP3。在报警场合下已经够用了。

   基本播放语音及文件。支持异步。

using System;
using System.Threading;
using SpeechLib;

namespace  Model.AlarmHandle
{
   
    /// <summary>
    ///语音播报
    /// </summary>
    public class SpeechVoice
    {
        /// <summary>
        /// The _voice
        /// </summary>
        private SpVoice _voice;
        private SpVoiceClass spVoice;
        private readonly SpFileStreamClass spFile;



        /// <summary>
        /// Initializes a new instance of the <see cref="SpeechVoice"/> class.
        /// </summary>
        public SpeechVoice()
        {
            _voice = new SpVoice();
            spVoice = new SpVoiceClass();
            spFile = new SpFileStreamClass();
        }



        /// <summary>
        /// 播放
        /// </summary>
        /// <param name="text">The text.</param>
        /// <param name="speakFlag">The speak flag.</param>
        public void Speak(string text, SpeechVoiceSpeakFlags speakFlag = SpeechVoiceSpeakFlags.SVSFDefault)
        {
            _voice.Speak(string.Empty); _voice.Speak(text, speakFlag);
        }


        /// <summary>
        /// 异步播放
        /// </summary>
        /// <param name="text">The text.</param>
        public void SpeakAsync(string text)
        {
            _voice.Speak(text, SpeechVoiceSpeakFlags.SVSFlagsAsync);
        }

        /// <summary>
        /// Plays the sound.
        /// </summary>
        /// <param name="fileName">Name of the file.</param>
        public void PlaySound(string fileName)
        {
            //要加载COM组件:Microsoft speech object Library
            if (!System.IO.File.Exists(fileName)) return;
            spFile.Open(fileName, SpeechStreamFileMode.SSFMOpenForRead, true);
            var istream = spFile as ISpeechBaseStream;
            spVoice.SpeakStream(istream, SpeechVoiceSpeakFlags.SVSFIsFilename);
            spFile.Close();
        }

        /// <summary>
        /// 暂停
        /// </summary>
        public void Pause()
        {
            if (_voice != null)
                _voice.Pause();
        }

        /// <summary>
        /// Stops the voice.
        /// </summary>
        public void StopVoice()
        {
            _voice.Pause(); 
            _voice.Speak(string.Empty, SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak);
        }

        /// <summary>
        /// Pauses the file. 
        /// </summary>
        public void StopFile()
        {
            try
            {
                spFile.ISpStream_Close();
            }
            catch (Exception)
            {
            }
        }

        /// <summary>
        /// 恢复
        /// </summary>
        public void Resume()
        {
            if (_voice != null)
                _voice.Resume();
        }


    }
    /// <summary>
    ///语音播报状态
    /// </summary>
    public enum VoiceStatus
    {
        /// <summary>
        /// The play
        /// </summary>
        Play,
        /// <summary>
        /// The ready
        /// </summary>
        Ready,
        /// <summary>
        /// The pause
        /// </summary>
        Pause,
    }

}
View Code

   但真的运用时,还需要支持循环播放,以及播放状态。

   

   private SpeechVoice _speaker;
   private bool _isLoopAudioFile; // 是否循环播放声音文件
   private bool _isLoopSpeech;  //循环语音
  private VoiceStatus speakStatus=VoiceStatus.Ready;
  private bool IsStopPlayFile;    //是否停止
 private bool IsStopPlayVoice;

     /// <summary>
        /// 播放文件结束
        /// </summary>
        public event EventHandler PlayFileComplete;
        /// <summary>
        /// 播放文件开始
        /// </summary>
        public event EventHandler PlayFileStart;

        /// <summary>
        /// 播放文件结束
        /// </summary>
        public event EventHandler PlayAudioComplete;
        /// <summary>
        /// 播放文件开始
        /// </summary>
        public event EventHandler PlayAudioStart;

  /// <summary>
        /// 播放语言
        /// </summary>
        /// <param name="voiceContent">Content of the voice.</param>
        public void SpeechVoice(string voiceContent)
        {
            IsStopPlayVoice = false;
            if (speakStatus == VoiceStatus.Play) return; //正在播放就返回
            Speaker.Resume();
            Action invoke = () =>
            {
                OnPlayAudioStart();//触发开始播放事件 
                speakStatus = VoiceStatus.Play;
                Speaker.Speak(voiceContent);
            };
            invoke.BeginInvoke(VoiceCallback, invoke);
        }
  private void VoiceCallback(IAsyncResult ar)
        {
            var ac = ar.AsyncState as Action;
            if (ac != null)
            {
                try//原dll不能多次停止 所以加了try catch 和状态判断
                {
                    if ((IsLoopSpeech) && !IsStopPlayVoice)
                    {
                        //一次播放结束之后如果是循环播放 就继续播放
                        ac.BeginInvoke(VoiceCallback, ac);
                    }
                    else
                    {
                        speakStatus = VoiceStatus.Pause;
                        //触发停止事件
                        OnPlayAudioComplete(this, new EventArgs());
                        ac.EndInvoke(ar);
                    }
                }
                catch (Exception)
                {

                }
            }
        }

//以下同理
  /// <summary>
        /// 暂停播放
        /// </summary>
        public void StopSpeechVoice()
        {
            if (IsStopPlayVoice) return;
            IsStopPlayVoice = true;
            speakStatus = VoiceStatus.Pause;
            Action invoke = () => Speaker.StopVoice();
            invoke.BeginInvoke(null, invoke);
            OnPlayAudioComplete(this, new EventArgs());
        }
        /// <summary>
        /// 停止播放声音文件
        /// </summary>
        public void StopPlayer()
        {
            if (IsStopPlayVoice) return;
            IsStopPlayFile = true;
            speakStatus = VoiceStatus.Pause;
            Speaker.PauseFile();
            OnPlayFileComplete(this, new EventArgs());
        }

        /// <summary>
        /// 播放声音文件
        /// </summary>
        public void PlayAudioFile()
        {
            player = new SoundPlayer { SoundLocation = _audioFile.FilePath };
            if(speakStatus==VoiceStatus.Play) return;
            IsStopPlayFile = false;
            if (File.Exists(_audioFile.FilePath))
            {
                Action invoke = () =>
                {
                    OnPlayFileStart();
                    speakStatus = VoiceStatus.Play;
                    Speaker.PlaySound(_audioFile.FilePath);
                };
                invoke.BeginInvoke(Callback, invoke);
            }
        }
  
       /// <summary>
        /// Called when [play start].
        /// </summary>
        public void OnPlayFileStart()
        {
            var handler = PlayFileStart;
            if (handler != null) handler(this, EventArgs.Empty);
        }

        /// <summary>
        /// Called when [play start].
        /// </summary>
        public void OnPlayAudioStart()
        {
            var handler = PlayAudioStart;
            if (handler != null) handler(this, EventArgs.Empty);
        }

        /// <summary>
        /// Called when [play complete].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        public void OnPlayAudioComplete(object sender, EventArgs e)
        {
            EventHandler handler = PlayAudioComplete;
            if (handler != null) handler(this, EventArgs.Empty);
        }


        /// <summary>
        /// Called when [play complete].
        /// </summary>
        /// <param name="sender">The sender.</param>
        /// <param name="e">The <see cref="EventArgs"/> instance containing the event data.</param>
        public void OnPlayFileComplete (object sender, EventArgs e)
        {
            EventHandler handler = PlayFileComplete;
            if (handler != null) handler(this, EventArgs.Empty);
        }

             /// <summary>
        /// Callbacks the specified ar.
        /// </summary>
        /// <param name="ar">The ar.</param>
        private void Callback(IAsyncResult ar)
        {
            var ac = ar.AsyncState as Action;
            if (ac != null)
            {
                OnPlayFileComplete(this,new EventArgs());
                try
                {
                    if ((IsLoopAudioFile)&& !IsStopPlayFile)
                    {
                        ac.BeginInvoke(Callback, ac);
                    }
                    else
                    {
                        speakStatus = VoiceStatus.Pause; 
                        ac.EndInvoke(ar);
                    }
                }
                catch (Exception)
                {
                  
                }
            }
        }

语音播放小Demo:SpeechVoice  

在繁体系统,或者英文系统下面,有时候出现只能播报英文的情况,这个是犹豫语言资源没有安装。

判断操作系统是否安装中文最简单的方法:

64位系统:查看C:\Program Files (x86)\Common Files\SpeechEngines\Microsoft\TTS20路径下是否有zh-CHS文件夹

32位系统:查看C:\Program Files\Common Files\SpeechEngines\Microsoft\TTS20路径下是否有zh-CHS文件夹

 

如果不存在则表明缺少中文语言包,一般情况下,win7及以上的中文操作系统都自带了,不需要安装,其他操作系统基本上都没有安装,简体XP系统也没有安装

安装方法是:

1、  打开控制面板的window update,见下图:

2. 选择检查更新按钮,然后再更新列表中选择“可用的附件程序”

3、   选择简体中文语言包,勾选并安装即可

 

4、  安装完成后可以检查C:\Program Files (x86)\Common Files\SpeechEngines\Microsoft\TTS20路径下是否有zh-CHS文件夹,有则表明安装成功

 

安装成功以后就可以使用语音播报功能了。