与简单的低通/带通/带阻/高通分类相比,有许多设计选项可以匹配更多任意频段规范。最常见的是:
前两个可从scipy.signal 轻松获得,分别为scipy.firls 和scipy.remez,而第三个可以通过采样频率响应曲线的逆FFT 来完成。
使用最小二乘法的示例实现:
from scipy import signal
import matplotlib.pyplot as plt
import numpy as np
bands = [0, fL1, fL2, fH1, fH2, fs/2]
desired = [Bl, Bl, 1, 1, Bh, Bh]
y = signal.firls(numtaps, bands, desired, fs=fs)
f,h = signal.freqz(y, fs=fs)
plt.plot(bands, desired, 'k', linewidth=2)
plt.plot(f, np.abs(h), 'r')
使用 Parks-McClellan 算法的示例实现:
from scipy import signal
import matplotlib.pyplot as plt
import numpy as np
bands = [0, fL1, fL2, fH1, fH2, fs/2]
desired = [Bl, 1, Bh]
y = signal.remez(numtaps, bands, desired, fs=fs)
f,h = signal.freqz(y, fs=fs)
plt.plot(bands, desired, 'k', linewidth=2)
plt.plot(f, np.abs(h), 'b')
使用频率采样方法的示例实现:
from scipy import interpolate, fft
import matplotlib.pyplot as plt
import numpy as np
# interpolate desired response at equally spaced frequency points
interpolator = interpolate.interp1d(bands, desired)
N = 1024
fsampling = np.linspace(0, fs/2, N)
sampled = interpolator(fsampling)
# take the inverse FFT
y = fft.fftshift(fft.irfft(sampled))
# truncate response to keep numtaps coefficients
n1 = N-numtaps//2
n2 = n1 + numtaps
y = y[n1:n2]
为了便于说明,使用下面的一组参数
numtaps = 19
fL1 = 100
fL2 = 200
fH1 = 500
fH2 = 600
fs = 1600
Bl = 2
Bh = 2.3
会产生相应的设计:
请注意,如果您的频率规格曲线是不超过值(而不是标称值),您仍然可以在每次调整 bands 和 desired 参数时以迭代方式使用上述方法,直到您收敛到可接受的响应。使用上面的初始参数集,使用最小二乘法,您最终可能会得到调整后的参数,例如
bands = [0, 100, 180, 520, 600, fs/2]
desired = [1.966,1.966,0.980,0.980,2.225,2.225]
有相应的回应: