一文了解语音合成技术(TTS)

2023-09-18 14:33:10

TTS是Text To Speech的缩写,即“从文本到语音”。 它将计算机自己产生的、或外部输入的文字信息转变为可以听得懂的、流利的汉语口语(或者其他语言语音)输出的技术,隶属于语音合成(SpeechSynthesis)。

语音,在人类的发展过程中,起到了巨大的作用。语音是语言的外部形式,是最直接地记录人的思维活动的符号体系,也是人类赖以生存发展和从事各种社会活动最基本、最重要的交流方式之一。

而让机器开口说话,则是人类千百年来的梦想。语音合成(Text To Speech),是人类不断探索、实现这一梦想的科学实践,也是受到这一梦想不断推动、不断提升的技术领域。

图片

语音合成作为人机交互中必不可少的一个环节,随着计算机的运算和存储能力的迅猛发展,语音合成技术由早期的基于规则的参数合成,到基于小样本的拼接调整合成,并逐渐发展为现在比较流行的基于大语料库的拼接合成。

图片

与此同时,合成语音的自然度和音质都得到了明显的改善,在一定程度上达到了人们的应用需求,从而促进了其在实际系统中的应用。

语音合成发展历史

在第二次工业革命之前,语音的合成主要以机械式的音素合成为主。1779年,德裔丹麦科学家 Christian Gottlieb Kratzenstein 建造了人类的声道模型,使其可以产生五个长元音。

1791年, Wolfgang von Kempelen 添加了唇和舌的模型,使其能够发出辅音和元音。

贝尔实验室于20世纪30年代发明了声码器(Vocoder),将语音自动分解为音调和共振,此项技术由 Homer Dudley 改进为键盘式合成器并于 1939年纽约世界博览会展出。

图片

第一台基于计算机的语音合成系统起源于20世纪50年代。1961年,IBM 的 John Larry Kelly,以及 Louis Gerstman 使用 IBM 704 计算机合成语音,成为贝尔实验室最著名的成就之一。

1975年,第一代语音合成系统之一 —— MUSA(MUltichannel Speaking Automation)问世,其由一个独立的硬件和配套的软件组成。1978年发行的第二个版本也可以进行无伴奏演唱。90 年代的主流是采用 MIT 和贝尔实验室的系统,并结合自然语言处理模型。

基于深度学习的技术

当前的主流方法分为基于统计参数的语音合成、波形拼接语音合成、混合方法以及端到端神经网络语音合成。

基于参数的语音合成包含隐马尔可夫模型(Hidden Markov Model,HMM)以及深度学习网络(Deep Neural Network,DNN)。

图片

语音合成流水线包含 文本前端(Text Frontend) 、声学模型(Acoustic Model) 和 声码器(Vocoder) 三个主要模块:

通过文本前端模块将原始文本转换为字符/音素;通过声学模型将字符/音素转换为声学特征,如线性频谱图、mel 频谱图、LPC 特征等;通过声码器将声学特征转换为波形。

 

图片

语音合成基本流程图

文本前端

文本前端模块主要包含: 分段(Text Segmentation)、文本正则化(Text Normalization, TN)、分词(Word Segmentation, 主要是在中文中)、词性标注(Part-of-Speech, PoS)、韵律预测(Prosody)和字音转换(Grapheme-to-Phoneme,G2P)等。

声学模型

声学模型将字符/音素转换为声学特征,如线性频谱图、mel 频谱图、LPC 特征等。 声学特征以 “帧” 为单位,一般一帧是 10ms 左右,一个音素一般对应 5~20 帧左右。

声学模型需要解决的是 “不等长序列间的映射问题”,“不等长”是指,同一个人发不同音素的持续时间不同,同一个人在不同时刻说同一句话的语速可能不同,对应各个音素的持续时间不同,不同人说话的特色不同,对应各个音素的持续时间不同。

声码器

声码器将声学特征转换为波形,它需要解决的是 “信息缺失的补全问题”。 信息缺失是指,在音频波形转换为频谱图时,存在相位信息的缺失; 在频谱图转换为 mel 频谱图时,存在频域压缩导致的信息缺失。

假设音频的采样率是 16kHz, 即 1s 的音频有 16000 个采样点,一帧的音频有 10ms,则 1s 中包含 100 帧,每一帧有 160 个采样点。 声码器的作用就是将一个频谱帧变成音频波形的 160 个采样点,所以声码器中一般会包含上采样模块。

随着车联网和智能汽车的兴起,越来越多的语音功能被搭载在车机上,仙林智能也将持续深耕智能出行场景,以前沿AI科技赋能智能车联网,为汽车用户带来更便捷、更安全、更有温度的语音交互体验。

更多推荐

代理IP和Socks5代理:跨界电商与全球爬虫的关键技术

