Qwen3-TTS 那篇讲过,TTS 分两步:先把文字变成中间表示,再由声码器(vocoder)还原成能播放的波形。当时提到它的扩散解码器配了「一个改版 BigVGAN 声码器」,一笔带过;语音 tokenizer 那篇里,各家 codec 的解码端也总有它的影子。这个在语音生成系统里几乎无处不在、却总被当成黑箱的组件,值得专门讲透一次。
主角是 NVIDIA 的 BigVGAN(ICLR 2023)和它 2024 年的升级版 BigVGAN-v2——今天开源世界里最接近「万能声码器」的东西:一次训练,不分说话人、语言、录音环境,甚至歌声和乐器都能还原。这篇按论文和官方代码拆开讲:它到底改了 HiFi-GAN 的什么、为什么这么改、每一层长什么样,以及 v2 又升级了哪里。
一、最后一公里:声码器在补什么
主流 TTS 的声学模型(或语音 token 的解码器)输出的多半是 mel 频谱:每隔一小段时间(一帧)给出一组「各频段能量」的数字。它是声音的有损压缩——在 BigVGAN 的 24kHz 设定里,一帧 100 个数,对应 256 个波形采样点。
声码器要做的,就是把这条链路走完:
难点有两个:
- 信息不够。mel 只有幅度、没有相位(波峰波谷的对齐方式),而且频率轴被压缩过。100 个数还原 256 个采样点,缺的信息全靠模型「脑补」。
- 耳朵很挑。相位错一点、谐波脏一点,人耳立刻听出「电流声」「机器人味」。声码器是全链路的音质天花板:前面的模型再好,最后一步糊了就全糊了。
这一步的主流做法经历过三代:WaveNet 一类自回归模型逐点生成,音质好但慢到不能用;流模型(WaveGlow 等)可以并行但又大又难训;然后是 GAN 声码器——MelGAN 证明了对抗训练能出声,HiFi-GAN(NeurIPS 2020)把它做到了「又快又好」,成为之后几年的事实标准。BigVGAN 正是站在 HiFi-GAN 肩上。
二、「万能」为什么难
HiFi-GAN 在训练集同分布的数据上几乎无懈可击,但它有个隐疾:出了分布就露馅。用干净英语朗读训练的模型,遇到没见过的语言、带噪声的录音、情绪激烈的喊叫、更别说歌声和乐器,就会冒出音高抖动、呼吸音发糊、高频发闷这类毛病。
而「万能声码器」(universal vocoder)恰恰要求 zero-shot 泛化:训练一次,什么音频都能还原。这个能力越来越重要——语音 token 解码、语音增强、音频编辑,下游没人愿意为每个场景单独训一个声码器。
BigVGAN 的判断是:光靠堆数据不够,得给生成器装上符合声音物理的归纳偏置(inductive bias)。论文动的两刀,都砍在一个此前没人细究的地方——激活函数:
- 声音天生由周期振动组成,而 LeakyReLU 对「周期」一无所知 → 换成周期激活函数 Snake;
- 非线性天生会产生新的高频分量,数字信号里超标的高频会「折」回来变成杂音 → 给激活函数包一层抗混叠滤波。
两件事合起来,就是 BigVGAN 的核心模块 AMP(Anti-aliased Multi-Periodicity composition,抗混叠多周期组合)。下面两节一件一件说。
三、第一板斧:Snake——给网络装上「周期直觉」
先看毛病出在哪。神经网络常用的激活函数(ReLU、LeakyReLU、tanh……)全是单调或分段线性的形状,Snake 论文(NeurIPS 2020)证明了它们学不会外推周期函数:训练区间内拟合得再好,一出区间就退化成直线或常数。而波形恰恰「可以自然地表示为基本周期分量的组合」(傅里叶级数)——BigVGAN 论文原话。用不懂周期的零件去拼周期信号,分布内靠死记硬背还行,分布外立刻现形。
Snake 的解法极其简单——在恒等映射上叠一层正弦涟漪:
snake(x) = x + (1/α) · sin²(α·x)
几个关键设计(对应官方 activations.py):
- 保留 x 主干:不是纯 sin,而是 x 加上涟漪。这保住了类似残差的优化性质,梯度不会消失,网络想退化回「近似线性」也容易(α→0 时涟漪消失)。
- α 逐通道可学:α 控制涟漪频率,初始化为 1。每个卷积通道一个 α,相当于给每个通道配一把可调频的「音叉」,让不同通道自己学会负责不同的周期成分——这就是 AMP 名字里 Multi-Periodicity(多周期)的来源。
- SnakeBeta 变体:官方发布的所有 checkpoint 用的其实是加强版,把幅度从频率里拆出来单独学,并在对数刻度上参数化(学 log α、log β,用时取 exp,保证恒正、训练更稳):
snakeβ(x) = x + (1/β) · sin²(α·x) α 管涟漪频率,β 管涟漪幅度
(均为逐通道可学参数,log-scale 存储)
官方 README 明确说:checkpoint 采用 log-scale 参数化的 snakebeta 激活,「整体质量最好」。
一个容易被忽略的收益是外推:LeakyReLU 网络在训练分布外的行为是未定义的瞎猜,而周期激活让网络在没见过的音高、语言、音色上仍然倾向输出「周期的东西」——这正是万能声码器要的性格。
四、第二板斧:抗混叠——别让高频折回来变成杂音
Snake 好是好,但它引入了一个信号处理的经典麻烦:混叠(aliasing)。
30 秒补个背景。数字音频是对连续声波的采样,采样率 fs 只能忠实表示 fs/2(奈奎斯特频率)以下的分量;超过的分量不会消失,会被「折叠」回低频区,变成原信号里根本不存在的杂音。经典例子是老电影里车轮越转越快时突然看起来倒转——时间轴上的采样不够密,高速旋转被「折」成了慢速倒转。
Snake 为什么会踩这个坑?看它的展开:
sin²(α·x) = (1 − cos(2α·x)) / 2 ← 平方一下,频率翻倍
非线性变换天生会产生输入中不存在的更高次谐波(这正是它表达力的来源),而 BigVGAN 生成器里要连续过几十次 snake——新产生的谐波很容易越过奈奎斯特线,折回来污染可听频段。论文的说法是:snake「可以为连续时间信号产生任意高频细节,而这些细节无法被离散时间输出表示」。
解法借自图像界的 StyleGAN3(alias-free GAN):别在原采样率上做非线性——先升到 2 倍采样率,做完再滤波降回来。
对应官方 alias_free_activation/torch/ 的实现,每一次 snake 实际上是个三明治(代码里叫 Activation1d):
# 每个 snake 都夹在 2× 过采样里做
x = upsample_2x(x) # 零插值 + 低通:升到 2 倍采样率,频谱上腾出「余量区」
x = snake(x) # 非线性此刻才发生——新谐波落在余量区里,不折叠
x = downsample_2x(x) # 低通滤掉超出原奈奎斯特的部分,再抽取回原采样率
低通滤波器用的是 Kaiser 窗 sinc 滤波器,窗长 12 taps,截止频率设在原采样率的奈奎斯特处(cutoff = 0.5/ratio,过渡带半宽 0.6/ratio)——这是经典 DSP 里「加窗理想低通」的标准配方,滤波器系数是固定算出来的,不参与学习。
两个工程细节值得记下(都来自论文的失败实验):
- 只给激活函数加抗混叠,不给上采样层加。生成器主干的转置卷积升采样理论上也会产生混叠,但论文试过给它加同款滤波,结果训练不稳定,遂作罢。
- 这层「三明治」在推理时开销不小——上采样让激活函数的计算量翻倍,还多了两次卷积。这个伏笔到 v2 的 CUDA 融合算子才解决。
五、组装:AMP 模块与整机结构
两板斧备齐,现在把它们塞回 HiFi-GAN 的骨架。先看整机:
生成器的 forward 流程(简化自官方 bigvgan.py,结构忠实):
x = conv_pre(mel) # [B, 100, T] → [B, 1536, T],kernel 7
for i in range(6): # 上采样率 [4,4,2,2,2,2],总计 ×256
x = ups[i](x) # 转置卷积升采样,通道减半
x = ( amp_k3(x) + amp_k7(x) # 3 个 AMP 块并行(卷积核 3/7/11)
+ amp_k11(x) ) / 3 # 输出取平均——继承自 HiFi-GAN 的 MRF
x = aas_post(x) # 最后再过一次抗混叠 snake
wav = conv_post(x) # kernel 7 → 单通道波形,tanh 收尾
逐层拆解:
- conv_pre:一层 kernel 7 的一维卷积,把 100 维 mel 帧升到 1536 通道。
- 6 级转置卷积上采样:升采样率 [4,4,2,2,2,2],连乘正好 256——每帧 mel 展开成 256 个采样点;每级通道数减半(1536 → 768 → 384 → 192 → 96 → 48 → 24),越接近波形分辨率越高、通道越窄,像一支逐渐变细的画笔。转置卷积的 kernel 取升采样率的 2 倍([8,8,4,4,4,4])。
- 每级 3 个并行 AMP 块取平均:这是 HiFi-GAN 的 MRF(多感受野融合)结构原样保留——卷积核分别为 3、7、11 的三个残差块并行看不同尺度的上下文。BigVGAN 动的只是块的内部。
- AMP 块内部(
AMPBlock1):对膨胀率 d ∈ {1, 3, 5} 依次执行
for d in (1, 3, 5):
t = aas(x) # 抗混叠 snake(上一节的三明治)
t = conv(t, k, dilation=d) # 膨胀卷积扩大感受野
t = aas(t)
t = conv(t, k, dilation=1)
x = x + t # 残差
一个 AMP 块 6 层卷积、6 次抗混叠 snake;每级 3 个块、共 6 级,加上首尾——整机 100+ 次「三明治」激活。HiFi-GAN 里所有 LeakyReLU 就这样被逐个换成了带滤波的周期激活。
论文给了两个规格(数字来自论文与官方 config):
| BigVGAN-base | BigVGAN | |
|---|---|---|
| 参数量 | 14M | 112M |
| 上采样率 | [8,8,2,2] | [4,4,2,2,2,2] |
| 初始通道 | 512 | 1536 |
| 拓扑对照 | 同 HiFi-GAN V1 | 更深更宽 |
base 版本用来和 HiFi-GAN V1 同规模公平对比(验证 AMP 本身的收益);112M 版本则是论文标题里的 Big——「把 GAN 声码器训到前所未有的规模」(摘要原话,unprecedented in the literature)。
输入侧也有个容易错过的升级:以往声码器常用 80-band、fmax 8kHz 的带限 mel,BigVGAN 用 100-band、fmax 12kHz 的全带 mel(24kHz 采样的奈奎斯特),高频细节从输入端就没丢。
六、判别器与损失:挑毛病的另一半
GAN 声码器的质量一半靠生成器,一半靠判别器——它决定了「什么样的毛病会被挑出来」。BigVGAN 的配置是两组判别器并联,每组内部又是多个子判别器:
MPD(多周期判别器,继承自 HiFi-GAN):把一维波形按周期 p 折叠成 2D(T/p 行 × p 列),再过二维卷积。p 取素数 {2, 3, 5, 7, 11},五个子判别器各看一种折法——素数保证互相不重叠地覆盖各种周期结构。每个子判别器 5 层 kernel (5,1)、stride (3,1) 的二维卷积,通道 32→128→512→1024→1024,LeakyReLU(0.1),weight norm。
MRD(多分辨率判别器,来自 UnivNet,替换 HiFi-GAN 的 MSD):对波形做三种分辨率的 STFT([n_fft, hop, win] = [1024, 120, 600]、[2048, 240, 1200]、[512, 50, 240]),取幅度谱当图像,过 5 层 kernel (3,9) 的二维卷积(沿频率轴 stride 2 下采样)。三种分辨率对应「时间细/频率粗」到「时间粗/频率细」的不同取舍,互为补充。
为什么扔掉 HiFi-GAN 的 MSD(多尺度判别器,在 1×/2×/4× 平均池化后的波形上做一维卷积)?论文的消融结论:换成 MRD 全面提升音质、并减少音高和周期性伪影——直接在频域挑毛病,比在模糊化的波形上挑更准。
损失函数是 GAN 声码器的标准全家桶(沿用 HiFi-GAN,权重也不变):
L_G = L_adv(LSGAN 最小二乘) + 2 · L_fm(特征匹配) + 45 · L_mel(频谱 L1)
- 对抗损失:least-squares GAN 形式,真样本推向 1、假样本推向 0;
- 特征匹配损失(×2):生成样本与真样本在判别器每一层中间特征上的 L1 距离——让生成器「骗过判别器的每一层」,而不只是最终输出;
- mel 重建损失(×45):生成波形与真波形的 mel 频谱 L1 距离,权重最大,负责把生成结果钉在正确的内容上,对抗损失只负责把纹理磨真。
七、Big 的代价:把 GAN 训到 112M 踩过的坑
GAN 出了名的难训,放大到 112M(当时 GAN 声码器的最大规模)更是坑连坑。论文很实诚地把失败实验都写了出来,这部分对想复现的人最值钱:
- 学习率减半:HiFi-GAN 的 2×10⁻⁴ 在大模型上会早期崩溃(训练初期直接发散),BigVGAN 降到 1×10⁻⁴。
- 批大小加倍:16 → 32,换取稳定性(对 GAN 来说 32 仍然很小)。
- 梯度裁剪救场:抗混叠 snake 会放大 MPD 传回的梯度,导致生成器在训练后期突然发散。论文的对策是把全局梯度范数裁剪到 10³——阈值远高于正常梯度,平时不干预,只在爆炸瞬间兜底。
- spectral norm 是歧途:给判别器加谱归一化确实能止住发散,但代价是相位失配伪影(phase mismatch artifacts),音质不可接受,弃用。
- 上采样层不加抗混叠(上文提过):理论正确、实践不稳的典型。
训练配置(论文 + 官方 config):AdamW(β₁=0.8, β₂=0.99),初始学习率 1×10⁻⁴ 按步指数衰减(γ=0.9999996),batch 32,每条样本随机截 8192 个采样点(约 0.34 秒),8 张 V100 训 1M 步。数据只用 LibriTTS 全量(train-clean-100 + 360 + train-other-500,24kHz 英语朗读)——注意:训练数据并不「万能」,泛化能力全部来自结构归纳偏置,这正是论文想证明的点。
八、成绩单:泛化能力到底涨了多少
分布内(LibriTTS dev 集,数字来自论文):
| 指标 | HiFi-GAN V1 | BigVGAN-base (14M) | BigVGAN (112M) |
|---|---|---|---|
| M-STFT ↓ | 1.0017 | — | 0.7997 |
| PESQ ↑ | 2.947 | — | 4.027 |
| MOS ↑ | 4.08±0.09 | 4.10±0.09 | 4.11±0.09 |
| SMOS ↑ | 4.15±0.09 | 4.20±0.08 | 4.26±0.08 |
(真实录音 MOS 4.40、SMOS 4.44 是天花板。)客观指标大幅领先,主观听感稳步领先——分布内大家本来就都不差。
分布外才是主战场(全部 zero-shot,模型只见过干净英语朗读):
| 测试集 | HiFi-GAN V1 | BigVGAN | 说明 |
|---|---|---|---|
| 未见语言·干净录音 | 4.39±0.07 | 4.41±0.07 | 爪哇语、高棉语、尼泊尔语等(SMOS) |
| 未见语言·模拟噪声 | 4.13±0.08 | 4.26±0.07 | 加性噪声混入 |
| 未见语言·真实噪声 | 4.21±0.08 | 4.38±0.07 | 真实环境录音 |
| MUSDB18-HQ 音乐 | 4.08±0.05 | 4.26±0.04 | 人声/鼓/贝斯/其他/混音五类平均(SMOS) |
规律很清楚:越出分布,差距越大。干净语音上两者打平,一进噪声和音乐,BigVGAN 的优势就拉开了。
消融实验回答「功劳是谁的」(MUSDB18-HQ 上、以 base 规模做的对照,SMOS):
BigVGAN-base(完整) 4.20
− 抗混叠滤波 4.15 ← 滤波贡献
− 滤波 − snake 4.12 ← snake 贡献(≈ HiFi-GAN + MRD)
两刀各有各的功劳,且统计显著(p ≪ 0.01)。论文还做了一个狠对照:把 HiFi-GAN 也放大到同等参数量再比,58% 的听感评分仍偏向 BigVGAN——优势来自结构,不是白嫖参数量。
速度上(RTX 8000 实测,论文 Table 1):base 版 70.18× 实时,112M 版 44.72× 实时——比 HiFi-GAN 慢(三明治激活的代价),但离实时红线还很远。
九、BigVGAN-v2:数据、判别器、损失、算子全升级
2024 年 7 月,NVIDIA 发布 BigVGAN-v2。注意它没有新论文——升级细节以官方仓库 README、配置文件和代码为准(本节全部对照这三处)。生成器结构基本不动(细节改动:去掉末尾 tanh 改为直接 clamp 到 [−1,1],最后一层卷积去掉 bias),刀全部动在生成器之外:
① 判别器换血:MRD → 多尺度子带 CQT 判别器。 来自 Gu et al., ICASSP 2024(代码改自 Amphion)。STFT 的时频分辨率是均匀的——整个频轴一把尺子;而 CQT(Constant-Q 变换)按对数频率划分,低频窄带、高频宽带,天然贴合音高与谐波结构(音乐的「八度」就是频率翻倍)。
实现细节(discriminators.py):3 个子判别器,hop 分别 [512, 256, 256],各覆盖 9 个八度、每八度 bin 数 [24, 36, 48];输入先 2× 重采样再做 CQT,振幅和相位拼成双通道一起看(v1 的 MRD 只看幅度谱);先按八度分组各过一层卷积(子带处理),再拼起来过主干。MPD 原样保留——周期毛病和频域纹理毛病仍然分工负责。
② 损失升级:单尺度 mel L1 → 多尺度 mel 损失。 来自 DAC 的配方:7 种 STFT 窗长 [32, 64, …, 2048] 配 7 种 mel 带数 [5, 10, …, 320],log-mel 上做 L1 再求和。短窗看瞬态、长窗看音高,一张网多个尺度同时约束。权重 λ 从 45 降到 15。
③ 数据放开:LibriTTS → 大规模混合音频。 多语言语音+环境声+乐器。v1 靠纯英语朗读证明了结构泛化,v2 则把数据也补上——结构和数据双管齐下。checkpoint 一路做到 44kHz 采样、512× 上采样(122M 参数,上采样率 [8,4,2,2,2,2]),训练段长也从 8192 拉到 65536 个采样点(8×A100,5M 步)。梯度裁剪阈值随之降到 500(README 还提示:从头训遇到早期发散,可在前 2 万步先用 100)。
④ 推理算子:把三明治焊死。 第四节埋的伏笔——抗混叠激活推理慢——v2 用一个融合 CUDA kernel 解决:上采样、snake、下采样三步在一个 kernel 里完成,省掉中间张量的读写。官方数据 1.5–3× 加速:
| 环境(2048 帧 mel) | 无 kernel | 有 kernel |
|---|---|---|
| A100 | 79.2× 实时 | 222.1× 实时 |
| RTX 3080 | 38.7× 实时 | 82.1× 实时 |
质量收益(LibriTTS dev 客观指标,README 报告,24kHz 模型):
| 模型 | PESQ ↑ | M-STFT ↓ | 周期性误差 ↓ | V/UV F1 ↑ |
|---|---|---|---|---|
| BigVGAN 1M 步 | 4.027 | 0.7997 | 0.1018 | 0.9598 |
| BigVGAN 5M 步 | 4.256 | 0.7409 | 0.0809 | 0.9698 |
| BigVGAN-v2 5M 步 | 4.362 | 0.7026 | 0.0593 | 0.9793 |
官方还特别注明:v2 在非语音音频上的感知伪影明显减少——万能声码器的短板补齐了。
最终发布的 checkpoint 家族一共 9 个(HuggingFace nvidia/bigvgan*),覆盖 22/24/44kHz、80/100/128 band、256×/512× 上采样,按你的 mel 配置对号入座即可,from_pretrained 三行代码用起来。
十、结语:为什么它成了默认选项
回头看,BigVGAN 系列的路线其实非常克制:不改 HiFi-GAN 的骨架、不改训练框架,只是把「声音是周期的」和「数字信号有奈奎斯特上限」这两条物理常识,翻译成了网络结构里的归纳偏置——一个周期激活,一层抗混叠滤波。剩下的就是把规模和数据老老实实堆上去,并把踩过的坑(学习率、梯度裁剪、spectral norm)如实写进论文。
这套「snake + 抗混叠」的手艺后来被广泛借走:DAC 等神经音频 codec 的解码器直接采用了 snake 激活,语音 tokenizer 一文里那些 codec 的波形还原端、以及 Qwen3-TTS 那个「改版 BigVGAN」,都是这条血脉。下次再看到 TTS 系统结构图右下角那个不起眼的 vocoder 框,你知道里面是一百多层夹着滤波器的正弦涟漪,在把频谱一点点还原成空气的振动。
参考
- BigVGAN: A Universal Neural Vocoder with Large-Scale Training(arXiv:2206.04658,ICLR 2023,本文主要依据)
- NVIDIA/BigVGAN 官方仓库(v2 细节、配置文件与代码实现均引自此处;demo 页可试听)
- HiFi-GAN(arXiv:2010.05646,生成器骨架与 MPD 的来源)
- Neural networks fail to learn periodic functions and how to fix it(arXiv:2006.08195,Snake 激活出处)
- Alias-Free GAN / StyleGAN3(arXiv:2106.12423,抗混叠思想来源)
- UnivNet(arXiv:2106.07889,MRD 出处)
- Multi-Scale Sub-Band CQT Discriminator(arXiv:2311.14957,v2 判别器出处)
- DAC: High-Fidelity Audio Compression(arXiv:2306.06546,v2 多尺度 mel 损失出处)