<Window x:Class="Synthesizer.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Synthesizer" mc:Ignorable="d" d:DesignHeight="450" d:DesignWidth="800"> <Window.Title>Synthesizer</Window.Title> <Window.Resources> <local:DoubleToStringConverter x:Key="converter" /> </Window.Resources> <Grid> <Grid.RowDefinitions> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="*" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBox Name="PreviewTextBox" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Margin="5 5 5 5" VerticalScrollBarVisibility="Auto" TextWrapping="Wrap"/> <ComboBox Name="VoiceComboBox" Grid.Row="1" Grid.Column="0" Width="320" Height="30" Margin="5 5 5 5" Grid.ColumnSpan="2"/> <Slider Name="SpeedSlider" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Width="320" Margin="5 5 5 5" Minimum="0.5" Maximum="1.0" Value="1.0"/> <Label Name="SpeedLabel" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Margin="5 5 5 5" HorizontalAlignment="Center" Content="{Binding ElementName=SpeedSlider, Path=Value, Converter={StaticResource converter}}"/> <Button Name="SaveButton" Grid.Row="3" Grid.Column="1" Width="80" Height="45" Margin="5 5 5 5" Content="Save" Click="SaveButtonClick" /> </Grid> </Window>
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; 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.Navigation; using System.Windows.Shapes; using Microsoft.Win32; using Windows.Storage; using Windows.Storage.Streams; using Windows.Media.SpeechSynthesis; using System.IO; namespace Synthesizer { /// <summary> /// MainWindow.xaml 的交互逻辑 /// </summary> public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); foreach (var voice in SpeechSynthesizer.AllVoices.OrderBy(voice => voice.Language)) { VoiceComboBox.Items.Add(new ComboBoxItem() { Tag=voice,Content=string.Format("{0} ({1})",voice.DisplayName, voice.Language)}); } if (VoiceComboBox.Items.Count > 0) { VoiceComboBox.SelectedIndex = 0; } } [STAThread] public static void Main(string[] args) { new MainWindow().ShowDialog(); } private async void SaveButtonClick(object sender, RoutedEventArgs e) { var dialog = new SaveFileDialog() { Filter = "WAV File|*.wav" }; if (dialog.ShowDialog() != true) { return; } var synthesizer = new SpeechSynthesizer() { Voice = (VoiceComboBox.SelectedItem as ComboBoxItem).Tag as VoiceInformation }; synthesizer.Options.SpeakingRate = SpeedSlider.Value; var stream = await synthesizer.SynthesizeTextToStreamAsync(PreviewTextBox.Text); using (var file = new FileStream(dialog.FileName, FileMode.Create)) { stream.AsStream().CopyTo(file); } } } }
using System; using System.Collections.Generic; using System.Globalization; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Data; namespace Synthesizer { [ValueConversion(typeof(double), typeof(string))] class DoubleToStringConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { return (value as double?)?.ToString("F2"); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { return double.Parse(value as string); } } }