使用 Scilab 设计半带 FIR 滤波器

信息处理 声音的 插值 有限脉冲响应
2022-02-06 06:29:16

我正在尝试使用 Scilab 的eqfir函数设计一个半带插值滤波器,该函数在内部使用 Remez 算法:

hn = eqfir(N, [0 .23; .27 .5], [1 0], [1 1]);

尽管过渡带在 0.25 左右对称,但它并没有给我一个真正的半带响应,奇数系数为零。也许我应该直接使用remezbremez函数,但我不完全理解它们输入参数的含义。

根据互联网上的一些来源(我无法证明),被混淆地称为remez的等效 MATLAB 函数给出了完美的结果。

2个回答

在商业滤波器设计软件中,当设计奇抽头半带滤波器时,您的中心系数(最大值系数)的值为 0.5。因此,如果您的滤波器系数之一的值为 0.000002,则与最大系数相比,该系数的值是 250,000 的一部分。该超小值系数对滤波器的频率响应的影响可以忽略不计,因此可以将其值设置为零。

在 MATLAB 中,尝试以下操作之一:

hn = remez(26, 2*[0 .23 .27 .5], [1 1 0 0], [1 1])
hn = firpm(26, 2*[0 .23 .27 .5], [1 1 0 0], [1 1])

(注意 '2*' 乘数需要符合 MATLAB 的命令语法!)检查系数的值,发现没有一个是完全零值的。现在绘制滤波器的频率响应(以 dB 为单位的垂直轴)。接下来,使用以下方法将绝对值小于 0.001 的所有系数清零:

hn = hn.*(abs(hn)>0.001)

并绘制新的频率响应(以 dB 为单位)。注意两个频率响应本质上是相同的。

正如理查德莱昂斯回答中正确指出的那样,大多数实现都会出现一些小的数值错误。

减少这些数值误差(并完全避免奇数系数的误差)的方法是使用本文中记录的技巧来有效地计算半带滤波器的系数。总结这篇论文,一个半带滤波器N=4m1系数可以从一个全频带滤波器设计产生2m系数g(n)使用关系:

h(n)={0.5g(n2)neven0nodd,nN120.5n=N12
请注意,奇数系数(或基于 1 的索引中的偶数系数)将通过构造为 0。

按照参考论文,半带滤波器必须具有奇数个系数N(然后必须是形式N=4m±1, 对于某个正整数m)。此外,过滤器N=4m+1系数可以简化为一个滤波器,只有N=4m1通过消除第一个和最后一个索引处产生的零系数来获得系数。因此,我们只需要专注于过滤器的设计N=4m1系数(即滤波器的顺序4m),这可以通过以下 Matlab 脚本来实现:

if (0 == rem(N,2))
  disp("Number of coefficients needs to be odd (even order)");
else
  M = floor((N+1)/4);
  K = 2*M;
  % design full-band filter
  g = firpm(K-1, 4*[0 .23], [1 1], [1]);

  % convert to half-band filter
  offset = 0;
  if (1 == rem(N,4))
    disp("Warning: tail coefficients will be zero (effective order reduced by 2)");
    offset = 1;
  end
  hn = zeros(1,N);
  hn((1+offset):2:(K-1+offset)) = 0.5*g(1:M);
  hn(K+offset)                  = 0.5;
  hn((K+1+offset):2:N)          = 0.5*g(M+1:K);
end

最后对于 Scilab,您应该能够通过将firpm调用替换为

g = eqfir(K, 2*[0 .23], [1], [1]);