跨界电商在全球化市场中崭露头角,而代理IP和Socks5代理则成为实现全球市场洞察和数据采集的不可或缺的工具。本文将深入探讨这两种代理技术在跨界电商、爬虫技术和出海战略中的关键作用。引言:介绍跨界电商的崛起和全球市场的机遇与挑战。引出代理IP和Socks5代理作为技术解决方案的重要性。代理IP的应用:多地区数据采集:介

如何评估测试用例的优先级?

评估测试用例的优先级,有助于我们及早发现和解决可能对系统稳定性和功能完整性产生重大影响的问题,助于提高测试质量,提高用户满意度。如果没有做好测试用例的优先级评估,往往容易造成对系统关键功能和高风险场景测试的忽略,增加了项目风险,浪费了资源,甚至可能导致系统出现重大问题。因此做好测试用例的优先级评估非常重要,一般主要从以

Socket编程基础(1)

目录预备知识socket通信的本质认识TCP协议和UDP协议网络字节序socket编程流程socket编程时常见的函数服务端绑定整数IP和字符串IP客户端套接字的创建和绑定预备知识理解源IP和目的IP源IP指的是发送数据包的主机的IP地址,目的IP指的是接收数据包的主机的IP地址。在网络通信中,当一台主机需要向另一台主

基于springboot地方废物回收机构管理系统springboot11

大家好✌!我是CZ淡陌。一名专注以理论为基础实战为主的技术博主,将再这里为大家分享优质的实战项目,本人在Java毕业设计领域有多年的经验,陆续会更新更多优质的Java实战项目,希望你能有所收获,少走一些弯路,向着优秀程序员前行!🍅更多优质项目👇🏻👇🏻可点击下方获取🍅文章底部或评论区获取🍅Java项目精品实

新手学习:ArcGIS 提取SHP 路网数据、节点

新手学习:ArcGIS提取SHP路网数据、节点参考连接OSM路网提取道路节点ArcGIS:如何创建地理数据库、创建要素类数据集、导入要素类、表?1.导入开源路网SHP文件2.在交点处打断路网数据未打断路网数据有一些路径很长,并且和多个路径存在交点,所以需要打断相交线。打开要编辑的shp数据,工具栏中,编辑器-开始编辑,

PHP 如何创建一个 composer 包 并在 项目中使用自己的 composer sdk 包

第一步创建一个composerSDK项目创建一个composer.json文件或使用命令(如果不清楚怎么弄直接跳过即可,一般都会默认配置)composerinit这是生成的composer.json文件将自己要使用的包添加到require中,如果没有require则自己添加(composer文件中必须用双引号不能使用单

加密货币交易所偿付能力的零知识证明

如何检测下一个FTX和Mt.Gox加密货币交易所FTX的内爆导致数十亿客户资金流失,这是加密货币历史上交易所破产的最新例子。历史可以追溯到2014年,当时处理70%比特币交易的历史最悠久、规模最大的交易所Mt.Gox丢失了用户的850,000个比特币。如今,许多用户更喜欢将他们的加密货币资产存储在集中式交易所中,以便于

区块链交易平台开发流程

随着区块链技术的日益发展,越来越多的金融机构和创业公司开始探索开发区块链交易平台的潜力。以下是一篇关于区块链交易平台开发流程的指南。一、理解区块链技术在开发区块链交易平台之前,必须深入理解区块链技术的内在机制和原理。区块链是一种分布式数据库,通过去中心化和去信任的方式维护可靠的数据记录,使得任何达成一致的双方能够直接进

springboot和vue:三、web入门(spring-boot-starter- web+控制器+路由映射+参数传递)

spring-boot-starter-webSpringBoot将传统Web开发的mvc、json、tomcat等框架整合,提供了spring-boot-starter-web组件,简化了Web应用配置。创建SpringBoot项目勾选SpringWeb选项后,会自动将spring-boot-starter-web组

Android 回声消除

Android回声消除前言在语音聊天、语音通话、互动直播、语音转文字类应用或者游戏中,需要采集用户的麦克风音频数据,然后将音频数据发送给其它终端或者语音识别服务。如果直接使用采集的麦克风数据,就会存在回音问题。所谓回音就是在语音通话过程中,如果用户开着扬声器,那么自己讲话的声音和对方讲话的声音(即是扬声器的声音)就会混

c++基础:new函数

new函数new是用于动态分配内存的操作符。它用于在堆内存中创建一个新的对象或数据结构,并返回一个指向该内存的指针。这是C++中进行动态内存分配的主要方式之一,通常与delete操作符一起使用来释放先前分配的内存。以下是使用new操作符的一些示例:动态分配一个整数,并将其赋值给指针:int*pInt=newint;*p

热文推荐