语音合成_语音合成技术 - CSDN
语音合成 订阅
语音合成是通过机械的、电子的方法产生人造语音的技术。TTS技术(又称文语转换技术)隶属于语音合成,它是将计算机自己产生的、或外部输入的文字信息转变为可以听得懂的、流利的汉语口语输出的技术。 展开全文
语音合成是通过机械的、电子的方法产生人造语音的技术。TTS技术(又称文语转换技术)隶属于语音合成,它是将计算机自己产生的、或外部输入的文字信息转变为可以听得懂的、流利的汉语口语输出的技术。
信息
基础知识
数字信号处理,语言学知识
定    义
通过机械产生人造语音的技术
技    术
TTS技术
中文名
语音合成
应    用
计算机
外文名
speech synthesis
语音合成概述
语音合成是利用电子计算机和一些专门装置模拟人,制造语音的技术。语音合成和语音识别技术是实现人机语音通信,建立一个有听和讲能力的口语系统所必需的两项关键技术。使电脑具有类似于人一样的说话能力,是当今时代信息产业的重要竞争市场。和语音识别相比,语音合成的技术相对说来要成熟一些,并已开始向产业化方向成功迈进,大规模应用指日可待。语音合成,又称文语转换(Text to Speech)技术,能将任意文字信息实时转化为标准流畅的语音朗读出来,相当于给机器装上了人工嘴巴。它涉及声学、语言学、数字信号处理、计算机科学等多个学科技术,是中文信息处理领域的一项前沿技术,解决的主要问题就是如何将文字信息转化为可听的声音信息,也即让机器像人一样开口说话。我们所说的“让机器像人一样开口说话”与传统的声音回放设备(系统)有着本质的区别。传统的声音回放设备(系统),如磁带录音机,是通过预先录制声音然后回放来实现“让机器说话”的。这种方式无论是在内容、存储、传输或者方便性、及时性等方面都存在很大的限制。而通过计算机语音合成则可以在任何时候将任意文本转换成具有高自然度的语音,从而真正实现让机器“像人一样开口说话”。 [1]  文语转换系统实际上可以看作是一个人工智能系统。为了合成出高质量的语言,除了依赖于各种规则,包括语义学规则、词汇规则、语音学规则外,还必须对文字的内容有很好的理解,这也涉及到自然语言理解的问题。下图显示了一个完整的文语转换系统示意图。文语转换过程是先将文字序列转换成音韵序列,再由系统根据音韵序列生成语音波形。其中第一步涉及语言学处理,例如分词、字音转换等,以及一整套有效的韵律控制规则;第二步需要先进的语音合成技术,能按要求实时合成出高质量的语音流。因此一般说来,文语转换系统都需要一套复杂的文字序列到音素序列的转换程序,也就是说,文语转换系统不仅要应用数字信号处理技术,而且必须有大量的语言学知识的支持。 [1] 
收起全文
精华内容
参与话题
  • 文章目录语音合成参数选择情感语音合成HMMLSTM神经网络语音合成模型音素到倒频谱映射递归神经网络语音合成主要流程框架基于 HMM 的蒙古语语音合成方法参数法:基于深度神经网络的蒙古语语音合成方法端到端语音合成...

    语音合成参数选择

    • 特征参数选择:提取语音信号的频谱参数作为模型的特征参数(观测值)
    • 语音识别和说话人识别:Mel域倒谱系数(Mel—Frequency Cepstral Coefficiem,,MFCC)参数,倒谱(Cepstrum)和Mel域倒谱(Mel.Cepstnun)

    情感语音合成

    • 语音合成:最初的物理机理语音合成,波形拼接语音合成,韵律转换语音合成到统计参数语音合成和深度学习语音合成
    • 情感语音合成:波形拼接合成方法,韵律特征修改方法和基于隐马尔可夫模型( hidden Markov model, HMM )的统计参数语音合成方法

    HMM

    • 传统参数语音合成方法是基于统计学习和决策树的隐马尔科夫-高斯混合模型 (HMM)。HMM 对声音特征的适应性和鲁棒性高、需要较小的计算代价和在 训练数据较少的时候有更好的表现[3]等诸多优点,使其 长期成为语音合成方法的主流技术。
      • 但是合成的质量不高,主要的原因是由于其生成的过程是离散的

    LSTM神经网络

    • 神经网络是更为广泛的数值型计算模式,前向网络模型建立样本到标签的一对一映射,循环神经网络(RNN)在序列间建立映射,全部计算均为连续数值空间,没有HMM离散规则跳转。长短期记忆神经网络 (LSTM)克服了普通循环神经网络梯度消散或爆炸问题。

    语音合成模型

    音素到倒频谱映射

    • 文本音素信息到倒频谱之间的映射关系是语音合成系统的核心部分。神经网络一次输入对应一次输出,需要训练两个模型:1.音素时长模型,倒频谱模型。
      • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8LeNeHYE-1594971713014)(https://i.loli.net/2020/07/08/wm3biF92ZtWcoMq.jpg)]
        • 音素因袭是包含发音与语言相关的向量序列。预测时长后使用时长扩展音素信息为多个描述帧,对应预测倒谱帧。时长模型决定韵律,倒频谱决定音色和音调,两这对合成质量有决定性作用
        • 音素信息序列和帧序列都是一系列配对向量。使 用深度神经网络和循环神经网络都可以对输入和输出 进行映射。

    递归神经网络

    • 当前输出会受上一次前馈计算的影响,而当前输出后的 网络状态又继续影响下一次输出。
    • AdGu1ESfBCTqwk7
      • ht是网络当前状态,由上一状态ht-1、当前输入xt 和激活函数f共同影响。
      • LSTM 包含输入门(IG)、遗忘门(FG)和输出门 (OG)将状态传递变为累加。输入门控制新状态(NI)加 到当前状态中的比例,遗忘门决定保留多少旧状态,输出门将状态映射到最终输出。三个门限各自有的功能,不能简单地去掉。

    语音合成主要流程

    框架

    • 主要分为前端处理和后端处理:前端处理主要是根据先验知识对文本进行语言及语法层面的分析。对于后端合成部分,主要是对波形拼接和参数合成。
    • 波形拼接方法是根据文本分析从语料库中选取相应的语音单元片段,然后进行单元片段的拼接完成语音合成。参数合成方法是从数字信号处理,统计学等角度,对声 码器提取的声学特征参数进行统计建模,然后把模型预测得到的声学特征参数输入声码器完 成语音合成。
    • 主流的框架有:百度的Deepvoice Google的tacotron 和Tacotron2, wavenet(直接对语音参数和波形之间进行建模,弥补传统声码器损失语音细节信息的缺陷。

    基于 HMM 的蒙古语语音合成方法

    • 基于 HMM 的蒙古语语音合成方法主要包括以下流程:前端处理、模型训练和后端合成。 前端处理部分主要是文本处理,输入的文本经过特殊字符转换、拉丁校正、字母转音素、上 下文标注转换为对应的语言特征。对于模型训练部分,选取谱特征和激励特征及其动态特性 作为声学特征,训练流程如下:首先进行单音素 HMM 模型的初始化及训练,并使用预先设 计的问题集进行上下文(三音素)决策聚类,然后使用训练得到的单音素 HMM 模型参数初始 化决策聚类后的上下文 HMM 模型,最后进行上下文 HMM 模型及时长 HMM 模型的训练。 对于后端合成部分,输入的蒙古语文本经过前端处理得到相应的语言特征,根据训练得到的 上下文 HMM 模型及时长 HMM 模型,预测声学参数及持续时长,然后使用声码器完成语音 的合成。
    • HMM的声学特征的建模:谱特征MGC和激励特征logF0作为声学特征。
    • oFQVvE5KgUlSNbP
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MBLLRuT2-1594971713023)(https://i.loli.net/2020/07/14/dFVRS8Bq29fmMNA.png)]
    • 马尔科夫
      • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UCJarUZU-1594971713024)(https://i.loli.net/2020/07/09/32eICSQluzcHTrG.png)]
    • 隐马尔科夫链
      • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Q5Zs7IMV-1594971713025)(https://i.loli.net/2020/07/14/BNwE87AkvOSpY9r.png)]
      • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BvCWfes2-1594971713026)(https://i.loli.net/2020/07/14/TSiXa1hmwuf3bUW.png)]
    • Mel域倒谱特征或者线谱对特征,和提取了浊音段的基频参数描述语音中的激励。
    • 建模单元:一般是以音素作为建模单元,中文是对声韵母建模。
    • HMM拓扑结构:HMM一般采用由左向右并且各态历经的拓扑结构。
      • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XFnEk196-1594971713027)(https://i.loli.net/2020/07/14/yrfXlbD7pH6AY5z.png)]
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5gMXo6ev-1594971713028)(https://i.loli.net/2020/07/14/v85jTqhZ2FeMiPs.png)]
    • 语音合成阶段
      • sF2wxBRrQOE7CDM
    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FjaUOhYi-1594971713029)(https://i.loli.net/2020/07/14/QynJfB47CrkwOZs.png)]
    • AxgibT9QPydH6tn

    参数法:基于深度神经网络的蒙古语语音合成方法

    • 运用深度神经网络进行声学特征参数的预测是该方法的核心,该方法同样有三个部分组 成,前端处理,模型训练,后端合成。对于前端处理部分,与基于 HMM 的蒙古语语音合成 方法的前端处理类似,其作用是把输入的蒙古语文本转换为对应的语言特征。模型训练部分, 采用谱特征、激励特征、频带周期特征及其动态特性作为声学特征。模型包括基于 HMM 的 时长模型和基于 DNN 的声学模型,时长模型训练与基于 HMM 的蒙古语语音合成方法中时 长模型训练流程相同。对于声学模型训练,使用 DNN 对语言特征与声学特征之间的映射关系 进行建模。对于后端合成,输入文本经过前端处理,得到相应的语言特征,然后根据 HMM 时 长模型和 DNN 声学模型分别预测持续时长和声学特征参数,最后使用声码器重构语音波形。

    端到端语音合成

    • 语音合成方法主 要分为三个部分,其一,前端处理部分,主要包括特殊字符转换,拉丁校对。其二,预测梅 尔频谱模型部分,该部分采用梅尔频谱作为中间特征,模型部分采用带有注意力机制的编码器-解码器模型结构。最后是梅尔频谱转换语音波形部分,该部分首先使用了梅尔频谱预测频 谱幅度模型即带有多层高速公路网络和双向门控循环单元的卷积单元(Convolutional Bank with Highway networks and Grated recurrent unit, CBHG) 模块把梅尔频谱转换为频谱幅度(目 标特征),然后根据得到的频谱幅度使用 Griffin-Lim 算法进行相位预测,重构语音波形。
    • 2UNMKBjtLcGCiqY
    • 前端处理流程
      • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aVQZjrAA-1594971713032)(https://i.loli.net/2020/07/09/Hr29y8QibkM5ZlJ.png)]
        • 前端处理、预测梅尔频谱 模型、梅尔频谱转换语音波形模块。蒙古语文本经过前端处理得到对应的拉丁字符序列,然 后字符序列输入到预测梅尔频谱模型得到对应的梅尔频谱,最后梅尔频谱经过梅尔频谱转换 语音波形模块进行蒙古语语音的合成。
        • 端到端语音合成主要包括两个模型:预测梅尔频谱模型和梅尔频谱预测频谱幅度模型,梅尔频谱作为中间转换特征,频谱幅度作为目标特征。
        • 选择梅尔频谱作为主要的声学特征参数,由于梅尔频谱对短时傅里叶变换的频率轴做一个非线性变换,用较少的维度对频率范围进行压缩变换得到,比波形样本更具有平滑。

    wavenet 声码器

    • wavenet是一种自回归的深度生成模型,该模型可以直接在原始音频层面上进行建模,具有全概率和自回归性,每个音频样本点的预测分布取决于之前的所有音频样本点,对于音频样本x=x1,…xt的联合概率被分解为条件概率的乘积。
      • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9lbUOp0E-1594971713033)(https://i.loli.net/2020/07/09/dqOGhrWcRCLTJFw.png)]
        • WaveNet 结构优于 PixelCNNs 结构最突出的特点是采用扩展因果卷积,使用因果卷积可以保证建模时不会违反样本点的先后顺序,预测 p(xt+1,x1,…,xt)使用的是样本点xt+1之前的序列信息,而不使用xt+1,xt+2,…,xT 等未来样本点的信息。

    基于情感的语音合成

    • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9up0nM2G-1594971713033)(https://i.loli.net/2020/07/09/CXuATslE9B4zcQF.png)]
    • 基于HMM的语音合成
      • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QeKTmFqD-1594971713034)(https://i.loli.net/2020/07/09/cI8lJzFgxPrqY5n.png)]
    • DNN情感语音合成
      • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-h61jaEJJ-1594971713035)(https://i.loli.net/2020/07/09/KpT8bZgka4tq3Wc.png)]
      • 基频( fundamental frequency ,F0)、谱参数(MGC, BAP)和浊音/清音(voice/unvoiced,V/UV)

    语音分析合成算法

    straight

    • STRAIGHT是一种针对语音信号的分析合成算法,经过其分析合成后的语 音可以保留较高质量,并且可以利用该算法可以对语音的时长、基频和频谱参数进行调整。
      • 去除周期影响的谱估计
        • 在分析语音信号时,我们首先对语音信号进行加 窗处理,研究其短时谱。因此语音信号的短时谱在时域及频域上表现出和 基音周期相关的周期性。利用STRAIGHT语音分析合成算法可以分别去;
      • 可靠的基频提取:
        • STRAIGHT语音分析合成算法通过对频谱进行谐波分析 得到浊音段的基频参数,该算法提取的基频轨迹更为精确和稳定;
      • 合成器的实现:
        • STRAIGHT进行合成时采用基于基音同步叠加和最小相位 冲激响应的方法,并且可以在合成过程中对时长、基频和谱参数进行灵活 地调整。
    展开全文
  • 语音合成技术

    千次阅读 2017-12-01 18:59:10
    本期分享的主题是语音合成技术,以下是本次分享的主要内容: 1.语音合成技术简介 1.1 什么是语音合成语音合成技术是将任意文本转换成语音的技术。是人与计算机语音交互必不可少的模块。如果说语音识别技术是让...

    关注52AI,做AI的行业领先者。QQ人工智能行业交流群:626784247.




    01



    本期分享的主题是语音合成技术,以下是本次分享的主要内容:
    1.语音合成技术简介
    1.1 什么是语音合成?
    语音合成技术是将任意文本转换成语音的技术。是人与计算机语音交互必不可少的模块。如果说语音识别技术是让计算机学会“听”人的话,将输入的语音信号转换成文字,那么语音合成技术就是让计算机程序把我们输入的文字“说”出来,将任意输入的文本转换成语音输出。


    640?wx_fmt=png&wxfrom=5&wx_lazy=1


    1.2 语音合成的应用场景和研究范围
    语音合成技术是人与计算机语音交互中必不可少的模块。从地图导航(例如高德地图高晓松语音导航),语音助手(Apple Siri, Google Assistant,微软 Cortana, Nuance Nina), 小说、新闻朗读(书旗、百度小说), 智能音箱(Amazon Alexa, 天猫精灵, Google Home,Apple Pod Home 等 ),语音实时翻译,到各种大大小小的客服,呼叫中心,甚至机场广播,地铁公交车报站都少不了语音合成技术的身影。
    而且不仅仅是文字转语音,语音合成技术研究范围还包括且不限于:说话人转换(看过007么), 语音频带拓展, 歌唱语音合成(例如:日本很火的初音未来),耳语语音合成(whisper), 方言合成(四川话,粤语, 甚至古代汉语发音),动物叫声合成,等等等等。

    0?wx_fmt=png


    1.3 一个典型的语音合成系统流程图
    如下图所示,一个典型的语音合成系统主要包括前端和后端两个部分。前端部分主要是对输入文本的分析,从输入的文本提取后端建模需要的信息。例如:分词(判断句子中的单词边界),词性标注(名词,动词,形容词等),韵律结构预测(是否韵律短语边界),多音字消岐等等。后端的部分读入前端文本分析结果,并且对语音部分结合文本信息进行建模。在合成过程中,后端会利用输入的文本信息和训练好的声学模型,生成出语音信号,进行输出。

    0?wx_fmt=png


    1.4 语音产生的过程
    一个人发声的过程可以看成肺部气流通过人的声带,并经过口腔形状调制,最后从嘴唇发出的过程。当人发轻声时,肺部气流通过声带时,声带不会振动,因此我们可以将通过的气流用白噪声信号来表示。相对的,当人发元音或者浊辅音时,当气流通过声带时,声带会有节奏地振动,这时,我们将通过的气流用冲激串表示。同时,我们把声带振动的频率叫做基频(f0)。人的音色和具体发什么音是和发音时的口腔形状相关。因此我们可以将人发生的过程简单的看成一个激励信号(气流)通过滤波器(口腔形状)调制,最后通过嘴唇发射出去的过程。

    0?wx_fmt=png


    1.5 三种现阶段主要的语音合成系统
    现阶段的语音合成系统,根据所采用的方法和框架不同,主要可以分为三种: A. 参数语音合成系统。B. 拼接语音合成系统。C. 基于波形的统计合成系统(WaveNet) 。其中A, B 是现阶段各大公司线上主流的合成系统,C WaveNet 的方法还在研究阶段,是现阶段研究的热门。
    A. 参数语音合成系统的特点是,在语音分析阶段,需要根据语音生成的特点,将语音波形(speech waves) 通过声码器转换成频谱,基频,时长等语音或者韵律参数。在建模阶段对语音参数进行建模。并且在语音合成阶段,通过声码器从预测出来的语音参数还原出时域语音信号。参数语音合成系统的优势在于模型大小较小,模型参数调整方便(说话人转换,升降掉),而且合成语音比较稳定。缺点在于合成语音音质由于经过参数化,所以和原始录音相比有一定的损失。
    B. 拼接语音合成系统的特点是,不会对原始录音进行参数化,而会将原始录音剪切成一个一个基本单元存储下来。在合成过程中,通过一些算法或者模型计算每个单元的目标代价和连接代价,最后通过Viterbi算法并且通过PSOLA(Pitch Synchronized Overlap-Add)或者WSOLA(Waveform Similarity based Overlap-Add)等信号处理的方法“拼接”出合成语音。因此,拼接语音合成的优势在于,音质好,不受语音单元参数化的音质损失。但是在数据库小的情况下,由于有时挑选不到合适的语音单元,导致合成语音会有Glitch 或者韵律、发音不够稳定。而且需要的存储空间大。
    C. WaveNet 波形统计语音合成是Deep Mind 首先提出的一种结构,主要的单元是 Dilated CNN (卷积神经网络)。这种方法的特点是不会对语音信号进行参数化,而是用神经网络直接在时域预测合成语音波形的每一个采样点。优势是音质比参数合成系统好,略差于拼接合成。但是较拼接合成系统更稳定。缺点在于,由于需要预测每一个采样点,需要很大的运算量,合成时间慢。WaveNet 证明了语音信号可以在时域上进行预测,这一点以前没有方法做到。现阶段WaveNet是一个研究热点。
    1.6 合成语音的评价标准
    声音的好听与难听是一个相对主观的概念,因此合成语音的好坏主要通过找很多测听人员对合成语音进行打MOS(Mean Opinion Score)分,其中MOS的范围是 1-5 分,分别代表 1: Bad, 2: Poor, 3: Fair, 4: Good, 5: Excellent 。MOS打分可以对合成语音的音质,可懂度,相似度,或者其他的分项进行评价,也可以对语音的整体自然度进行评价。


    2. INTERSPEECH 2017 语音合成论文介绍
    下面介绍一些INTERSPEEECH 2017 语音合成方面的论文。本次INTERSPEECH会议WaveNet是很火的一个题目,专门有一个部分是讲WaveNet的各种应用。另外,本次会议里,各大公司也发表了介绍自己线上语音合成系统的文章,特别是苹果的Siri, 这也是Siri第一次发表介绍系统结构的论文。
    2.1 WaveNet and Novel Paradigms
    这个 Section都是以WaveNet为结构来做一些事情。主要介绍一下几篇论文。

    0?wx_fmt=png


    2.1.1 PAPER Tue-O-4-1-1 — Speaker-Dependent WaveNet Vocoder
    这篇文章是日本名古屋大学的文章,主要是用WaveNet来做声码器,不同于基本的WaveNet,这篇文章不再condition on 每一帧的 linguistic feature, 而是condition on acoustic feature(声学参数,比如频谱参数 ,基频参数)。通过给定每一帧的acoustic feature,通过WaveNet, 而不是传统的声码器,就能得到合成语音。实验证明了,对于不同的说话人集合,WaveNet声码器都好于传统的 MLSA (Mel-Log S)声码器。
    但作者也提到训练和WaveNet预测的过程非常慢,用单GPU TITAN X, 对每一个说话人训练需要2天时间,并且合成仅仅2秒钟的语音需要6分钟的时间。

    0?wx_fmt=png


    0?wx_fmt=png


    0?wx_fmt=png

    2.1.2 PAPER Tue-O-4-1-2 — Waveform Modeling Using Stacked Dilated Convolutional Neural Networks for Speech Bandwidth Extension
    这篇文章是中科大讯飞实验室发表的文章,文章的目标是用WaveNet的结构,从窄带语音信号预测出相应的宽带语音信号。和基础的WaveNet相比,文章将auto-regressive的生成方式换成了直接mapping 的方式,同时尝试了用non-casual CNN 和 casual CNN作比较。结论是用non-casual CNN先只预测高频信号,然后再跟原始低频信号相加生成宽带信号能得到最好的结果。

    0?wx_fmt=png


    0?wx_fmt=png


    0?wx_fmt=png


    2.1.3 PAPER Tue-O-4-1-5 — Statistical Voice Conversion with WaveNet-Based Waveform Generation
    这篇文章也是名古屋大学的文章,文章用WaveNet的结构实现说话人语音转换(Voice Conversion),结论是好于传统的GMM说话人转换的方法。这篇文章其实也是将WaveNet作为一个声码器,在合成的时候,将转换以后的语音参数作为condition生成speech wave。下图是基于WaveNet语音转换的结构框图。

    0?wx_fmt=png


    2.2 公司发表的介绍自己合成系统的文章
    2.2.1 Apple : Siri On-Device Deep Learning-Guided Unit Selection Text-to-Speech System
    这是 Siri 系统第一次发文章,主要介绍了apple最近 TTS 方面的 deep learning 方面的进展, TTS 的性能提升。从实验结果来看,在各种不同的语种上,基于Mix density network (MDN)的拼接语音合成系统明显优于之前的传统的Siri拼接合成系统。以下是具体结果。

    0?wx_fmt=png


    0?wx_fmt=png


    2.2.2 Google’s Next-Generation Real-Time Unit-Selection Synthesizer using Sequence-To-Sequence LSTM-based Autoencoders

    0?wx_fmt=png


    2.2.3 Nuance : Unit selection with Hierarchical Cascaded Long Short Term Memory Bidirectional Recurrent Neural Nets
    Nuance 公司也发表了介绍自己合成系统的文章。是一个基于Hierarchical LSTM 的拼接合成系统。结果证明Hierarchical LSTM结构在合成语音韵律上好于非Hierarchical LSTM。

    0?wx_fmt=png


    0?wx_fmt=png


    2.2.4 Google : Tacotron: Towards End-to-End Speech Synthesis
    这篇 google 的文章早前在 arxiv 上放出,和 WaveNet 相比 Tacotron 系统是以 frame 而不是每一个 sample 点为单位进行模型训练和预测,所以速度上会更快。Tacotron 是在 Spectrogram 上建模,不像 WaveNet 是在波形上建模。所以和 WaveNet 相比, Tacotron 还是损失了frame 相位的信息。最后Tacotron 通过 Griffin-Lim 算法直接从 Spectrogram 还原出wave。 在 acoustic model 上面, Tacotron 用了 pre-net 对每一个字的 embedding 进行了进一步的非线性编码, 并且通过 CBHG 结构来增加模型的鲁棒性。在建模过程中,作者使用了 Attention 的机制来控制每一帧的 condition。 模型也是通过 feed in 上一帧的输出来得到当前帧的输入。总的来说,这是一篇非常值得借鉴的文章。


    0?wx_fmt=png

    0?wx_fmt=png

    2.3一些其他的论文

    0?wx_fmt=png

    0?wx_fmt=png




    02


    52AI


    52AI,专注服务于普通人的AI 学习和发展,让大众受益于人工智能就是我们的愿望。我们坚信只有对大众收益的科技才是有意义的,也是我们追求的方向。

    0?wx_fmt=jpeg







    展开全文
  • TTS语音合成

    千次阅读 2019-05-29 09:59:43
    Text To Speech ,语音合成就是让机器模仿人类说话。即输入一段文字,最终输出一段语音。 做个比较,当机器的“脑子”里想到了一段内容时,或者是看到了一段话时,知道哪些字应该怎么读: 拆解文字,得到音素的时...

     什么是TTS?

    Text To Speech ,语音合成就是让机器模仿人类说话。即输入一段文字,最终输出一段语音。

    做个比较,当机器的“脑子”里想到了一段内容时,或者是看到了一段话时,知道哪些字应该怎么读:

    1. 拆解文字,得到音素的时长、频率变化,就和我们有时拆解文字的偏旁、前后缀来获得文字发音一样
    2. 知道哪些字的组合会是一个词,将这段内容按照人类容易理解的方式说出来知道哪些字的组合会是一个词,将这段内容按照人类容易理解的方式说出来
    3. 在说出来的过程中还会结合这个人的说话习惯、发音特色、口音特点等,得到一段人类特性明显的语音。(Google 已经做出了很想人类的机器声音

    和人类学说话一样,机器也需要通过大量的语音片段作为“听力材料”,才能学会发音技巧。以及还得学会一些语言规则,比如语法和韵律,才能像人类一样,说话语气、语境,能表达出字面之外的表意。不然,机器只会说出生硬、没有情感、不连贯的话(就像一些动漫或游戏作品中机器人角色的对话)。

    音合成技术目前主要应用在读书软件、导航软件、对话问答系统等中。

     

    常见的第三方平台

    百度AI,科大讯飞...

    http://ai.baidu.com/tech/speech/tts?track=cp:ainsem|pf:pc|pp:chanpin-yuyin|pu:yuyin-yuyinhecheng-pinpai|ci:|kw:10003538

    https://www.baidu.com/link?url=IyCma66rgrZjER-paAgrHkAvRq5Xw39vtlPxqfX_ZOu&wd=&eqid=8cde5ae1003cfe86000000035cede6be

     

    百度百科版本

    语音合成是通过机械的、电子的方法产生人造语音的技术。TTS技术(又称文语转换技术)隶属于语音合成,它是将计算机自己产生的、或外部输入的文字信息转变为可以听得懂的、流利的汉语口语输出的技术。

    https://baike.baidu.com/item/%E8%AF%AD%E9%9F%B3%E5%90%88%E6%88%90

    维基百科版本

    语音合成是人类语音的人工生成。用于此目的的计算机系统称为语音计算机或语音合成器,并且可以用软件或硬件产品实现。甲文本到语音(TTS)系统转换正常语言文本转换成语音; 其他系统呈现符号语言表征,如将语音转录为发音。

     https://en.wikipedia.org/wiki/Speech_synthesis

     

                                             


     

     

                                                                                                                                 by .k

     

    关注"编程v",每一天涨一点

    STAY HUNGRY & STAY FOOLISH

    展开全文
  • 本片主要讲解如果使用科大讯飞和云知音这两个离线语音合成功能。目前语音合成的主要有科大讯飞、百度语音、云知声。一、三大产品功能分析1.百度语音百度语音合成只有离在线语音服务(免费),没有纯离线,离在线语音...

    本片主要讲解如果使用科大讯飞和云知音这两个离线语音合成功能。

    目前语音合成的主要有科大讯飞、百度语音、云知声。

    一、三大产品功能分析

    1.百度语音

    百度语音合成只有离在线语音服务(免费),没有纯离线,离在线语音合成,在首次使用语音功能,必须联网,让其通过网络获得百度的授权文件之后,方可正常使用,之后不联网也可以正常使用,联网使用优先使用在线包,不联网则使用离线包。百度语音合成文档地址:http://ai.baidu.com/docs#/TTS-Android-SDK/top,每天有调用次数限制,如下图:


    2.科大讯飞

    讯飞语语音合成有在线和离线两种,在线免费,离线收费,收费标准如下:


    在线只有联网的时候才可以正常使用,离线则无需任何联网,就可正常使用,如果选择离线包,体验版SDk下载后就可以为你生产专用的SDK,SDK的demo中会配置好一切,比如说key这些,都会使用你建应用所给的,无需你手动再进行配置了,简单易用,但下载下来还得调试一番方可正常使用。科大讯飞官网:http://www.xfyun.cn/,SDK文档地址:http://mscdoc.xfyun.cn/android/api/

    3.云知声

    云知声有在线和离线的,在线的官方号称永久免费,离线的也是收费的,但是没能查到收费标准,语音文档地址:http://admin-web-files.ks3-cn-shanghai.ksyun.com/docs/sdk/USC_DevelGuide_Android_common.pdf,置于其他详细信息可以上官网了解,地址:http://dev.hivoice.cn/

    二、三者使用

    1.百度语音

    如何使用请见文档,文档写的相当详细,地址:http://ai.baidu.com/docs#/Begin/top,截图如下:


    包括如何注册如何使用,都明确标出来了,我只将自己的关于语音合成的代码贴出来,如下:

    public class BaiDuSpeechUtil {
    
        private final String TAG = this.getClass().getSimpleName();
        private SpeechSynthesizer mSpeechSynthesizer;
        private String mSampleDirPath;
        private static final String SAMPLE_DIR_NAME = "baiduTTS";
        //-------以下全是在assets下的文件,使用离线时必须全部copy到手机中方可使用----start--
        private static final String SPEECH_FEMALE_MODEL_NAME = "bd_etts_speech_female.dat";
        private static final String SPEECH_MALE_MODEL_NAME = "bd_etts_speech_male.dat";
        private static final String TEXT_MODEL_NAME = "bd_etts_text.dat";
        private static final String ENGLISH_SPEECH_FEMALE_MODEL_NAME = "bd_etts_speech_female_en.dat";
        private static final String ENGLISH_SPEECH_MALE_MODEL_NAME = "bd_etts_speech_male_en.dat";
        private static final String ENGLISH_TEXT_MODEL_NAME = "bd_etts_text_en.dat";
    
        //--------end-------------------------------------------------------------
    
    
        private static BaiDuSpeechUtil baiDuSpeechUtil = null;
        public static BaiDuSpeechUtil getInstance(){
            if(baiDuSpeechUtil == null) {
                synchronized (BaiDuSpeechUtil.class) {
                    if(baiDuSpeechUtil == null) {
                        baiDuSpeechUtil = new BaiDuSpeechUtil();
                    }
                }
            }
            return baiDuSpeechUtil;
        }
    
        /**
         * 初始化百度语音资源
         * @param context
         */
        public void setInitialEnv(Context context) {
            initialEnv(context);
        }
        /**
         * 初始化百度语音播报相关
         * @param context
         */
        public void setInitialTts(Context context, SpeechSynthesizerListener speechSynthesizerListener){
            initialTts(context,speechSynthesizerListener);
        }
    
    
        private void initialEnv(Context context) {
    //        long start_time= System.currentTimeMillis();
            if (mSampleDirPath == null) {
                String sdcardPath = Environment.getExternalStorageDirectory().toString();
                mSampleDirPath = sdcardPath + "/" + SAMPLE_DIR_NAME;
            }
            makeDir(mSampleDirPath);
            copyFromAssetsToSdcard(context,false, SPEECH_FEMALE_MODEL_NAME, mSampleDirPath + "/" + SPEECH_FEMALE_MODEL_NAME);
            copyFromAssetsToSdcard(context,false, SPEECH_MALE_MODEL_NAME, mSampleDirPath + "/" + SPEECH_MALE_MODEL_NAME);
            copyFromAssetsToSdcard(context,false, TEXT_MODEL_NAME, mSampleDirPath + "/" + TEXT_MODEL_NAME);
            copyFromAssetsToSdcard(context,false, "english/" + ENGLISH_SPEECH_FEMALE_MODEL_NAME, mSampleDirPath + "/"
                    + ENGLISH_SPEECH_FEMALE_MODEL_NAME);
            copyFromAssetsToSdcard(context,false, "english/" + ENGLISH_SPEECH_MALE_MODEL_NAME, mSampleDirPath + "/"
                    + ENGLISH_SPEECH_MALE_MODEL_NAME);
            copyFromAssetsToSdcard(context,false, "english/" + ENGLISH_TEXT_MODEL_NAME, mSampleDirPath + "/"
                    + ENGLISH_TEXT_MODEL_NAME);
    
    //        Log.d(TAG,"initialEnv cost:"+ (System.currentTimeMillis()-start_time));
        }
    
        private void makeDir(String dirPath) {
            File file = new File(dirPath);
            if (!file.exists()) {
                file.mkdirs();
            }
        }
    
        /**
         * 将sample工程需要的资源文件拷贝到SD卡中使用(授权文件为临时授权文件,请注册正式授权)
         * 主要是在离线时候用到,只需执行一次即可,这里写的不严谨,应该去判断一下离线用的那些文件,sd卡是否存在,如果不存在,则copy,如果存在则无需在copy,可在子线程操作
         * @param isCover 是否覆盖已存在的目标文件
         * @param source
         * @param dest
         */
        private void copyFromAssetsToSdcard(Context context,boolean isCover, String source, String dest) {
            File file = new File(dest);
            if (isCover || (!isCover && !file.exists())) {
                InputStream is = null;
                FileOutputStream fos = null;
                try {
                    is = context.getAssets().open(source);
                    String path = dest;
                    fos = new FileOutputStream(path);
                    byte[] buffer = new byte[1024];
                    int size = 0;
                    while ((size = is.read(buffer, 0, 1024)) != -1) {
                        fos.write(buffer, 0, size);
                    }
                    fos.flush();
    
    
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
    
                    if (is != null) {
                        try {
                            is.close();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
    
                    }
                    if (fos != null) {
                        try {
                            is.close();
                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }
    
    
                }
            }
    
    
        }
    //此方法可在子线程中操作,由于这个初始化过程比较费时,大概在1s左右,看项目需求而定,如果是进入界面就必须播放(伴随UI改变的)的,在UI线程,如无其他特殊要求,放在子线程中即可
        private void initialTts(Context context,SpeechSynthesizerListener speechSynthesizerListener) {
    //        long start_time= System.currentTimeMillis();
            mSpeechSynthesizer = SpeechSynthesizer.getInstance();
            mSpeechSynthesizer.setContext(context);
            mSpeechSynthesizer.setSpeechSynthesizerListener(speechSynthesizerListener);
            mSpeechSynthesizer.setApiKey(Constant.APP_KEY_BAIDU, Constant.APP_SECRET_BAIDU);
            mSpeechSynthesizer.setAppId(Constant.APP_ID_BAIDU);
    
            // 文本模型文件路径 (离线引擎使用)
            mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_TEXT_MODEL_FILE, mSampleDirPath + "/"
                    + TEXT_MODEL_NAME);
            mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_TTS_SPEECH_MODEL_FILE, mSampleDirPath + "/"
                    + SPEECH_FEMALE_MODEL_NAME);
            // 本地授权文件路径,如未设置将使用默认路径.设置临时授权文件路径,LICENCE_FILE_NAME请替换成临时授权文件的实际路径,仅在使用临时license文件时需要进行设置,如果在[应用管理]中开通了正式离线授权,不需要设置该参数,建议将该行代码删除(离线引擎)
            // 如果合成结果出现临时授权文件将要到期的提示,说明使用了临时授权文件,请删除临时授权即可。
    
            // 发音人(在线引擎),可用参数为0,1,2,3。。。(服务器端会动态增加,各值含义参考文档,以文档说明为准。0--普通女声,1--普通男声,2--特别男声,3--情感男声。。。)
            mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_SPEAKER, "0");
            // 设置Mix模式的合成策略,  //mix模式下,wifi使用在线合成,非wifi使用离线合成)
            mSpeechSynthesizer.setParam(SpeechSynthesizer.PARAM_MIX_MODE, SpeechSynthesizer.MIX_MODE_HIGH_SPEED_SYNTHESIZE_WIFI);
    //        if(SystemUtil.isNetWorkConnected(getCurrentActivity())) {
    //            // AuthInfo接口用于测试开发者是否成功申请了在线或者离线授权,如果测试授权成功了,可以删除AuthInfo部分的代码(该接口首次验证时比较耗时),不会影响正常使用(合成使用时
    //            AuthInfo authInfo=this.mSpeechSynthesizer.auth(TtsMode.MIX);
    //
    //            if (authInfo.isSuccess()){
    //                toPrint("auth success");
    //            }else{
    //                String errorMsg=authInfo.getTtsError().getDetailMessage();
    //                toPrint("auth failed errorMsg=" + errorMsg);
    //            }
    //        }
    
            // 初始化tts
            mSpeechSynthesizer.initTts(TtsMode.MIX);
            // 加载离线英文资源(提供离线英文合成功能)
            int result = mSpeechSynthesizer.loadEnglishModel(mSampleDirPath + "/" + ENGLISH_TEXT_MODEL_NAME, mSampleDirPath + mSampleDirPath + "/" + ENGLISH_SPEECH_FEMALE_MODEL_NAME);
    //        Log.d(TAG,"initialTts cost:"+ (System.currentTimeMillis()-start_time));
        }
    
    
        /**
         * 播报的文字
         * @param content
         */
        public  void speakText(String content) {
            try{
                if(mSpeechSynthesizer != null) {
                    int result = mSpeechSynthesizer.speak(content);
                    if (result < 0) {
                        Log.d(TAG,"error,please look up error code in doc or URL:http://yuyin.baidu.com/docs/tts/122 ");
                    }
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
    
        }
    
        /**
         * 暂停
         */
        public void pauseSpeechSynthesizer(){
            if(mSpeechSynthesizer != null) {
                mSpeechSynthesizer.pause();
            }
        }
    
        /**
         *  停止播放
         */
        public void stopSpeechSynthesizer(){
            if(mSpeechSynthesizer != null) {
                mSpeechSynthesizer.stop();
            }
        }
    
        /**
         * 接着停止后的地方播放
         */
    
        public void resumeSpeechSynthesizer(){
            if(mSpeechSynthesizer != null) {
                mSpeechSynthesizer.resume();
            }
        }
    
        /**
         *  释放mSpeechSynthesizer,在使用完之后必须调用,确保下个界面使用的时候资源已经释放掉了,否则下个界面将无法正常播放
         */
        public void releaseSpeechSynthesizer(){
            if(mSpeechSynthesizer != null) {
                mSpeechSynthesizer.release();
            }
        }
    
        public void setSpeechSynthesizerNull(){
            if(mSpeechSynthesizer != null) {
                mSpeechSynthesizer = null;
            }
        }
    
        public void endSpeechSynthesizer(){
            pauseSpeechSynthesizer();
            stopSpeechSynthesizer();
            releaseSpeechSynthesizer();
            setSpeechSynthesizerNull();
        }
    }

    如何调用:

    public class MeasurePromptActivity extends BaseActivity implements SpeechSynthesizerListener {
    
        private BaiDuSpeechUtil mBaiDuSpeechUtil;
        private static final String WARM_PROMPT = "百度语音测试,你好开发者";
       
        @Override
        protected void setCurrentContentView() {
            setContentView(R.layout.activity_measure_prompt);
        }
    
        @Override
        protected void init(Bundle savedInstanceState) {
    
        }
    //   语音初始化及播报
        private void startSpeakText() {
            mBaiDuSpeechUtil = BaiDuSpeechUtil.getInstance();
            mBaiDuSpeechUtil.setInitialEnv(getCurrentActivity());
            mBaiDuSpeechUtil.setInitialTts(getCurrentActivity(), this);
    
            speakText(WARM_PROMPT);
        }
    
        private void speakText(String content) {
            if (mBaiDuSpeechUtil != null) {
                mBaiDuSpeechUtil.speakText(content);
            }
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            startSpeakText();
        }
    //在离开次页面时调用
        private void releaseSpeechSynthesizer() {
    
            if (mBaiDuSpeechUtil != null) {
                mBaiDuSpeechUtil.releaseSpeechSynthesizer();
            }
        }
    
        @Override
        public void onSynthesizeStart(String s) {
    
        }
    
        @Override
        public void onSynthesizeDataArrived(String s, byte[] bytes, int i) {
    
        }
    
        @Override
        public void onSynthesizeFinish(String s) {
    
        }
    
        @Override
        public void onSpeechStart(String s) {
    
        }
    
        @Override
        public void onSpeechProgressChanged(String s, int i) {
    
        }
    
        @Override
        public void onSpeechFinish(String s) {
          
        }
    
        @Override
        public void onError(String s, SpeechError speechError) {
          
        }
    }
    

    以上就是百度语音合成的使用,百度其他使用亲自行下载官网提供的sample即可。

    2.科大讯飞

    科大讯飞在线和离线无非就是配置的问题,这里我只贴重点代码,代码都是copy官网提供的sample下的,如下:

    /**
    	 * 参数设置
    	 * @return 
    	 */
    	private void setParam(){
    		// 清空参数
    		mTts.setParameter(SpeechConstant.PARAMS, null);
    		//设置合成
    		if(mEngineType.equals(SpeechConstant.TYPE_CLOUD))
    		{
    			//设置使用云端引擎
    			mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
    			//设置发音人
    			mTts.setParameter(SpeechConstant.VOICE_NAME,voicerCloud);
    		}else {
    			//设置使用本地引擎
    			mTts.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_LOCAL);
    			//设置发音人资源路径
    			mTts.setParameter(ResourceUtil.TTS_RES_PATH,getResourcePath());
    			//设置发音人
    			mTts.setParameter(SpeechConstant.VOICE_NAME,voicerLocal);
    		}
    		//设置合成语速
    		mTts.setParameter(SpeechConstant.SPEED, mSharedPreferences.getString("speed_preference", "50"));
    		//设置合成音调
    		mTts.setParameter(SpeechConstant.PITCH, mSharedPreferences.getString("pitch_preference", "50"));
    		//设置合成音量
    		mTts.setParameter(SpeechConstant.VOLUME, mSharedPreferences.getString("volume_preference", "50"));
    		//设置播放器音频流类型
    		mTts.setParameter(SpeechConstant.STREAM_TYPE, mSharedPreferences.getString("stream_preference", "3"));
    		
    		// 设置播放合成音频打断音乐播放,默认为true
    		mTts.setParameter(SpeechConstant.KEY_REQUEST_FOCUS, "true");
    		
    		// 设置音频保存路径,保存音频格式支持pcm、wav,设置路径为sd卡请注意WRITE_EXTERNAL_STORAGE权限
    		// 注:AUDIO_FORMAT参数语记需要更新版本才能生效
    		mTts.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
    		mTts.setParameter(SpeechConstant.TTS_AUDIO_PATH, Environment.getExternalStorageDirectory()+"/msc/tts.wav");
    	}

    回调监听,什么时候开始,什么时候停止....这些都有的

    	 * 合成回调监听。
    	 */
    	private SynthesizerListener mTtsListener = new SynthesizerListener() {
    		
    		@Override
    		public void onSpeakBegin() {
    			showTip("开始播放");
    		}
    
    		@Override
    		public void onSpeakPaused() {
    			showTip("暂停播放");
    		}
    
    		@Override
    		public void onSpeakResumed() {
    			showTip("继续播放");
    		}
    
    		@Override
    		public void onBufferProgress(int percent, int beginPos, int endPos,
    				String info) {
    			// 合成进度
    			mPercentForBuffering = percent;
    			showTip(String.format(getString(R.string.tts_toast_format),
    					mPercentForBuffering, mPercentForPlaying));
    		}
    
    		@Override
    		public void onSpeakProgress(int percent, int beginPos, int endPos) {
    			// 播放进度
    			mPercentForPlaying = percent;
    			showTip(String.format(getString(R.string.tts_toast_format),
    					mPercentForBuffering, mPercentForPlaying));
    		}
    
    		@Override
    		public void onCompleted(SpeechError error) {
    			if (error == null) {
    				showTip("播放完成");
    			} else if (error != null) {
    				showTip(error.getPlainDescription(true));
    			}
    		}
    
    		@Override
    		public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
    			// 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
    			// 若使用本地能力,会话id为null
    			//	if (SpeechEvent.EVENT_SESSION_ID == eventType) {
    			//		String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
    			//		Log.d(TAG, "session id =" + sid);
    			//	}
    		}
    	};
    
    切记在结束当前页面的时候必须将SpeechSynthesizer  mTts 释放掉
    if( null != mTts ){
    	mTts.stopSpeaking();
    	// 退出时释放连接
    	mTts.destroy();
    }

    注意:使用时切记一定要配置正确,离线资源播报人必须copy到正确的目录下,libs的so库根据需要添加,否则可能导致包体积过大,gradle必须配置正确libs的目录,否则就会找不见so库了,报常见的java.lang.UnsatisfiedLinkError错误,如下图



    3.云知声

    云之声只介绍离线的,代码截取都是官网的sample中的,用法和百度的类似,如下:

    public class TTSOfflineActivity extends Activity {
    
    	private static boolean TTS_PLAY_FLAGE = false;
    
    	private EditText mTTSText;
    	private TextView mTextViewTip;
    	private TextView mTextViewStatus;
    	private Button mTTSPlayBtn;
    	private SpeechSynthesizer mTTSPlayer;
    	private final String mFrontendModel= "frontend_model";
    //	private final String mBackendModel = "backend_lzl";
    	private final String mBackendModel = "backend_female";
    	
    	@Override
    	public void onCreate(Bundle savedInstanceState) {
    		requestWindowFeature(Window.FEATURE_CUSTOM_TITLE);
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_offline_tts);
    		getWindow().setFeatureInt(Window.FEATURE_CUSTOM_TITLE, R.layout.status_bar_main);
    
    		mTTSText = (EditText) findViewById(R.id.textViewResult);
    		mTextViewStatus = (TextView) findViewById(R.id.textViewStatus);
    		mTextViewTip = (TextView) findViewById(R.id.textViewTip);
    		mTTSPlayBtn = (Button) findViewById(R.id.recognizer_btn);
    		mTTSPlayBtn.setEnabled(false);
    		mTTSPlayBtn.setOnClickListener(new OnClickListener() {
    
    			@Override
    			public void onClick(View arg0) {
    				TTSPlay();
    			}
    		});
    
    
    		initialEnv();
    		// 初始化本地TTS播报
    		initTts();
    	}
    
    	/**
    	 * 初始化本地离线TTS,sample中判断了是否将assets中的文件copy到sd卡中了,正式项目无需此操作,直接copy即可,但注意权限问题,尤其是高版本
    	 */
    	private void initTts() {
    
    		// 初始化语音合成对象
    		mTTSPlayer = new SpeechSynthesizer(this, Config.appKey, Config.secret);
    		// 设置本地合成
    		mTTSPlayer.setOption(SpeechConstants.TTS_SERVICE_MODE, SpeechConstants.TTS_SERVICE_MODE_LOCAL);
    //		File _FrontendModelFile = new File(mFrontendModel);
    //		if (!_FrontendModelFile.exists()) {
    //			toastMessage("文件:" + mFrontendModel + "不存在,请将assets下相关文件拷贝到SD卡指定目录!");
    //		}
    //		File _BackendModelFile = new File(mBackendModel);
    //		if (!_BackendModelFile.exists()) {
    //			toastMessage("文件:" + mBackendModel + "不存在,请将assets下相关文件拷贝到SD卡指定目录!");
    //		}
    		// 设置前端模型
    		mTTSPlayer.setOption(SpeechConstants.TTS_KEY_FRONTEND_MODEL_PATH, mDirPath+ "/" + mFrontendModel);
    		// 设置后端模型
    		mTTSPlayer.setOption(SpeechConstants.TTS_KEY_BACKEND_MODEL_PATH, mDirPath + "/" + mBackendModel);
    		// 设置回调监听
    		mTTSPlayer.setTTSListener(new SpeechSynthesizerListener() {
    
    			@Override
    			public void onEvent(int type) {
    				switch (type) {
    					case SpeechConstants.TTS_EVENT_INIT:
    						// 初始化成功回调
    						log_i("onInitFinish");
    						mTTSPlayBtn.setEnabled(true);
    						break;
    					case SpeechConstants.TTS_EVENT_SYNTHESIZER_START:
    						// 开始合成回调
    						log_i("beginSynthesizer");
    						break;
    					case SpeechConstants.TTS_EVENT_SYNTHESIZER_END:
    						// 合成结束回调
    						log_i("endSynthesizer");
    						break;
    					case SpeechConstants.TTS_EVENT_BUFFER_BEGIN:
    						// 开始缓存回调
    						log_i("beginBuffer");
    						break;
    					case SpeechConstants.TTS_EVENT_BUFFER_READY:
    						// 缓存完毕回调
    						log_i("bufferReady");
    						break;
    					case SpeechConstants.TTS_EVENT_PLAYING_START:
    						// 开始播放回调
    						log_i("onPlayBegin");
    						break;
    					case SpeechConstants.TTS_EVENT_PLAYING_END:
    						// 播放完成回调
    						log_i("onPlayEnd");
    						setTTSButtonReady();
    						break;
    					case SpeechConstants.TTS_EVENT_PAUSE:
    						// 暂停回调
    						log_i("pause");
    						break;
    					case SpeechConstants.TTS_EVENT_RESUME:
    						// 恢复回调
    						log_i("resume");
    						break;
    					case SpeechConstants.TTS_EVENT_STOP:
    						// 停止回调
    						log_i("stop");
    						break;
    					case SpeechConstants.TTS_EVENT_RELEASE:
    						// 释放资源回调
    						log_i("release");
    						break;
    					default:
    						break;
    				}
    
    			}
    
    			@Override
    			public void onError(int type, String errorMSG) {
    				// 语音合成错误回调
    				log_i("onError");
    				toastMessage(errorMSG);
    				setTTSButtonReady();
    			}
    		});
    		// 初始化合成引擎
    		mTTSPlayer.init("");
    	}
    
    	private void TTSPlay() {
    		if (!TTS_PLAY_FLAGE) {
    			mTTSPlayer.playText(mTTSText.getText().toString());
    			setTTSButtonStop();
    		} else {
    			mTTSPlayer.stop();
    			setTTSButtonReady();
    		}
    
    	}
    
    	private void setTTSButtonStop() {
    		TTS_PLAY_FLAGE = true;
    		mTTSPlayBtn.setText(R.string.stop_tts);
    	}
    
    	private void setTTSButtonReady() {
    		mTTSPlayBtn.setText(R.string.start_tts);
    		TTS_PLAY_FLAGE = false;
    	}
    
    	protected void setTipText(String tip) {
    
    		mTextViewTip.setText(tip);
    	}
    
    	protected void setStatusText(String status) {
    
    		mTextViewStatus.setText(getString(R.string.lable_status) + "(" + status + ")");
    	}
    
    	@Override
    	public void onPause() {
    		super.onPause();
    		// 主动停止识别
    		if (mTTSPlayer != null) {
    			mTTSPlayer.stop();
    		}
    	}
    
    	private void log_i(String log) {
    		Log.i("demo", log);
    	}
    
    	@Override
    	protected void onDestroy() {
    		// 主动释放离线引擎
    		if (mTTSPlayer != null) {
    			mTTSPlayer.release(SpeechConstants.TTS_RELEASE_ENGINE, null);
    		}
    		super.onDestroy();
    	}
    
    	private void toastMessage(String message) {
    		Toast.makeText(this, message, Toast.LENGTH_SHORT).show();
    	}
    
    
    
    	/**
    	 * 将assets文件下的离线资源copy到sd卡,操作同百度的
    	 *
    	 * @param isCover 是否覆盖已存在的目标文件
    	 * @param source
    	 * @param dest
    	 */
    	private void copyFromAssetsToSdcard(Context context, boolean isCover, String source, String dest) {
    		File file = new File(dest);
    		if (isCover || (!isCover && !file.exists())) {
    			InputStream is = null;
    			FileOutputStream fos = null;
    			try {
    				is = context.getAssets().open(source);
    				String path = dest;
    				fos = new FileOutputStream(path);
    				byte[] buffer = new byte[1024];
    				int size = 0;
    				while ((size = is.read(buffer, 0, 1024)) != -1) {
    					fos.write(buffer, 0, size);
    				}
    				fos.flush();
    
    
    			} catch (Exception e) {
    				e.printStackTrace();
    			} finally {
    
    				if (is != null) {
    					try {
    						is.close();
    					} catch (Exception e) {
    						e.printStackTrace();
    					}
    
    				}
    				if (fos != null) {
    					try {
    						is.close();
    					} catch (Exception e) {
    						e.printStackTrace();
    					}
    				}
    
    
    			}
    		}
    
    
    	}
    
    	private void makeDir(String dirPath) {
    		File file = new File(dirPath);
    		if (!file.exists()) {
    			file.mkdirs();
    		}
    	}
    
    	private String mDirPath = null;
    	private void initialEnv(){
    		if(mDirPath == null) {
    			String sdcardPath = Environment.getExternalStorageDirectory().toString();
    			mDirPath = sdcardPath + "/unsound/tts/";
    		}
    
    		makeDir(mDirPath);
    		copyFromAssetsToSdcard(this,false,mFrontendModel,mDirPath +"/" + mFrontendModel);
    		copyFromAssetsToSdcard(this,false,mBackendModel,mDirPath + "/" + mBackendModel);
    	}
    
    }

    assets下的文件入下图所示:


    这样基本就正常使用了,还是主要gradle的配置

    总结:三种方案中,百度无离线,离线使用个人觉得讯飞优于云知音,但奈何价格贵呀;如果是定位互联网产品的话,百度的还是比较好的,离在线融合使用,主要是免费了,科大讯飞的在线也是不错的;语音合成播报离线,可能是由于模型训练问题,对于英文和特殊数字的处理有时候不准确,例如110,分场合使用,有时候读一百一十,有时候读一一零,还有离线包对英文的识别不准确,有时候会逐个字母的读,在线一般不会有问题的,由于大多是互联网产品,都会联网的,所以上述问题可以忽略的。

    关于上方SDK的使用,个人认为先去研究其demo,先保证下载下来能正常使用,大多数出现最多的问题可能是由于无法正确配置导致的,一般主要有以下两点:

    1.so库没放对位置

    2.gradle文件配置错误(包括lib/jinLibs的路径配置,gradle版本等等)

    3.AndroidManifest配置错误,包括权限等等

    这些问题只要细心点都是可以避免的,如果出现问题仔细阅读官网的文档,寻找解决方法,如果无法解决可以联系其技术帮忙解析

    以上使用如果不想去官网下载,可以去github下载以上项目,地址:https://github.com/2966325911/SpeechSynthesis.git

    展开全文
  • 中文语音合成代码

    万次阅读 2020-05-13 19:55:35
    https://github.com/NVIDIA/tacotron2
  • 百度语音合成精简版

    千次阅读 2018-05-03 17:07:08
    我参照文档合成的源码下载: https://download.csdn.net/download/qq_31939617/10388588 下载 文档: Android TTS SDK 集成进入helloworld 项目 (一) 简介: 本文针对遇见集成Android合成SDK有困难的用户,以...
  • 语音合成

    2019-07-24 20:36:22
    语音合成 一、 前端 NT,将阿拉伯数字变成大写,标点符号进行变换,是否读 多音字 短句 二、 模型—HMM OR LSTM 三、 vocoder生成wav end2end的语音合成 合并1&2,or合并1&2&3 但实际上训练一个多音字...
  • 第一次使用本地语音合成需要下载语记.相当于一个本地资源库,可暂停合成,继续合成,取消合成
  • ICASSP2020在5月份已经结束,拿到论文集后,慢慢花时间看一看同行的成果和进展,也算是汲取一点新鲜养分吧。 简短介绍的同时也会附上自己粗浅鄙陋的想法。谬误良多,不吝指教。 文章目录一. 综述二....
  • 这个模型合成速度比tacotron快3-4倍,合成质量也比较高。每步大概需要0.5秒。 没有使用wavenet声码器,使用tacotron的CBHG模型,使用griffin-lim算法将频谱图转换为原始波。 model结构 [外链图片转存失败,源站可能...
  • 讯飞离线语音合成(离线资源包)

    万次阅读 2015-08-30 15:18:05
    讯飞离线语音合成(离线资源包) 讯飞的语音合成有三种方式 在线语音合成(免费) 离线使用语记语音合成(免费,需要本地装一个语记App并且下载离线资源) 使用讯飞离线语音包(付费) 这里使用离线资源包...
  • 前端实现语音合成

    2020-06-28 18:59:57
    语音合成的实现方式有多种: 第一种:HTML5语音Web Speech API 第二种:百度文字转语音开放API 第三种:微软TTS引擎(没有实际使用,此文章就不多赘述) 实现方式(vue环境) 一、HTML5语音Web Speech API Web ...
  • 离线终于语音合成软件 语音合成,又称文语转换(Text to Speech)技术,能将任意文字信息实时转化为标准流畅的语音朗读出来,相当于给机器装上了人工嘴巴。它涉及声学、语言学、数字信号处理、计算机科学等多个学科...
  • PHP在线语音合成

    千次阅读 2018-04-14 11:22:23
    在线语音合成 PHP SDKhttp://yuyin.baidu.com/docs/tts/194PHP SDK文档简介Hi,您好,欢迎使用百度语音合成服务。本文档主要针对PHP开发者,描述百度语音合成接口服务的相关技术内容。如果您对文档内容有任何疑问,...
  • 语音识别与语音合成

    千次阅读 2018-08-06 14:45:33
    1.语音合成就是文字转语音,识别就是语音转文字。 2.在看uni-app框架demo的时候,发现里面有内置的语音识别模块,自然就想到了语音合成。以前做过一个功能,就是扫码后语音播报扫码结果,比如支付成功后的提醒音。...
  • 作为语音芯片的另一个分支,语音合成这个方案已经经过5年的市场考验,相对市场的认可度也比较高,在曾经的相对落后的方案面前,如ISD系列芯片,语音合成的出现无疑是填补了很多的市场空白。但是技术是一刻也不会停留...
  • 语音合成技术及国内外发展现状

    万次阅读 2016-08-09 19:12:38
    一、语音合成技术简介  语音识别和语音合成技术是实现人机语音通信,建立一个有听和讲能力的口语系统所必需的两项关键技术。使电脑具有类似于人一样的说话和听懂人说话的能力,是90年代信息产业的重要竞争市场。...
  • 本资源包含网页和JAVA代码,分别演示基于百度语音合成REST API对接的POST方式提交接口数据,及其返回格式。网页格式直接返回语音,JAVA程序将POST调用返回的二进制数据流以字节流的方式存储在本地.mp3文件中。鉴于...
  • android集成科大讯飞语音听写和语音合成 集成科大讯飞语音听写和语音合成,语音听写只是语音识别下面的一部分,别弄混淆了,由于科大讯飞暂未开放gradle引包方式,所以目前集成还是手动引包。我的流程是点击语音...
  • 奇易语音合成工具是一款免费的简单易于使用的文字语音合成软件,能够提供普通话、广东话、方言、英语、外国语等上几十个语种,包含业界领先的普通话与英语同音混读、广东话与英语同音混读。有时候我们下载的一些文档...
1 2 3 4 5 ... 20
收藏数 25,439
精华内容 10,175
关键字:

语音合成