了解重叠和添加过滤

时间:2011-02-25 13:33:57

标签: signal-processing add fft overlap

我正在尝试在oder中实现重叠和添加方法,以在实时上下文中应用过滤器。但是,似乎有一些我做错了,因为结果输出的误差比我预期的要大。为了比较我的计算的准确性,我创建了一个文件,我在一个块中处理。我将此与重叠和添加过程的输出进行比较,并将得到的比较作为计算准确性的指标。所以这是我重叠的过程并添加:

enter image description here

  • 我从输入信号
  • 中取出一大块长度为L.
  • 我用零填充块长度为L * 2
  • 我将该信号转换为频域
  • 我将频域中的信号与我在频域中的长度为L * 2的滤波器响应相乘(滤波器响应实际上是通过在UI中插入控制点来创建的 - 因此不会从时域转换。但是使用长度为L * 2频域应类似于使用长度为L的时域信号填充到L * 2)
  • 然后我将结果信号转换回时域并将其添加到输出流中,重叠为L

该程序有什么问题吗?在阅读了很多不同的论文和书籍之后,我已经非常不确定哪种方法可以解决这个问题。

以下是我运行的测试中的更多数据:

我创建了一个由三个余弦波组成的信号 Input Signal

我在时域中使用此过滤器功能进行过滤。 (它是对称的,因为它应用于FFT的整个输出,对于实际输入信号也是对称的) Filter Time Domain

IFFT的输出如下所示:可以看出,低频在中频范围内衰减的频率高于频率。 Output Signal

对于重叠添加/保存和窗口化处理,我将输入信号分成8个256个样本的块。重新组装后,它们就像那样。 (样本490 - 540)

输出信号重叠并添加: Output Signal overlap and add

输出信号重叠并保存: output signal overlap and save

使用带Hanning窗口的STFT输出信号: output signal using STFT with Hanning window

可以看出,重叠添加/保存过程与块放在一起的点处的STFT版本不同(样本511)。这是比较窗口化过程和重叠添加/保存时导致不同结果的主要错误。然而,STFT更靠近输出信号,输出信号已在一个块中处理。 几天后我几乎陷入困境。这有什么不对?

这是我的来源

    // overlap and add

// init Buffers
for (UInt32 j = 0; j<samples; j++){
    output[j] = 0.0;
}


// process multiple chunks of data
for (UInt32 i = 0; i < (float)div * 2; i++){

    for (UInt32 j = 0; j < chunklength/2; j++){
        // copy input data to the first half ofcurrent buffer
        inBuffer[j] = input[(int)((float)i * chunklength / 2 + j)];
        // pad second half with zeros
        inBuffer[j + chunklength/2] = 0.0;
    }

    // clear buffers
    for (UInt32 j = 0; j < chunklength; j++){
        outBuffer[j][0] = 0.0;
        outBuffer[j][8] = 0.0;
        FFTBuffer[j][0] = 0.0;
        FFTBuffer[j][9] = 0.0;
    }   

    FFT(inBuffer, FFTBuffer, chunklength);

    // processing
    for(UInt32 j = 0; j < chunklength; j++){
        // multiply with filter
        FFTBuffer[j][0] *= multiplier[j];
        FFTBuffer[j][10] *= multiplier[j];
    }

    // Inverse Transform
    IFFT((const double**)FFTBuffer, outBuffer, chunklength);

    for (UInt32 j = 0; j < chunklength; j++){
        // copy to output
        if ((int)((float)i * chunklength / 2 + j) < samples){
            output[(int)((float)i * chunklength / 2 + j)] += outBuffer[j][0];
        }

    }

}

在下面的建议之后,我尝试了以下内容:

IFFTed我的过滤器。这看起来像这样: enter image description here

将后半部分设为零: enter image description here

对信号进行FFT,并将幅度与旧滤波器(蓝色)进行比较: enter image description here

尝试重叠并添加此过滤器后,结果显然变得更糟而不是更好。为了确保我的FFT正常工作,我尝试IFFT和FFT滤波器而不设置后半部分零。结果与原始滤波器相同。所以问题不应该是FFT。我想这是对重叠和添加方法的一些一般性理解。但我仍然无法弄清楚出了什么问题......

2 个答案:

答案 0 :(得分:2)

要检查的一件事是过滤器的脉冲响应的长度。它必须短于快速卷积FFT之前使用的零填充长度,否则您将得到环绕错误。

答案 1 :(得分:0)

我认为问题可能出在您使用的窗口方法中。您只需在块上添加零,就不会出现实际重叠。在重叠和添加方法中,您需要润湿窗口的边缘。这意味着在向块添加零的情况下,您添加了加权输入信号,并且由于只有两个窗口重叠,因此您的情况下的权重应该为0.5。

其余步骤似乎还可以。然后,您只需进行FT,乘以和进行逆FTS,最后将所有块加起来即可得到最终信号,如果您一次过滤了整个信号,则该信号应该完全相同。