C#中调用SAPI实现语音合成的2种方法

我们都知道现在的语音合成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;
      }
    }
}

(0)

相关推荐

  • RFC2702 Requirements for Traffic Engineering over MPLS

    基于MPLS的流量工程要求 (RFC2702   Requirements for Traffic Engineering over MPLS) 1. 介绍 2. 流量工程 2.1 流量工程性能指标 2.2 流量与资源控制 2.3 现有IGP控制机制的局限性 3. MPLS和流量工程  3.1MPLS导图  3.2 基于MPLS流量工程的基本问题 4.基于MPLS流量工程的增强功能 5.流量主干的属性和特征  5.1 双向的流量主干  5.2 对流量主干的基本操作 5.3 统计与性能监测 5.4

  • c#中SAPI使用总结——SpVoice的使用方法

    要使用SAPI,首先添加引用DotNetSpeech,请自行下载DotNetSpeech.dll. 初始化对象,SpVoice voice = new DotNetSpeech.SpVoiceClass(); 朗读时,使用 voice.Speak(string,SpeechVoiceSpeakFlags.SVSFlagsAsync); 暂停,使用 voice.Pause(); 从暂停中继续刚才的朗读,使用 voice.Resume(); 停止功能是大多资料都没有写清楚的,而且在网上很少能找到,这

  • 使用C#实现RTP数据包传输 参照RFC3550

    闲暇时折腾IP网络视频监控系统,需要支持视频帧数据包在网络内的传输.未采用H.264或MPEG4等编码压缩方式,直接使用Bitmap图片.由于对帧的准确到达要求不好,所以采用UDP传输.如果发生网络丢包现象则直接将帧丢弃.为了记录数据包的传输顺序和帧的时间戳,所以研究了下RFC3550协议,采用RTP包封装视频帧.并未全面深究,所以未使用SSRC和CSRC,因为不确切了解其用意.不过目前的实现情况已经足够了. 复制代码 代码如下: /// <summary>   /// RTP(RFC3550

  • C#如何通过RFC连接sap系统

    先理解一下 RFC(Romote Function Call)远程函数调用 调用前提: 1.要想通过C# 通过RFC调用SAP端,SAP端要存在RFC远程调用的函数才行(例如SAP端通过SE37创建),要不然是无法调用的. 2.C#调用RFC要有NCO DLL支持(我们使用NCO3.0,VS2013,framework2.0才行否则会报错) 注:好多人64位系统,开发的时候报错,到处找支持64位的NCO3.0,这里可以说一下,是木有的,报错是困为Framework的原因.NCO3.0只支持2.0

  • C#中调用SAPI实现语音识别的2种方法

    通过微软的SAPI,不仅仅可以实现语音合成TTS,同样可以实现语音识别SR.下面我们就介绍并贴出相关代码.主要有两种方式: 1.使用COM组件技术,不管是C++,C#,Delphi都能玩的转,开发出来的东西在XP和WIN7都能跑.(注意要引入系统组件SpeechLib,XP要安装识别引擎) 2.使用WIN7的windows api,其实最终还是调用了SAPI,所以开发出来的东西就只能在WIN7上面跑. 其实不管是哪一种,都是调用SAPI,可能后一种代码比较简单. 使用第一种方式,需要注意在COM

  • C#中调用SAPI实现语音合成的2种方法

    我们都知道现在的语音合成TTS是可以通过微软的SAPI实现的,好处我就不多说了,方便而已,因为在微软的操作系统里面就自带了这个玩意,主要的方式有两种: 1.使用COM组件技术,不管是C++,C#,Delphi都能玩的转,开发出来的东西在XP和WIN7都能跑.(要引入SpeechLib,好像在项目上点引用,然后选到系统COM吧,好久没弄,记不清楚了) 2.使用WIN7的windows api,其实最终还是调用了SAPI,所以开发出来的东西就只能在WIN7上面跑. 其实不管是哪一种,都是调用SAPI

  • Ruby中调用执行shell命令的6种方法

    碰到需要调用操作系统shell命令的时候,Ruby为我们提供了六种完成任务的方法: 1.Exec方法: Kernel#exec方法通过调用指定的命令取代当前进程例子: 复制代码 代码如下: $ irb       >> exec 'echo "hello $HOSTNAME"'          hello nate.local       $ 值得注意的是,exec方法用echo命令来取代了irb进程从而退出了irb.主要的缺点是,你无法从你的ruby脚本里知道这个命令是

  • 一个Js文件函数中调用另一个Js文件函数的方法演示

    我们知道,在html中,利用<script language="javascript" type="text/javascript" src="./script.js"></script>引入的两个js是不可以相互调用的.那么该如何解决呢?当然,你可以将代码通通copy过来,也许你并不喜欢这样. 例如有这样一个html,里面有一个按钮,当按下时调用b.js文件中的方法b().而b()中又要调用a.js文件中的方法a().若

  • python 在某.py文件中调用其他.py内的函数的方法

    假设名为A.py的文件需要调用B.py文件内的C(x,y)函数 假如在同一目录下,则只需 import B if __name__ == "__main__": B.C(x,y) 若只需调用单个函数,也可以 from B import C if __name__ == "__main__": C(x,y) 若A.py和B.py位于不同的目录下,可以用以下方法 (假设B.py位于D盘的根目录下) 1.引用所在路径 import sys sys.path.append(

  • IOS中Json解析实例方法详解(四种方法)

    作为一种轻量级的数据交换格式,json正在逐步取代xml,成为网络数据的通用格式. 有的json代码格式比较混乱,可以使用此"http://www.bejson.com/"网站来进行JSON格式化校验(点击打开链接).此网站不仅可以检测Json代码中的错误,而且可以以视图形式显示json中的数据内容,很是方便. 从IOS5开始,APPLE提供了对json的原生支持(NSJSONSerialization),但是为了兼容以前的iOS版本,可以使用第三方库来解析Json. 本文将介绍Tou

  • 网页中JS函数自动执行常用三种方法

    本文为大家分享了在网页中JS函数自动执行常用方法,供大家参考,具体内容如下 一.JS方法 1.最简单的调用方式,直接写到html的body标签里面: <body onload="myfunction()"> <html> <body onload="func1();func2();func3();"> </body> </html> 2.在JS语句调用: <script type="text

  • 查看远程 Linux 系统中某个端口是否开启的三种方法

    这是一个很重要的话题,不仅对 Linux 管理员而言,对于我们大家而言也非常有帮助.我的意思是说对于工作在 IT 基础设施行业的用户来说,了解这个话题也是非常有用的.他们需要在执行下一步操作前,检查 Linux 服务器上某个端口是否开启. 假如这个端口没有被开启,则他们会直接找 Linux 管理员去开启它.如果这个端口已经开启了,则我们需要和应用团队来商量下一步要做的事. 在本篇文章中,我们将向你展示如何检查某个端口是否开启的 3 种方法. 这个目标可以使用下面的 Linux 命令来达成: nc

  • Shell脚本调用另一个脚本的三种方法

    假如有脚本 first.sh: #!/bin/bash #------------------ #@file:first.sh #------------------ echo 'your are in first file' 如何在其它Shell脚本中调用first.sh呢?主要有三种方法:source.点号以及sh命令. 1.source #!/bin/bash #--------------- #@file:second.sh #--------------- echo 'your are

  • C#中关于序列化与反序列化的三种方法

    目录 一.序列化与反序列化解释 二.序列化目的 三.C#中的三种序列化说明 1.以二进制格式序列化 2.以SOAP格式序列化 3.将对象序列化到XML文档 三.C#中的三种序列化代码示例 一.序列化与反序列化解释 序列化 (Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程.在序列化期间,对象将其当前状态写入到临时或持久性存储区.以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象. 二.序列化目的 1.以某种存储形式使自定义对象持久化: 2.将对象从一个

随机推荐