快速卷积算法

时间:2011-05-18 09:54:10

标签: delphi filter signal-processing convolution

我需要对两个一维信号进行卷积,一个平均有500个点(这一个是Hanning窗口函数),另一个是125000.每次运行,我需要应用三次卷积运算。我已经有一个基于scipy文档运行的实现。如果你愿意,你可以在这里看到代码(Delphi代码提前):

function Convolve(const signal_1, signal_2 : ExtArray) : ExtArray;
var
  capital_k : Integer;
  capital_m : Integer;
  smallest : Integer;
  y : ExtArray;
  n : Integer;
  k : Integer;
  lower, upper : Integer;
begin
  capital_k := Length(signal_1) + Length(signal_2) - 1;
  capital_m := Math.Max(Length(signal_1), Length(signal_2));
  smallest := Math.Min(Length(signal_1), Length(signal_2));
  SetLength(y, capital_k);
  for n := 0 to Length(y) - 1 do begin
    y[n] := 0;
    lower := Math.Max(n - capital_m, 0);
    upper := Math.Min(n, capital_k);
    for k := lower to upper do begin
      if (k >= Length(signal_1)) or (n - k >= Length(signal_2)) then
        Continue;
      y[n] := y[n] + signal_1[k] * signal_2[n - k];
    end;
  end;
  Result := Slice(y,
                  Floor(smallest / 2) - 1,
                  Floor(smallest / 2) - 1 + capital_m);
end;

问题是,这个实现太慢了。整个过程大约需要五分钟。我想知道我是否能找到更快的计算方法。

2 个答案:

答案 0 :(得分:5)

那里有很多快速卷积算法。他们中的大多数使用FFT例程,如FFTW。这是因为像卷积(在时域中)的操作减少到频域中的(频域表示的)乘法。一旦使用FFT例程实现卷积,目前大约需要5分钟(根据您自己的估计)的卷积操作可能只需几秒钟。

此外,如果过滤器的长度与信号长度之间存在很大差异,您可能还需要考虑使用重叠保存或重叠添加。更多信息here。如果Delphi中的编码不是最重要的问题,那么你可能想要使用C / C ++,只是因为FFTW和其他一些库在C / C ++中可用(不确定scipy或Delphi)。

答案 1 :(得分:3)

Fast convolution可以使用FFT执行。对两个输入信号进行FFT(具有适当的零填充),在频域中相乘,然后进行逆FFT。对于大N(通常N> 100),这比直接方法快。