c++ - 使用 FFTW 进行实时脉冲响应卷积——结果听起来 IR 是对称的

标签 c++ audio signal-processing convolution fftw

出于研究目的,我正在使用 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/

相关文章:

python - 平滑框过滤器的内核大小

python - 确定振荡信号上的事件位置

c++ - 在模板类中初始化静态 std::map 成员?

c++ - 使用 delete [] 运算符取消分配类中数据成员的内存

c++ - 为什么编译器不会拒绝以加法运算符开头的行?

c++ - 为什么使用引用限定符 & 声明删除的赋值运算符

c++ - 如何获取WAV文件的音量级别?

javascript - 有没有更好的方法将音频与视频同步(不只是将其放入视频本身)?

c++ - 当迭代器是类成员时,为什么在C++中for循环变慢

c# - 使用卷积在连续的声音流中找到引用音频样本