你有没有想过,手机里的导航语音、银行客服的自动播报,这些声音在 AI 大爆发之前是怎么“造”出来的?那时候没有会学习的神经网络,科学家们就像两个手艺不同的工匠,走出了两条完全不同的路。一条路像“拼图师傅”——事先录好成千上万块声音碎片,要说话时一块块拼起来;另一条路像“绘图师”——先研究人说话时喉咙、声带、口腔的运动规律,再用这些规律“画”出声音来。这两条路,就是拼接合成(Concatenative TTS)和参数合成(Parametric TTS),它们统治了语音合成领域几十年。今天,我们就用“拼图”和“画图”这对好搭档,把这个老故事讲明白——理解了它们,你就理解了为什么后来神经网络 TTS 能一统江湖。

岗位关联

学习传统 TTS 能帮你建立语音合成技术的完整时间线,在维护老系统、迁移历史代码、对比新旧方案时,你能准确说出“旧方案差在哪、新方案好在哪”,这是语音产品经理和 AI 工程师的基本功。

目录
  1. 可视化演示
  2. 声音的基本单位
  3. 拼接法工作流程
  4. 拼接法核心难题
  5. 拼接法优势与局限
  6. 参数法合成原理
  7. HMM建模机制
  8. 参数法优劣分析
  9. 被取代的深层原因
  10. AI 应用场景
  11. Python 演示
  12. 常见误区
  13. 面试题

可视化演示

动态演示语音合成老路的核心机制,通过总览/传输/转换/输出四种模式展示关键概念与交互流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

语音合成老路:传统TT 传统TTS技术分类概述 拼接合成原理与单元选择 核心机制可视化 语音合成老路整体架构与关键组件

声音的基本单位

想象你面前有一盒乐高积木,每一块积木都是一个小小的声音零件——这就是“音素”(phoneme)。汉语里,“你好”两个字可以拆成 n、i、h、a、o 五个音素;英语里,单词 "speech" 可以拆成 s、p、ee、ch 四个音素。音素是语音的最小单位,就像乐高积木是最小的拼接元件。而由音素组合成的音节、词语,就像用积木搭出的小车、房子,是更大的结构。

在传统语音合成中,音素是最基础的声音单元。拼接合成系统会事先准备一个巨大的“声音零件仓库”——专业上叫语料库(corpus),里面存放着各种音素在不同上下文中的录音片段。比如同一个音素 a,在“爸爸”里和“阿姨”里的发音略有不同,工程师会把这两种都录下来存进仓库。

这个仓库的覆盖度(coverage)决定了拼接法能拼出多好的声音。就好比你的乐高盒子里如果只有红色积木,就拼不出蓝色的城堡。语料库越丰富,覆盖的上下文情况越多,拼接出来的语音就越自然。覆盖度不足时,系统只能“退而求其次”地挑选发音相近的音素,结果就会像拼图缺了一块硬塞进另一块,听起来别扭。

覆盖度是拼接合成的地基,语料库的质量直接决定合成语音的上限。 这就是为什么早期拼接系统需要录制几个小时的语音数据——工程师得像搬家一样,把每个角落的声音都装进这个“积木盒”。

那么,有了这一盒子积木,拼图师傅是怎么工作的呢?这就引出了拼接法的工作流程。

拼接法工作流程

拼图师傅拿到一句要合成的话,他不会直接去找一整块拼图,而是先把这句话拆解成一块块小小的积木零件。这个过程在技术上的专业术语叫文本前端分析(text frontend),包括分词、注音、判断声调等步骤。就像你拿到一张乐高说明书,先要搞清楚每一步需要哪些零件。

拆解完成后,系统进入核心环节——单元选择(unit selection)。它会在语料库这个“大仓库”里,为每一个目标音素寻找最合适的候选录音片段。挑选的标准有两个:一是目标成本(target cost),即候选单元和目标上下文的匹配程度——就像挑积木时先看颜色和形状是否匹配;二是拼接成本(concatenation cost),即相邻两个候选单元在声学上是否连贯——就像两块积木拼接处的咬合是否严丝合缝。

