使用FFTW进行实时脉冲响应卷积 - 结果听起来像IR是对称的
Real-time impulse response convolution with FFTW -- result sounds like IR is symmetrical
出于研究目的,我正在使用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
复杂的数组。目前,我正在使用没有重叠的矩形窗口,如果在解决此问题后可以改善事情,将实施汉明。
此外,我在 0 填充长度 n+m - 1
后执行 h
的单个前向 FFT,并存储这个与其他数组大小相同的单个复数组。
在实时阶段
与大多数音频引擎一样,PortAudio 会调用回调以定期用声音数据填充缓冲区out
。在我的回调(根据设计请求FFT_SIZE
音频样本)中,我每次都选择表示下一个窗口的复杂数组(因为一个回调调用对应于与 FFT 的一个窗口相同的声音长度)。
执行这个数组与我通过 FFT-ing h
制作的数组逐点乘法,并执行 IFFT。生成的声音缓冲区n+m-1
长,比FFT_SIZE
大得多,因此我只将开头复制到out
缓冲区中,并将其余部分添加到重叠/进位缓冲区(每次回调调用都会累积混响尾音)在将进位缓冲区的开头移动到out
后(因此out
现在包含一个窗口的新 IFFT'd 数据添加到一个窗口的先前计算的衰减尾巴中)。
现在的担忧
就像我之前提到的,听起来脉冲响应在某种程度上没有被正确FFT,并导致它表现得好像它是对称的 - 颠倒然后添加到自身。我不确定我做错了什么,但我看不出我的携带问题是如何产生这种效果的——尽管如果我是,我很高兴发现了这个错误!
我最好的猜测是,不知何故我也应该对h
执行窗口化。然而,根据我读过的文献,你只是将每个x
窗口与整个h
卷入并做携带。这也许是错误的吗?
感谢您的帮助!
逐点乘以 2 个 FFT 向量时的算术似乎是错误的。复向量乘法必须考虑实部和虚部之间的叉积。例如,re = re1*re2 - im1*im2;im = re1*im2 + re2*im1 ,依此类推。
- 为什么"do while"循环不断退出,即使条件计算结果为 false?
- valgrind-hellgrind与泄漏检查的结果不同
- 用C++20 fmt限制结果的总大小
- 如何返回一个类的两个对象相加的结果
- std::vector的包装器,使数组的结构看起来像结构的数组
- 使用QProcess执行命令,并将结果存储在QStringList中
- 如果我std::dynamic_pointer_cast并且底层dynamic_cast的结果为null,那么返回的sh
- 在没有定义返回类型的函数中返回布尔值,并将结果保存在无错误的char编译中-为什么
- 我可以将一个用clang c++11编译的对象与另一个用c++17编译的对象链接起来吗
- 序列化,没有库的整数,得到奇怪的结果
- 使用取消引用的指针的多态性会产生意外的结果.为什么?
- 在更改for循环的第三部分后,未使用for循环结果
- 看起来is_nothrow_constructible_v()在MSVC中被破坏了,我错了吗
- 为什么MP3解码的输出听起来如此延迟?(使用FFMPEG mp3lame lib)
- 将已经采样的吉他弦更改为听起来有点被手阻尼的算法
- 使用FFTW进行实时脉冲响应卷积 - 结果听起来像IR是对称的
- 听起来没有在我的代码上播放
- 为什么我的除法结果看起来是错的
- 子字符串给出看似随机的结果,即使其参数看起来正确
- "vector" C++听起来很奇怪,因为我的母语不是英语吗?