
3.6.2 滤波器设计
signal模块提供了许多滤波器设计的函数。在下面的实例中,我们设计一个IIR带通滤波器,并查看其频率响应,最后使用它对频率扫描信号进行滤波计算。
sampling_rate = 8000.0 # 设计一个带通滤波器: # 通带为0.2* 4000 - 0.5* 4000 # 阻带为<0.1* 4000, >0.6* 4000 # 通带增益的最大衰减值为2dB # 阻带的最小衰减值为40dB b, a = signal.iirdesign([0.2, 0.5], [0.1, 0.6], 2, 40) ❶ # 使用freq计算滤波器的频率响应 w, h = signal.freqz(b, a) ❷ # 计算增益 power = 20* np.log10(np.clip(np.abs(h), 1e-8, 1e100)) ❸ freq = w / np.pi * sampling_rate / 2
❶首先用iirdesign( )设计一个IIR带通滤波器。这个滤波器的通带为0.2f0到0.5f0,阻带为小于0.1f0和大于0.6f0,其中f0为信号取样频率的一半。如果取样频率为8kHz,那么这个带通滤波器的通带为800Hz到2kHz。通带的最大增益衰减为2dB,阻带的最小增益衰减为40dB,即通带的增益浮动在2dB之内,阻带至少有40dB的衰减。
iirdesgin( )返回两个数组b和a,它们分别是IIR滤波器的分子和分母部分的系数。其中a[0]恒等于1。❷调用freqz( )计算所得到的滤波器的频率响应。freqz( )返回两个数组w和h,其中w是圆频率数组,通过ωf0/π可以计算出与其对应的实际频率。h是w中对应频率点的响应,它是一个复数数组,其幅值表示滤波器的增益特性,相角表示滤波器的相位特性。
❸计算h的增益特性,并使用dB进行度量。由于h中存在幅值几乎为0的值,因此先用clip( )对其裁剪之后,再调用对数函数,避免计算出错。
在实际运用中为了测量未知系统的频率特性,经常将频率扫描波输入到系统中,观察系统的输出,从而计算其频率特性。下面让我们模拟这一过程:
# 产生两秒钟的取样频率为sampling_rate Hz的频率扫描信号 # 开始频率为0,结束频率为sampling_rate/2 t = np.arange(0, 2, 1/sampling_rate) ❶ sweep = signal.chirp(t, f0=0, t1=2, f1=sampling_rate/2) ❷ # 对频率扫描信号进行滤波 out = signal.lfilter(b, a, sweep) ❸ # 将波形转换为能量 out = 20* np.log10(np.abs(out)) ❹ # 找到所有局部最大值的下标 index = signal.argrelmax(out, order=3) ❺ # 绘制滤波之后的波形的增益 pl.figure(figsize=(8, 2.5)) pl.plot(freq, power, label=u"带通IIR滤波器的频率响应") pl.plot(t[index]/2.0* 4000, out[index], label=u"频率扫描波测量的频谱", alpha=0.6) ❻ pl.legend(loc="best")
❶为了调用chirp( )产生频率扫描波形的数据,首先需要产生一个表示取样时间的等差数组,这里产生两秒的取样频率为8kHz的取样时间数组。❷然后调用chirp( )得到两秒的频率扫描波形的数据。频率扫描波的开始频率f0为0Hz,结束频率f1为4kHz,到达4kHz的时间为两秒,使用数组t作为取样时间点。❸最后调用lfilter( )计算频率扫描波形经过带通滤波器之后的结果。
❹为了和系统的增益特性图进行比较,需要获取输出波形的包络,因此先将输出波形数据转换为能量值。❺为了计算包络,调用argrelmax( )找到out数组中所有局部最大值的下标,order参数指定局域最大值的范围,这里的值为3表示所有的局域最大值都是连续7个元素(前后各三个元素)中的最大值。❻最后将时间转换为对应的频率,绘制所有局部最大点的能量值。
图3-32显示了freqz( )计算的频谱和频率扫描波得到的频率特性,可以看到结果是一致的。

图3-32 用频率扫描波测量的频率响应