网上去找发现语音合成效果都差不多,没有太好的,TTS有点过于古老,然后发现SpeechSynthesizer不错

C#文本阅读器,C#文本朗读器,Text文档朗读器开发_.Net

C#文本阅读器,C#文本朗读器,Text文档朗读器开发_.Net_02

程序界面

C#文本阅读器,C#文本朗读器,Text文档朗读器开发_.Net_03

废话不说上代码

PlayItem.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TextToSpeech.General
{
    public class PlayItem
    {
        public string Content { get; set; }
        public int Index { get; set; }
        public int Lenght { get; set; }
    }
}

主程序 

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Speech.Synthesis;
using System.Windows;
using System.Windows.Forms;
using TextToSpeech.General;
using TextToSpeech.Properties;

namespace TextToSpeech
{
    /// <summary>
    /// MainWindow.xaml 的交互逻辑
    /// </summary>
    public partial class MainWindow : Window
    {
        private SpeechSynthesizer speechSynthesizer = new SpeechSynthesizer();
        private List<PlayItem> PlayData = new List<PlayItem>();
        private int PlayLine = 0;
        public MainWindow()
        {
            InitializeComponent();
            this.Left = Settings.Default.Left;
            this.Top = Settings.Default.Top;
            this.Width = Settings.Default.Width;
            this.Height = Settings.Default.Height;
        }

        private void Play()
        {
            PlayLine++;
            LbPlayLine.Content = $"播放:{PlayLine.ToString()}行";
            Play(PlayLine);
        }

