4、频域自适应滤波:频域块LMS(FBLMS)、多带结构自适应滤波、子带自适应滤波

各位同学,咱们今天聊点硬核的——频域自适应滤波。

时域自适应滤波,比如NLMS,大家应该都熟悉。但有个问题,当滤波器阶数很高时,时域的计算量会爆炸。我早年做声反馈消除时,采样率48kHz,滤波器长度动辄2048阶,时域NLMS跑起来,DSP芯片直接冒烟(夸张说法,但确实烫手)。

怎么办?转频域。

4.1 为什么要把滤波搬到频域?

说白了,时域卷积在频域就是点乘。这个性质太香了。

时域做一次N点卷积,计算量是O(N²)。而频域用FFT,计算量是O(N log N)。当N=1024时,频域比时域快几十倍。我在项目中实测过,同样的硬件平台,FBLMS比NLMS快了将近一个数量级。

另外,频域还有个好处——可以方便地控制每个频点的步长。比如,某个频段反馈啸叫严重,我可以单独加大那个频点的收敛速度。这在时域里很难做到。

核心思想: 利用FFT将时域卷积转换为频域点乘,用块处理方式降低计算量,同时获得更好的频域控制能力。

4.2 频域块LMS(FBLMS)

FBLMS,全称Frequency-domain Block LMS。它是LMS的频域版本,但不是逐点更新,而是按块更新。

4.2.1 基本原理

我习惯用“重叠保留法”来实现FBLMS。步骤如下:

  1. 收集L个新输入样本,和之前的L个样本拼接成2L点数据块
  2. 做2L点FFT,得到频域信号
  3. 频域滤波器系数与频域信号点乘,得到频域输出
  4. IFFT回到时域,取后L个有效点作为输出
  5. 计算误差信号,补零后做FFT到频域
  6. 频域梯度更新:W(k+1) = W(k) + μ * X*(k) * E(k)

嗯,这里要注意,梯度更新时,需要把结果IFFT回时域,强制时域滤波器长度约束(只保留前L个系数,后面置零),再FFT回频域。这个约束很重要,否则滤波器会发散。

避坑指南: 我曾经在项目里忘了做时域约束,结果滤波器系数在频域自由生长,最后直接溢出。调试了两天才发现这个低级错误。记住:频域更新,时域约束,缺一不可。

4.2.2 代码示例

下面是一个简化的FBLMS实现框架,用Python风格伪代码表示:

def fblms(x, d, L, mu):
    # x: 输入信号, d: 期望信号, L: 块大小
    N = 2 * L
    W = np.zeros(N, dtype=complex)  # 频域滤波器系数
    x_buffer = np.zeros(N)
    
    for k in range(0, len(x)-N, L):
        # 取当前块
        x_block = x[k:k+N]
        # FFT
        X = fft(x_block)
        # 频域滤波
        Y = W * X
        y = ifft(Y)[L:]  # 取后L个点
        # 误差
        e = d[k+L:k+2*L] - y
        # 频域误差
        E = fft(np.concatenate([np.zeros(L), e]))
        # 梯度更新
        grad = ifft(np.conj(X) * E)
        grad[L:] = 0  # 时域约束
        W += mu * fft(grad)
    return y

4.2.3 FBLMS的优缺点

优点 缺点
计算量低,适合高阶滤波器 存在块处理延迟(至少L个样本)
频域步长可独立控制 对非平稳信号收敛稍慢
收敛速度比时域LMS快 实现复杂度高于NLMS

4.3 多带结构自适应滤波

多带结构,说白了就是把全频带拆成几个子带,每个子带独立做自适应滤波。

你想想看,声反馈的频谱特性往往不均匀。低频段可能反馈严重,高频段可能很干净。如果全频带用一个滤波器,低频的强反馈会拖慢高频的收敛。多带结构就能解决这个问题。

4.3.1 多带分解与合成

典型的多带结构使用分析滤波器组将信号分解为M个子带,每个子带降采样后做自适应滤波,最后用综合滤波器组合成。

我建议使用余弦调制滤波器组(如MDCT),它的重构特性好,而且计算效率高。当然,也可以用简单的多相结构。

经验之谈: 子带数量M的选择很关键。M太小,多带优势不明显;M太大,子带间混叠严重。我个人习惯在声反馈消除中用8-16个子带,效果比较均衡。

4.3.2 多带结构的优势

  • 收敛加速: 每个子带的自适应滤波器阶数降低,收敛速度提升
  • 步长独立: 反馈严重的子带用大步长,干净的子带用小步长
  • 计算量降低: 子带降采样后,总计算量比全频带低

4.4 子带自适应滤波

子带自适应滤波和多带结构很像,但侧重点不同。多带结构强调的是“分而治之”,而子带自适应滤波更关注“如何利用子带特性优化算法”。

4.4.1 子带分解的两种方式

  1. 均匀子带: 等间隔划分频带,实现简单,但低频分辨率可能不够
  2. 非均匀子带: 低频子带窄、高频子带宽,更符合人耳听觉特性

我在做助听器声反馈消除时,用过非均匀子带。低频段(0-1kHz)分4个子带,中频段(1-4kHz)分4个,高频段(4-8kHz)分2个。效果比均匀子带好不少,因为反馈啸叫大多发生在低频。

4.4.2 子带自适应滤波的流程

画个流程图大家就明白了:

子带自适应滤波流程图 输入信号 x(n) 分析滤波器组 子带自适应滤波(每个子带独立处理) 子带1: FBLMS | 子带2: FBLMS | ... | 子带M: FBLMS 综合滤波器组 输出 y(n)

4.4.3 子带自适应滤波的关键点

  • 子带间混叠: 分析滤波器组如果设计不好,子带间会有混叠,影响自适应滤波效果。我建议用原型滤波器设计法,阻带衰减至少60dB。
  • 降采样率: 通常降采样率等于子带数,但要注意满足奈奎斯特定理。
  • 延迟问题: 滤波器组会引入延迟,对实时性要求高的场景需要优化。
总结一下: 频域自适应滤波的核心思想就是“分而治之+频域加速”。FBLMS适合高阶滤波器场景,多带结构适合频谱不均匀的场景,子带自适应滤波则兼顾了计算效率和收敛性能。实际项目中,我经常把FBLMS和子带结构结合起来用——每个子带内部用FBLMS,效果非常棒。
小技巧: 如果你在调试FBLMS时发现收敛不稳定,试着把步长μ设小一点,或者加一个归一化因子。我曾经遇到过步长设大了,滤波器直接发散,输出全是噪声。后来加了归一化,问题就解决了。

好了,这一章的内容就到这里。频域自适应滤波是声反馈消除的核心技术之一,掌握了它,你就能应对大部分高阶滤波场景。下一章我们会聊更高级的话题——双麦克风波束成形与声反馈联合抑制,敬请期待。


公众号:蓝海资料掘金营,微信deep3321