选好所有单元后,系统将它们按顺序拼接起来,进行信号处理和韵律调整,最终输出完整的语音。这个过程如果一切顺利,效果就像俄罗斯方块里每一块都正好卡进空位——严丝合缝,流畅自然。

这就是拼接法的打分机制。但拼积木总会遇到一个问题——两块积木拼不紧怎么办?这正是拼接法一直头疼的核心难题。

总成本=∑i=1NTargetCost(ui,ti)+∑i=1N−1ConcatCost(ui,ui+1)\text{总成本} = \sum_{i=1}^{N} \text{TargetCost}(u_i, t_i) + \sum_{i=1}^{N-1} \text{ConcatCost}(u_i, u_{i+1})
目标函数就是“拼图师傅的决策规则”:既要每个零件选得合适(目标成本),又要相邻零件拼接顺畅(拼接成本),总成本最低的那组单元就是最优选择。
  1. 目标成本累加对每个目标音素 $t_i$,计算候选单元 $u_i$ 与它的匹配度,N 个音素的匹配成本相加。
    ∑i=1NTargetCost(ui,ti)\sum_{i=1}^{N} \text{TargetCost}(u_i, t_i)
  2. 拼接成本累加对每相邻的两个候选单元 $u_i$ 和 $u_{i+1}$,计算它们在声学上的连续性,共有 N-1 个拼接点。
    ∑i=1N−1ConcatCost(ui,ui+1)\sum_{i=1}^{N-1} \text{ConcatCost}(u_i, u_{i+1})
  3. 总成本最小化两部分成本加起来,用动态规划算法找到使总成本最低的单元组合。
    总成本=目标成本+拼接成本\text{总成本} = \text{目标成本} + \text{拼接成本}

拼接法核心难题

拼积木的时候,最让人沮丧的是什么?两块积木颜色形状都合适,但拼接口就是差那么一点,有缝隙、不对齐。拼接法的最大痛点就在这里——拼接点不连续。哪怕单元选择算法再聪明,从不同的录音片段里截取的声音,在拼接处总会留下“接缝”:音高跳变、能量突变、频谱断裂,就像拼图边缘有一道毛边,怎么修都不完美。

第二个难题是韵律不匹配。一段自然的话语有快有慢、有抑扬顿挫,这是韵律(prosody)——语调、重音、节奏的总称。拼接法在选单元时主要考虑音素本身的匹配度,却很难同时照顾好整句话的韵律走向。结果就是:每个单字都听清了,但整句话听起来像机器人念稿,该上扬的地方没上扬,该停顿的地方没停顿。想象一个人说话时每个字都咬得特别清楚,但完全没有语气起伏——这就是韵律不匹配的听觉感受。

第三个难题是数据稀疏。语料库再大,也不可能覆盖所有上下文组合。当库中没有符合需求的高质量单元时,系统只能选“差强人意”的替补,导致说话结结巴巴或音质明显下降。单元选择算法的复杂度也随之上升——在几万个候选单元中找最优组合,计算量相当可观。

面对这些难题,拼图师傅并非没有优点——真实积木的手感和质感是无法替代的。

Prosody(S)=∑j=1M[α⋅∂f0∂tj+β⋅∂E∂tj+γ⋅Durj]\text{Prosody}(S) = \sum_{j=1}^{M} \left[ \alpha \cdot \frac{\partial f_0}{\partial t_j} + \beta \cdot \frac{\partial E}{\partial t_j} + \gamma \cdot \text{Dur}_j \right]
韵律建模要考虑基频 $f_0$ 的变化率、能量 $E$ 的变化率和音长 $\text{Dur}_j$,因为拼接单元的韵律模式难以全局规划,合成语音总带着“念稿腔”。
  1. 基频变化率基频 $f_0$ 是声音的“音高”,$\frac{\partial f_0}{\partial t_j}$ 表示音高随时间的变化速度,决定语调的升降。
    α⋅∂f0∂tj\alpha \cdot \frac{\partial f_0}{\partial t_j}
  2. 能量变化率能量 $E$ 是声音的“响度”,$\frac{\partial E}{\partial t_j}$ 表示响度变化的速度,决定重音和强调位置。
    β⋅∂E∂tj\beta \cdot \frac{\partial E}{\partial t_j}
  3. 音长信息$\text{Dur}_j$ 表示每个音节的持续时长,决定语速和节奏感。
    γ⋅Durj\gamma \cdot \text{Dur}_j

