设计并应用一个IIR-ButterWorth-Filter的例子
设计一个butter-worth filter
为何是巴特沃斯滤波器
首先我们需要知道我们为什么要设计一个巴特沃斯滤波器,巴特沃斯滤波器有一个重要的特点就是最大平坦通带(Maximally Flat Passband):在通带内(0 ≤ ω ≤ ωₐ)幅度响应尽可能平坦(无波纹)
如图所示
这个函数是幅度平方函数,即
考虑一阶滤波器
step 1 定义幅度平方响应
∣ H ( j ω ) ∣ 2 = 1 1 + ( ω ω c ) 2 n |H(j\omega)|^2 = \frac{1}{1+(\frac{\omega}{\omega_c})^2n} ∣H(jω)∣2=1+(ωcω)2n1
其中n是滤波器阶数, w c w_c wc指的是截止频率
step 2 解析延拓到s域
用 s = j ω s = j\omega s=jω替换,得到s域表达式:
H ( s ) H ( − s ) = 1 ( s j ) 2 = 1 1 − s 2 H(s)H(-s)=\frac{1}{(\frac{s}{j})^2}= \frac{1}{1-s^2} H(s)H(−s)=(js)21=1−s21
step 3 获得极点
求分母的根,得到 s = ± 1 s = \pm1 s=±1
我们选择左边平面极点
p = − 1 p=-1 p=−1
step 4 构造传递函数
其实很容易观察得到, H ( s ) = 1 s + 1 H(s)=\frac{1}{s+1} H(s)=s+11
二阶巴特沃斯滤波器推导
Step 1 定义幅度平方响应
幅度平方函数的一般形式:
∣ H ( j ω ) ∣ 2 = 1 1 + ( ω ω c ) 2 n |H(j\omega)|^2 = \frac{1}{1 + \left(\frac{\omega}{\omega_c}\right)^{2n}} ∣H(jω)∣2=1+(ωcω)2n1
对于二阶滤波器(n=2):
∣ H ( j ω ) ∣ 2 = 1 1 + ( ω ω c ) 4 |H(j\omega)|^2 = \frac{1}{1 + \left(\frac{\omega}{\omega_c}\right)^4} ∣H(jω)∣2=1+(ωcω)41
Step 2 解析延拓到s域
用 s = j ω s = j\omega s=jω 替换,得到s域表达式:
H ( s ) H ( − s ) = 1 1 + ( s j ω c ) 4 H(s)H(-s) = \frac{1}{1 + \left(\frac{s}{j\omega_c}\right)^4} H(s)H(−s)=1+(jωcs)41
将 j 4 = 1 j^4 = 1 j4=1 代入:
H ( s ) H ( − s ) = 1 1 + ( s ω c ) 4 H(s)H(-s) = \frac{1}{1 + \left(\frac{s}{\omega_c}\right)^4} H(s)H(−s)=1+(ωcs)41
Step 3 获得极点
求分母的根(极点):
1 + ( s ω c ) 4 = 0 1 + \left(\frac{s}{\omega_c}\right)^4 = 0 1+(ωcs)4=0
解得:
s k = ω c ⋅ e j π 4 ( 2 k + 1 ) ( k = 0 , 1 , 2 , 3 ) s_k = \omega_c \cdot e^{j\frac{\pi}{4}(2k + 1)} \quad (k = 0,1,2,3) sk=ωc⋅ej4π(2k+1)(k=0,1,2,3)
具体极点位置(取 ω c = 1 \omega_c = 1 ωc=1 归一化):
s 0 = e j π 4 = 2 2 + j 2 2 s 1 = e j 3 π 4 = − 2 2 + j 2 2 s 2 = e j 5 π 4 = − 2 2 − j 2 2 s 3 = e j 7 π 4 = 2 2 − j 2 2 \begin{aligned} s_0 &= e^{j\frac{\pi}{4}} = \frac{\sqrt{2}}{2} + j\frac{\sqrt{2}}{2} \\ s_1 &= e^{j\frac{3\pi}{4}} = -\frac{\sqrt{2}}{2} + j\frac{\sqrt{2}}{2} \\ s_2 &= e^{j\frac{5\pi}{4}} = -\frac{\sqrt{2}}{2} - j\frac{\sqrt{2}}{2} \\ s_3 &= e^{j\frac{7\pi}{4}} = \frac{\sqrt{2}}{2} - j\frac{\sqrt{2}}{2} \end{aligned} s0s1s2s3=ej4π=22+j22=ej43π=−22+j22=ej45π=−22−j22=ej47π=22−j22
选择左半平面极点( s 1 s_1 s1 和 s 2 s_2 s2)以保证系统稳定。
Step 4 构造传递函数
将左半平面极点组合成传递函数:
H ( s ) = ω c 2 ( s − s 1 ) ( s − s 2 ) H(s) = \frac{\omega_c^2}{(s - s_1)(s - s_2)} H(s)=(s−s1)(s−s2)ωc2
代入具体值( ω c = 1 \omega_c = 1 ωc=1):
H ( s ) = 1 ( s + 2 2 − j 2 2 ) ( s + 2 2 + j 2 2 ) = 1 s 2 + 2 s + 1 \begin{aligned} H(s) &= \frac{1}{\left(s + \frac{\sqrt{2}}{2} - j\frac{\sqrt{2}}{2}\right)\left(s + \frac{\sqrt{2}}{2} + j\frac{\sqrt{2}}{2}\right)} \\ &= \frac{1}{s^2 + \sqrt{2}s + 1} \end{aligned} H(s)=(s+22−j22)(s+22+j22)1=s2+2s+11
最终标准形式:
H ( s ) = ω c 2 s 2 + 2 ω c s + ω c 2 H(s) = \frac{\omega_c^2}{s^2 + \sqrt{2}\omega_c s + \omega_c^2} H(s)=s2+2ωcs+ωc2ωc2
关键特性
- -40 dB/decade 高频衰减
- 最大平坦通带(Butterworth特性)
- 截止频率处增益为 − 3 dB -3\text{dB} −3dB(即 ∣ H ( j ω c ) ∣ = 1 2 |H(j\omega_c)| = \frac{1}{\sqrt{2}} ∣H(jωc)∣=21)
对比一阶二阶巴特沃斯滤波器
详细推导过程
1.连续域原型(模拟滤波器)
二阶归一化巴特沃斯低通滤波器(截止频率ωₐ=1 rad/s):
H a n a l o g ( s ) = 1 s 2 + 2 s + 1 H_{analog}(s)=\frac{1}{s^2+\sqrt{2}s+1} Hanalog(s)=s2+2s+11 显然极点位置 s = − − 2 2 ± j 2 2 s=-\frac{-\sqrt{2}}{2}\pm j\frac{\sqrt{2}}{2} s=−2−2±j22
-3db的点: ω = 1 r a d / s \omega=1rad/s ω=1rad/s
2.频率预畸变(关键代码变量 C)
双线性变换会导致频率扭曲,需对截止频率预补偿:
ω c = 2 π f c \omega_c=2\pi f_c ωc=2πfc
预畸变公式:
C = 1 t a n ( ω c T 2 ) = 1 t a n ( π f c f s ) C= \frac{1}{tan(\frac{\omega_cT}{2})} = \frac{1}{tan(\frac{\pi f_c}{f_s})} C=tan(2ωcT)1=tan(fsπfc)1
3. 双线性变换
双线性变换公式
s = 2 T ⋅ 1 − z − 1 1 + z − 1 s = \frac{2}{T} ·\frac{1-z^{-1}}{1+z^{-1}} s=T2⋅1+z−11−z−1 其中T为采样间隔
双线性变换会将模拟频率( ω a \omega_a ωa)和数字频率( ω d \omega_d ωd)的非线性映射
ω a = 2 T t a n ( ω d T 2 ) \omega_a=\frac{2}{T}tan(\frac{\omega_dT}{2}) ωa=T2tan(2ωdT)
这种映射会导致低频段近似相等,高频段扭曲严重
为了保证数字滤波器的截止频率 ω d = ω c \omega_d=\omega_c ωd=ωc准确对应模拟滤波器中的 ω a = ω c \omega_a=\omega_c ωa=ωc,需要对模拟截止频率进行预畸变:
ω a = ω c = 2 T t a n ω c T 2 \omega_a=\omega_c=\frac{2}{T}tan\frac{\omega_cT}{2} ωa=ωc=T2tan2ωcT
从而引入预畸变系数
C = 1 t a n ( ω c T 2 ) = 1 t a n ( π f c f s ) C= \frac{1}{tan(\frac{\omega_cT}{2})} = \frac{1}{tan(\frac{\pi f_c}{f_s})} C=tan(2ωcT)1=tan(fsπfc)1
//C++ 中如此表示
double C = 1 / std::tan(M_PI * center_freq / (double)PublicVar::ins().sample_rate);
修正后的双线性变换 s = C ⋅ 1 − z − 1 1 + z − 1 s = C·\frac{1-z^{-1}}{1+z^{-1}} s=C⋅1+z−11−z−1
可以尝试一下
4:代入双线性变换
将 s = C ⋅ 1 − z − 1 1 + z − 1 s = C \cdot \frac{1 - z^{-1}}{1 + z^{-1}} s=C⋅1+z−11−z−1 代入连续传递函数:
H ( z ) = 1 ( C ⋅ 1 − z − 1 1 + z − 1 ) 2 + 2 ( C ⋅ 1 − z − 1 1 + z − 1 ) + 1 H(z) = \frac{1}{\left(C \cdot \frac{1 - z^{-1}}{1 + z^{-1}}\right)^2 + \sqrt{2} \left(C \cdot \frac{1 - z^{-1}}{1 + z^{-1}}\right) + 1} H(z)=(C⋅1+z−11−z−1)2+2(C⋅1+z−11−z−1)+11
5:通分整理分母
分母部分展开:
分母 = C 2 ( 1 − z − 1 1 + z − 1 ) 2 + 2 C ( 1 − z − 1 1 + z − 1 ) + 1 = C 2 ( 1 − z − 1 ) 2 + 2 C ( 1 − z − 1 ) ( 1 + z − 1 ) + ( 1 + z − 1 ) 2 ( 1 + z − 1 ) 2 \begin{aligned} \text{分母} &= C^2 \left(\frac{1 - z^{-1}}{1 + z^{-1}}\right)^2 + \sqrt{2} C \left(\frac{1 - z^{-1}}{1 + z^{-1}}\right) + 1 \\ &= \frac{C^2 (1 - z^{-1})^2 + \sqrt{2} C (1 - z^{-1})(1 + z^{-1}) + (1 + z^{-1})^2}{(1 + z^{-1})^2} \end{aligned} 分母=C2(1+z−11−z−1)2+2C(1+z−11−z−1)+1=(1+z−1)2C2(1−z−1)2+2C(1−z−1)(1+z−1)+(1+z−1)2
6:展开分子
分子是 ( 1 + z − 1 ) 2 (1 + z^{-1})^2 (1+z−1)2,分母展开为:
分子 = C 2 ( 1 − 2 z − 1 + z − 2 ) + 2 C ( 1 − z − 2 ) + ( 1 + 2 z − 1 + z − 2 ) = ( C 2 + 2 C + 1 ) + ( − 2 C 2 + 2 ) z − 1 + ( C 2 − 2 C + 1 ) z − 2 \begin{aligned} \text{分子} &= C^2 (1 - 2z^{-1} + z^{-2}) + \sqrt{2} C (1 - z^{-2}) + (1 + 2z^{-1} + z^{-2}) \\ &= (C^2 + \sqrt{2} C + 1) + (-2C^2 + 2)z^{-1} + (C^2 - \sqrt{2} C + 1)z^{-2} \end{aligned} 分子=C2(1−2z−1+z−2)+2C(1−z−2)+(1+2z−1+z−2)=(C2+2C+1)+(−2C2+2)z−1+(C2−2C+1)z−2
7:合并传递函数
组合分子分母:
H ( z ) = ( 1 + z − 1 ) 2 ( C 2 + 2 C + 1 ) + ( − 2 C 2 + 2 ) z − 1 + ( C 2 − 2 C + 1 ) z − 2 H(z) = \frac{(1 + z^{-1})^2}{(C^2 + \sqrt{2} C + 1) + (-2C^2 + 2)z^{-1} + (C^2 - \sqrt{2} C + 1)z^{-2}} H(z)=(C2+2C+1)+(−2C2+2)z−1+(C2−2C+1)z−2(1+z−1)2
8:归一化分母
将分母首项系数归一化为1:
H ( z ) = 1 C 2 + 2 C + 1 ( 1 + 2 z − 1 + z − 2 ) 1 + − 2 C 2 + 2 C 2 + 2 C + 1 z − 1 + C 2 − 2 C + 1 C 2 + 2 C + 1 z − 2 H(z) = \frac{\frac{1}{C^2 + \sqrt{2} C + 1}(1 + 2z^{-1} + z^{-2})}{1 + \frac{-2C^2 + 2}{C^2 + \sqrt{2} C + 1}z^{-1} + \frac{C^2 - \sqrt{2} C + 1}{C^2 + \sqrt{2} C + 1}z^{-2}} H(z)=1+C2+2C+1−2C2+2z−1+C2+2C+1C2−2C+1z−2C2+2C+11(1+2z−1+z−2)
9:系数对应
定义系数:
b 0 = 1 C 2 + 2 C + 1 b 1 = 2 b 0 b 2 = b 0 a 1 = 2 − 2 C 2 C 2 + 2 C + 1 a 2 = C 2 − 2 C + 1 C 2 + 2 C + 1 \begin{aligned} b_0 &= \frac{1}{C^2 + \sqrt{2} C + 1} \\ b_1 &= 2b_0 \\ b_2 &= b_0 \\ a_1 &= \frac{2 - 2C^2}{C^2 + \sqrt{2} C + 1} \\ a_2 &= \frac{C^2 - \sqrt{2} C + 1}{C^2 + \sqrt{2} C + 1} \end{aligned} b0b1b2a1a2=C2+2C+11=2b0=b0=C2+2C+12−2C2=C2+2C+1C2−2C+1
最终差分方程:
y [ n ] = b 0 x [ n ] + b 1 x [ n − 1 ] + b 2 x [ n − 2 ] − a 1 y [ n − 1 ] − a 2 y [ n − 2 ] y[n] = b_0 x[n] + b_1 x[n-1] + b_2 x[n-2] - a_1 y[n-1] - a_2 y[n-2] y[n]=b0x[n]+b1x[n−1]+b2x[n−2]−a1y[n−1]−a2y[n−2]
python代码示例
import mathclass TFZ_coefficients:def __init__(self):self.b0 = 0.0self.b1 = 0.0self.b2 = 0.0self.a1 = 0.0self.a2 = 0.0class PublicVar:_instance = None@classmethoddef ins(cls):if cls._instance is None:cls._instance = cls()return cls._instancedef __init__(self):self.sample_rate = 44100.0 # Default value, adjust as neededdef MakeCoeffLowPass(center_freq):ret = TFZ_coefficients()C = 1 / math.tan(math.pi * center_freq / float(PublicVar.ins().sample_rate))SqC = math.pow(C, 2)MultC = math.sqrt(2) * Cc = 1.0 / (1.0 + MultC + SqC)ret.b0 = cret.b1 = 2.0 * cret.b2 = cret.a1 = 2.0 * c * (1.0 - SqC)ret.a2 = c * (1.0 - MultC + SqC)return ret