我正在尝试实现8阶IIR滤波器,我阅读的每个应用笔记和教科书都说,最好将2阶以上的任何滤波器实现为二阶部分。我在MATLAB中使用了tf2sos来获取二阶部分的系数,这与我预期的4个二阶部分的6x4系数有关。
在实施为SOS之前,8阶滤波器需要存储7个先前的采样值(以及输出值)。现在,当实现为二阶部分时,流程如何从输入到输出工作,我是否只需要存储2个先前的样本值?还是第一个过滤器的输出作为x_in馈入第二个过滤器,依此类推?

评论

您需要为每个阶段存储以前的状态,具体取决于该阶段中过滤器的顺序,因此它不会像您提到的那样只是2

#1 楼

这是您说的最后一句话(“还是第一个过滤器的输出作为x_in馈入第二个过滤器,依此类推?”)。这个想法很简单:您将双二阶视为级联的独立二阶滤波器。第一个滤波器的输出是第二个滤波器的输入,依此类推,因此延迟线分布在各个滤波器之间。如果您需要在内存受限的环境中优化结构,则可以注意到相邻的二元模型具有冗余延迟存储器(即,阶段1的最后几个输出样本与阶段2的最后几个输入样本相同,因此您不必不必像单独隔离过滤器那样单独存储它们。

评论


$ \ begingroup $
谢谢!我只是设法在MATLAB中快速做到这一点。早先造成混乱的原因是我忘了增加收益(ugh!),因此各种各样的想法开始蔓延。
$ \ endgroup $
–anasimtiaz
2011-09-12 14:20

$ \ begingroup $
如果您不费吹灰之力从tf2sos请求增益作为输出arg(就像在我发布的示例代码中一样),那么您就不必费心将其再次乘回。
$ \ endgroup $
–learnvst
2012-2-24在17:55

#2 楼

实际上,有两种方法可以实现二阶部分:并行和串行。在串行版本中,第N部分的输出是第N + 1部分的输入。在并行版本中,所有部分都具有相同的输入(并且只有一个实零而不是共轭复数零对),并且每个部分的输出都被简单地求和。
这两种方法是通过对Z域传递函数。警告:这是一个数值棘手的问题,对于极点靠近单位圆的典型音频滤波器,标准的Matlab实现“ residuez”可能会产生很大的数值误差。

#3 楼

这里有一些演示代码,以说明为什么更好地级联二阶部分。

clc

sr = 44100;
order = 13;

[b,a] = butter(order,1000/(sr/2),'low');
[sos] = tf2sos(b,a);

x = [1; zeros(299,1)]; %impulse


% all in one
Y = filter(b,a,x);

% cascaded biquads
Z = x;
for nn = 1:size(sos,1);
    Z = filter(sos(nn,1:3),sos(nn,4:6), Z );
end


cla; plot(Y, 'k'); hold on; plot(Z,':r'); hold off


对于上面示例中给出的低通滤波器,大约12到13的数量级,会增加数值误差,从而给出明显不同的脉冲响应。不使用级联二元组的实现。

ORDER = 10



ORDER = 13



评论


$ \ begingroup $
@learvst如果我错了,请纠正我,但是您的代码却错过了收获。不应该是:[sos gain] = tf2sos(b,a); // nn = 1的其余代码:size(sos,1); Z = filter(sos(nn,1:3),sos(nn,4:6),Z);结束Z = filter(gain,1,Z);
$ \ endgroup $
–user915783
2015年3月30日23:44