        private void Play(int playLine)
        {
            if (playLine < PlayData.Count())
            {
                speechSynthesizer.SpeakAsync(PlayData[playLine].Content);
                try
                {
                    TbTextBox.Focus();
                    //选择指定行内容
                    TbTextBox.Select(PlayData[playLine].Index, PlayData[playLine].Lenght);
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
            else
            {
                LbPlayLine.Content = $"播放结束:{PlayLine.ToString()}行";
            }    
        }

        private void synth_StateChanged(object sender, StateChangedEventArgs e)
        {
            if(e.State == SynthesizerState.Ready)
            {
                Play();
            }
        }

        private void Button_Click_Open(object sender, RoutedEventArgs e)
        {
            System.Windows.Forms.OpenFileDialog fileDialog = new System.Windows.Forms.OpenFileDialog();//打开文件对话框 
            fileDialog.InitialDirectory = System.AppDomain.CurrentDomain.BaseDirectory;//初始化路径
            fileDialog.Filter = "文档(*.txt)|*.txt";//或"图片(*.jpg;*.bmp)|*.jpg;*.bmp";//过滤选项设置,文本文件,所有文件。
            fileDialog.FilterIndex = 0;//当前使用第二个过滤字符串
            fileDialog.RestoreDirectory = true;//对话框关闭时恢复原目录
            fileDialog.Title = "选择文档";
            if (fileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                Settings.Default.FilePath = fileDialog.FileName;
                Settings.Default.Save();
                TbTextBox.Text = ReadFile(fileDialog.FileName);
            }
        }

        private void Button_Click_Start(object sender, RoutedEventArgs e)
        {
            speechSynthesizer.StateChanged += new EventHandler<StateChangedEventArgs>(synth_StateChanged);
            Play();
        }

        private void Button_Click_Stop(object sender, RoutedEventArgs e)
        {
            Stop();
        }

        private void Stop()
        {
            speechSynthesizer.StateChanged -= new EventHandler<StateChangedEventArgs>(synth_StateChanged);
            speechSynthesizer.SpeakAsyncCancelAll();
        }

        private string ReadFile(string path)
        {
            try
            {
                string str = "";
                // 创建一个 StreamReader 的实例来读取文件 
                // using 会自动释放资源
                using (StreamReader sr = new StreamReader(path))
                {
                    // 从文件读取并显示行,直到文件的末尾 
                    str = sr.ReadToEnd();
                }
                var datas = str.Split('\n');
                int index = 0;
                foreach (var data in datas)
                {
                    PlayItem playItem = new PlayItem();
                    playItem.Content = data;
                    playItem.Index = index;
                    playItem.Lenght = data.Length + 1;
                    index += playItem.Lenght;
                    PlayData.Add(playItem);
                }
                return str;
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            LoadingWindow loadingWindow = new LoadingWindow();
            loadingWindow.Show();
            TbTextBox.FontSize = Settings.Default.FontSize;
            if (!string.IsNullOrEmpty(Settings.Default.FilePath))
            {
                TbTextBox.Text = ReadFile(Settings.Default.FilePath);
            }
            PlayLine = Settings.Default.PlayLine;
            LbPlayLine.Content = $"播放:{PlayLine.ToString()}行";
            loadingWindow.Close();
        }

        private void Window_Closed(object sender, EventArgs e)
        {
            Stop();
            Settings.Default.PlayLine = PlayLine;
            Settings.Default.Save();
        }

        private void Button_Click_Set(object sender, RoutedEventArgs e)
        {
            try
            {
                PlayLine = int.Parse(TbPlayLine.Text) - 1;
                if(PlayLine<=0)
                {
                    PlayLine = 0;
                }
                speechSynthesizer.SpeakAsyncCancelAll();
            }
            catch(Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.ToString());
            }
        }

        private void Window_LocationChanged(object sender, EventArgs e)
        {
            Settings.Default.Left = this.Left;
            Settings.Default.Top = this.Top;
            Settings.Default.Width = this.Width;
            Settings.Default.Height = this.Height;
            Settings.Default.Save();
        }

        private void Window_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            Settings.Default.Left = this.Left;
            Settings.Default.Top = this.Top;
            Settings.Default.Width = this.Width;
            Settings.Default.Height = this.Height;
            Settings.Default.Save();
        }

        private void Button_Click_Add(object sender, RoutedEventArgs e)
        {
            TbTextBox.FontSize = TbTextBox.FontSize + 1 ;
            Settings.Default.FontSize = TbTextBox.FontSize;
            Settings.Default.Save();
        }

        private void Button_Click_Subtract(object sender, RoutedEventArgs e)
        {
            TbTextBox.FontSize = TbTextBox.FontSize - 1;
            Settings.Default.FontSize = TbTextBox.FontSize;
            Settings.Default.Save();

        }
    }
}

界面代码

<Window x:Class="TextToSpeech.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:TextToSpeech"
        mc:Ignorable="d"
        Title="TextShoundPlay" Height="450" Width="800" Loaded="Window_Loaded" Closed="Window_Closed" LocationChanged="Window_LocationChanged" SizeChanged="Window_SizeChanged">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="100*"/>
            <ColumnDefinition Width="100"/>
        </Grid.ColumnDefinitions>
        <Grid Grid.Row="0" Grid.Column="0">
            <TextBox x:Name="TbTextBox" TextWrapping="Wrap" VerticalScrollBarVisibility="Visible"/>
        </Grid>
        <StackPanel Grid.Row="0" Grid.Column="1">
            <Button Content="打开" Click="Button_Click_Open"/>
            <Button Content="播放" Click="Button_Click_Start"/>
            <Button Content="停止" Click="Button_Click_Stop"/>
            <StackPanel HorizontalAlignment="Center" Orientation="Horizontal">
                <TextBlock Text="转到:"></TextBlock>
                <TextBox x:Name="TbPlayLine" Text="0" Width="60"></TextBox>
                <TextBlock Text="行"></TextBlock>
            </StackPanel>
            <Button Content="跳转" Click="Button_Click_Set"/>
            <Label x:Name="LbPlayLine"></Label>
            <Button Content="增大字体" Click="Button_Click_Add"/>
            <Button Content="减小字体" Click="Button_Click_Subtract"/>
        </StackPanel>
    </Grid>
</Window>