使用向量实现FIR滤波器

时间:2017-04-22 10:52:58

标签: algorithm haskell signal-processing

我在Haskell中实现了FIR滤波器。我对FIR滤波器知之甚少,而且我的代码很大程度上基于现有的C#实现。因此,我觉得我的实现有太多的C#风格,并不像Haskell那样。我想知道是否有更惯用的Haskell方式来实现我的代码。理想情况下,我很幸运能够实现算法的高阶函数(map,filter,fold等)的组合。

我的Haskell代码如下所示:

var allPanels = $(".panel");
allPanels.hide(2000);
allPanels.stop().show();

此代码基于以下C#代码:

  applyFIR :: Vector Double -> Vector Double -> Vector Double
  applyFIR b x = generate (U.length x) help
      where
        help i = if i >= (U.length b - 1) then loop i (U.length b - 1) else 0
        loop yi bi = if bi < 0 then 0 else b !! bi * x !! (yi-bi) + loop yi (bi-1)
        vec !! i = unsafeIndex vec i -- Shorthand for unsafeIndex

正如您所看到的,它几乎是一个直接的副本。如何将我的实现转变为更像Haskell的实现呢?你有什么想法?我唯一能想到的就是使用public float[] RunFilter(double[] x) { int M = coeff.Length; int n = x.Length; //y[n]=b0x[n]+b1x[n-1]+....bmx[n-M] var y = new float[n]; for (int yi = 0; yi < n; yi++) { double t = 0.0f; for (int bi = M - 1; bi >= 0; bi--) { if (yi - bi < 0) continue; t += coeff[bi] * x[yi - bi]; } y[yi] = (float) t; } return y; }

我知道Vector.generate库有一个可用的实现。但它使用列表,对我的用例来说太慢了。此DSP实施比Vector中的实施快得多。

我也尝试使用DSP实现算法。它比Repa实施更快。结果如下:

Vector

1 个答案:

答案 0 :(得分:2)

首先,我不认为你的初始矢量代码是忠实的翻译 - 也就是说,我认为它不同意C#代码。例如,假设“x”和“b”(C#中的“b”为coeff)长度为3,并且所有值均为1.0。然后,对于y[0],C#代码将生成x[0] * coeff[0]1.0。 (对于continue

的所有其他值,它会点击bi

但是,使用您的Haskell代码,help 0会生成0.您的Repa版本似乎遇到了同样的问题。

让我们从一个更忠实的翻译开始:

applyFIR :: Vector Double -> Vector Double -> Vector Double
applyFIR b x = generate (U.length x) help
    where
      help i = loop i (min i $ U.length b - 1)
      loop yi bi = if bi < 0 then 0 else b !! bi * x !! (yi-bi) + loop yi (bi-1)
      vec !! i = unsafeIndex vec i -- Shorthand for unsafeIndex

现在,你基本上是在进行计算这样的计算,比如y[3]

  ... b[3]   |   b[2]   |   b[1]   |   b[0]
      x[0]   |   x[1]   |   x[2]   |   x[3]   |   x[4]   |   x[5]   | ....
           multiply
    b[3]*x[0]|b[2]*x[1] |b[1]*x[2] |b[0]*x[3] 
           sum
      y[3] = b[3]*x[0] + b[2]*x[1] + b[1]*x[2] + b[0]*x[3]

因此,考虑你正在做的事情的一种方法是“取b向量,反转它,并计算结果的点i,行b[0]向上{ {1}},将所有相应的x[i]x条目相乘,并计算总和“。

让我们这样做:

b