IIR 到 FIR,通常需要最佳拟合多项式吗?

信息处理 过滤器 多项式
2022-02-14 01:10:42

我在搞乱 IIR/FIR 滤波器,想将前者转换为后者。

我建立了一个经典的脉冲响应计算。

        X[4] = 1.0

        Y[0] = 0.0
        Y[1] = 0.0

        对于范围内的n(2,L):
          Y[n] = 0.5 * X[n] + 0.3 * X[n-1] + 0.2 * Y[n-1] + 0.1 * Y[n-2]

并且(向 Dan B 和 Matt L 大喊)使用 scipy “lfilter” 和 “dimpulse” 函数。当使用零的初始值时,它们匹配。

        Y2 = sig.lfilter( [ 0.5 , 0.3 ], [ 1, -0.2, -0.1], X )
        T3, Y3 = sig.dimpulse( ( [ 0.5 , 0.3 ], [ 1, -0.2, -0.1], 1 ) )
        
        对于范围内的n(20):
          打印(“%4d %10.5f %10.5f %10.5f”%\
                 (n, Y3[0][n].real, Y2[n].real, Y[n].real))

这是价值观。

   0 0.00000 0.00000 0.00000
   1 0.50000 0.00000 0.00000
   2 0.40000 0.00000 0.00000
   3 0.13000 0.00000 0.00000
   4 0.06600 0.50000 0.50000
   5 0.02620 0.40000 0.40000
   6 0.01184 0.13000 0.13000
   7 0.00499 0.06600 0.06600
   8 0.00218 0.02620 0.02620
   9 0.00094 0.01184 0.01184
  10 0.00041 0.00499 0.00499
  11 0.00017 0.00218 0.00218
  12 0.00008 0.00094 0.00094
  13 0.00003 0.00041 0.00041
  14 0.00001 0.00017 0.00017
  15 0.00001 0.00008 0.00008
  16 0.00000 0.00003 0.00003
  17 0.00000 0.00001 0.00001
  18 0.00000 0.00001 0.00001
  19 0.00000 0.00000 0.00000

直接获得 FIR 系数的明显方法是进行多项式除法。

H(z)=B(z)A(z)=b0+b1z+b2z2...1+a1z+a2z2....=h[0]+h[1]z+h[2]z2....

所以我做了一些搜索并找到了numpy.polydiv( B, A ),但很失望它没有按照我想要的方式工作。它停在“整数”而不是“计算小数部分”。

我写了一个例程来做到这一点(包括在这里是为了其他人的利益)。

将 numpy 导入为 np

#=================================================== ==============================
定义主():

        B = np.array( [ 0.5 , 0.3 ] )
        
        A = np.array( [ 1, -0.2, -0.1] )
        
        打印(乙)
        打印(一)
        
        Q, R = 除法多项式(B, A, 15)
        
        打印(问)
        打印(R)

#=================================================== ==============================
def DividePolynomials(ArgNum,ArgDen,ArgLength):

        Q = np.zeros(ArgLength * 2, dtype=complex)  
        R = np.zeros(ArgLength * 2,dtype=complex)  
        S = np.zeros(ArgLength * 2, dtype=complex)  
        
        R[0:len(ArgNum)] = ArgNum
        
        对于范围内的 d(ArgLength):
          rd = R[d] / ArgDen[0]
          
          Q[d] = rd
          
          S.fill(0.0)
          
          S[d:d+len(ArgDen)] = rd * ArgDen
          
          R -= S

        返回 Q[0:ArgLength], R[ArgLength:]

#=================================================== ==============================
主要的()

这是输出:

[ 0.5 0.3]
[ 1. -0.2 -0.1]
[ 5.00000000e-01+0.j 4.00000000e-01+0.j 1.30000000e-01+0.j
   6.60000000e-02+0.j 2.62000000e-02+0.j 1.18400000e-02+0.j
   4.98800000e-03+0.j 2.18160000e-03+0.j 9.35120000e-04+0.j
   4.05184000e-04+0.j 1.74548800e-04+0.j 7.54281600e-05+0​​.j
   3.25405120e-05+0​​.j 1.40509184e-05+0​​.j 6.06423488e-06+0.j]
[ 2.61793882e-06+0.j 6.06423488e-07+0.j 0.00000000e+00+0.j
   0.00000000e+00+0.j 0.00000000e+00+0.j 0.00000000e+00+0.j
   0.00000000e+00+0.j 0.00000000e+00+0.j 0.00000000e+00+0.j
   0.00000000e+00+0.j 0.00000000e+00+0.j 0.00000000e+00+0.j
   0.00000000e+00+0.j 0.00000000e+00+0.j 0.00000000e+00+0.j]

系数与来自脉冲分析的预期值很好地匹配,其余的让我了解它的收敛程度。

当然,我做了一些搜索,发现了这个:

有没有办法使用 IIR 滤波器导出 FIR 滤波器?

在链接的问题中,选择的答案涉及曲线拟合,其他答案与我的预期一致。但是,添加您希望保持过滤器阶数较低的条件,当然可以比截断的多项式更好地拟合多项式H(z). 我没有遵循论文参考。IEEE 论文通常在一些付费墙后面。但我认为这与我们在这里遇到的相同的数学问题“什么是最适合的多项式”sin(x)ab" 与商B(z)/A(z)扮演泰勒级数的角色。

  • 问题 1:我在 numpy/scipy 中是否有一个多项式除法函数可以满足我的要求。[已解决:见 Olli 的回答]

  • 问题 2:在“现实生活”中,典型 IIR 到 FIR 转换的典型 FIR 长度是多少,这个额外的多项式拟合步骤通常需要/有益吗?

我意识到在我的示例中,我正在处理一个很小的、表现良好的 IIR。

3个回答

问题 2:在“现实生活”中,典型 IIR 到 FIR 转换的典型 FIR 长度是多少,这个额外的多项式拟合步骤通常需要/有益吗?

这在很大程度上取决于您的 IIR 滤波器的功能。在我的树林里(音频),答案通常是“几千”。

这实际上取决于“频率”分辨率。“有趣”的事情发生的频率是多少?这是一个简单的例子:假设您有一个 40 Hz 的 3 阶黄油价值高通,以 44.1kHz 采样。将两者相除得到 1000,这是在球场上。结果 1024 非常糟糕,2048 是“好的”,而 4096 是“好”。

更正式地说:这真的取决于你的杆子的位置。频率越低,Q 值越高,您需要的 FIR 系数就越多。

我认为多项式除法在这里没有多大帮助。您要么需要截断 IIR 脉冲响应(在尾端可能有一些窗口/篡改),要么对传递函数进行直接 FIR 拟合,您可以在其中使用错误标准。尝试匹配特定的 IIR 响应可能没有用:去掉“中间人”并直接根据要求设计 FIR 滤波器

polydiv如果您首先使用零填充,您仍然可以使用 NumPy B在 Python 中,在numpy导入AB初始化之后:

print(np.polydiv(np.pad(B, (0, 10)), A)[0])

在较旧的 NumPy 版本中,numpy.pad需要一个额外的参数mode='constant',自 NumPy 1.17 起该参数成为默认值。运行上面的代码会打印出一系列与你通过其他方式得到的数字相同的数字:

[5.00000e-01 4.00000e-01 1.30000e-01 6.60000e-02 2.62000e-02
 1.18400e-02 4.98800e-03 2.18160e-03 9.35120e-04 4.05184e-04]

我不确定您为什么要尝试使用 FIR 来近似 IIR,但一种有效的方法是使用截断 IIR 滤波器

可能值得探索。