一個基於Windows Vista speech API5.3以及WPF技術的語音朗讀程式碼
閒暇無事,利用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); }
//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,我給大家發