zoukankan      html  css  js  c++  java
  • 20.5 语音合成(百度2016年2月29日发布的tts引擎)

    分类:C#、Android、VS2015;

    创建日期:2016-03-17

    一、简介

    编写手机App时,有时需要使用文字转语音(Text to Speech)的功能,比如开车时阅读收到的短信、导航语音提示、界面中比较重要的信息通过语音强调、……等。

    由于Android自带的Pico TTS并不支持中文,所以要既能阅读中文文本,还能阅读英文文本,必须下载第三方提供的能说中文的语音包。

    二、申请百度tts授权

    本节以百度2016年2月29日发布的“离在线融合语音合成SDK_Android 2.2.3版”为例说明用C#实现语音合成的基本用法。之所以选择百度语音合成来实现,是因为据百度官网声明,该开发包是“永久免费”的。网址如下:

    http://yuyin.baidu.com/tts/

    由于原来已经申请过MyDemos的授权,所以再继续申请tts授权就比较简单了,申请和设置步骤如下。

    1、申请授权

    进入 http://yuyin.baidu.com/tts/ 的首页:

    image

    单击【立即使用】,进入“开通语音合成服务”的页面:

    image

    在下拉框中选择原来已经申请的某个应用,单击【下一步】,然后按提示操作,开通离线服务即可。

    2、在BdMapV371BindingLib项目中转换JAR文件

    先通过 http://yuyin.baidu.com/tts/ 首页中的【相关下载】下载对应的开发包,然后再按下面的步骤操作。

    1、将示例中的com.baidu.tts_2.2.3.20160229_359d952_release.jar、galaxy-v2.0.jar添加到Jars文件夹下,如下图所示,然后将其【生成操作】属性全部设置为“EmbeddedJar”。

    image

    2、在Metadata.xml文件中添加下面的语句:

    <remove-node path="/api/package[@name='com.baidu.tts.aop']/interface[@name='IProxyFactory']/method[@name='createProxied' and count(parameter)=0]" />

    3、重新生成项目,此时应该无错误。

    经过这3个步骤,就完成了tts的Jar包导入和转换为.cs文件的过程。

    3、在MyDemos项目中添加.so文件

    将tts相关的4个.so文件添加到MyDemos项目的x86文件夹下,如下图所示,然后将其【生成操作】属性全部设置为“AndroidNativeLibrary”。

    image

    4、将.dat文件添加到sd卡的BaiduTTS文件夹下

    具体添加办法见【常见问题解答】,这里不再截图。

    也可以先将这些文件添加到Assets文件夹下,然后通过代码将其复制到sd卡的文件夹下。为简化起见,这里通过手工直接复制了。

    OK,经过上面这4步,以后就可以在MyDemos项目中的任何模块中轻松利用百度tts实现语音阅读的功能了

    三、示例

    1、运行截图

    单击【阅读】,就会自动用女音朗读文本框中的内容,单击【批量阅读】,就会依次朗读队列中添加的文字段(主要是为了演示阅读各种不同的中英文短句)。

    image

    2、设计步骤

    (1)添加ch2005Main.axml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="50dp"
            android:orientation="horizontal"
            android:weightSum="4">
            <Button
                android:id="@+id/speak"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1"
                android:lines="2"
                android:text="阅读"
                android:textSize="12dp" />
            <Button
                android:id="@+id/pause"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1"
                android:lines="2"
                android:text="暂停"
                android:textSize="12dp" />
            <Button
                android:id="@+id/resume"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1"
                android:lines="2"
                android:text="继续"
                android:textSize="12dp" />
            <Button
                android:id="@+id/stop"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1"
                android:lines="2"
                android:text="停止"
                android:textSize="12dp" />
        </LinearLayout>
        <LinearLayout
            android:layout_width="fill_parent"
            android:layout_height="50dp"
            android:orientation="horizontal"
            android:weightSum="4">
            <Button
                android:id="@+id/synthesize"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1"
                android:lines="2"
                android:text="synthesize"
                android:textSize="12dp" />
            <Button
                android:id="@+id/play"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1"
                android:lines="2"
                android:text="play"
                android:textSize="12dp" />
            <Button
                android:id="@+id/batchSpeak"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1"
                android:lines="2"
                android:text="批量阅读"
                android:textSize="12dp" />
            <Button
                android:id="@+id/nextActivity"
                android:layout_width="fill_parent"
                android:layout_height="fill_parent"
                android:layout_weight="1"
                android:lines="2"
                android:enabled="false"
                android:text="备用"
                android:textSize="12dp" />
        </LinearLayout>
        <EditText
            android:id="@+id/input"
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:hint="input" />
        <TextView
            android:id="@+id/showText"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent"
            android:layout_margin="10dp"
            android:background="@android:color/darker_gray"
            android:minLines="3"
            android:scrollbars="vertical" />
    </LinearLayout>

    2、添加ch2005MainActivity.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    using Android.App;
    using Android.OS;
    using Android.Widget;
    using Com.Baidu.Tts.Client;
    using Com.Baidu.Tts.Answer.Auth;
    
    namespace MyDemos.SrcDemos
    {
        [Activity(Label = "【例20-5】百度tts基本用法")]
        public class ch2005MainActivity : Activity, ISpeechSynthesizerListener
        {
            private EditText mInput;
            private TextView mShowText;
    
            private SpeechSynthesizer mSpeechSynthesizer;
    
            /// <summary>
            /// sd卡上保存百度tts文件的路径
            /// </summary>
            private string mSampleDirPath;
    
            private const string SpeechFemaleModelName = "bd_etts_speech_female.dat";
            private const string SpeechMaleModelName = "bd_etts_speech_male.dat";
            private const string TextModelName = "bd_etts_text.dat";
            private const string EnglishSpeechFemaleModelName = "bd_etts_speech_female_en.dat";
            private const string EnglishSpeechMaleModelName = "bd_etts_speech_male_en.dat";
            private const string EnglishTextModelName = "bd_etts_text_en.dat";
    
            protected override void OnCreate(Bundle savedInstanceState)
            {
                base.OnCreate(savedInstanceState);
    
                SetContentView(Resource.Layout.ch2005Main);
                mSampleDirPath = Android.OS.Environment.ExternalStorageDirectory.Path + "/baiduTTS";
                Console.WriteLine("mSampleDirPath=" + mSampleDirPath);
                initialView();
                initialTts();
            }
    
            private void initialTts()
            {
                mSpeechSynthesizer = SpeechSynthesizer.Instance;
                mSpeechSynthesizer.SetContext(this);
                mSpeechSynthesizer.SetSpeechSynthesizerListener(this);
                // 文本模型文件路径 (离线引擎使用)
                mSpeechSynthesizer.SetParam(SpeechSynthesizer.ParamTtsTextModelFile,
                    mSampleDirPath + "/" + TextModelName);
                // 声学模型文件路径 (离线引擎使用)
                mSpeechSynthesizer.SetParam(SpeechSynthesizer.ParamTtsSpeechModelFile,
                    mSampleDirPath + "/" + SpeechFemaleModelName);
    
                // 请替换为语音开发者平台上注册应用得到的App ID (离线授权)
                //mSpeechSynthesizer.SetAppId("your_app_id");
                mSpeechSynthesizer.SetAppId(ch.TtsAppID);
    
                // 请替换为语音开发者平台注册应用得到的apikey和secretkey (在线授权)
                //this.mSpeechSynthesizer.SetApiKey("your_api_key", "your_secret_key");
                this.mSpeechSynthesizer.SetApiKey(ch.TtsApiKey, ch.TtsSecretKey);
    
                // 发音人(在线引擎),可用参数为0,1,2,3。。。(服务器端会动态增加,各值含义参考文档,以文档说明为准。0--普通女声,1--普通男声,2--特别男声,3--情感男声。。。)
                mSpeechSynthesizer.SetParam(SpeechSynthesizer.ParamSpeaker, "0");
                // 设置Mix模式的合成策略
                mSpeechSynthesizer.SetParam(SpeechSynthesizer.ParamMixMode, SpeechSynthesizer.MixModeDefault);
    
                // 授权检测接口(可以不使用,只是验证授权是否成功)
                AuthInfo authInfo = this.mSpeechSynthesizer.Auth(TtsMode.Mix);
                if (authInfo.IsSuccess)
                {
                    Console.WriteLine("授权检测--授权成功(auth success)。");
                }
                else
                {
                    string errorMsg = authInfo.TtsError.DetailMessage;
                    Console.WriteLine("授权检测--授权失败(auth failed),errorMsg=" + errorMsg);
                }
    
                // 初始化tts
                mSpeechSynthesizer.InitTts(TtsMode.Mix);
                // 加载离线英文资源(提供离线英文合成功能)
                int result = mSpeechSynthesizer.LoadEnglishModel(
                    mSampleDirPath +
                    "/" + EnglishTextModelName, mSampleDirPath +
                    "/" + EnglishSpeechFemaleModelName);
            }
    
            private void initialView()
            {
                mInput = FindViewById<EditText>(Resource.Id.input);
                mInput.Text = "今天阳光明媚,风和日丽!";
    
                mShowText = FindViewById<TextView>(Resource.Id.showText);
    
                var speak = FindViewById<Button>(Resource.Id.speak);
                speak.Click += delegate
                {
                    string text = this.mInput.Text;
                    int result = this.mSpeechSynthesizer.Speak(text);
                    if (result < 0)
                    {
                        System.Diagnostics.Debug.WriteLine("出错了,错误码:{0},请检查百度tts文档中对应错误码的含义。", result);
                    }
                };
    
                var pause = FindViewById<Button>(Resource.Id.pause);
                pause.Click += delegate
                {
                    mSpeechSynthesizer.Pause();
                };
    
                var resume = FindViewById<Button>(Resource.Id.resume);
                resume.Click += delegate
                {
                    mSpeechSynthesizer.Resume();
                };
    
                var stop = FindViewById<Button>(Resource.Id.stop);
                stop.Click += delegate
                {
                    mSpeechSynthesizer.Stop();
                };
    
                var synthesize = FindViewById<Button>(Resource.Id.synthesize);
                synthesize.Click += delegate
                {
                    string text = this.mInput.Text;
                    int result = this.mSpeechSynthesizer.Synthesize(text);
                    if (result < 0)
                    {
                        System.Diagnostics.Debug.WriteLine("error,please look up error code in doc or URL:http://yuyin.baidu.com/docs/tts/122 ");
                    }
                };
    
                var play = FindViewById<Button>(Resource.Id.play);
                play.Click += delegate { };
    
                var batchSpeak = FindViewById<Button>(Resource.Id.batchSpeak);
                batchSpeak.Click += delegate
                {
                    List<SpeechSynthesizeBag> bags = new List<SpeechSynthesizeBag>();
                    bags.Add(GetSpeechSynthesizeBag("123456", "0"));
                    bags.Add(GetSpeechSynthesizeBag("你好", "1"));
                    bags.Add(GetSpeechSynthesizeBag("使用百度语音合成SDK", "2"));
                    bags.Add(GetSpeechSynthesizeBag("hello", "3"));
                    bags.Add(GetSpeechSynthesizeBag("这是一个demo工程", "4"));
                    int result = this.mSpeechSynthesizer.BatchSpeak(bags);
                    if (result < 0)
                    {
                        System.Diagnostics.Debug.WriteLine("error({0}),please look up error code in doc or URL:http://yuyin.baidu.com/docs/tts/122 ", result);
                    }
                };
            }
    
            protected override void OnDestroy()
            {
                base.OnDestroy();
            }
    
            private SpeechSynthesizeBag GetSpeechSynthesizeBag(string text, string utteranceId)
            {
                SpeechSynthesizeBag speechSynthesizeBag = new SpeechSynthesizeBag();
                speechSynthesizeBag.SetText(text);
                speechSynthesizeBag.UtteranceId = utteranceId;
                return speechSynthesizeBag;
            }
    
            public void OnError(string utteranceId, SpeechError error)
            {
                Console.WriteLine("onError error=" + error.Description + "--utteranceId=" + utteranceId);
            }
    
            public void OnSpeechFinish(string utteranceId)
            {
                Console.WriteLine("onSpeechFinish utteranceId=" + utteranceId);
            }
    
            public void OnSpeechProgressChanged(string p0, int p1)
            {
                //Console.WriteLine("onSpeechProgressChanged");
            }
    
            public void OnSpeechStart(string utteranceId)
            {
                Console.WriteLine("onSpeechStart utteranceId=" + utteranceId);
            }
    
            public void OnSynthesizeDataArrived(string utteranceId, byte[] data, int progress)
            {
                Console.WriteLine("onSynthesizeDataArrived");
            }
    
            public void OnSynthesizeFinish(string utteranceId)
            {
                Console.WriteLine("onSpeechFinish utteranceId=" + utteranceId);
            }
    
            public void OnSynthesizeStart(string utteranceId)
            {
                Console.WriteLine("onSynthesizeStart utteranceId=" + utteranceId);
            }
        }
    }
  • 相关阅读:
    关于asp.net页面自定义404错误码返回302的最新解决方法
    基于sharpdevelop核心和ArcEngine打造插件式桌面GIS应用(概述)
    WPF自定义控件踩坑记录,用户自定义控件 绑定后台定义的 命令 依赖项属性 注意事项 静态
    WPF C# 以非独占式读取本地图片
    C#DataGridView控件60招(一)
    用TEXT文件做数据源
    boost智能指针
    linux下安装boost库
    ASP/ASP.NET程序设计电子书专题下载
    Highcharts 点击多选框取消,添加数据上绑定最大,最小值和图例上绑定提示框数据
  • 原文地址:https://www.cnblogs.com/rainmj/p/5285967.html
Copyright © 2011-2022 走看看