我正在尝试在oder中实现重叠和添加方法,以在实时上下文中应用过滤器。但是,似乎有一些我做错了,因为结果输出的误差比我预期的要大。为了比较我的计算的准确性,我创建了一个文件,我在一个块中处理。我将此与重叠和添加过程的输出进行比较,并将得到的比较作为计算准确性的指标。所以这是我重叠的过程并添加:
该程序有什么问题吗?在阅读了很多不同的论文和书籍之后,我已经非常不确定哪种方法可以解决这个问题。
以下是我运行的测试中的更多数据:
我创建了一个由三个余弦波组成的信号
我在时域中使用此过滤器功能进行过滤。 (它是对称的,因为它应用于FFT的整个输出,对于实际输入信号也是对称的)
IFFT的输出如下所示:可以看出,低频在中频范围内衰减的频率高于频率。
对于重叠添加/保存和窗口化处理,我将输入信号分成8个256个样本的块。重新组装后,它们就像那样。 (样本490 - 540)
输出信号重叠并添加:
输出信号重叠并保存:
使用带Hanning窗口的STFT输出信号:
可以看出,重叠添加/保存过程与块放在一起的点处的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我的过滤器。这看起来像这样:
将后半部分设为零:
对信号进行FFT,并将幅度与旧滤波器(蓝色)进行比较:
尝试重叠并添加此过滤器后,结果显然变得更糟而不是更好。为了确保我的FFT正常工作,我尝试IFFT和FFT滤波器而不设置后半部分零。结果与原始滤波器相同。所以问题不应该是FFT。我想这是对重叠和添加方法的一些一般性理解。但我仍然无法弄清楚出了什么问题......
答案 0 :(得分:2)
要检查的一件事是过滤器的脉冲响应的长度。它必须短于快速卷积FFT之前使用的零填充长度,否则您将得到环绕错误。
答案 1 :(得分:0)
我认为问题可能出在您使用的窗口方法中。您只需在块上添加零,就不会出现实际重叠。在重叠和添加方法中,您需要润湿窗口的边缘。这意味着在向块添加零的情况下,您添加了加权输入信号,并且由于只有两个窗口重叠,因此您的情况下的权重应该为0.5。
其余步骤似乎还可以。然后,您只需进行FT,乘以和进行逆FTS,最后将所有块加起来即可得到最终信号,如果您一次过滤了整个信号,则该信号应该完全相同。