歌声转换SVC主流方法原理剖析1 — DDSP-SVC

news/2025/10/29 22:20:48/文章来源:https://www.cnblogs.com/Stareven233/p/19175482

pre

本文SVC指的是歌声转换(Singing Voice Conversion (SVC)),例如常见且开源的 So-VITS-SVC, RVC, DDSP-SVC
关键词:歌声转换、声音克隆、音色

最早在23年刷到了惠惠的冬之花翻唱,惊为天人,一直对这块很感兴趣,奈何当时有其他研究,平时时间太少,直到最近才起了认真研究的念头。

观前提示:本文聚焦于算法流程和模型细节,虽然也会涉及预处理、训练推理等步骤,但并非使用手册。

code

https://github.com/yxlllc/DDSP-SVC/tree/6.3
latest commit: bf82125a85fe5fc9fbecd9433df0a74a812b8bdc

数据

预处理

首先准备好训练数据,支持多说话人同时训练。假设数据文件夹为data/,先新建两个子目录data/train以及data/val,分别存放训练和测试数据。
其中再各自新建子目录存放音频文件: data/train/audio/data/val/audio/

如果训练数据仅包含单角色,那么直接把数据划分好扔到上述两个子目录中即可。否则需要按不同角色划分次一级目录,例如: data/train/audio/1data/val/audio/2等等。

预处理阶段会遍历data/train/audio/,对其中每一个音频文件调用下面四个模型:
F0_Extractor: 提取音高(基频)信息
Volume_Extractor: 提取音量包络信息
Vocoder: 声码器。重建音频
Units_Encoder: 提取内容特征(语义信息)

基频(F0) 一个声音中频率最低、通常振幅(能量)最大的那个频率。决定了音高。有多种提取算法(parselmouth, dio, harvest, crepe, rmvpe, fcpe),常用rmvpe,对无声区域还会进行插值

泛音/谐波 在基频之上,还有一系列频率是基频整数倍的音,它们被称为泛音或谐波。泛音组合决定了音色。

音色小提琴和钢琴弹同一个C,基频是相同的(都是261.6 Hz),所以听到的音高是一样的。但它们各自的泛音组合和强度完全不同。小提琴的泛音可能更丰富、更突出某些高频泛音,所以听起来“明亮”、“有穿透力”;而钢琴的泛音组合则让它听起来“圆润”、“饱满”。

音量包络 用于保持原始音频的动态特性,通常以图形形式展示,横轴是时间,纵轴是音量大小。观察曲线的起伏,可以直观地看到声音的强弱变化。预处理的时候会对音量进行随机增强。

梅尔频谱(mel-spectrograms) 将音频信号从时域转换到了一个同时包含时间频率能量信息的二维表示中,并且特别强调了人耳敏感的频率区域。横轴是时间,一列代表音频在某个时间片段(比如几十毫秒)内的频率快照。纵轴是频率,梅尔刻度,低频区域有更高的分辨率,贴合人耳感知特性。纵轴上能看到声音的音高轮廓,图中每个点的颜色/亮度代表了在特定时间、特定频率上的能量大小。常利用短时傅里叶变换(STFT)算法抽取。预处理时根据config对每个音频会进行随机音高增强(use_pitch_aug),随机从\([-5, 5]\)取值,单位大概是半音,并将其保存至pitch_aug_dict.npy文件。

梅尔频谱生成过程有损:

  1. 相位信息丢失: 原始音频波形可以看作是无数个不同频率、不同相位的正弦波的叠加。相位描述了每个频率成分的起始时间点,它对声音的瞬态特性(如打击乐的清脆感、辅音的爆发感)至关重要。频谱只记录了每个频率成分的幅度(能量),而完全丢弃了相位信息。
  2. 高频压缩: 梅尔滤波器组将高频区域的频率信息进行了“压缩”和“平滑”,原始频谱的许多细节被合并。
  3. 窗口化处理: 计算频谱时,音频被切成短帧,这本身就引入了一些近似,丢失了帧与帧之间最精细的过渡信息。

声码器(Vocoder) 神经网络模型例如 WaveNet, HiFi-GAN ,常用nsf-hifigan。由于梅尔频谱有损,无法直接倒推得到原音频,因此需要声码器根据输入的梅尔频谱以及基频重建对应的音频。也有只依赖梅尔频谱的声码器,但由于基频信息在频谱中也是模糊的,带上能减轻声码器学习压力/数据需求,效果也更好,同时还能通过修改基频来改变音高。其中梅尔频谱决定音色,基频决定音高。

