双二阶滤波器之MATLAB设计及C语言实现

参考:
双二阶滤波器

本文中的例子和代码放在Github

First,什么是双二阶滤波器?wiki上是这么说的:二阶、递归、线性,含有两个极点和两个零点,“双二阶”的名字来源于它的传递函数是两个二次多项式的比值。

In signal processing, a digital biquad filter is a second order recursive linear filter, containing two poles and two zeros. “Biquad” is an abbreviation of “biquadratic”, which refers to the fact that in the Z domain, its transfer function is the ratio of two quadratic functions: H(z)=(b₀+b₁z⁻¹+b₂z⁻²)/(a₀+a₁z⁻¹+a₂z⁻²) The coefficients are often normalized such that a₀ = 1: H(z)=(b₀+b₁z⁻¹+b₂z⁻²)/(1+a₁z⁻¹+a₂z⁻²) High-order IIR filters can be highly sensitive to quantization of their coefficients, and can easily become unstable.

归一化传递函数写成这样:
H ( z ) = b ₀ + b ₁ z ⁻ ¹ + b ₂ z ⁻ ² 1 + a ₁ z ⁻ ¹ + a ₂ z ⁻ ² H(z)= \frac{b₀+b₁z⁻¹+b₂z⁻²}{1+a₁z⁻¹+a₂z⁻²} H(z)=1+az¹+az²b+bz¹+bz²

用MATLAB的Filter Designer来设计一个:400Hz带通IIR,需要用4个Sections来实现,默认给出的滤波器结构是Direct-Form II。
在这里插入图片描述
在菜单栏的Analysis中选择Filter Coeffients就能看到滤波器系数了:
在这里插入图片描述
Numerator,分子,也就是传递函数中的b项们,从上到下依次为 b 0 b_0 b0 b 1 b_1 b1 b 2 b_2 b2
Denominator,分母,也就是传递函数中的a项,从上到下依次为 a 0 a_0 a0 a 1 a_1 a1 a 2 a_2 a2,其中 a 0 a_0 a0总是为1。
Gain,增益。

用数组来存放滤波器系数:

//8-order IIR filter with 4 sections
const int sections = 4;

//nominator
const float b[4][3] = {
	{ 1, -1.984454421, 1 },
	{ 1, -1.999405318, 1 },
	{ 1, -1.993167556, 1 },
	{ 1, -1.998644244, 1 }
};

//denominator
const float a[4][3] = {
	{ 1, -1.984532740, 0.9884094716 },
	{ 1, -1.988571923, 0.9909378613 },
	{ 1, -1.991214225, 0.9962624248 },
	{ 1, -1.995917854, 0.9977478940 }
};

const float gain[4] = { 0.583805364, 0.583805364, 0.170388576, 0.170388576 };

以Direct-Form II为例来写个实现代码,计算过程是:
y [ n ] = b 0 w [ n ] + b 1 w [ n − 1 ] + b 2 w [ n − 2 ] y[n]=b_{0}w[n]+b_{1}w[n-1]+b_{2}w[n-2] y[n]=b0w[n]+b1w[n1]+b2w[n2]
其中 w [ n ] = x [ n ] − a 1 w [ n − 1 ] − a 2 w [ n − 2 ] w[n]=x[n]-a_{1}w[n-1]-a_{2}w[n-2] w[n]=x[n]a1w[n1]a2w[n2]
代码如下:
用一个数组来存放滤波器的中间状态量 w [ n − 1 ] w[n-1] w[n1] w [ n − 2 ] w[n-2] w[n2]

float w[sections][2]; //filter states

在滤波计算之前,初始化滤波器:

for (int i = 0; i < sections; i++) {
		w[i][0] = 0; //w[n-1]
		w[i][1] = 0; //w[n-2]
}

正式开始计算:pcmIn[i]是原始的输入信号,输入section 1,section 1的输出则作为section 2的输入,以此类推,由于这个滤波器由4个sections构成,因此要循环4次。
注意输出要乘gain。

y[0] = pcmIn[i];
		for (j = 0; j < sections; j++) {
			tmp[j] = y[j] - a[j][1] * w[j][0] - a[j][2] * w[j][1]; //calculate w[n]
			y[j+1] = tmp[j] + b[j][1] * w[j][0] + b[j][2] * w[j][1]; //calculate the j-th section filter output y[n]
			w[j][1] = w[j][0]; //move w[n-1] -> w[n-2]
			w[j][0] = tmp[j]; //move w[n] -> w[n-1]
			y[j+1] = gain[j] * y[j+1]; //multiply with gain
		}
			
out = y[j];

如果需要得到例如PCM16的输出,那么再对out进行限幅,that’s all.

  • 6
    点赞
  • 42
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值