出于研究目的,我正在使用 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 填充到长度 n+m - 1
之后对 h
执行单个前向 FFT,并存储这个与其他大小相同的单个复杂数组.
在实时阶段
与大多数音频引擎一样,PortAudio 调用回调以定期用声音数据填充缓冲区 out
。在我的回调中(根据设计要求 FFT_SIZE
音频样本,我每次都选择代表下一个窗口的复杂数组(因为一个回调调用对应于与 FFT 的一个窗口相同的声音长度)。
我将该数组与我通过 FFT-ing h
生成的数组进行逐点乘法,然后执行 IFFT。生成的声音缓冲区是 n+m-1
长,比 FFT_SIZE
大得多,所以我只将开头复制到 out
缓冲区中并添加在将进位缓冲区的开头移动到 out
之后(因此 out
现在包含一个窗口的值(value)),休息到重叠/进位缓冲区(它在每次回调调用时累积混响尾音)添加到一个窗口的先前计算的衰变尾部的新 IFFT 数据)。
现在的关注点
就像我之前提到的,这听起来好像脉冲响应没有被正确地 FFT,并且导致表现得好像它是对称的 - 反转然后添加到自身。我不确定我做错了什么,但我看不出我的携带问题如何产生这种效果——但如果我是,我会很高兴找到这个错误!
我最好的猜测是我也应该以某种方式执行 h
的窗口化。但是,根据我读过的文献,您只需将 x
的每个窗口与整个 h
进行卷积并进行进位。也许这是错误的?
感谢您的帮助!
最佳答案
当逐点乘以 2 个 FFT vector 时,您的算法似乎是错误的。复 vector 乘法必须考虑实部和虚部之间的叉积。例如re = re1*re2 - im1*im2; im = re1*im2 + re2*im1 等
关于c++ - 使用 FFTW 进行实时脉冲响应卷积——结果听起来 IR 是对称的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34760137/