第9章:加法合成与重合成
加法合成是最直观却也最强大的声音合成方法之一。基于傅里叶定理,任何周期信号都可以分解为一系列正弦波的叠加,这为我们提供了一个从频域角度理解和创造声音的框架。本章将深入探讨加法合成的数学原理,从基本的正弦模型到复杂的谱分析技术,最终实现对自然声音的精确重合成和创造性变形。
9.1 正弦模型与谐波/非谐波分解
9.1.1 傅里叶级数的音频视角
对于周期为T的信号x(t),其傅里叶级数展开为:
x(t) = a₀/2 + Σ[aₙcos(2πnf₀t) + bₙsin(2πnf₀t)]
其中f₀ = 1/T是基频。在音频合成中,我们通常使用振幅-相位形式:
x(t) = Σ Aₙ(t)sin(2πfₙ(t)t + φₙ(t))
这里引入了时变参数,使模型能够表示非平稳信号:
- Aₙ(t):第n个分音的时变振幅
- fₙ(t):第n个分音的瞬时频率
- φₙ(t):第n个分音的瞬时相位
9.1.2 谐波与非谐波成分
自然乐器声音通常包含两类频率成分:
谐波成分:频率为基频整数倍的分音
非谐波成分:频率不满足整数倍关系的分音
其中βₙ是非谐波偏移系数。钢琴、钟声等乐器具有显著的非谐波特性。
9.1.3 部分音跟踪算法
从频谱中提取各个部分音的轨迹是加法合成的关键步骤:
- 峰值检测:在每帧频谱中找到局部最大值
- 轨迹连接:基于频率和振幅的连续性连接相邻帧的峰值
- 生灭处理:处理部分音的出现和消失
轨迹连接的代价函数:
C = α·|f₁ - f₂|/f₁ + β·|A₁ - A₂|/A₁
9.1.4 噪声成分建模
许多声音包含随机噪声成分(如气流声、弓擦声)。完整的加法模型:
x(t) = Σ Aₙ(t)sin(θₙ(t)) + n(t)
其中n(t)是随机噪声成分,通常用滤波白噪声建模。
9.2 短时傅里叶变换(STFT)
9.2.1 STFT的数学定义
STFT通过在信号上滑动窗函数来获得局部频谱:
X(m,k) = Σ x(n)w(n-mH)e^(-j2πkn/N)
其中:
- w(n):窗函数(如汉宁窗、汉明窗)
- H:跳跃大小(hop size)
- N:FFT大小
- m:帧索引
- k:频率箱索引
9.2.2 窗函数的选择
不同窗函数在频率分辨率和旁瓣抑制之间权衡:
汉宁窗(Hanning):
w(n) = 0.5 - 0.5cos(2πn/(N-1))
布莱克曼窗(Blackman):
w(n) = 0.42 - 0.5cos(2πn/(N-1)) + 0.08cos(4πn/(N-1))
9.2.3 时频分辨率的权衡
海森堡不确定性原理在时频分析中的体现:
窗长N与采样率fs决定了分辨率:
- 频率分辨率:Δf = fs/N
- 时间分辨率:Δt = N/fs
典型参数选择:
- 语音分析:N=512-1024(fs=16kHz)
- 音乐分析:N=2048-4096(fs=44.1kHz)
9.2.4 重叠-相加重构
从STFT重构时域信号需要满足完美重构条件:
对于50%重叠的汉宁窗,此条件自动满足。重构公式:
x(n) = [Σ X̃(m,n-mH)w(n-mH)] / [Σ w²(n-mH)]
9.3 相位声码器原理
9.3.1 相位的重要性
虽然人耳对相位不如振幅敏感,但相位对于信号重构和变换至关重要:
相位累积模型:
φ(m+1,k) = φ(m,k) + 2πkH/N + Δφ(m,k)
其中Δφ(m,k)是相位偏差,反映了实际频率与频率箱中心的差异。
9.3.2 瞬时频率估计
从相位差估计瞬时频率:
f_inst(m,k) = k·fs/N + Δφ(m,k)·fs/(2πH)
相位展开(phase unwrapping)处理2π跳变:
选择M使得|Δφ_unwrapped| < π
9.3.3 音高移位算法
改变音高而不改变时长:
- 分析原始信号的STFT
- 频率映射:f_new = α·f_old(α是音高比例)
- 相位传播:保持相位连续性
- 重合成
相位传播公式:
φ_synth(m+1,k') = φ_synth(m,k') + α·Δφ_anal(m,k)
9.3.4 时间拉伸算法
改变时长而不改变音高:
- 改变分析帧的读取速度
- 保持合成帧率不变
- 相位调整以保持连续性
时间拉伸因子β的相位调整:
φ_synth(m,k) = φ_anal(βm,k) + φ_correction(m,k)
9.3.5 相位锁定技术
为避免相位失真造成的金属声,使用相位锁定:
- 识别谐波峰值
- 锁定相邻谐波的相位关系
- 从峰值向外传播相位
锁定条件:
φ(k+1) - φ(k) = φ_original(k+1) - φ_original(k)
9.4 谱包络与共振峰
9.4.1 谱包络的概念
谱包络描述了频谱的整体形状,决定了音色的主要特征。对于语音和许多乐器,谱包络可以分解为:
其中:
- E(f):谱包络(缓慢变化)
- S(f):精细结构(谐波线谱)
9.4.2 线性预测编码(LPC)
LPC通过全极点滤波器建模谱包络:
自相关法求解LPC系数:
- 计算自相关函数:r(k) = Σx(n)x(n+k)
- 解Yule-Walker方程:Ra = -r
- 其中R是Toeplitz矩阵
预测阶数p的选择:
- 语音:p = fs/1000 + 2
- 乐器:p = 20-40
9.4.3 倒谱分析
倒谱将乘性谱分解转换为加性分解:
谱包络提取步骤:
- 计算对数幅度谱
- 进行逆FFT得到倒谱
- 低通滤波(保留低倒谱系数)
- FFT返回频域
倒谱截断(liftering):
C_liftered(n) = C(n)·w_lifter(n)
其中w_lifter是倒谱窗(通常保留前30-50个系数)。
9.4.4 共振峰检测与跟踪
共振峰是谱包络的局部最大值,对应声道的共振频率:
LPC根求解法:
- 求解LPC多项式的根
- 选择靠近单位圆的复共轭对
- 转换为频率和带宽
共振峰频率和带宽:
F = fs·arg(z)/(2π)
B = -fs·ln|z|/π
峰值拾取法:
- 平滑频谱(如使用中值滤波)
- 检测局部最大值
- 测量3dB带宽
9.4.5 共振峰修改与合成
通过修改共振峰参数实现音色变换:
共振峰移位:
- α > 1:声音变细(女性化)
- α < 1:声音变粗(男性化)
共振峰带宽调整:
- β < 1:增强共振(更清晰)
- β > 1:减弱共振(更模糊)
9.5 音色变形技术
9.5.1 谱插值方法
在两个音色之间进行平滑过渡:
线性谱插值:
|X_morph(k)| = (1-α)|X₁(k)| + α|X₂(k)|
φ_morph(k) = (1-α)φ₁(k) + αφ₂(k)
对数域插值(更自然):
log|X_morph| = (1-α)log|X₁| + α·log|X₂|
9.5.2 交叉合成
使用一个声音的谱特征调制另一个声音:
谱乘法:
保留源1的相位,用源2的振幅包络。
声码器模式:
- 提取载波的谐波结构
- 提取调制信号的谱包络
- 将包络应用到谐波上
X_vocoded(k) = H_carrier(k)·E_modulator(k)
9.5.3 谱滤波技术
动态均衡:
X_filtered(k) = X(k)·F(k,t)
其中F(k,t)是时变滤波曲线。
谱压缩/扩展:
- γ < 1:压缩(减少动态范围)
- γ > 1:扩展(增加对比度)
9.5.4 实时控制映射
将演奏控制参数映射到变形参数:
2D变形空间:
其中wᵢ是基于控制坐标(x,y)的权重函数。
径向基函数插值:
wᵢ(x,y) = φ(||p-(xᵢ,yᵢ)||)
常用φ(r) = e^(-r²/σ²)(高斯核)。
9.5.5 高级变形技术
SMS(Spectral Modeling Synthesis)框架:
X = X_deterministic + X_stochastic
分别处理确定性(谐波)和随机(噪声)成分:
- 谐波变形:频率和振幅的独立控制
- 噪声变形:谱包络的形状控制
时间对齐:
使用动态时间规整(DTW)对齐不同长度的音色:
D(i,j) = d(x₁[i], x₂[j]) + min{D(i-1,j), D(i,j-1), D(i-1,j-1)}
本章小结
加法合成提供了从频域角度理解和操控声音的强大框架。关键概念包括:
- 正弦模型:任何声音都可分解为时变正弦分量的叠加,包括谐波和非谐波成分
- 基本公式:x(t) = Σ Aₙ(t)sin(2πfₙ(t)t + φₙ(t))
- 部分音跟踪是提取这些参数的关键
- STFT分析:通过窗函数在时频域之间建立桥梁
- 时频分辨率权衡:Δt·Δf ≥ 1/(4π)
- 重叠-相加法实现完美重构
- 相位声码器:利用相位信息实现高质量的音高和时间变换
- 瞬时频率:f_inst = f_bin + Δφ·fs/(2πH)
- 相位锁定避免金属声伪影
- 谱包络分析:捕获音色的宏观特征
- LPC和倒谱提供互补的包络提取方法
- 共振峰是决定音色特征的关键参数
- 音色变形:创造性地组合和变换声音
- 谱插值实现平滑过渡
- 交叉合成结合不同声音的特征
- SMS框架分离处理确定性和随机成分
这些技术的组合使得加法合成成为声音分析、变换和合成的完整解决方案,广泛应用于音乐制作、语音处理和声音设计领域。
练习题
练习9.1:谐波分析(基础题)
给定一个基频f₀=440Hz的复合音,其前5个谐波的振幅比为1:0.5:0.33:0.25:0.2,相位均为0。写出该信号的时域表达式,并计算t=0.001秒时的瞬时值。
提示:使用正弦叠加公式,注意频率的整数倍关系。
参考答案
时域表达式:
```
x(t) = sin(2π·440t) + 0.5sin(2π·880t) + 0.33sin(2π·1320t)
+ 0.25sin(2π·1760t) + 0.2sin(2π·2200t)
```
t=0.001秒时:
```
x(0.001) = sin(0.88π) + 0.5sin(1.76π) + 0.33sin(2.64π)
+ 0.25sin(3.52π) + 0.2sin(4.4π)
= 0.951 + 0.125 - 0.208 - 0.125 + 0.126
≈ 0.869
```
练习9.2:STFT参数选择(基础题)
对于采样率44.1kHz的音频信号,如果要分析一个频率范围在200Hz-2000Hz的乐器声音,应该如何选择STFT的窗长N和跳跃大小H?解释你的选择理由。
提示:考虑最低频率成分需要的时间分辨率和频率分辨率要求。
参考答案
窗长选择:
- 最低频率200Hz,周期T=5ms
- 至少需要2-3个周期,即10-15ms
- N = 0.015 × 44100 ≈ 661,取N=1024(2的幂次)
- 频率分辨率:Δf = 44100/1024 ≈ 43Hz
跳跃大小:
- 50%重叠:H = N/2 = 512
- 75%重叠:H = N/4 = 256(更平滑但计算量大)
推荐:N=1024, H=512,提供23ms时间分辨率和43Hz频率分辨率的平衡。
练习9.3:相位声码器音高移位(基础题)
使用相位声码器将一个440Hz的正弦波音高提升一个八度(变为880Hz),写出频率映射关系和相位传播公式。如果原始相位在第m帧为π/4,计算第m+1帧的合成相位。
提示:八度对应频率翻倍,α=2。
参考答案
频率映射:f_new = 2 × f_old = 2 × 440 = 880Hz
相位传播:
```
φ_synth(m+1,k') = φ_synth(m,k') + 2 × Δφ_anal(m,k)
```
假设跳跃大小H=256,采样率fs=44100:
```
Δφ_anal = 2π × 440 × 256/44100 ≈ 16.04 rad
φ_synth(m+1) = π/4 + 2 × 16.04 ≈ 32.86 rad
```
考虑2π折叠:φ_synth(m+1) ≈ 1.43 rad
练习9.4:LPC谱包络(挑战题)
给定4阶LPC系数a=[1, -1.5, 0.8, -0.3, 0.1],计算并绘制对应的频率响应草图。找出共振峰的大致位置。
提示:计算H(z) = 1/(1 + Σaᵢz⁻ⁱ)在单位圆上的值。
参考答案
传递函数:
```
H(z) = 1/(1 - 1.5z⁻¹ + 0.8z⁻² - 0.3z⁻³ + 0.1z⁻⁴)
```
求极点(分母的根):
特征方程:z⁴ - 1.5z³ + 0.8z² - 0.3z + 0.1 = 0
近似解:
- 一对复共轭极点靠近单位圆 → 第一共振峰
- 另一对极点较远 → 第二共振峰(较弱)
频率响应在极点角度处出现峰值,共振峰位置取决于极点的相位角。
练习9.5:音色变形插值(挑战题)
有两个音色A和B,在1000Hz处的幅度分别为0.8和0.2,相位分别为π/3和2π/3。使用线性插值和对数域插值分别计算α=0.5时的变形结果,比较两种方法的差异。
提示:注意对数域需要先取对数再插值。
参考答案
线性插值:
```
|X_morph| = 0.5 × 0.8 + 0.5 × 0.2 = 0.5
φ_morph = 0.5 × π/3 + 0.5 × 2π/3 = π/2
```
对数域插值:
```
log|X_morph| = 0.5 × log(0.8) + 0.5 × log(0.2)
= 0.5 × (-0.223) + 0.5 × (-1.609) = -0.916
|X_morph| = e^(-0.916) ≈ 0.4
```
差异:对数域插值结果(0.4)小于线性插值(0.5),更接近几何平均值,在感知上更自然。
练习9.6:交叉合成应用(挑战题)
设计一个声码器效果,将说话声的谱包络应用到锯齿波载波上。描述完整的处理流程,包括分析窗口选择、包络提取方法和合成步骤。
提示:考虑语音的特点和锯齿波的谐波结构。
参考答案
处理流程:
1. **分析阶段**:
- 语音:20-30ms窗口(汉宁窗),50%重叠
- 提取谱包络:LPC(p=20)或倒谱平滑
2. **载波准备**:
- 生成锯齿波(基频可跟踪语音音高)
- 计算锯齿波的谐波幅度
3. **合成**:
- 将语音谱包络采样到载波谐波频率
- 调制载波谐波幅度:A_out(k) = A_carrier(k) × E_voice(f_k)
- 保持载波相位结构
4. **后处理**:
- 添加噪声成分(模拟摩擦音)
- 动态范围压缩增强清晰度
练习9.7:相位一致性问题(挑战题)
在使用相位声码器进行2倍时间拉伸时,发现输出有”回声”效果。分析可能的原因,并提出解决方案。
提示:考虑垂直相位一致性和水平相位一致性。
参考答案
原因分析:
1. 相邻频率箱之间的相位关系被破坏
2. 谐波成分的相位不再保持整数倍关系
3. 瞬态被过度拉伸产生预回声
解决方案:
1. **相位锁定**:保持谐波间的相位关系
```
φ(kf₀) = k × φ(f₀)
```
2. **瞬态保护**:
- 检测瞬态位置
- 瞬态区域不拉伸,只移动位置
3. **相位重置**:
- 在静音或能量低点重置相位累积
- 避免相位误差累积
4. **使用PSOLA**:
- 基于音高周期的同步叠加
- 自然保持相位一致性
练习9.8:SMS分解实现(开放题)
设计一个简化的SMS(Spectral Modeling Synthesis)系统,能够将钢琴音分解为确定性(谐波)和随机(噪声)成分。描述你的算法流程,讨论可能遇到的挑战和解决思路。
提示:考虑钢琴音的特点:清晰的起音、缓慢衰减的谐波、琴槌噪声。
参考答案
算法流程:
1. **预处理**:
- STFT分析(N=4096, H=512 @44.1kHz)
- 起音检测标记瞬态位置
2. **谐波分析**:
- 基频检测(自相关或谐波乘积谱)
- 谐波峰值跟踪(频率容差±50音分)
- 振幅和频率轨迹平滑
3. **残差计算**:
- 减去谐波成分:R = X - H
- 谱白化处理残差
4. **噪声建模**:
- 时变谱包络(LPC或谱平滑)
- 起音瞬态单独建模
挑战与解决:
- **非谐性**:钢琴高频偏离整数倍→使用非谐性系数
- **快速衰减**:指数包络拟合
- **踏板共鸣**:检测并保留低频共振
- **瞬态保真**:起音前10-20ms特殊处理
实现建议:
- 使用查找表加速正弦合成
- 分频段处理(低频精确,高频统计)
- 实时应用需要帧缓冲和延迟补偿
常见陷阱与错误
1. 频谱泄漏问题
错误:直接对非周期信号进行FFT,导致频谱模糊。
正确做法:
- 始终使用窗函数(汉宁、汉明、布莱克曼)
- 选择合适的窗长匹配信号特性
- 考虑窗函数的频率响应特性
错误:X = FFT(x)
正确:X = FFT(x * window)
2. 相位展开错误
错误:忽略相位的2π跳变,导致频率估计错误。
正确做法:
# 错误的相位差计算
phase_diff = phase2 - phase1
# 正确的相位展开
phase_diff = np.angle(np.exp(1j*(phase2-phase1)))
3. 时频分辨率误解
错误:试图同时获得高时间和高频率分辨率。
理解要点:
- 长窗口 = 好的频率分辨率,差的时间分辨率
- 短窗口 = 好的时间分辨率,差的频率分辨率
- 多分辨率分析可以部分缓解这个问题
4. 重构时的能量不守恒
错误:STFT重构后信号能量变化。
解决方案:
- 确保窗函数满足COLA(Constant Overlap-Add)条件
- 正确归一化:除以窗函数平方和
- 50%重叠的汉宁窗自动满足COLA
5. 部分音跟踪断裂
错误:轨迹连接算法过于简单,导致跟踪错误。
改进方法:
- 使用预测模型(线性或二次)
- 考虑振幅连续性
- 设置合理的频率跳变阈值
- 使用隐马尔可夫模型(HMM)
6. 谐波/噪声分离不彻底
错误:简单的峰值检测无法区分宽带噪声中的弱谐波。
解决技巧:
- 使用谐波性度量(如谐波比)
- 多帧平均提高信噪比
- 基频引导的谐波提取
- 迭代细化分离结果
7. 音高移位的共振峰失真
错误:简单频率缩放导致共振峰移动,音色不自然。
正确方法:
# 错误:同时移动音高和共振峰
f_new = alpha * f_old
# 正确:分离音高和共振峰
1. 提取谱包络
2. 移位谐波频率
3. 保持原始谱包络
8. 实时处理的延迟问题
错误:没有考虑处理延迟,导致音视频不同步。
延迟来源:
- 分析窗长度:N/2采样点
- 重叠缓冲:H采样点
- 处理时间:依赖算法复杂度
补偿策略:
- 预先计算总延迟
- 使用循环缓冲区
- 考虑使用更小的窗口或帧
9. 数值精度问题
错误:对数运算时遇到零值或负值。
安全处理:
# 危险
log_spectrum = np.log(spectrum)
# 安全
epsilon = 1e-10
log_spectrum = np.log(spectrum + epsilon)
10. 插值伪影
错误:音色变形时的线性插值产生不自然的过渡。
改进:
- 使用对数域插值(幅度)
- 考虑感知权重
- 平滑插值参数轨迹
- 使用高阶插值(样条)
调试技巧
- 可视化检查:
- 绘制频谱图验证分析结果
- 检查相位展开的连续性
- 观察部分音轨迹
- 单元测试:
- 用已知信号(正弦波)测试
- 验证完美重构条件
- 检查能量守恒
- 增量开发:
- 参考实现:
- 对比成熟库(librosa, Essentia)
- 使用标准测试信号
- 记录并分析差异