闲暇无事,利用window SDK 与vs2008,基于Windows Vista speech API5.3以及WPF技术开发了一套语音朗读的代码,
牛刀小试,
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.Collections.ObjectModel;
using System.Xml;
using System.Speech.Synthesis;
namespace speechSynth
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : System.Windows.Window
{
private SpeechSynthesizer synth;
public Window1()
{
InitializeComponent();
synth = new SpeechSynthesizer();
synth.StateChanged += new EventHandler<StateChangedEventArgs>(synth_StateChanged);
synth.BookmarkReached += new EventHandler<BookmarkReachedEventArgs>(synth_BookmarkReached);
synth.PhonemeReached += new EventHandler<PhonemeReachedEventArgs>(synth_PhonemeReached);
synth.SpeakCompleted += new EventHandler<SpeakCompletedEventArgs>(synth_SpeakCompleted);
synth.SpeakProgress += new EventHandler<SpeakProgressEventArgs>(synth_SpeakProgress);
synth.SpeakStarted += new EventHandler<SpeakStartedEventArgs>(synth_SpeakStarted);
synth.VisemeReached += new EventHandler<VisemeReachedEventArgs>(synth_VisemeReached);
synth.VoiceChange += new EventHandler<VoiceChangeEventArgs>(synth_VoiceChange);
this.btnSpeakText.Click += new RoutedEventHandler(btnSpeakText_Click);
this.btnWavFile.Click += new RoutedEventHandler(btnWavFile_Click);
this.btnVoices.Click += new RoutedEventHandler(btnVoices_Click);
this.btnSpeakSsml.Click += new RoutedEventHandler(btnSpeakSsml_Click);
this.btnPause.Click += new RoutedEventHandler(btnPause_Click);
this.btnResume.Click += new RoutedEventHandler(btnResume_Click);
this.btnPromptBuilder.Click += new RoutedEventHandler(btnPromptBuilder_Click);
this.btnToXml.Click += new RoutedEventHandler(btnToXml_Click);
this.btnSsmlPitch.Click += new RoutedEventHandler(btnSsmlPitch_Click);
this.btnCutIn.Click += new RoutedEventHandler(btnCutIn_Click);
this.sliderRate.ValueChanged += new RoutedPropertyChangedEventHandler<double>(sliderRate_ValueChanged);
this.sliderVolume.ValueChanged += new RoutedPropertyChangedEventHandler<double>(sliderVolume_ValueChanged);
}
void btnCutIn_Click(object sender, RoutedEventArgs e)
{
synth.SpeakAsyncCancelAll(); //stops current async call
synth.SpeakAsync("this is some interrupting text"); //just appends, unless AsyncCancelAll() called first
//synth.Speak("this is some interrupting text"); //does not interrupt async call
}
void btnSsmlPitch_Click(object sender, RoutedEventArgs e)
{
XmlDocument xd = new XmlDocument();
xd.Load("ssmlPitch.xml");
synth.SpeakSsmlAsync(xd.OuterXml);
}
#region SYNTHESIZER_EVENTS
void synth_VoiceChange(object sender, VoiceChangeEventArgs e)
{
System.Diagnostics.Debug.WriteLine("VoiceChange : " + e.Voice.Name);
}
void synth_VisemeReached(object sender, VisemeReachedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("VisemeReached : " + e.Viseme.ToString());
}
void synth_SpeakStarted(object sender, SpeakStartedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("SpeakStarted");
}
void synth_SpeakProgress(object sender, SpeakProgressEventArgs e)
{
System.Diagnostics.Debug.WriteLine("SpeakProgress : " + e.AudioPosition.TotalSeconds.ToString());
}
void synth_SpeakCompleted(object sender, SpeakCompletedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("SpeakCompleted");
}
void synth_PhonemeReached(object sender, PhonemeReachedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("PhonemeReached : " + e.Phoneme.ToString());
}
void synth_BookmarkReached(object sender, BookmarkReachedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("BookmarkReached : " + e.Bookmark);
}
void synth_StateChanged(object sender, StateChangedEventArgs e)
{
System.Diagnostics.Debug.WriteLine("StateChanged : " + e.State.ToString());
lblState.Content = e.State.ToString();
}
#endregion
void btnToXml_Click(object sender, RoutedEventArgs e)
{
PromptBuilder myPrompt = GetBuiltPrompt();
MessageBox.Show(myPrompt.ToXml());
}
void btnPromptBuilder_Click(object sender, RoutedEventArgs e)
{
PromptBuilder pb = GetBuiltPrompt();
//Now let's get the synthesizer to render this message
//SpeechSynthesizer synth = new SpeechSynthesizer();
synth.SetOutputToDefaultAudioDevice();
synth.SpeakAsync(pb);
}
private PromptBuilder GetBuiltPrompt()
{
//from http://msdn.microsoft.com/msdnmag/issues/06/01/speechinWindowsVista/
//This prompt is quite complicated
//So I'm going to build it first, and then render it.
PromptBuilder myPrompt = new PromptBuilder();
//Start the main speaking style
PromptStyle mainStyle = new PromptStyle();
mainStyle.Rate = PromptRate.Medium;
mainStyle.Volume = PromptVolume.Loud;
myPrompt.StartStyle(mainStyle);
//Alert the listener
myPrompt.AppendAudio(new Uri("file://c://windows//media//notify.wav"), "Attention!");
myPrompt.AppendText("Here are some important messages.");
//Here's the first important message
myPrompt.AppendTextWithPronunciation("WinFX", "wɪnɛfɛks");
myPrompt.AppendText("is a great platform.");
//And the second one
myPrompt.AppendTextWithHint("ASP", SayAs.SpellOut);
myPrompt.AppendText("is an acronym for Active Server Pages. Whereas an ASP is a snake.");
myPrompt.AppendBreak();
//Let's emphasise how important these messages are
PromptStyle interimStyle = new PromptStyle();
interimStyle.Emphasis = PromptEmphasis.Strong;
myPrompt.StartStyle(interimStyle);
myPrompt.AppendText("Please remember these two things.");
myPrompt.EndStyle();
//Then we can revert to the main speaking style
myPrompt.AppendBreak();
myPrompt.AppendText("Thank you");
myPrompt.EndStyle();
return myPrompt;
}
void btnResume_Click(object sender, RoutedEventArgs e)
{
synth.Resume();
}
void btnPause_Click(object sender, RoutedEventArgs e)
{
synth.Pause();
}
void btnSpeakSsml_Click(object sender, RoutedEventArgs e)
{
//http://www.w3.org/TR/speech-synthesis/
synth.SetOutputToDefaultAudioDevice();
//XmlDocument xd = new XmlDocument();
////xd.Load("sampleSSML.xml"); //works
//xd.Load("ssmlPitch.xml"); //works
//synth.SpeakSsmlAsync(xd.OuterXml);
//XmlDocument xd = new XmlDocument();
////xd.Load("sampleSSML.xml"); //TODO doesn't work?
//xd.Load("ssmlPitch.xml"); //TODO doesn't work?
//PromptBuilder pb = new PromptBuilder();
//pb.AppendSsmlMarkup(xd.DocumentElement.OuterXml);
//synth.SpeakAsync(pb);
PromptBuilder pb = new PromptBuilder();
pb.AppendText("blah");
pb.AppendSsml("sampleSSML.xml"); //works
//pb.AppendSsml("ssmlPitch.xml"); //TODO doesn't work
synth.SpeakAsync(pb);
}
void sliderVolume_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
synth.Volume = (int)sliderVolume.Value;
}
void sliderRate_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
synth.Rate = (int)sliderRate.Value;
}
void btnVoices_Click(object sender, RoutedEventArgs e)
{
ReadOnlyCollection<InstalledVoice> voices = synth.GetInstalledVoices();
string retVal = String.Empty;
foreach (InstalledVoice iv in voices)
{
retVal += iv.VoiceInfo.Name + "/r/n";
}
MessageBox.Show(retVal);
}
void btnWavFile_Click(object sender, RoutedEventArgs e)
{
synth.SetOutputToWaveFile("spoken.wav");
synth.Speak(GetText());
synth.SetOutputToNull();
MessageBox.Show("done");
}
void btnSpeakText_Click(object sender, RoutedEventArgs e)
{
synth.SetOutputToDefaultAudioDevice();
synth.SpeakAsync(GetText());
}
private string GetText()
{
return txtToSpeak.Text.Trim();
}
}
}
需要的留下Email,我给大家发