我应该使用 scipy.signal.firwin 进行放大吗?

Should I use scipy.signal.firwin for amplification?

Scipy 的 firwin2 函数接受增益值 > 1.0,这会导致相应频率的放大。我已经对此进行了测试,它似乎按预期工作。但是,我在网上找到的所有示例都只使用了 0.0 到 1.0 之间的增益值。这让我想知道:用firwin2函数制作和放大滤波器是不是一个坏主意?

firwin不接受增益因子,只接受numtaps和

firwin(numtaps, cutoff, width=None, window='hamming', pass_zero=True,
           scale=True, nyq=None, fs=None)

要么是我理解错了你的问题,要么是你混淆了 cutoff 和收益。 截断表示 cutoff freqeuncy.

如果您想应用增益,请将返回的滤波器乘以您的增益。

from scipy import signal
numtaps = 3
f = 0.1
gain = 5;
h = gain * signal.firwin(numtaps, f)

您可以按如下方式绘制过滤器的响应

import numpy as np;
import matplotlib.pyplot as plt;

h1 = signal.firwin(256, 0.1)
h2 = signal.firwin(256, 0.3)

plt.plot(np.fft.rfftfreq(len(h1)), abs(np.fft.rfft(h1)))
plt.plot(np.fft.rfftfreq(len(h2)), abs(np.fft.rfft(h2)))
plt.xlabel('F / Fs')
plt.ylabel('Filter gain')

编辑:关于 firwin2 的问题

函数 firwin2(freq, gain) returns 一个滤波器,它是通过频域中的插值构造的,然后是 window(标量乘法)。该操作在增益阵列上是线性的。即 firwin2(freq, A*gain) = A*firwin2(freq, gain)。所以有像 gain < 1.

这样的限制

您可以通过

确认
from scipy import signal
import numpy as np
taps1 = signal.firwin2(150, [0.0, 0.5, 1.0], [1.0, 1.0, 0.0]) * 2
taps2 = signal.firwin2(150, [0.0, 0.5, 1.0], [2.0, 2.0, 0.0])
assert(np.allclose(taps1, taps2))

这主意不错!与其他 window-based 设计一样,您需要确保您的 numtaps(也就是滤波器的阶数)足以代表您想要的频率响应。

你看到的 gain=[0,1] 的 pseudo-standard 是因为,在大多数情况下,over-unity 放大不被认为可以改善 signal-to-noise 相对于别管它(相反,放大可能会引入削波)。要提高 signal-to-noise 和 signal-to-interference 比率,您需要消除噪音或干扰。如果噪声和干扰的频率与您想要的信号不同,您可以通过过滤来衰减它们。在这种情况下,您的信号频率将保持 1.0 的增益,而您不需要的部分将具有 0.0 的增益。

但是,有 次您想要放大某些频率而同时保留其他频率或衰减它们。这方面的一个例子是音频均衡器。假设您有一个 computer-based 音频均衡器。用户会看到一系列不同频率的滑块,并根据需要向上或向下调整它们。你的车里可能有其中之一。您可以轻松地使用 firwin2 创建相应的 FIR 系数,只需传入频率向量和相应的增益向量即可。如果用户调高低音,同时将所有其他频率保持在 0 dB(即单位增益),您将在您设计的低音频率处获得增益,在所有其他频率处获得 1.0。


这是使用音频均衡器增益的示例。我为 Equalizer extension for Google Chrome:

找到了这张图片

要用 firwin2 实现这个,我可以使用下面的脚本:

from scipy import signal
import numpy as np
import matplotlib.pyplot as plt;

Fs = 44100
order = 4096+1
freqs = [0, 32, 64, 125, 250, 500, 1000, 2000, 4000, 8000, 16000, Fs/2]
gains_dB = [4.0, 4.0, 2.3, 1.0, 0.3, -0.3, -1.2, 0.1, 1.6, 3.1, 3.3, 3.3]
gains = 10.**(np.asarray(gains_dB)/10.)
h = signal.firwin2(order, freqs, gains, fs=Fs)

plt.semilogx(np.fft.rfftfreq(len(h))*Fs, 10*np.log10(abs(np.fft.rfft(h))))
plt.title('Equalizer Example')
plt.xlabel('Frequency, Hz')
plt.ylabel('Filter Magnitude Response, dB')
plt.grid(True,which='both')
plt.show()

一些注意事项:

  • 您通常会在半对数图上绘制滤波器,因为每个八度音程都会发生滚降。
  • 您通常根据分贝绘制增益。
  • firwin2 接受线性单位增益,而不是分贝,因此需要进行转换。
  • firwin2 需要 0 和 Fs/2 处的频率表示,所以我添加了它们并使它们等于它们的邻居。