Text to Speech in WPF


One of the new features that came out with .NET 3.5 and 4.0 is the addition of the System.Speech library. This library is a collection of classes that enables speech recognition and speech synthesis (text-to-speech). 

Speech synthesis artificially produces human speech and talk to users. Windows 7's Text-To-Speech (TTS) engine converts text in a specific language into speech. The speech synthesis engine is accessed directly in managed applications by using the classes in System.Speech.Synthesis or, alternatively, by the Speech API (SAPI) when used in unmanaged applications.
 
1.gif 

2.gif

Here is a small sample of using the System.Speech.Synthesis. Add a reference to System.Speech.

3.gif
 
Create WPF window as below

<Window x:Class="Text_to_Speech.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="400" Width="600" Loaded="Window_Loaded">
    <Grid Width="auto" Height="auto">
        <Label Content="Voice:" Height="28" HorizontalAlignment="Left" Margin="12,12,0,0" Name="label3" VerticalAlignment="Top" Width="45" />        <ComboBox Height="23" HorizontalAlignment="Left" Margin="54,12,0,0" Name="comboVoice" ItemsSource="{Binding}" VerticalAlignment="Top" Width="110" />
        <Label Height="28" HorizontalAlignment="Left" Margin="182,12,0,0"
               Name="label1" VerticalAlignment="Top" Width="54">Volume:</Label>
        <Slider Height="23" HorizontalAlignment="Left" Margin="231,12,0,0" Name="sliderVolume" VerticalAlignment="Top" Width="110" Value="50" Maximum="100" ValueChanged="sliderVolume_ValueChanged" />
        <Label Height="28" Margin="369,12,173,0" Name="label2" VerticalAlignment="Top">
            Rate:</Label>
        <Slider Height="23" HorizontalAlignment="Left" Margin="402,12,0,0" Maximum="5" Name="sliderRate" Value="3" VerticalAlignment="Top" Width="110" ValueChanged="sliderRate_ValueChanged" />
        <Button Height="23" HorizontalAlignment="Right" Margin="0,0,12,8"
                Name="ButtonSpeak" VerticalAlignment="Bottom" Width="101" Click="ButtonSpeak_Click">
            Speak
        </Button>
        <RichTextBox Margin="54,106,0,37" Name="richTextBox1"  />
        <Button Height="23" HorizontalAlignment="Left" Margin="351,77,0,0"
                Name="OpenTextFileButton" VerticalAlignment="Top" Width="110" Click="OpenTextFileButton_Click">
            Open a Text File
        </Button>
        <TextBox Height="23" Margin="54,77,0,0" Name="FileNameTextBox" VerticalAlignment="Top"
                 HorizontalAlignment="Left" Width="299" />
        <Label Content="(Open text file or type text in textbox)" HorizontalAlignment="Left" Margin="12,54,0,0" Name="label4" VerticalAlignment="Top" />
        <Label Height="28" HorizontalAlignment="Left" Margin="266,330,0,0" Name="labelProgress" VerticalAlignment="Top" />
        <Label Content="Text:" Height="28" HorizontalAlignment="Left" Margin="12,106,0,0" Name="label5" VerticalAlignment="Top" />
        <Label Content="File:" Height="28" HorizontalAlignment="Left" Margin="12,75,0,0" Name="label6" VerticalAlignment="Top" />
        <Label Height="28" HorizontalAlignment="Left" Margin="12,330,0,0" Name="labelState" VerticalAlignment="Top" />
    </Grid>
</Window>

Now let's start with the code
  1. Add using directive

    using System.Speech.Synthesis;

  2. Initialize SpeechSynthesizer object

    //speech synthesizer
    private
    SpeechSynthesizer synthesizer;

  3. Add SpeechSynthesizer events on window load

    private
    void Window_Loaded(object sender, RoutedEventArgs e)
    {
        synthesizer = new SpeechSynthesizer();
        #region synthesizer eventes
        synthesizer.StateChanged += new EventHandler<StateChangedEventArgs>(synthesizer_StateChanged);
        synthesizer.SpeakStarted += new EventHandler<SpeakStartedEventArgs>(synthesizer_SpeakStarted);
        synthesizer.SpeakProgress += new EventHandler<SpeakProgressEventArgs>(synthesizer_SpeakProgress);
        synthesizer.SpeakCompleted += new EventHandler<SpeakCompletedEventArgs>(synthesizer_SpeakCompleted);
        #endregion
    }

  4. Add event handlers 

    private
    void synthesizer_StateChanged(object sender, StateChangedEventArgs e)
    {
        //show the synthesizer's current state
        labelState.Content = e.State.ToString();
    }
    private void synthesizer_SpeakStarted(object sender, SpeakStartedEventArgs e)
    {
    }
    void synthesizer_SpeakProgress(object sender, SpeakProgressEventArgs e)
    {
        //show the synthesizer's current progress
        labelProgress.Content = e.Text;
    }
    private void synthesizer_SpeakCompleted(object sender, SpeakCompletedEventArgs e)
    {
        //reset when complete
        ButtonSpeak.Content = "Speak";
        labelProgress.Content = "";


  5. And finally the buttonSpeak_click

    private
    void ButtonSpeak_Click(object sender, RoutedEventArgs e)
    {
        if (comboVoice.SelectedItem != null)
            synthesizer.SelectVoice(comboVoice.SelectedItem.ToString());
        synthesizer.Volume = Convert.ToInt32(sliderVolume.Value);
        synthesizer.Rate = Convert.ToInt32(sliderRate.Value);
        switch (synthesizer.State)
        {
            //if synthesizer is ready
            case SynthesizerState.Ready:
                synthesizer.SpeakAsync(ConvertRichTextBoxContentsToString());
                ButtonSpeak.Content = "Pause";
                break;
            //if synthesizer is paused
            case SynthesizerState.Paused:
                synthesizer.Resume();
                ButtonSpeak.Content = "Pause";
                break;
            //if synthesizer is speaking
            case SynthesizerState.Speaking:
                synthesizer.Pause();
                ButtonSpeak.Content = "Resume";
                break;
        }
    }
The resulting screen of the application will be as-

4.gif