出于研究目的,我正在使用FFTW(以及用于声音传递的PortAudio)在C ++中构建实时混响卷积引擎,并使用重叠加法进行卷积。其中大部分都在起作用,但会产生一种非常奇特的效果。虽然我不明白为什么,但听起来好像脉冲响应变得对称:h[n]
变为h[n] + h[-n]
。有谁知道以下我描述的方式执行FFT会产生这种影响吗?
基本上,我的流程如下:
h
,脉冲响应m
长样本x
,声音n
长样本FFT_SIZE
,分区大小/窗口大小 n > m
因子为3,但FFT_SIZE
要小得多(目前为1024)
我将x
分成FFT_SIZE
长度的部分。因为我将使用h
对每个窗口进行卷积,所以我将每个窗口复制到长度为n+m - 1
个样本的0填充缓冲区中,并执行正向FFT,从而保存生成的复杂数组。 (我有n/FFT_SIZE
个复杂的数组。)现在我使用没有重叠的矩形窗口,如果我在解决这个问题后改进了东西就会实现Hamming。
我还在0-padding到h
之后执行n+m - 1
的单个正向FFT,并存储与其他相同大小的单个复数数组。
PortAudio像大多数音频引擎一样调用回调来定期填充带有声音数据的缓冲区out
。在我的回调中(通过设计请求FFT_SIZE
音频样本,我每次都选择表示下一个窗口的复杂数组(因为一个回调调用对应于与FFT的一个窗口相同的声音长度)。
我使用FFT-ing h
进行逐点乘法运算,然后执行IFFT。产生的声音缓冲区长n+m-1
,比FFT_SIZE
大得多,因此我只将开头复制到out
缓冲区,并将其余部分添加到重叠/进位缓冲区(累积混响尾音)在将进位缓冲区的开头移动到out
之后(每次回调调用)(因此out
现在包含一个窗口的新IFFT数据添加到一个窗口'值得先前计算的衰变尾部。)
就像我之前提到的那样,听起来好像脉冲响应不是正确的FFT,并且导致行为就好像是对称的 - 反转然后添加到自身。我不确定我做错了什么,但是我无法看到我的携带问题是如何产生这种效果的 - 虽然我是,但我很高兴发现了这个错误!
我最好的猜测是,我应该以{{1}}的方式进行窗口化。但是,根据我读过的文献,您只需将h
的每个窗口与整个x
进行卷积并执行进位。这可能是错的吗?
感谢您的帮助!
答案 0 :(得分:2)
当逐点乘以2个FFT向量时,算术似乎是错误的。复矢量乘法必须考虑实部和虚部之间的叉积。例如re = re1 * re2 - im1 * im2; im = re1 * im2 + re2 * im1等。