如何级联两个二阶巴特沃斯滤波器

Posted

技术标签:

【中文标题】如何级联两个二阶巴特沃斯滤波器【英文标题】:How do I cascade two second order butterworth filters 【发布时间】:2014-02-05 11:53:47 【问题描述】:

我已经计算出二阶低通和高通巴特沃斯滤波器的系数。

系数如下。我正在实现这个 C。

float cutoff = 600.00f * M_PI * 2;
float c = 2.0f / sampleRate;
float q = sqrt(2.0f)/2.0f;

g_a1LP = (2.0f * pow(c, 2.0f) - (2.0f * pow(cutoff, 2.0f))) / (pow(c, 2.0f) + ((cutoff*c)/q) + pow(cutoff, 2.0f));

g_a2LP = -(pow(c, 2.0f)  + pow(cutoff, 2.0f) - (cutoff*c)/q ) / (pow(c, 2.0f) + ((cutoff*c)/q) + pow(cutoff, 2.0f));

g_b0LP = 1.0f;
g_b1LP = 2.0f;
g_b2LP = 1.0f; 

g_a1HP = (2.0f - (2.0f * pow(cutoff, 2.0f))/ pow(c, 2.0f)) / (1.0f + (2.0f/sqrt(2.0f)) * (1.0f/c) * cutoff + (pow(cutoff, 2.0f) / pow(c, 2.0f)));

g_a2HP = -(1.0f - (2.0f/sqrt(2.0f) * 1.0f/c * cutoff) + pow(cutoff, 2.0f)/pow(c, 2.0f)) / (1.0f + (2.0f/sqrt(2.0f)) * (1.0f/c) * cutoff + (pow(cutoff, 2.0f) / pow(c, 2.0f)));

g_b0HP = 1.0;
g_b1HP = -2.0;
g_b2HP = 1.0; 

我现在必须进行 4 阶 Linkwitz-Riley 交叉。我知道这是两个巴特沃斯的级联。我不太确定我应该怎么做。我只是将系数相乘吗?我在正确的轨道上吗?如果有人感到困扰,我的系数看起来还好吗?他们在 matlab 中绘制得很好。

【问题讨论】:

我可以补充一下,我使用双线性变换来获得这些系数 我不认为你可以乘以系数,你可以乘以频率空间中的传递函数。或者您可以按顺序通过它们运行您的信号。 但这不是先衰减高频,然后再衰减低频,反之亦然吗? 是的。这不是你想要的吗?基本上创建一个带通滤波器?这就是级联 LPF 和 HPF 的作用...您确定要级联它们吗? 在交叉网络中,两个过滤器没有级联。相反,将相同的信号并行应用于两个滤波器。每个滤波器的输出分别为您提供高频和低频(每个都被发送到不同的扬声器)。参见例如here 【参考方案1】:

为什么不使用

Matlab: 如果你负担得起(不是免费的) SciPy 如果你准备好尝试 Python(免费)

他们建议在 Python 中用两行代码来做这样的操作

from scipy.signal import butter
# generate the coefficients (discrete time) of a 4 order butterworth bandpass filter, where low cutoff frequency is 0.3 the Nyquist frequency and the high cutoff is 0.4 the Nyquist frequency
butter(4, [0.3, 0.4], 'band')

这将输出以下系数:

>>> (array([  4.16599204e-04,   0.00000000e+00,  -1.66639682e-03,
     3.25816475e-19,   2.49959523e-03,  -3.25816475e-19,
    -1.66639682e-03,   0.00000000e+00,   4.16599204e-04]), array([  1.        ,  -3.30057727,   7.28008314, -10.20570426,
    10.95189946,  -8.30658348,   4.82226759,  -1.77664475,   0.43826514]))

【讨论】:

我正在做一个实时 dsp 项目,所以它必须在 C 中完成。不过干杯。 好的,我现在明白了。所以我的回答没有帮助。但是,我知道要获得级联滤波器(四阶),您必须对 2 个滤波器系数(分子和分母)进行卷积。因为级联滤波器是频域中的乘法,它相当于时域。您拥有的滤波器系数是滤波器的脉冲(时域)响应。您可能应该在 dsp.stackexchange.com 上询问详细信息。【参考方案2】:

为了创建一个四阶高通(分别是低通)Linkwitz-Riley 滤波器,您必须级联 2 个相同二阶高通(分别是低通)巴特沃斯过滤器。

使用过滤器多项式,这意味着:

巴特沃斯滤波器:

h = b0 + b1.X + b2.X**2 / a0 + a1.X + a2.X**2

Linkwitz-Riley 过滤器:

h' = h**2

因此,如果您的实现允许,您可以简单地平方 Butterworth 过滤器。

如果您想拥有 Linkwitz-Riley 数字滤波器系数,您可以:

通过开发以下等式找到它们:

(b0 + b1.X + b2.X**2) ** 2 = (b0' + b1'.X + b2'.X**2 + b3'.X**3 + b4'.X**4)

它将为您提供 5 个系数 b0' ... b4' 作为 b0 ... b3 的函数(类似地,a0' ... a4' 作为 a0 ... a3 的函数),您可以将其实现到您的代码。

使用 Matlab 或 Python

这是一个使用 scipy.signal 的 Python 示例函数,它返回数字滤波器的分子和分母 Linkwitz-Riley 系数。

import scipy.signal as sig
def linkril(filter_order, w_center, btype='lowpass', analog=False):
   butter_order = int(filter_order / 2.)
   numbut, denbut = sig.butter(butter_order, w_center,
                           btype = btype, analog=analog)
   num = np.convolve(numbut, numbut)
   den = np.convolve(denbut, denbut)
   return(num, den)

【讨论】:

经过一些数学运算:b0' = b02, b1'=2*b0*b1, b2'=b12+2*b0*b2, b3' =2*b1*b2, b4'=b2**2【参考方案3】:

RawBean 在他的评论中是正确的......

首先,为了创建 Linkwitz Riley 滤波器(同样适用于低通或高通),您必须级联两个 相同 滤波器,就像 Aporee 提到的那样.现在,这与 RawBean 的注释相结合意味着您必须对系数进行卷积。这可以分别对分子和分母进行,最终结果将对应于您正在寻找的 Linkwitz-Riley 系数的分子和分母系数。

如果您查看 Aporee 的示例,卷积函数用于计算最终系数。您可以很好地使用此代码 sn-p 来获取您的系数,如果实现将是一个静态交叉滤波器,您甚至可以对它们进行硬编码。

【讨论】:

以上是关于如何级联两个二阶巴特沃斯滤波器的主要内容,如果未能解决你的问题,请参考以下文章

二阶 IIR 滤波器,巴特沃斯带通 (EQ) 的系数?

设计一个巴特沃斯低通滤波器

如何使用 Scipy.signal.butter 实现带通巴特沃斯滤波器

6.3.2巴特沃斯(butterworth)低通滤波器

OpenCV 完整例程82. 频率域巴特沃斯低通滤波器

MATLAB中图像的高通巴特沃斯滤波器