拼接法优势与局限

拼图师傅最自豪的是什么?他手里每一块积木都是“原装正品”——直接从真人的录音里切下来的,所以拼接出来的声音音质非常高,最接近真人说话的自然感。在波形层面,每一段都是真实录音,不存在“画出来”的人工痕迹,这是拼接法最大的杀手锏。

拼接法另一个优势是搭建快速、无需训练。只要有一个好的语料库,基本不需要复杂的模型训练过程,系统就可以上线使用了。这好比一个经验丰富的拼图师傅,手里有了充足的积木盒,拿到任何新句子都能马上拼出来,不需要临时学习。

但它的局限也很明显:深度依赖语料库质量。语料库的音质、覆盖度、录音环境直接决定了合成效果的瓶颈。录得好就好,录得不好就只能将就。更要命的是,新增语种类别成本高昂——每增加一种语言或一个说话人,都需要重新录制大量语料,时间和金钱成本都非常可观。

从“零件质量”的角度看,拼接法像一位追求完美的工匠,每一块材料都必须亲力亲为地准备。这种“手工感”既是它的骄傲,也是它无法规模化的致命伤。所以,当市场需要快速、低成本地生成多种语言和音色的语音时,另一条路——参数法,开始崭露头角。

参数法合成原理

如果说拼图师傅是“攒零件”,那么参数法的“绘图师”走的是另一条路:不打碎声音,而是研究声音的“配方”。这就是参数合成(Parametric TTS)——它不直接使用录音片段,而是通过统计模型预测声音的声学特征参数,再根据这些参数重新“画”出声音。

绘图师的工作分三步。第一步是提炼配方:从录音数据中提取声学特征,比如基频(音高)、频谱包络(音色)、时长(节奏)等,这些参数就像做菜的配方——盐几克、糖几克、火候几分。第二步是训练模型:用大量录音和对应文本训练一个生成模型,让它学会“看到文字,预测配方”。第三步是按配方做菜:输入新文本,模型预测出对应的声学参数,再用声码器(vocoder)把参数重建为波形。

参数法的灵活性在于——因为模型学的是“配方”而非“食材”本身,它可以轻松调整声音的音色、语速、情感。想换个说话人?重新调整模型参数即可;想让声音年轻一点?修改配方中的某些特征就行。这种灵活性是拼接法难以企及的。那么,参数法里的“绘图师”靠什么核心技术来“画声音”呢?答案是 HMM。

O=arg⁡max⁡oP(o∣w,λ)\mathbf{O} = \arg\max_{\mathbf{o}} P(\mathbf{o} | \mathbf{w}, \lambda)
参数合成的核心公式:给定文本 $\mathbf{w}$ 和训练好的模型参数 $\lambda$,寻找最可能的声学特征序列 $\mathbf{o}$,即让概率 $P$ 最大的 $\mathbf{o}$。
  1. 符号定义$\mathbf{o}$ 是声学特征序列(配方),$\mathbf{w}$ 是输入的文本(菜名),$\lambda$ 是模型参数(厨师的手艺)。
    O=arg⁡max⁡o\mathbf{O} = \arg\max_{\mathbf{o}}
  2. 条件概率$P(\mathbf{o} | \mathbf{w}, \lambda)$ 表示在给定文本和模型参数时,生成某个声学特征序列的概率。
    P(o∣w,λ)P(\mathbf{o} | \mathbf{w}, \lambda)

HMM建模机制

要理解参数法,必须认识它的心脏——隐马尔可夫模型(Hidden Markov Model,HMM)。你可以把 HMM 想象成一个“声音状态自动机”:每一种发音状态(比如发“a“时的口型、发”i“时的舌位)是一个隐藏的”工作台状态”,系统在这些状态之间转移,每到一个状态就产生一个声音观测值。

HMM 的核心有两个部分。一是状态转移概率——从当前发音状态跳到下一个状态的概率。比如发完“a“之后,30% 的概率发”i“,70% 的概率发”n“,这就像一个人说话时口型切换的”惯性“。二是观测概率——在某个状态下产生某个声音特征的概率。每个状态发出的声音都是在一种概率分布下”画”出来的,由于不是固定值,所以 HMM 天然支持同一文本的多种自然发音变化。

HMM 的工作分两个阶段。训练阶段——给定大量录音和对应文本,用 Baum-Welch 算法(一种期望最大化方法)学习模型的参数 $\lambda$,让模型学到“文字→声音”的统计规律。合成阶段——给定新文本,用 Viterbi 算法找出最可能的状态序列,再据此生成声学参数。这套“训练-合成”的双阶段架构,是参数法 TTS 的经典范式。

HMM 让绘图师有了“画声音”的统计规则,但画出来的声音始终带着一层“机器味”。

λ=(A,B,π)\lambda = (\mathbf{A}, \mathbf{B}, \boldsymbol{\pi})
HMM 的三要素:$\mathbf{A}$ 是状态转移矩阵(口型切换规律),$\mathbf{B}$ 是观测概率矩阵(每个状态画出的声音分布),$\boldsymbol{\pi}$ 是初始状态分布(第一个音从哪开始)。
  1. 状态转移矩阵$A = [a_{ij}]$,$a_{ij}$ 表示从状态 $i$ 转移到状态 $j$ 的概率,控制发音状态的序列走向。
    A=[aij],aij=P(sj∣si)\mathbf{A} = [a_{ij}], \quad a_{ij} = P(s_j | s_i)
  2. 观测概率矩阵$B = [b_j(k)]$,$b_j(k)$ 表示在状态 $j$ 时产生观测符号 $k$ 的概率,决定每个状态发出的声音特征。
    B=[bj(k)],bj(k)=P(ok∣sj)\mathbf{B} = [b_j(k)], \quad b_j(k) = P(o_k | s_j)
  3. 初始状态分布$\boldsymbol{\pi} = [\pi_i]$,$\pi_i$ 表示第一个状态是 $s_i$ 的概率。
    π=[πi],πi=P(si at t=1)\boldsymbol{\pi} = [\pi_i], \quad \pi_i = P(s_i \text{ at } t=1)

参数法优劣分析

参数法这位“绘图师”的优点是模型小巧、灵活性高。相比拼接法动辄几 GB 的语料库,参数法的模型通常只有几十 MB——你可以把它装进手机、车载系统、智能音箱等资源受限的设备里。而且因为学的是统计规律,改变说话人只需要调整模型参数的一小部分,甚至可以通过插值创造出一个“全新的声音”,这就像调色师在调色盘上混合出新的颜色。

参数法的另一个优势是可控性强。工程师可以直接修改预测的韵律参数来改变语速、语调、情感色彩,这在拼接法中几乎是不可能的。想让它说得更快?把时长参数缩一缩就行。想让声音更兴奋?把基频范围拉大一点就行。这种“参数化”带来的灵活性,让参数法在很多产品场景中成为更务实的选择。

但绘图师也有自己的软肋——音质天花板。由于声学参数是对真实声音的压缩表示(就像 JPEG 图像压缩会损失细节),从参数重建出来的波形总有一定的信息损失,听起来不如拼接法那样“血肉丰满”。更麻烦的是 “机械感”——HMM 统计建模擅长平均规律,但语音恰恰富含大量“超出平均”的精细变化,模型把这些变化平滑掉了,导致声音听起来闷闷的、缺乏生气,像隔着毛玻璃听人说话。

尽管参数法有这些不足,但它的“模型化、参数化”思路,为语音合成打开了一扇新的大门。而这扇门,最终通向了一场革命。

Distance(x,x^)=1T∑t=1T(xt−x^t)2\text{Distance}(x, \hat{x}) = \frac{1}{T}\sum_{t=1}^{T} \left( x_t - \hat{x}_t \right)^2
参数合成重建出的波形 $\hat{x}$ 与真实波形 $x$ 之间存在均方误差,这个“信息损失”是参数法音质上限的根本原因。
  1. 误差定义$x_t$ 是真实波形在时刻 $t$ 的采样值,$\hat{x}_t$ 是重建波形的采样值,两者之差就是重建误差。
    (xt−x^t)2\left( x_t - \hat{x}_t \right)^2
  2. 平均误差对整个时长 $T$ 内的误差取平均,得到整体的距离度量,越小说明重建质量越高。
    1T∑t=1T\frac{1}{T}\sum_{t=1}^{T}

被取代的深层原因

从 1990 年代到 2016 年,拼接法和参数法各领风骚又互相补位——拼接法音质好但笨重,参数法灵活但机械。直到 WaveNet 的出现,这场持续二十多年的“双雄对决”被彻底终结。WaveNet 是 DeepMind 在 2016 年提出的神经声码器,它用深度神经网络直接逐样本地预测语音波形,音质远超传统的参数声码器。随后,Tacotron、FastSpeech 等端到端神经网络 TTS 相继问世,把文本直接映射到语音,彻底绕开了“人工设计特征+统计模型”的老路。

为什么神经网络能后来居上?核心在于数据规模。传统 TTS 的设计思路是“人类专家手工设计规则”,靠的是对语音学知识的深入理解——这就像绘图师自己研究光线、透视、色彩原理,一笔一笔地画。而神经网络 TTS 走的是“大数据+自动学习”的路——它不需要人类告诉它语音的规则,只需要喂给它海量的录音,它自己就能“悟”出声音的规律。当训练数据从几百小时跃升到几万小时时,机器学到的规律已经超过了人类专家的手工设计。

还有个关键因素是Attention 机制和端到端训练。传统 TTS 要拆成“文本分析→单元选择/参数预测→波形生成”多个独立模块,每个模块都要单独优化;而端到端模型把整条链路统一训练,全局优化所有环节,就像一位全能的画家,从构思到落笔一气呵成,而不是每个环节请一位工匠。

但这并不意味着老路全无价值。今天,很多银行的电话客服系统、老式导航设备仍在运行着传统的拼接或参数 TTS——它们稳定、快速、成本低。理解这些历史方案,不仅对于维护老系统很有价值,更是理解 TTS 技术演进脉络的必经之路。

老话说得好:“不识来路,焉知归途。”拼接法和参数法的故事告诉我们:每一代技术都是在解决上一代的问题中诞生的。理解了拼图师傅和绘图师各自的困境,你才能真正理解神经网络 TTS 为什么会成为今天的“声音大师”。

P(y1:T∣x)=∏t=1TP(yt∣y1:t−1,x)P(y_{1:T} | x) = \prod_{t=1}^{T} P(y_t | y_{1:t-1}, x)
这是 WaveNet 的核心公式——条件概率的连乘:预测当前时刻的采样值 $y_t$ 时,基于过去所有采样值和输入文本 $x$,神经网络用“滚雪球”式的方式生成整段波形。
  1. 条件概率链整段波形的概率等于每个时刻采样值条件概率的乘积,这是自回归生成(auto-regressive)的核心思想。
    ∏t=1TP(yt∣y1:t−1,x)\prod_{t=1}^{T} P(y_t | y_{1:t-1}, x)
  2. 历史依赖$y_{1:t-1}$ 表示预测当前时刻之前的所有历史采样值,体现“听了前面才知道后面”的序列生成逻辑。
    yt∣y1:t−1,xy_t | y_{1:t-1}, x

AI 应用场景

存量呼叫中心系统的语音播报

阶段:模型评估与系统升级

解决的问题:在 AI 客服系统普及前,大量银行、保险公司的呼叫中心使用的是基于拼接 TTS 的语音播报系统。这些系统的语音是事先录好的真人录音拼接而成,音质自然但“死板”——同样的句子永远一个语调,遇到包含数字、地址的动态信息时,拼接痕迹明显,客户体验不佳。维护团队需要在“保持低成本”和“提升流畅度”之间做取舍。

具体案例:某国有银行在 2018 年升级信用卡催收话术系统时,工程师将原有的拼接 TTS 替换为 HMM 参数合成方案。新的参数系统虽然音质略降,但支持动态调整语速和语调,催收话术从“念稿腔”变成了“有起伏的对话感”,客户拒接率下降了 12%。

嵌入式设备的离线语音合成

阶段:模型部署与资源优化

解决的问题:车载导航、智能手表、电梯广告屏等嵌入式设备存储空间有限、算力不足,无法运行深度神经网络 TTS 模型。参数合成 TTS 以其“模型小、速度快、可离线运行”的优势,在这些场景中仍有不可替代的价值。

具体案例:某车载导航厂商在低配版车机中部署了基于 HMM 的参数合成语音包,模型仅 15MB,在 200MHz 的处理器上即可实时合成语音。虽然音质不如旗舰车型的神经网络 TTS,但胜在稳定、省电、无需联网,满足了核心导航播报需求。

多语种语音产品的快速落地

阶段:数据准备与模型训练

解决的问题:面向东南亚市场推出语音助手时,如果采用拼接 TTS,每种语言都需要录制几十小时的母语者语音,成本极高且周期长。参数合成方案只需少量录音训练 HMM 模型,即可快速生成新语种的语音基础能力,让产品快速试水市场。

具体案例:某互联网公司在 6 周内为语音助手新增了印尼语和泰语支持。团队使用参数合成 TTS 快速生成基础语音,配合后续收集真实用户语音数据逐步优化。这种“快速上线-渐进优化”的节奏,正是传统方案的“灵活”基因。

Python 演示

python92 行
import numpy as np # 最小化的语音合成单元选择演示# 目标:从语料库中为音素序列挑选最优的录音单元# 算法:动态规划维特比算法求解最小成本路径 class UnitSelectionTTS:    def __init__(self, corpus_size=100):        # 语料库中每个音素单元的声学特征(模拟数据)        # 每列代表: [基频, 能量, 时长]        rng = np.random.default_rng(42)        self.units = rng.uniform(0, 1, (corpus_size, 3))        self.target_cost_cache = {}        self.concat_cost_cache = {}     def target_cost(self, unit_idx, target_feat):        # 目标成本: 候选单元与目标音素的声学特征差异        key = (unit_idx, tuple(target_feat))        if key not in self.target_cost_cache:            self.target_cost_cache[key] = np.linalg.norm(                self.units[unit_idx] - target_feat            )        return self.target_cost_cache[key]     def concat_cost(self, unit_a, unit_b):        # 拼接成本: 相邻单元在拼接点附近的不连续程度        key = (unit_a, unit_b)        if key not in self.concat_cost_cache:            self.concat_cost_cache[key] = np.linalg.norm(                self.units[unit_a] - self.units[unit_b]            )        return self.concat_cost_cache[key]     def select(self, target_feats, top_k=10):        # 动态规划: 寻找总成本最低的单元序列        T = len(target_feats)  # 目标音素数量        n = len(self.units)    # 语料库单元数量        total_cost = np.zeros(n) + 1e9        prev = np.zeros((T, n), dtype=int) - 1         for i in range(n):            total_cost[i] = self.target_cost(i, target_feats[0])         for t in range(1, T):            new_cost = np.zeros(n) + 1e9            for j in range(n):                candidates = np.argpartition(                    total_cost, top_k                )[:top_k]                best_cost = 1e9                best_prev = -1                for i in candidates:                    c = total_cost[i] + self.concat_cost(i, j)                    if c < best_cost:                        best_cost = c                        best_prev = i                new_cost[j] = best_cost + self.target_cost(                    j, target_feats[t]                )                prev[t, j] = best_prev            total_cost = new_cost         # 回溯最优路径        path = [0] * T        path[T-1] = int(np.argmin(total_cost))        for t in range(T-2, -1, -1):            path[t] = prev[t+1, path[t+1]]        return path     def synthesize(self, text):        # 模拟文本到声学特征的映射        rng = np.random.default_rng(hash(text) % 12345)        return rng.uniform(0, 1, (len(text), 3))  def main():    tts = UnitSelectionTTS(corpus_size=200)    text = "hello"    target_feats = tts.synthesize(text)    path = tts.select(target_feats, top_k=8)    print("目标音素数:", len(text))    print("选中的单元编号:", path)    total = 0.0    for t, unit in enumerate(path):        total += tts.target_cost(unit, target_feats[t])    for t in range(len(path) - 1):        total += tts.concat_cost(path[t], path[t+1])    print("总成本:", round(total, 4))  if __name__ == "__main__":    main()
目的:用动态规划实现拼接法 TTS 的核心单元选择算法,模拟从语料库中挑选最优声音碎片拼接成句的过程。
  1. self.units = rng.uniform(0, 1, (corpus_size, 3))模拟语料库:每行代表一个录音单元的声学特征(基频、能量、时长)
  2. np.linalg.norm(self.units[unit_idx] - target_feat)计算候选单元与目标特征的差异,差异越小匹配度越高
  3. np.argpartition(total_cost, top_k)[:top_k]只考虑当前成本最低的前 top_k 个候选单元,降低计算量
  4. path[t-1] = prev[t+1, path[t+1]]回溯阶段从最后一个状态回推最优路径
  5. rng.uniform(0, 1, (len(text), 3))模拟文本前端的输出:每个字符映射为一个三维声学特征向量

常见误区

误区拼接法不就是查表选录音吗?不用训练任何模型,直接拼起来就行,所以比参数法简单多了。

正解拼接法确实不需要像 HMM 那样进行参数估计,但单元选择算法本身就是一种“隐式模型”——目标成本和拼接成本的权重需要根据听感反复调优,语料库的筛选、切分、标注也需要大量离线处理。就像一位拼图师傅虽然不用“训练”,但他挑积木的眼光和手法,是多年经验积累起来的,这个经验过程就是工程师在做的事。

为何常见:人们容易把“不需要训练神经网络”等同于“不需要模型”,忽略了单元选择背后的成本函数设计和参数调优工作。

误区HMM 参数合成和拼接法本质一样,都是从库里找模板来匹配文本,只是匹配的粒度更细而已。

正解两者的根本区别在于:拼接法直接使用“真实录音片段”作为输出;而 HMM 参数合成是用统计模型“生成”声学参数,再通过声码器重建波形。前者是“拿来主义”,后者是“创造主义”。绘图师不是从图库里找模板贴上去,而是根据学到的统计规律重新画一张图。

为何常见:两者都需要“文本到声音”的映射,表面上看起来相似,但一个是在样本空间里搜索,一个是在参数空间里生成,本质完全不同。

误区HMM 参数合成的声音机械感强,是因为 HMM 模型本身太简单,换成更复杂的模型就能解决。

正解机械感的来源不仅是模型容量,更是“参数化+统计平均”这个架构本身的信息瓶颈。声学参数是对复杂波形的降维表示,这个降维过程必然损失细节;而统计模型倾向于学习“平均形态”,恰好抹平了语音中最有表现力的变化。这是统计参数合成的天花板,模型升级只能缓解,不能根除。

为何常见:人们容易把问题归因于“模型不够好”,而忽略了架构层面的信息瓶颈——就像认为画家画得不像是因为画笔不够贵,其实是对光影理解的问题。

面试题

Q1. 拼接合成 TTS 的核心思想是什么?

单选题 · easy

  • A.用统计模型生成声音参数
  • B.从语料库挑选录音单元拼接← 正确答案
  • C.用神经网络直接生成波形
  • D.对文本进行情感分析

答案:B。拼接法的核心是把事先录好的音素单元从语料库中选出来拼成句子,像拼积木一样。A 是参数法的做法,C 是神经网络 TTS 的做法,D 与合成方式无关。

Q2. 参数合成 TTS 中,HMM 的输入和输出分别是什么?

单选题 · easy

  • A.输入文本,输出波形文件
  • B.输入录音,输出文本
  • C.输入文本特征,输出声学参数← 正确答案
  • D.输入波形,输出音素序列

