常用音频DSP算法:FIR与IIR滤波器、FFT与IFFT、卷积与相关、重采样算法
这一章,我们聊聊音频DSP里最常用的几类算法。说实话,这些算法就像工具箱里的螺丝刀和扳手——你未必天天用,但真遇到活儿的时候,少了哪一把都别扭。
我个人习惯把音频DSP算法分成四类:滤波、变换、运算、重采样。下面我们逐个拆开看。
核心观点:这四类算法覆盖了90%以上的音频处理场景。理解它们的计算模式和瓶颈,是性能优化的起点。
4.1 FIR与IIR滤波器
滤波器是音频DSP的看家本领。不管是EQ、去噪、还是分频,背后都是滤波器在干活。
4.1.1 FIR滤波器
FIR(有限冲激响应)滤波器,说白了就是一组加权求和。它的公式很简单:
y[n] = b0 * x[n] + b1 * x[n-1] + ... + bN * x[n-N]
每个输出样本,是当前输入和过去N个输入的加权和。N就是滤波器的阶数。
FIR的优点:
- 绝对稳定——没有反馈,不会炸
- 可以做到严格的线性相位——这对音频很重要
- 实现简单,适合SIMD优化
FIR的缺点:
- 要达到陡峭的截止特性,阶数往往很高
- 延迟大——阶数越高,延迟越大
- 计算量大——每个样本要做N次乘加
我的经验:在嵌入式平台上,我一般把FIR阶数控制在128以内。超过这个数,延迟和计算量都开始变得棘手。如果非要高阶,我会考虑用FFT加速卷积。
4.1.2 IIR滤波器
IIR(无限冲激响应)滤波器引入了反馈。它的差分方程长这样:
y[n] = b0*x[n] + b1*x[n-1] + b2*x[n-2] - a1*y[n-1] - a2*y[n-2]
IIR可以用很低的阶数实现陡峭的截止特性。一个二阶IIR(双二阶滤波器)就能做很多事。
IIR的优点:
- 计算量小——二阶IIR只需要5次乘法和4次加法
- 延迟低——几乎没有群延迟
- 频率选择性好——阶数低,过渡带窄
IIR的缺点:
- 可能不稳定——反馈系数搞不好就炸了
- 非线性相位——对某些应用是硬伤
- 定点实现时容易有精度问题
避坑指南:我曾经在定点DSP上实现IIR滤波器,系数量化后直接自激振荡。后来我养成了一个习惯:每次改系数,先用双精度仿真跑一遍,再量化到定点,最后在目标板上用正弦扫频验证稳定性。
4.1.3 FIR vs IIR 对比
| 特性 | FIR | IIR |
|---|---|---|
| 稳定性 | 绝对稳定 | 可能不稳定 |
| 相位特性 | 线性相位 | 非线性相位 |
| 计算量 | 大(高阶) | 小(低阶) |
| 延迟 | 大 | 小 |
| 频率选择性 | 需高阶才能陡峭 | 低阶即可陡峭 |
| 定点实现 | 容易 | 容易出问题 |
4.2 FFT与IFFT
FFT(快速傅里叶变换)是音频DSP的瑞士军刀。它把时域信号变到频域,让我们能看到声音的“频谱”。
你想想看,如果没有FFT,我们怎么分析一段音频的频率成分?只能靠耳朵听,或者用滤波器组一个个扫。FFT一次搞定。
4.2.1 FFT的核心思想
FFT是DFT(离散傅里叶变换)的快速算法。DFT的公式是:
X[k] = Σ x[n] * e^(-j*2π*k*n/N), n=0..N-1
直接算DFT,复杂度是O(N²)。FFT利用旋转因子的对称性和周期性,把复杂度降到O(N log N)。
常用的FFT算法有:
- 基-2 FFT:最经典,要求N是2的幂
- 基-4 FFT:比基-2少一些乘法,但实现更复杂
- 分裂基FFT:混合基-2和基-4,效率更高
- 实序列FFT:利用实序列的对称性,可以省一半计算
我的习惯:在ARM Cortex-M上,我常用基-2 FFT,因为CMSIS-DSP库已经优化好了。在x86上,我会用FFTW或者Intel IPP。别自己手写FFT——除非你想练手,或者平台太特殊。
4.2.2 FFT在音频中的应用
FFT在音频里能干的事太多了:
- 频谱分析:显示均衡器、VU表、频谱图
- 快速卷积:用FFT加速长卷积(后面会讲)
- 频域滤波:在频域直接修改幅度和相位
- 音高检测:找频谱峰值对应的频率
- 音频编解码:MP3、AAC都用MDCT(基于FFT)
4.2.3 IFFT
IFFT(逆FFT)就是把频域变回时域。公式和FFT几乎一样,只是指数符号相反,最后除以N。
很多音频处理流程是:时域 → FFT → 频域处理 → IFFT → 时域。比如噪声抑制、混响、变调,都是这个套路。
注意:FFT和IFFT的缩放因子怎么放,不同库不一样。有的库在FFT里放1/N,有的在IFFT里放,有的各放1/√N。用之前一定要看清楚文档,否则信号幅度会不对。
4.3 卷积与相关
卷积和相关,听起来像数学概念,但在音频里非常实用。
4.3.1 卷积
卷积的公式:
y[n] = Σ x[k] * h[n-k], k=-∞..∞
说白了,卷积就是输入信号x和冲激响应h的“加权叠加”。在音频里,卷积可以用来:
- 模拟混响:用真实空间的冲激响应和干信号卷积
- 实现FIR滤波器:FIR滤波就是卷积
- 模拟音箱/话筒特性:用测得的冲激响应卷积
直接卷积的复杂度是O(N*M),N和M分别是信号长度和冲激响应长度。如果M很大(比如混响的IR有几十万点),直接算就太慢了。
快速卷积:用FFT加速。把信号分块,每块和IR做FFT → 频域相乘 → IFFT。复杂度降到O(N log N)。
我常用的方法:对于短IR(几百点以内),直接卷积更快。对于长IR(几千点以上),用重叠保留法(Overlap-Save)做快速卷积。中间那个区间,两种方法都可以,看平台。
4.3.2 相关
相关分两种:自相关和互相关。
- 自相关:信号和自身的延迟版本做相关。用于音高检测、周期估计。
- 互相关:两个不同信号做相关。用于时延估计、信号匹配、模式识别。
相关的计算和卷积很像,也可以用FFT加速。我记得有一次做麦克风阵列的声源定位,就是用互相关估计各通道之间的时延差,然后算角度。
4.4 重采样算法
重采样,就是把音频从一个采样率变到另一个。比如44.1kHz转48kHz,或者48kHz转16kHz。
重采样的核心是:先插值,再滤波,再抽取。
4.4.1 重采样的基本流程
- 插值(上采样):在样本之间插零,提高采样率
- 低通滤波:滤掉镜像频率
- 抽取(下采样):每隔M个点取一个,降低采样率
举个例子:48kHz转44.1kHz。先上采样到48*441=21168kHz(插零),然后低通滤波(截止频率22.05kHz),再下采样441倍,得到44.1kHz。
当然,实际不会这么暴力。一般用多相滤波器实现,一次搞定。
4.4.2 常用重采样算法
| 算法 | 质量 | 计算量 | 适用场景 |
|---|---|---|---|
| 最近邻插值 | 差 | 极低 | 实时预览、低质量需求 |
| 线性插值 | 一般 | 低 | 简单应用、嵌入式 |
| 三次样条 | 好 | 中等 | 通用音频处理 |
| Sinc插值 | 极好 | 高 | 高保真音频、专业软件 |
| 多相滤波器 | 好~极好 | 中等 | 固定比例重采样 |
避坑指南:我曾经在重采样时没注意抗混叠滤波,结果高频出现了严重的混叠失真。后来我学乖了:不管上采样还是下采样,低通滤波的截止频率一定要小于min(原采样率/2, 目标采样率/2)。
4.5 本章知识体系
下面这张图,把这四类算法的关系串起来了。你可以看到,它们不是孤立的——FFT可以用来加速卷积,卷积可以用来实现FIR滤波,重采样里也离不开滤波。
4.6 小结
这一章我们聊了四类核心算法:
- FIR/IIR滤波器:时域滤波的两种思路,各有优劣
- FFT/IFFT:时频变换的利器,很多高级处理的基础
- 卷积/相关:运算操作,混响、匹配、估计都靠它
- 重采样:采样率转换,插值和滤波的组合拳
这些算法不是孤立的。FFT加速卷积,卷积实现FIR,滤波用于重采样——它们互相交织,构成了音频DSP的骨架。