Answers:
使用卷积,您不会遇到任何稳定性问题,因为没有递归过滤,因此您不会累积任何错误。换句话说,系统全为零,没有极点。我曾经听说过,但未经我自己证实,基于FFT的卷积比时域卷积具有更低的误差,仅因为它具有O(n log n)个算术运算而不是O(n ^ 2)。
据我所知,通常,巴特沃思过滤器被实现为递归(IIR)过滤器,因此这是一个不同的主题。IIR滤波器具有极点和零点,因此实际上可能存在稳定性问题。同样,对于IIR滤波器,不是基于FFT的方法,但是从好的方面来说,IIR滤波器的阶数往往很低。
至于IIR滤波器的稳定性问题,它们往往在高阶时会出现问题-我将抛出一个数字,说大约是6阶正推动它。取而代之的是,它们通常被实现为级联双二阶(二阶滤波器部分)。对于您的5阶滤波器,将其写为z域传递函数(它将是5阶有理函数),然后将其分解为5个极点和5个零点。收集复共轭,您将拥有两个二阶和一个一阶滤波器。通常,随着磁极接近单位圆,稳定性问题趋于加剧。
IIR滤波器中也可能存在噪声和极限周期的问题,因此存在具有不同数值属性的不同滤波器拓扑(即直接形式I,直接形式II),但我不会考虑这一点-只需使用double-精度,几乎可以肯定是足够了。
y(n) = b0 * x(n) + b1 * x(n-1) + b2 * x(n-2) - a1 * y(n-1) - a2 * y(n-2)
。请注意,这是先前输入样本(x值)和先前输出样本(y值)的组合。FIR滤波器仅取决于过去的输入,因此可以接受高效的频域实现。IIR滤波器不是,但是无论如何还是非常有效的,因为IIR滤波器往往要低很多。
在几乎所有情况下,您的最佳选择既不是卷积也不是FFT,而只是直接应用IIR滤波器(例如使用sosfilt()函数)。就CPU和内存消耗而言,这将大大提高效率。
是否产生数值差异取决于特定的滤波器。如果极点非常非常靠近单位圆,则可能会出现一些差异。即使有一些技巧也可以提供帮助。请勿使用传递函数表示形式和filter(),而应将极点和零与sosfilt()一起使用。这是区别的一个例子。
n = 2^16; % filter length
fs = 44100; % sample rate
x = zeros(n,1); x(1) = 1;
f0 = 15; % cutoff frequency in Hz
% design with poles and zeroes
[z,p,k] = butter(5,f0*2/fs);
clf
plot(sosfilt(zp2sos(z,p,k),x));
% design with transfer function
[b,a] = butter(5,f0*2/fs);
hold on
plot(filter(b,a,x),'k');
filter()在44.1kHz处约15Hz的截止频率时变坏。对于sosfilt(),截止频率可以远低于1/100 Hz @ 44.1kHz,没有任何问题。
如果您遇到稳定性问题,FFT也无济于事。由于您的滤波器是IIR滤波器,因此脉冲响应是无限的,因此必须先将其截断。在这些非常低的频率下,脉冲响应变得很长,以至于FFT也变得不切实际。
例如,如果您想要在44.1 kHz处的1/100 Hz截止频率,并且想要100 dB的脉冲响应中的动态范围,则大约需要2500万个采样!在44.1 kHz的频率下将近10分钟,比原始信号长很多倍
filter
-谢谢!我的高通截止频率为0.5 Hz @ 250 Hz。出现问题的原因是什么filter
?我自己编写实现。
您为什么认为情况会有所不同?理论概念应转化为实际应用,唯一的区别是浮点问题,这是我们无法避免的。您可以使用MATLAB中的一个简单示例轻松进行验证:
x=randn(5,1);
y=randn(5,1);
X=fft(x,length(x)+length(y)-1);
Y=fft(y,length(x)+length(y)-1);
z1=conv(x,y);z2=ifft(X.*Y);
z1-z2
ans =
1.0e-15 *
-0.4441
-0.6661
0
-0.2220
0.8882
-0.2220
0
-0.4441
0.8882
如您所见,误差大约是机器精度的。应该没有任何理由不使用FFT方法。正如Endolith所提到的,使用FFT方法进行滤波/卷积/互相关等操作更为普遍,除了非常小的样本(如本例中所示)外,它的速度要快得多。并不是说时域处理永远不会完成……它全都归结为应用程序,需求和约束。