答案:C。HMM 在训练阶段学习“文本→声学参数”的映射,在合成阶段输入文本相关的上下文特征,输出基频、频谱包络等声学参数,再由声码器重建波形。

Q3. 拼接法比参数法音质更高的根本原因是什么?

单选题 · mid

  • A.拼接法使用了更复杂的神经网络
  • B.拼接法直接使用真实录音片段← 正确答案
  • C.拼接法不需要文本前端分析
  • D.拼接法的语料库一定更大

答案:B。拼接法的输出单元是真人录音的原声片段,在波形层面没有信息损失;参数法将声音压缩为参数再重建,必然丢失部分细节。这是两者音质差异的根本原因。

Q4. 关于拼接成本(concatenation cost),下列说法正确的是?

单选题 · mid

  • A.它衡量候选单元与目标文本的语义匹配度
  • B.它衡量相邻单元在拼接点的声学连续性← 正确答案
  • C.它是训练神经网络时的损失函数
  • D.它决定文本前端的切分方式

答案:B。拼接成本评估的是两个相邻候选单元在拼接处是否连续、有没有跳变,对应拼图中两块积木的咬合程度。目标成本才是衡量单元与目标匹配度的指标。

Q5. HMM 的三要素不包括以下哪项?

单选题 · mid

  • A.状态转移概率矩阵
  • B.观测概率矩阵
  • C.初始状态分布
  • D.反向传播梯度← 正确答案

答案:D。HMM 三要素是 $\mathbf{A}$(状态转移矩阵)、$\mathbf{B}$(观测概率矩阵)、$\boldsymbol{\pi}$(初始状态分布)。反向传播梯度是神经网络训练的概念,与 HMM 无关。

Q6. 参数合成 TTS 相对于拼接法的优势有哪些?

多选题 · mid

  • A.模型体积更小← 正确答案
  • B.合成音质更高
  • C.更容易改变说话人音色← 正确答案
  • D.不需要声码器

答案:AC。参数法的模型通常是几十 MB,远小于拼接法的 GB 级语料库;修改模型参数即可改变音色,灵活性高。但参数法的音质上限低于拼接法,且声码器是参数法重建波形的必需环节。

Q7. Viterbi 算法在拼接法单元选择中的作用是什么?

单选题 · hard

  • A.训练 HMM 模型的参数
  • B.计算语料库的覆盖率
  • C.寻找总成本最低的单元路径← 正确答案
  • D.对文本进行分词和注音

答案:C。Viterbi 算法是动态规划算法,用于在状态空间中找最优路径。在拼接法中,它被用来计算使“目标成本+拼接成本”总和最小的单元序列。

Q8. 拼接法在哪些场景中仍然具有实用价值?

多选题 · hard

  • A.需要极高音质的名人语音合成← 正确答案
  • B.低成本的存量系统维护← 正确答案
  • C.资源受限的离线设备
  • D.需要灵活变换情感风格的场景

答案:AB。需要高自然度、且可以接受高成本时,拼接法仍有价值;许多老系统也在继续运行。C 场景更适合参数法,D 场景参数法由于参数可直接修改而更有优势。

Q9. WaveNet 的突破性贡献主要体现在哪个层面?

单选题 · hard

  • A.首次将 HMM 用于语音合成
  • B.用神经网络逐样本预测波形← 正确答案
  • C.降低了语料库录制成本
  • D.解决了拼接点的声学不连续

答案:B。WaveNet 用自回归神经网络逐样本直接生成语音波形,绕开了“先预测参数再重建波形”的传统两步走,从根本上突破了参数法音质上限。

Q10. 拼接法出现“数据稀疏”问题时的典型表现是什么?

单选题 · extreme

  • A.模型训练时间过长
  • B.合成语音出现明显拼接痕迹← 正确答案
  • C.文本分析速度变慢
  • D.声码器重建效果变差

答案:B。数据稀疏意味着语料库中缺乏与目标上下文匹配的优质单元,系统只能选“次优”的替补单元,导致拼接点不连续、音质下降。这正是拼接法依赖覆盖度高的语料库的原因。