信号处理基础 | Butterworth IIR 低通滤波器结构:直接型、二阶节与级联实现
本文是二阶 Butterworth 低通滤波器系列文章的第 2 篇。上一篇文章主要讨论一个 IIR 低通滤波器是怎么从频率指标设计出来的:从 Butterworth 幅度响应,到稳定模拟原型,再通过双线性变换得到数字滤波器。
这一篇我们来讲Butterworth IIR 低通滤波器的结构,从差分方程到直接型(直接 Ⅰ 型、直接 Ⅱ 型、转置直接 Ⅱ 型)、二阶节与级联实现。
本文和仿真代码同步发在个人博客网站 VoxWorking · 声学与音频知识平台,网站定期更新音频处理、语音处理和声学相关知识,欢迎大家浏览交流~
1. 为什么 IIR 滤波器有不同的结构
设计滤波器时,通常先关心频率响应,比如截止频率、通带平坦度、阻带衰减等。对于 Butterworth 滤波器来说,设计方法决定了它的幅频响应特征是通带最大平坦,没有纹波。上篇讲到滤波器的z域传递函数是:
b0 + b1 z^-1 + b2 z^-2
H(z) = --------------------------------
1 + a1 z^-1 + a2 z^-2
滤波器差分方程是:
y[n] = b0 x[n] + b1 x[n-1] + b2 x[n-2]
- a1 y[n-1] - a2 y[n-2]
但是同一个H(z),在实际实现时可以有不同的滤波器结构,比如直接 I 型(Direct Form I)、直接 II 型 (Direct Form II)、
转置直接 II 型 (Transposed Direct Form II)、二阶节级联 (SOS cascade),这些结构在理想数学上可以表示同一个传递函数,但在实际计算中并不一样,不同的滤波器结构 保存历史状态、乘加组织方式、浮点或定点量化误差、高阶滤波器数值稳定性 等方面都有所不同。接下来我们会介绍他们之间的联系与区别
2. 直接 Ⅰ 型结构
如上图所示,直接 I 型,也就是 Direct Form I,可以理解为直接照着差分方程实现。
y[n] = b0 x[n] + b1 x[n-1] + b2 x[n-2]
- a1 y[n-1] - a2 y[n-2]
它需要保存两类历史量:输入历史:x[n-1], x[n-2] 和 输出历史:y[n-1], y[n-2], 所以二阶直接 I 型通常需要 4 个延迟状态。
从实现角度看,直接 I 型不是保存状态数量最少的结构,尤其当阶数变高时,它需要分别保存输入延迟线和输出延迟线。
3. 直接 Ⅱ 型结构
直接 II 型,也就是 Direct Form II,本质上仍然实现同一个传递函数 H(z),但它把直接 I 型中的输入延迟线和输出延迟线合并成一条内部状态延迟线。
我们来推导一下怎么从直接 Ⅰ 型转变成直接 Ⅱ 型结构,从传递函数开始:
b0 + b1 z^-1 + b2 z^-2
H(z) = --------------------------------
1 + a1 z^-1 + a2 z^-2
可以拆成两部分 H(z) = B(z) · 1 / A(z), 其中:
B(z) = b0 + b1 z^-1 + b2 z^-2
A(z) = 1 + a1 z^-1 + a2 z^-2
这可以理解成 输入 x[n] 先经过反馈部分 1/A(z) 得到中间变量 w[n],再经过前向 FIR 部分 B(z),得到输出 y[n]。即:
W(z) = X(z) / A(z)
Y(z) = B(z) W(z)
其中,第一式可以推导成:
W(z)(1 + a1 z^-1 + a2 z^-2) = X(z) →
w[n] + a1 w[n-1] + a2 w[n-2] = x[n] →
w[n] = x[n] - a1 w[n-1] - a2 w[n-2]
第二式可以推导成:
Y(z) = (b0 + b1 z^-1 + b2 z^-2) W(z) →
y[n] = b0 w[n] + b1 w[n-1] + b2 w[n-2]
所以我们就可以得到直接 Ⅱ 型的结构,与上图相对应,好处就是可以少记住一部分的历史状态,
现在只需要记住w[n-1], w[n-2]状态变量就可以。
w[n] = x[n] - a1 w[n-1] - a2 w[n-2]
y[n] = b0 w[n] + b1 w[n-1] + b2 w[n-2]
4. 转置直接 Ⅱ 型
直接 II 型滤波器结构还有一个常见变体:转置直接 II 型 (Transposed Direct Form II), 它和直接 II 型在数学上传递函数相同,但信号流图经过了转置变换。工程实现中,很多 DSP 库、音频处理库、嵌入式滤波器代码会使用转置直接 II 型,尤其是在实现二阶节时。
二阶转置直接 II 型常写成:
y[n] = b0 x[n] + s1[n-1]
s1[n] = b1 x[n] - a1 y[n] + s2[n-1]
s2[n] = b2 x[n] - a2 y[n]
其中 s1、s2 是内部状态。这里转置的意思是,假设原来有一个结构:
x ----> [a] ----> [b] ----> y
转置后变成:
x ----> [b] ----> [a] ----> y
比如直接 Ⅱ 型结构大致是:
x[n]
↓
先经过反馈部分 1/A(z)
↓
得到内部状态 w[n]
↓
再经过前向部分 B(z)
↓
y[n]
经过转置后变成:
x[n]
↓
先乘 b0 得到 y[n] 的一部分
↓
同时把当前 x[n] 和 y[n] 对未来输出的影响存进状态
这里不需要把他理解成新的滤波器类型,只是直接 Ⅱ 型的另一种计算组织方式。
5. 二阶节与级联型实现
阶数通常指传递函数分母多项式的最高阶数,也可以理解为极点数量。对于:
b0 + b1 z^-1 + b2 z^-2
H(z) = --------------------------------
1 + a1 z^-1 + a2 z^-2
最高延迟项是 z^-2,所以它是二阶滤波器。二阶节 (Second-Order Section, SOS),是一个最多包含二阶分母和二阶分子的滤波器小模块,传递函数H(z)跟上式一样,可以理解成二阶节就是一个二阶滤波器结构。节数指整个滤波器由多少个二阶节组成。
当滤波器阶数比较高时,我们可以把整个传递函数写成多个二阶节的乘积:
H(z) = H1(z) H2(z) ... HM(z)
这就是级联型结构。每个二阶节负责一对极点和一对零点,这样做的好处是可以改善数值实现。如果把高阶 IIR 直接展开成一个很长的分子、分母多项式:
b0 + b1 z^-1 + ... + bN z^-N
H(z) = ------------------------------------
1 + a1 z^-1 + ... + aN z^-N
那么系数的微小量化误差,可能会让极点位置发生比较明显的偏移。对于 IIR 来说,极点位置直接关系到稳定性和频率响应,因此高阶直接型实现会更敏感。而级联实现把高阶问题拆成多个二阶小问题,每一节只处理一对极点,每一节的系数量级更容易控制,每一节可以独立检查稳定性,更适合浮点、定点和嵌入式实现。
6. Matlab设计级联型 IIR 滤波器
以下是用Matlab的filterDesigner插件设计了一个直接 Ⅱ 型的级联式的IIR低通滤波器,从图中系数也可以看到共有3个二阶节,每个二阶阶都是一个二阶IIR滤波器。