NSF-HiFiGAN-声码器学习笔记
从 HiFi-GAN 到 NSF-HiFi-GAN:声码器学习笔记 本文基于 RVC(Retrieval-based Voice Conversion)项目的实际代码,从零开始梳理 HiFi-GAN 声码器的原理,再过渡到 RVC 中真正使用的 NSF-HiFi-GAN 变体。 代码位置:infer/lib/infer_pack/models.py 和 infer/lib/infer_pack/modules.py 一、先搞清楚声码器在干什么 在语音合成或语音转换的流程里,声码器处在最后一环。它的上游会输出某种"中间表示"——可能是 mel 频谱图,也可能是某个隐空间的向量。声码器要做的事情就一件:把这个中间表示变回可以听的音频波形。 说得直白点:频谱图是一张"图",声码器要把这张图"念"出来。 传统做法(Griffin-Lim 之类的)靠数学迭代来恢复相位信息,结果通常比较糊。HiFi-GAN 走的是神经网络的路线——用一个生成器直接输出波形采样点,同时用判别器来监督生成质量。 二、HiFi-GAN 的基本结构 HiFi-GAN 的论文是 2020 年发的(Jungil Kong 等人),核心思路可以用一句话概括: 转置卷积做上采样,残差块做波形精炼,多尺度判别器做质量监督。 2.1 生成器的整体流程 在 RVC 的代码里,标准 HiFi-GAN 生成器对应的是 Generator 类(models.py:204)。它的结构其实很规整: HiFi-GAN 生成器结构(40kHz 配置为例) ┌─────────────────────────────────────────────────────────────┐ │ 输入:隐变量 z │ │ [batch, 192, T帧] │ └────────────────────┬────────────────────────────────────────┘ │ ▼ ┌────────────────────┐ │ 预处理卷积层 │ │ Conv1d(192→512) │ ← 把输入投射到高维空间 │ kernel_size=7 │ └────────┬───────────┘ │ ┌────────────┴────────────┐ │ 上采样 Stage 1 (×10) │ │ ConvTranspose1d(512→256)│ ← 时间轴拉长到 T×10 └────────┬─────────────────┘ │ ┌────────┴──────────────────────────────────┐ │ MRF (多感受野融合) │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐│ │ │ResBlock │ │ResBlock │ │ResBlock ││ │ │kernel=3 │ │kernel=7 │ │kernel=11 ││ │ └──────────┘ └──────────┘ └──────────┘│ │ 输出取平均 │ └────────┬──────────────────────────────────┘ │ ┌────────┴────────────┐ │ 上采样 Stage 2 (×10)│ │ ConvTranspose1d(256→128)│ ← 时间轴拉长到 T×100 └────────┬─────────────┘ │ ┌────────┴──────────────────────────────────┐ │ MRF 融合 │ │ ResBlock×3 (kernel=3/7/11) → 平均 │ └────────┬──────────────────────────────────┘ │ ┌────────┴────────────┐ │ 上采样 Stage 3 (×2) │ │ ConvTranspose1d(128→64)│ ← 时间轴拉长到 T×200 └────────┬─────────────┘ │ ┌────────┴──────────────────────────────────┐ │ MRF 融合 │ │ ResBlock×3 (kernel=3/7/11) → 平均 │ └────────┬──────────────────────────────────┘ │ ┌────────┴────────────┐ │ 上采样 Stage 4 (×2) │ │ ConvTranspose1d(64→32) │ ← 时间轴拉长到 T×400 └────────┬─────────────┘ │ ┌────────┴──────────────────────────────────┐ │ MRF 融合 │ │ ResBlock×3 (kernel=3/7/11) → 平均 │ └────────┬──────────────────────────────────┘ │ ┌────┴────────────┐ │ 后处理卷积层 │ │ Conv1d(32→1) │ ← 压缩到单声道 │ kernel_size=7 │ └────┬─────────────┘ │ ▼ ┌────────────┐ │ Tanh │ ← 限幅到 [-1, 1] └─────┬──────┘ │ ▼ ┌──────────────────┐ │ 输出波形 │ │ [batch, 1, T×400]│ └──────────────────┘ 上采样的总倍率 = 10 × 10 × 2 × 2 = 400。这个数字等于 hop_length(帧移),含义是:输入的每一帧对应输出的 400 个采样点。对于 40kHz 采样率来说,一帧就是 10ms。 ...