简体   繁体   English

在Python中使用scipy.signal时的过滤增益问题

[英]Filter gain issue when using scipy.signal in Python

I am attempting to filter a list of 16-bit two's-complement integer using a Butterworth filter generated using scipy.signal.butter and scipy.signal.lfilter (the list was extracted from a PCM-encoded .wav file). 我正在尝试使用使用scipy.signal.butter和scipy.signal.lfilter生成的Butterworth过滤器来过滤16位二进制补码整数列表(该列表是从PCM编码的.wav文件中提取的)。 My primary language is C, however the majority of this project already exists in Python, and so I need to code this feature within the existing Python framework. 我的主要语言是C,但是该项目的大部分已经存在于Python中,因此我需要在现有的Python框架中编写此功能。

The butterworth filters produced by scipy.signal (as far as I'm aware) are unity gain, and based upon the plot of the frequency response of the filter, that should be the case. scipy.signal(据我所知)产生的巴特沃斯滤波器是单位增益,并且基于滤波器的频率响应图,应该是这种情况。 I designed the filter using butter() and filtered my dataset using: 我使用butter()设计了过滤器,并使用以下方法过滤了数据集:

data.l = lfilter(b, a, data.l)

where data.l is a class containing an list 'l' containing PCM data, and 'b' and 'a' are the coefficients produced by butter(). 其中data.l是包含列表“ l”的类,该列表包含PCM数据,“ b”和“ a”是butter()产生的系数。

However, regardless of the PCM data that I send in, the filter appears to be applying non-unity gain. 但是,无论我发送的PCM数据如何,该滤波器似乎都在应用非单位增益。

For example, filtering full-bandwidth pink noise with max(data.l) = 32,767 , and min(data.l) = -32,768 before filtering (as expected for a 16-bit PCM signal) returns a signal with approximately 5% increased gain in the passband. 例如,在进行过滤(如预期的16位PCM信号)之前,过滤具有max(data.l) = 32,767min(data.l) = -32,768全带宽粉红噪声会返回大约增加5%的信号通带增益。 ie max(data.l) = 34,319.0057 and min(data.l) = -37,593 . max(data.l) = 34,319.0057min(data.l) = -37,593

The filter appears to be correctly filtering the signal apart from the gain; 除增益外,滤波器似乎正在正确滤波信号。 if I save this PCM data back into a .wav file, and compare a spectrogram of the data to the original signal, the frequency response is exactly as would be expected from my test filters. 如果我将此PCM数据保存回.wav文件,并将数据的频谱图与原始信号进行比较,则频率响应与我的测试滤波器所期望的完全相同。 It seems to be functioning perfectly except for the odd increase in gain? 除了增益的奇数增加外,它似乎运行正常。

Obviously I can just rescale this output down to fit into my 16-bit PCM dataset, however I am writing this as part of a wider set of signal processing modules that are designed to be flexible and eventually include non-unity gain filters. 显然,我可以将输出缩小以适合我的16位PCM数据集,但是我将其编写为更广泛的信号处理模块集的一部分,这些模块旨在灵活并最终包括非单位增益滤波器。 For this reason, I want to attempt to figure out why this gain is being applied so as to potentially fix the issue, and not be arbitrarily rescaling the output of my butter() filter. 因此,我想尝试找出为什么要应用此增益以便潜在地解决该问题,而不是随意重新调整我的butter()过滤器的输出。

Does anyone with experience with scipy.signal have an idea as to why this may be the case? 有谁拥有scipy.signal经验的人对为什么会这样有想法吗?

It is normal for a discrete time Butterworth filter to have ringing transients, and these can overshoot the bounds of the input. 离散时间Butterworth滤波器具有振铃瞬变是正常现象,这些瞬变可能会超出输入范围。 Take a look at the step response of your filter (as opposed to the frequency response, which is a steady state calculation). 看一下滤波器的阶跃响应(与频率响应相反,后者是稳态计算)。

For example, the following code 例如下面的代码

In [638]: from scipy.signal import butter, lfilter, freqz

In [639]: b, a = butter(3, 0.2)

In [640]: step_response = lfilter(b, a, np.ones(50))

In [641]: plot(step_response)
Out[641]: [<matplotlib.lines.Line2D at 0x10ecb2850>]

generates the plot 生成情节

阶跃响应

Note the overshoot. 注意过冲。

The frequency response shows the expected gains for a (discrete time) Butterworth filter. 频率响应显示(离散时间)巴特沃斯滤波器的预期增益。

In [642]: w, h = freqz(b, a, worN=1000)

In [643]: plot(w/np.pi, np.abs(h))
Out[643]: [<matplotlib.lines.Line2D at 0x10f7a90d0>]

频率响应

See also: http://www.dspguide.com/ch20/3.htm 另请参阅: http : //www.dspguide.com/ch20/3.htm

Concerning your second question: If you remove the overshoots, you'll either cause distortions (clipping) or you'll end up with a different frequency response as impulse / step and frequency response are chained together by the Laplace transform. 关于第二个问题:如果消除过冲,将导致失真(削波),或者最终由于拉普拉斯变换将脉冲/阶跃和频率响应链接在一起而产生不同的频率响应。

By filtering, you change your samples, so the concept of "preserving signal level" is questionable in my opinion - the level of a stationary (eg sinusoidal) signal in the passband should remain more or less the same as a Butterworth filter has no ripple in the passband, but components in the stop band (transients -> high frequency) are changed of course. 通过滤波,您会更改采样,因此我认为“保持信号电平”的概念值得怀疑-通带中的固定(例如正弦)信号的电平应大致保持相同,因为Butterworth滤波器没有波动在通带中,阻带的成分(瞬态->高频)当然会改变。

You could try using a filter with Bessel characteristics that has no overshoot (at the cost of a more gentle slope between pass and stop band) if you want to avoid the rescaling. 如果要避免重新定标,可以尝试使用没有Bessel特性且没有过冲的滤波器(以通带和阻带之间更平缓的斜率为代价)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM