C++ 计算二阶巴特沃斯低通滤波器的系数
有了 采样频率:10kHzC++ 计算二阶巴特沃斯低通滤波器的系数,c++,signal-processing,C++,Signal Processing,有了 采样频率:10kHz 截止频率:1kHz 我如何计算下面差分方程的系数 我知道差分方程是这种形式的,但不知道如何计算出系数b0,b1,b2,a1,a2的数字 y(n) = b0.x(n) + b1.x(n-1) + b2.x(n-2) + a1.y(n-1) + a2.y(n-2) 我最终会在C++中实现这个LPF,但是我需要知道如何在我得到它之前的任何地方先计算系数 < p>这里,你走。ff是频率比,在您的情况下为0.1: const double ita =1.0/ ta
截止频率:1kHz 我如何计算下面差分方程的系数 我知道差分方程是这种形式的,但不知道如何计算出系数b0,b1,b2,a1,a2的数字
y(n) = b0.x(n) + b1.x(n-1) + b2.x(n-2) + a1.y(n-1) + a2.y(n-2)
<>我最终会在C++中实现这个LPF,但是我需要知道如何在我得到它之前的任何地方先计算系数 < p>这里,你走。ff是频率比,在您的情况下为0.1:
const double ita =1.0/ tan(M_PI*ff);
const double q=sqrt(2.0);
b0 = 1.0 / (1.0 + q*ita + ita*ita);
b1= 2*b0;
b2= b0;
a1 = 2.0 * (ita*ita - 1.0) * b0;
a2 = -(1.0 - q*ita + ita*ita) * b0;
结果是:
b0=0.0674553b1=0.134911
b2=0.0674553
a1=1.14298
a2=-0.412802
您可以使用此链接获得具有特定采样率和频率切割的n阶巴特沃斯滤波器的系数。为了测试结果。您可以使用MATLAB获得系数,并与程序的输出进行比较
最好的方法是使用lab view之类的工具来模拟您的过滤器,并根据您的fc和fs获得系数。然后在c中使用它们。最后把代码烧到你的microcon上。并将响应与lab view或simulink中的响应进行比较 供参考 如果需要高通滤波器coefs,只需使用相同的代码即可:
const double ita =1.0/ tan(M_PI*ff);
const double q=sqrt(2.0);
b0 = 1.0 / (1.0 + q*ita + ita*ita);
b1= 2*b0;
b2= b0;
a1 = 2.0 * (ita*ita - 1.0) * b0;
a2 = -(1.0 - q*ita + ita*ita) * b0;
但在把所有的b项乘以ita^2,然后取b1的反
b0 = b0*ita*ita;
b1 = -b1*ita*ita;
b2 = b2*ita*ita;
现在你有了一个二阶高通滤波器对于那些想知道其他答案中那些神奇公式来自何方的人来说,下面是一个推导 从巴特沃斯滤波器的传递函数开始
G(s)=wc^2/(s^2+s*sqrt(2)*wc+wc^2)
当wc
是截止频率时,应用双线性z变换,即替换s=2/T*(1-z^-1)/(1+z^-1)
:
G(z)=wc^2/((2/T*(1-z^-1)/(1+z^-1))^2+(2/T*(1-z^-1)/(1+z^-1))*sqrt(2)*wc+wc^2)
T
是采样周期[s]
截止频率需要预扭曲以补偿非线性
z变换引入的模拟和数字频率之间的关系:
wc=2/T*tan(wd*T/2)
其中,wd
是所需的截止频率[rad/s]
为了方便起见,让C=tan(wd*T/2)
,以便wc=2/T*C
将其代入方程式,则2/T
因子将退出:
G(z)=C^2/((1-z^-1)/(1+z^-1))^2+(1-z^-1)/(1+z^-1)*sqrt(2)*C+C^2)
将分子和分母乘以(1+z^-1)^2
,然后展开,得到:
G(z)=C^2*(1+2*z^-1+z^-2)/(1+sqrt(2)*C+C^2+2*(C^2-1)*z^-1+(1-sqrt(2)*C+C^2)*z^-2')
现在,将分子和分母除以分母中的常数项。为了方便起见,让D=1+sqrt(2)*C+C^2
:
G(z)=C^2/D*(1+2*z^-1+z^-2)/(1+2*(C^2-1)/D*z^-1+(1-sqrt(2)*C+C^2)/D*z^-2')
此表格等同于我们正在寻找的表格:
G(z)=(b0+b1*z^-1+b2*z^-1)/(1+a1*z^-1+a2*z^-2)
因此,我们通过将它们相等得到系数:
a0=1
a1=2*(C^2-1)/D
a2=(1-sqrt(2)*C+C^2)/D
b0=C^2/D
b1=2*b0
b2=b0
其中,
D=1+sqrt(2)*C+C^2
,C=tan(wd*T/2)
,wd
是所需的截止频率[rad/s],T
是采样周期[s]。我的a和b在这里切换,但我的代码如下:
//Boulanger and Lazzarini, The Audio Programming Book, pg 484
void calculateDifferenceEquation() {
float lambda = 1.0 / (tan(M_PI * mFrequency / mSampleRate));
a0 = 1.0 / (1.0 + (2.0 * lambda) + pow(lambda, 2.0));
a1 = 2.0 * a0;
a2 = a0;
b1 = 2.0 * a0 * (1.0 - pow(lambda, 2.0));
b2 = a0 * (1.0 - (2.0 * lambda) + pow(lambda, 2.0));
}
这个问题似乎离题了,因为它是关于信号处理理论,而不是编程。所以,简单地说,你检查过相关的维基百科条目吗?你提供的公式看起来像一个通用的二阶微分方程,你没有提供边界条件(或等效条件),因此,目前这个问题似乎无法回答。你能提供更多的上下文吗?@Talonmes我以前使用过堆栈溢出,收到了很好的响应,我不确定还能在哪里找到其他内容ask@KarolyHorvath是的,我查过维基百科,首先我知道这有帮助,是否有一种方法可以修改它,以便能够计算不同的截止频率和采样频率,以获得输入的任何参数的系数?只需使用提供的公式,ff是截止频率和采样频率之比:
ff=f_截止/f_采样
这里有一个关于计算巴特沃斯滤波器增益和编码巴特沃斯滤波器的例子。我不是来自信号/EE背景。有人能解释一下为什么系数不必加1吗?看起来OP发布的方程会接受x[n],x[n-1],等等,输出y[n]围绕一个完全不同的“平均”信号路径。数字加起来等于1,b0+b1+b2+a1+a2=1,所以我不确定你的意思。嘿,巴拉特,谢谢你的回答。你能编辑文章并添加一些例子吗?澄清:a1和a2保持不变。只有b值变化请注意,Matlab和Wn使用的Fnorm(SCIPY使用的)是Pentadecagon答案中使用的FF值的一半。我只是浪费了半天没注意到。。。。
//Boulanger and Lazzarini, The Audio Programming Book, pg 484
void calculateDifferenceEquation() {
float lambda = 1.0 / (tan(M_PI * mFrequency / mSampleRate));
a0 = 1.0 / (1.0 + (2.0 * lambda) + pow(lambda, 2.0));
a1 = 2.0 * a0;
a2 = a0;
b1 = 2.0 * a0 * (1.0 - pow(lambda, 2.0));
b2 = a0 * (1.0 - (2.0 * lambda) + pow(lambda, 2.0));
}