语义提取 Units_Encoder(ContentVec/HuBERT),常用contentvec,提取与说话者无关的语义内容。音色+音高+语义 => 音频 天呐,这简直就是风格迁移范式,需要精确的内容风格解耦。

每种抽取的特征都会单独被放在data/train/data/val/目录下的独立文件夹。虽然音量/梅尔频谱会进行增强,但对每个音频都只有一个固定的增强副本,也就是训练时最多额外增加一倍数据。但一般会对音频先切片成为多个小音频,所以也还好。

batch

dataloader准备预处理阶段保存的那些特征,每个batch中有以下数据:

  • mel(\(x_{spec}\)) 梅尔频谱
  • f0_frames 基频
  • volume_frames 音量
  • units 内容特征
  • spk_id 说话人id
  • aug_shift 随机音高增强,单位为半音,即预处理的keyshift
  • name 音频文件名(Path.stem)
  • name_ext 完整音频文件名(含后缀,Path.name)

需要注意的是 mel, f0_frames, volume_frames, units 这四个均是一个小时间段的切片,时间段起止每次读取时随机。

模型架构

模型类名为 Unit2Wav ,里面又有两个模块(模型) CombSubSuperFast, RectifiedFlow ,分别为 ddsp 以及 reflow 模型。

CombSubSuperFast

CombSubSuperFast 中有四个重要的控制参数: harmonic_magnitude, harmonic_phase, noise_magnitude, noise_phase,前两个与谐波(harmonic)成分相关,后两个则与噪声成分相关

接收 units_frames, f0_frames, volume_frames, spk_id, aug_shift 作为输入,首先根据基频信号f0_frames,使用 torch.sinc 函数生成抗混叠的激励?看不懂。大概是线性插值帧内频率,保持帧间相位连续,高效地生成一个周期性梳状波(combtooth)。

之后通过短时傅立叶变换(Short-Time Fourier Transform (torch.stft))将 combtooth 以及一个随机采样的噪声 noise 分别变换到频域,得到两个频域信号:combtooth_stft(谐波成分)和 noise_stft(非谐波/噪声成分)。

接着使用一个神经网络 Unit2Control ,输入 units_frames, combtooth_frames, noise_frames, volume_frames, spk_id, aug_shift,(combtooth_frames是combtooth的展开),输出控制信号ctrls

根据上述控制信号又能得到两个频域滤波器 src_filternoise_filter ,然后分两条路径在频域中线性叠加两种成分:

\[signal\_stft = combtooth\_stft * src\_filter.permute(0, 2, 1) + noise\_stft * noise\_filter.permute(0, 2, 1) \]

其中:

  • 谐波路径:梳状波 \(\times\) 谐波滤波器(控制音色、共振峰等)
  • 噪声路径:噪声 \(\times\) 噪声滤波器(控制摩擦音、气声、辅音等)

最后通过短时傅里叶逆变换(Inverse Short-Time Fourier Transform (torch.istft))将 signal_stft 还原为时域波形,也就是输出的音频\(g_{audio}\)

RectifiedFlow

第一次看它论文的时候就觉得很惊艳,没想到两年过去了,竟然能在SVC这边看到。RectifiedFlow论文的解读博文:[论文速览] RectifiedFlow@Flow Straight and Fast{colon}Learning to Generate and Transfer Data with Rectified Flow

传统扩散模型通过逐步加噪(前向过程)和去噪(反向过程)来建模数据分布。而 Rectified Flow 是一种更高效的替代方案,它基于 最优传输(Optimal Transport, OT) 和 直线路径(straight path) 的思想,构建一个从噪声分布(如标准高斯)到数据分布的 确定性常微分方程(Ordinary Differential Equation, ODE)路径。

Rectified Flow 用模型去学习两个分布数据点之间变化的速度 \(v\) ,通过 \(x_{t+1} = x_t + v_t,\; t=0,\ldots,1\) 将源数据转换为目标数据。模型通过最小化预测速度 \(v\) 与真实速度 \(x_1−x_0\) 之间的误差来训练,即代码中的 reflow_loss 函数。

损失

