C#中调用SAPI实现语音合成的2种方法
我们都知道现在的语音合成TTS是可以通过微软的SAPI实现的,好处我就不多说了,方便而已,因为在微软的操作系统里面就自带了这个玩意,主要的方式有两种:
1、使用COM组件技术,不管是C++,C#,Delphi都能玩的转,开发出来的东西在XP和WIN7都能跑。(要引入SpeechLib,好像在项目上点引用,然后选到系统COM吧,好久没弄,记不清楚了)
2、使用WIN7的windowsapi,其实最终还是调用了SAPI,所以开发出来的东西就只能在WIN7上面跑。
其实不管是哪一种,都是调用SAPI,可能后一种代码比较简单,使用已经安装的TTS引擎,现在一般用NeoSpeech,这个就不解释了,太强大了这个发音。。。
COM组件技术:
publicclassSpeach
{
privatestaticSpeach_Instance=null;
privateSpeechLib.SpVoiceClassvoice=null;//SAPI5.1
privateSpeechLib.SpVoicevoice=null;//SAPI5.4
privateSpeach()
{
BuildSpeach();
}
publicstaticSpeachinstance()
{
if(_Instance==null)
_Instance=newSpeach();
return_Instance;
}
privatevoidSetChinaVoice()
{
voice.Voice=voice.GetVoices(string.Empty,string.Empty).Item(0);
}
privatevoidSetEnglishVoice()
{
voice.Voice=voice.GetVoices(string.Empty,string.Empty).Item(1);
}
privatevoidSpeakChina(stringstrSpeak)
{
SetChinaVoice();
Speak(strSpeak);
}
privatevoidSpeakEnglishi(stringstrSpeak)
{
SetEnglishVoice();
Speak(strSpeak);
}
publicvoidAnalyseSpeak(stringstrSpeak)
{
intiCbeg=0;
intiEbeg=0;
boolIsChina=true;
for(inti=0;i<strSpeak.Length;i++)
{
charchr=strSpeak[i];
if(IsChina)
{
if(chr<=122&&chr>=65)
{
intiLen=i-iCbeg;
stringstrValue=strSpeak.Substring(iCbeg,iLen);
SpeakChina(strValue);
iEbeg=i;
IsChina=false;
}
}
else
{
if(chr>122||chr<65)
{
intiLen=i-iEbeg;
stringstrValue=strSpeak.Substring(iEbeg,iLen);
this.SpeakEnglishi(strValue);
iCbeg=i;
IsChina=true;
}
}
}//endfor
if(IsChina)
{
intiLen=strSpeak.Length-iCbeg;
stringstrValue=strSpeak.Substring(iCbeg,iLen);
SpeakChina(strValue);
}
else
{
intiLen=strSpeak.Length-iEbeg;
stringstrValue=strSpeak.Substring(iEbeg,iLen);
SpeakEnglishi(strValue);
}
}
privatevoidBuildSpeach()
{
if(voice==null)
voice=newSpVoiceClass();
}
publicintVolume
{
get
{
returnvoice.Volume;
}
set
{
voice.SetVolume((ushort)(value));
}
}
publicintRate
{
get
{
returnvoice.Rate;
}
set
{
voice.SetRate(value);
}
}
privatevoidSpeak(stringstrSpeack)
{
try
{
voice.Speak(strSpeack,SpeechVoiceSpeakFlags.SVSFlagsAsync);
}
catch(Exceptionerr)
{
throw(newException("发生一个错误:"+err.Message));
}
}
publicvoidStop()
{
voice.Speak(string.Empty,SpeechLib.SpeechVoiceSpeakFlags.SVSFPurgeBeforeSpeak);
}
publicvoidPause()
{
voice.Pause();
}
publicvoidContinue()
{
voice.Resume();
}
}//endclass
在privateSpeechLib.SpVoiceClassvoice=null;这里,我们定义个一个用来发音的类,并且在第一次调用该类时,对它用BuildSpeach方法进行了初始化。
我们还定义了两个属性Volume和Rate,能够设置音量和语速。
我们知道,SpVoiceClass有一个Speak方法,我们发音主要就是给他传递一个字符串,它负责读出该字符串,如下所示。
privatevoidSpeak(stringstrSpeack)
{
try
{
voice.Speak(strSpeack,SpeechVoiceSpeakFlags.SVSFlagsAsync);
}
catch(Exceptionerr)
{
throw(newException("发生一个错误:"+err.Message));
}
}
第二种使用.NET类库和系统API的代码如下:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Text;
usingSystem.Speech.Synthesis;
usingSystem.Speech;
namespaceStudyBeta
{
publicclassSRead
{
publicSpeechSynthesizersynth;//语音合成对象
publicSRead()
{
synth=newSpeechSynthesizer();
}
publicSRead(intm,intn)
{
//使用synth设置朗读音量[范围0~100]
synth.Volume=m;
//使用synth设置朗读频率[范围-10~10]
synth.Rate=n;
}
publicvoidSpeakChina(stringggg)
{
//SpVoiceVoice=newSpVoice();
synth.SelectVoice("MicrosoftLili");
//Voice.Speak(ggg,SpFlags);
synth.SpeakAsync(ggg);
//StringspeechPeople=synth.Voice;
//使用synth设置朗读音量[范围0~100]
//synth.Volume=80;
//使用synth设置朗读频率[范围-10~10]
//synth.Rate=0;
//使用synth合成wav音频文件:
//synth.SetOutputToWaveFile(stringpath);
}
publicvoidSpeakEnglish(stringggg)
{
//SpVoiceVoice=newSpVoice();
synth.SelectVoice("VWJulie");
synth.Speak(ggg);//ggg为要合成的内容
}
publicintm
{
get
{
returnsynth.Volume;
}
set
{
synth.Volume=value;
}
}
publicintn
{
get
{
returnsynth.Rate;
}
set
{
synth.Rate=value;
}
}
}