求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
  
 
 
     
   
分享到
Windows Phone 8 中的 TTS 文本朗读
 

作者:openkk,发布于2012-10-23,来源:OPEN经验库

 

自从 Windows Phone 8 SDK 泄漏后,经过一些研究以及官方文档和示例,我的注意力放到了新的 SpeechSynthesizer 和 InstalledVoices.All 类上。

于是我做了一个示例来试用 WP8 的 TTS 文本朗读,先开始 XAML:

<phone:PhoneApplicationPage
    x:Class="TextToSpeechDemo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:phone="clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone"
    xmlns:shell="clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    FontFamily="{StaticResource PhoneFontFamilyNormal}"
    FontSize="{StaticResource PhoneFontSizeNormal}"
    Foreground="{StaticResource PhoneForegroundBrush}"
    SupportedOrientations="Portrait" Orientation="Portrait"
    shell:SystemTray.IsVisible="True">

    <!--LayoutRoot is the root grid where all page content is placed-->
    <Grid x:Name="LayoutRoot" Background="Transparent">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <!--TitlePanel contains the name of the application and page title-->
        <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,17,0,28">
            <TextBlock Text="{Binding Path=LocalizedResources.ApplicationTitle, Source={StaticResource
 LocalizedStrings}}" Style="{StaticResource PhoneTextNormalStyle}"/>
            <TextBlock Text="{Binding Path=LocalizedResources.PageTitle, Source={StaticResource
 LocalizedStrings}}" Margin="9,-7,0,0" Style="{StaticResource PhoneTextTitle1Style}"/>
        </StackPanel>

        <!--ContentPanel - place additional content here-->
        <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
            <StackPanel>
                <ScrollViewer Height="200">
                    <ComboBox HorizontalAlignment="Left" Width="456" Name="voicesComboBox" DisplayMemberPath="Name"/>
                </ScrollViewer>
                <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
                    <RadioButton Content="Male" IsChecked="true" Name="MaleRadioButton"/>
                    <RadioButton Content="Female"/>
                </StackPanel>
                <TextBox HorizontalAlignment="Left" Height="230" TextWrapping="Wrap" Width="456" Text="I may be
 a sorry case, but I don't write jokes in base 13." Name="inputTextBox"/>
                <Button Content="Speak to me" HorizontalAlignment="Left" Width="456" Click="SpeakToMe_Click"/>
            </StackPanel>
        </Grid>
    </Grid>
</phone:PhoneApplicationPage>

接下来是 MainPage.xaml 对应的代码,其内容基本上都来自于 WP8 SDK 文档,我增加了一些错误检查和小改进:

using System;
using System.Linq;
using System.Windows;
using Microsoft.Phone.Controls;
using Windows.Phone.Speech.Synthesis;
 
namespace TextToSpeechDemo
{
    public partial class MainPage : PhoneApplicationPage
    {
        SpeechSynthesizer synth;
        // Constructor
        public MainPage()
        {
            InitializeComponent();
            voicesComboBox.ItemsSource = new MyLocals().Items();
        }
 
        private async void SpeakToMe_Click(object sender, RoutedEventArgs e)
        {
            if (voicesComboBox.SelectedIndex == -1)
            {
                MessageBox.Show("Please select a language.");
            }
            else
            {
                if (string.IsNullOrEmpty(inputTextBox.Text))
                {
                    MessageBox.Show("Please enter some text.");
                }
                else
                {
                    try
                    {
                        // Initialize the SpeechSynthesizer object.
                        synth = new SpeechSynthesizer();
 
                        var myLocal = (MyLocale)voicesComboBox.SelectedItem;
 
                        // Query for a voice. Results rdered by Gender to ensure the order always goes Female
                         then Male.
                        var voices = (from voice in InstalledVoices.All
                                      where voice.Language == myLocal.Lcid
                                      select voice).OrderByDescending(v => v.Gender);
 
                        // gender: 0 = Female, 1 = Male. Corresponds to the index of the above results.
                        int gender = 0;
                        if (MaleRadioButton.IsChecked == true) gender = 1; else gender = 0;
 
                        // Set the voice as identified by the query.
                        synth.SetVoice(voices.ElementAt(gender));
 
                        // Speak
                        await synth.SpeakTextAsync(inputTextBox.Text);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message);
                    }
                }
            }
        }
    }
}

然后是一个帮忙填充 ComboBox 列表语言的类,检查 InstalledVoices.All 显示出 30 条数据。我不知道为什么我无法直接获取,好像是一个 COM 对象跟 LINQ 查询的关系吧。这里我能监测出 12 种语言,我没有深入研究去找另外 3 个。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
 
namespace TextToSpeechDemo
{
    class MyLocale
    {
        public MyLocale(string name, string lcid)
        {
            _name = name;
            _lcid = lcid;
        }
 
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
 
        private string _lcid;
        public string Lcid
        {
            get { return _lcid; }
            set { _lcid = value; }
        }
    }
 
    class MyLocals
    {
        private IList<MyLocale> _myLocals;
 
        public MyLocals()
        {
            _myLocals = new List<MyLocale>();
 
            _myLocals.Add(new MyLocale("Chinese Simplified (PRC)", "zh-CN"));
            _myLocals.Add(new MyLocale("Chinese Traditional (Taiwan)", "zh-TW"));
            _myLocals.Add(new MyLocale("English (United States)", "en-US"));
            _myLocals.Add(new MyLocale("English (United Kingdom)", "en-GB"));
            _myLocals.Add(new MyLocale("French (France)", "fr-FR"));
            _myLocals.Add(new MyLocale("German (Germany)", "de-DE"));
            _myLocals.Add(new MyLocale("Italian (Italy)", "it-IT"));
            _myLocals.Add(new MyLocale("Japanese (Japan)", "ja-JP"));
            _myLocals.Add(new MyLocale("Polish (Poland)", "pl-PL"));
            _myLocals.Add(new MyLocale("Portuguese (Brazil)", "pt-BR"));
            _myLocals.Add(new MyLocale("Russian (Russia)", "ru-RU"));
            _myLocals.Add(new MyLocale("Spanish (Spain)", "es-ES"));
        }
 
        public IEnumerable<MyLocale> Items()
        {
            return (IEnumerable<MyLocale>)_myLocals;
        }
    }
}

接下来是设置 ID_CAP_SPEECH_RECOGNITION 功能,否则将会出异常:

下图是程序运行结果,选择其中一个语言并点击按钮将会开始阅读。

我注意到另外一件事:如果我选择一种非英语的语言让它朗读英语文本,朗读出来的效果是带口音的,例如我选择法语的1,2,3,4,然后用西班牙语来朗读,它发出的声音是西班牙语的法语4,很有趣。


 
分享到
 
 
     


android人机界面指南
Android手机开发(一)
Android手机开发(二)
Android手机开发(三)
Android手机开发(四)
iPhone消息推送机制实现探讨
手机软件测试用例设计实践
手机客户端UI测试分析
手机软件自动化测试研究报告
更多...   


Android高级移动应用程序
Android应用开发
Android系统开发
手机软件测试
嵌入式软件测试
Android软、硬、云整合


领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...