reflow_loss 接收输入 x_1, t, cond, loss_type ,分别表示 真值梅尔频谱、时间步、条件、损失类型 。先从标准高斯采样噪声作为 \(x_0\),再直线插值得到 \(x_t = x_0 + t (x_1 - x_0)\)。此时需要一个神经网络\(v_\theta\)velocity_fn),根据 \(x_t\)、时间步t和条件cond来预测速度 \(v_{pred}\)

代码中velocity_fn选用LYNXNet2(Linear Gated Depthwise Separable Convolution Network Version 2),这似乎是作者自创的网络结构?从名字上就能看出是一种利用线性层与深度可分离卷积的高效网络。关键词大概有 时间嵌入, 条件嵌入, 大核卷积(kernel=31), SwiGLU, 残差连接, LayerNorm 。总体感觉特化了效率,适合求解ODE时的高频调用。条件cond只靠一个线性层映射,然后加到输入的\(x_t\)上有些薄弱?而且卷积似乎会缺少特征的全局交互?

总之预测了\(v_{pred}\),接下来就是损失计算。有三种loss_type可选:l1, l2, l2_lognorml2_lognorm 通过引入 logit-normal 分布的密度作为损失权重,使得模型在训练时: 重点关注 \(t\)\(0.5\)左右的中间区域(信息丰富、信噪比高),忽略 \(t \rightarrow 0/1\) 的极端区域(目标速度噪声极大、难以学习)从而提升训练稳定性与收敛速度。l2_lognorm 属于一种重要性采样(importance sampling) 技巧,也是模型默认的设置。这相当于给损失加了一个权重\(\omega(t)\),便得到了损失函数:

\[\mathcal{L} = \mathbb{E}_{t}[\omega(t) \cdot \|v_\theta(x_t, t, cond) - (x_1 - x_0)\|^2] \]

其中,

\[w(t) = \frac{1}{\sqrt{2\pi}} \cdot \frac{1}{t(1-t)} \exp\left( -\frac{1}{2} \left[ \log\left( \frac{t}{1-t} \right) \right]^2 \right) \]

ps. \(\frac{1}{\sqrt{2\pi}} \approx 0.398942\)

根据RectifiedFlow原论文,通过多次reflow(用训练好的模型生成配对数据进行第二轮的模型训练,模型参数复制上一轮),可以拉直生成轨迹,加快生成速度。但DDSP这边似乎没有这步操作,因此推理仍然需要较多步数(默认50)。

采样

推理阶段的ODE求解器有两种:

  1. sample_euler 为Euler方法(一阶),采样公式为:

\[x_{t+1} = x_{t} + v_\theta(x_t, t, \text{cond}) * dt \]

  1. sample_rk4 为RK4(四阶龙格-库塔),采样公式为:

\[\begin{align} k_1 &= v_\theta\left(x_t, t, \text{cond}\right) \\ k_2 &= v_\theta\left(x_t + k_1 \cdot \frac{dt}{2}, \left(t + \frac{dt}{2}\right), \text{cond}\right) \\ k_3 &= v_\theta\left(x_t + k_2 \cdot \frac{dt}{2}, \left(t + \frac{dt}{2}\right), \text{cond}\right) \\ k_4 &= v_\theta\left(x_t + k_3 \cdot dt, (t + dt), \text{cond}\right) \\ x_{t+1} &= x_t + \frac{dt}{6} \left(k_1 + 2k_2 + 2k_3 + k_4\right) \\ \end{align} \]

很明显四阶龙格-库塔法需要4次采样的加权平均,精度更高,但计算量大。

其中\(dt\)可理解为每一小步的时间片,例如设定进行\(50\)步采样,那么应当调用上述两种sample函数之一共\(50\)次以得到最终结果,此时\(dt = \frac{1}{50}\)。而\(t = t_{start},dt,2dt,\ldots,1\)

注意DDSP引入了一个参数为t_start,顾名思义它决定t的初值。原本t从0开始,\(t_0 = 0\)。若设置了t_start\(t_0 = t_{start}\)。在保持采样步数仍为\(50\)的情况下,此时\(dt = \frac{1-t_{start}}{50}\)

由于推理时没有真值频谱,当\(t_{start}=0\)时(默认情况),RectifiedFlow的输入\(x_0 = \epsilon\),是从标准正态分布(torch.randn)中采样的噪声。若\(0 < t_{start} < 1\),将混合一部分CombSubSuperFast合成的频谱\(g_{spec}\)(用声码器从输出的音频\(g_{audio}\)提取): \(x_0 = t_{start} * g_{spec} + (1 - t_{start}) * \epsilon\)

不同的\(t_{start}\)相当于模拟训练时从不同的时间步开始降噪,不过仍然具有差别(\(g_{spec}\)总归不是\(x_{spec}\),依赖于DDSP部分的性能),存在一定的训练推理不一致,或许这也是为何默认\(t_{start}=0\)?但并不是说\(t_{start}=0\)\(g_{spec}\)就没有用处,实际上\(g_{spec}\)不管是训练还是推理时都作为输入的条件\(cond\)引导RectifiedFlow

总而言之,RectifiedFlow根据CombSubSuperFast的输出\(g_{audio}\),精炼了一个更优的生成频谱\(g^r_{spec}\)作为最终输出。

训练

总结一下上面的流程:

  1. CombSubSuperFast(ddsp)首先根据输入合成一段音频\(g_{audio}\)(ddsp_wav)
  2. 声码器从 \(g_{audio}\) 提取对应频谱\(g_{spec}\)(ddsp_mel)
  3. 计算ddsp_loss,即 \(g_{spec}\) 与真值频谱\(x_{spec}\)(gt_spec)的MSE
  4. 计算reflow_lossRectifiedFlow(reflow)根据 \(g_{spec}\)\(x_{spec}\) 预测速度 \(v_{pred}\) 并与真值速度x_1 - x_0计算MSE
  5. 上述两个损失通过 lambda_ddsp 加权反向传播,然后更新参数

推理

参考训练流程:

  1. 输入参考音频分段,对于每一段提取相应的特征:
    1. CombSubSuperFast(ddsp)合成\(g_{audio}\)(ddsp_wav)
    2. 声码器提取\(g_{spec}\)(ddsp_mel)
    3. RectifiedFlow(reflow)根据 \(g_{spec}\) 采样生成精炼的频谱\(g^r_{spec}\)(mel)
    4. 利用声码器将 \(g^r_{spec}\) 以及输入的基频信息(f0)合成精炼音频\(g^r_{audio}\)
  2. 拼合成完整输出

碎碎念

DDSP-SVC非常直观的感受就是音色泄漏,描述得不准确但差不多是:生成的音频除了音色外在咬字、唱法、发声等方面十分接近输入音频。如果原音频具有十分强烈的特征,会被保留,若目标音色差距过大会有很强的割裂感。但so-vits-svc似乎并没有这个问题?

不过除此之外DDSP-SVC无疑是非常成功的方法,生成音频干净清晰,训练推理速度都很快,资源开销小。而且代码清晰易于修改,同时原作者还在不停维护,从6.0一路更新到目前的6.3(虽然能感受出作者也有些没活了,没有大更新)。如果能解决音色泄漏的问题...

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/950295.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot整合邮件发送

一、邮件发送核心认知 1. 什么是邮件发送 邮件发送是应用程序中通过邮件服务器将信息传递给指定收件人的功能,支持纯文本、附件、图片、HTML 模板等多种形式。在 Spring Boot 中,借助 Spring 提供的邮件服务封装,可…

vyos syslog配置

设置syslog服务器和端口set system syslog host 10.1.1.2 port 514 设置记录全部内容 set system syslog console facility all 提交并保存 commit save稍后即可在日志服务器上看到日志。 如需记录到文件,使用下列命…

Unity3D URP中材质设置emission自发光但是没有辉光Bloom效果

如图,勾选了emission并且调高了强度,物体没有向外发光的辉光效果,原因是没有设置后处理,需要在Package Manager里下载post processing,然后新建Global Volume然后点开ProFile选中场景的profile即可,如果没有可以…

Ishibuchi教授与Lie Meng Pang博士受邀于本课题组开展学术交流与指导

2025年9月26日,本课题组成功举办了一场高水平的国际学术交流活动。此次活动邀请到了南方科技大学讲座教授、IEEE Fellow Hisao Ishibuchi 教授以及南方科技大学计算机科学与工程系的Lie Meng Pang 博士来院进行学术指…

【倒计时10天】第20届国际生物启发式计算:理论与应用会议(BIC-TA 2025)将于2025年11月7-9日在武汉召开!

【倒计时10天】各位老师好!第20届国际生物启发式计算:理论与应用会议(BIC-TA 2025)将于2025年11月7-9日在武汉召开!🔔 本次会议由华中科技大学主办,武汉科技大学、湖北省运筹学会协办。 会议已邀请四川大学Gar…

[TOOL] 二进制文件阅读与分析入门指南

[TOOL] 二进制文件阅读与分析入门指南$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");ChatGPT生成(2025年10月29日22:11:13)目录二进制文件阅读与分析入门…

[TOOL] hexdump: 二进制文件阅读指南

[TOOL] hexdump: 二进制文件阅读指南$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");DeepSeek生成(2025年10月29日22:03:39)目录Hexdump 二进制文件阅读指…

题解:CodeForces 715E Complete the Permutations

题意 对于两个排列 \(p,q\),定义它们的距离为将 \(p\) 变成 \(q\) 的最小操作次数,其中每次操作可以交换 \(p\) 中两个元素的位置。现在给定两个长度为 \(n\) 的排列 \(p,q\),其中一些位置被替换成了 \(0\)。对于每…

[TOOL] hexdump: 二进制文件分析指南

[TOOL] hexdump: 二进制文件分析指南$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");DeepSeek生成(2025年10月29日22:03:39)目录Hexdump 二进制文件分析指…

Day26-C:\Users\Lenovo\Desktop\note\code\JavaSE\Basic\src\com\Threadcase

等待唤醒机制 生产者和消费者package Basic.src.com.Threadcase.Threadwaitnotify;public class Desk {/** 控制生产者和消费者的执行* *///桌子上是否有面条 0;没有面条 1:有面条public static int foodFlag = 0;…

题解:CF715E Complete the Permutations

题意 对于两个排列 \(p,q\),定义它们的距离为将 \(p\) 变成 \(q\) 的最小操作次数,其中每次操作可以交换 \(p\) 中两个元素的位置。现在给定两个长度为 \(n\) 的排列 \(p,q\),其中一些位置被替换成了 \(0\)。对于每…

日总结 20

YARN(Yet Another Resource Negotiator)是 Hadoop 生态中的核心集群资源管理与任务调度框架,旨在解耦 Hadoop 1.x 中 MapReduce 的计算与资源管理功能,通过 ResourceManager(全局资源管理)、NodeManager(节点资…

重组蛋白与传统蛋白的区别:从来源到特性的全面解析

在生命科学研究中,蛋白质作为重要的实验试剂,其获取方式和特性直接影响研究结果。传统蛋白与重组蛋白在多个维度存在显著差异,本文将系统解析二者的区别。 一、定义与来源的本质差异 传统蛋白通常指从生物体组织、器…

交个朋友电商学苑直播运营集训班4.0第三天笔记

交个朋友电商学苑直播运营集训班4.0第三天笔记第一个直播现状诊断错误的方向,1 开播不说话 抖音必须要规避的坑,1.闲聊式的直播 2 状态要激情,要讲卖点,为啥要买 3 纯硬搬 4 广告式账号 应该怎么做 引流短视频…

网球馆自动预约框架的反调试

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

吃薯片2025有机 - Gon

随机说话竟然已经是最后一年了吗我大抵是不爱说话的 DAY -2 神秘普转提(讲真的,感觉那四位应该是看了标题觉得是信心赛所以就搬过来了 T2写了甲烷了的暴力然后就艹过去了 一整个下午加晚上没写啥东西,但还是感觉好累…

[TOOL] 个人必备工具

[TOOL] 个人必备工具$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");更新时间:2025年10月29日21:47:59 个人bash配置: [SHELL] 个人BASH配置与美化目录01 …

JTCatch 缓存部署与使用

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

CSP-S 2025 游记

序 即使把我关在果壳之中,我仍自以为是无限空间之王 ——《哈姆雷特》Day -2 上午模拟赛,炸炸炸 const int mod=998224353 我是唐必啊啊啊啊啊啊啊啊啊 下午放了《蜂鸟》,旋律很美,在我大脑里旋转了一个下午,但歌…

arm.dll armaccess.dll arkut.dll arkdd32.dll arizonadll.dll aritmoperacedll.dll ariesengine.dll - 实践

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …