使用FFTW进行实时脉冲响应卷积——结果听起来好像IR是对称的 为了研究目的,我在C++中用FFTW(和PotoTudio用于声音传递)建立一个实时混响卷积引擎,用重叠叠加法进行卷积。它大部分都在工作,但出现了一种非常奇特的效果。虽然我不明白为什么,但听起来很像脉冲响应变得对称:原来的h[n]变成了h[n]+h[-n]。有人知道我在下面描述的方式执行FFT是否会产生这种效果吗
基本上,我的过程如下: 事先知道:使用FFTW进行实时脉冲响应卷积——结果听起来好像IR是对称的 为了研究目的,我在C++中用FFTW(和PotoTudio用于声音传递)建立一个实时混响卷积引擎,用重叠叠加法进行卷积。它大部分都在工作,但出现了一种非常奇特的效果。虽然我不明白为什么,但听起来很像脉冲响应变得对称:原来的h[n]变成了h[n]+h[-n]。有人知道我在下面描述的方式执行FFT是否会产生这种效果吗,c++,audio,signal-processing,convolution,fftw,C++,Audio,Signal Processing,Convolution,Fftw,基本上,我的过程如下: 事先知道: h,脉冲响应m采样长度 x,一个声音n样本很长 FFT\u SIZE,分区大小/窗口大小 n>m增加了3倍,但FFT\u大小要小得多(目前为1024) 音频启动前在脱机阶段完成的工作: 我将x分割成FFT\u大小长度的部分。因为我将用h卷积每个窗口,所以我将每个窗口复制到长度为n+m-1样本的0填充缓冲区中,并执行前向FFT,保存生成的复杂数组。(我有n/FFT\u SIZEcomplex数组。)现在我使用的是没有重叠的矩形窗口,如果我解决了这个问题,它能
,脉冲响应h
采样长度m
,一个声音x
样本很长n
,分区大小/窗口大小FFT\u SIZE
n>m
增加了3倍,但FFT\u大小
要小得多(目前为1024)
音频启动前在脱机阶段完成的工作:
我将x
分割成FFT\u大小
长度的部分。因为我将用h
卷积每个窗口,所以我将每个窗口复制到长度为n+m-1
样本的0填充缓冲区中,并执行前向FFT,保存生成的复杂数组。(我有n/FFT\u SIZE
complex数组。)现在我使用的是没有重叠的矩形窗口,如果我解决了这个问题,它能改善情况,我将实现Hamming
此外,在0-padding到长度n+m-1
之后,我执行h
的单个前向FFT,并存储与其他数组大小相同的单个复杂数组
在实时阶段
与大多数音频引擎一样,PortAudio会调用回调函数,定期用声音数据填充缓冲区out
。在我的回调中(通过设计请求FFT\u SIZE
音频样本,我每次都选择表示下一个窗口的复杂数组(因为一个回调调用与FFT的一个窗口对应相同的声音长度)
我将这个数组与我通过FFT ingh
生成的数组进行逐点乘法,并执行IFFT。得到的声音缓冲区长度为n+m-1
远大于FFT\u SIZE
,因此我只将开始部分复制到out
缓冲区,并将其余部分添加到重叠/进位缓冲区将进位缓冲区的开始移动到out
(因此out
现在包含一个窗口的新IFFT数据,添加到先前计算的一个窗口的衰减尾中)后(每次回调调用时累积混响尾音)
现在的担忧
就像我之前提到的,它听起来像是脉冲响应没有被正确地FFT,并且导致了它的行为,好像它是对称的——反转,然后添加到它本身。我不确定我做错了什么,但我不知道我的携带问题怎么会产生这种效果——尽管如果我是,我很高兴有了它还有虫子
我最好的猜测是,不知何故,我也应该执行h
的窗口设置。然而,根据我所阅读的文献,您只需将x
的每个窗口与整个h
进行卷积并进行进位。这可能是错误的吗
感谢您的帮助!当逐点乘以2个FFT向量时,您的算术似乎是错误的。复向量乘法必须考虑实部和虚部之间的叉积。例如re=re1*re2-im1*im2;im=re1*im2+re2*im1,等等。当逐点乘以2个FFT向量时,您的算术向量似乎是错误的。复向量乘法必须考虑实部和虚部之间的叉积。例如re=re1*re2-im1*im2;im=re1*im2+re2*im1等。记住,你也可以在傅里叶域中分析你的问题。如果脉冲响应似乎是
h[n]+h[-n]
在时域中,它是H(f)+H(-f)
在频域中也是如此。加窗不会表现出类似的行为,也不会修复它。你将pad h归零到匹配的长度;现在,h是实值的,如果我理解正确的话;因此,你可能正在使用FFTW的real2complex变换之一?你确定你使用的是完整的对称DFT,而不是仅仅一半吗?你在做p吗使用复数运算的点式乘法?大家好,谢谢提问。顺序:@MSalters我的意思是说,我听到的声音是对称的h
所期望的声音;在调查包含h
的实际浮点数组后,它不是,看起来correct@Quintana,顺便说一句,你可以用这个作为参考nce实现:,其中感兴趣的部分由FFTW计划完成。但是,请查看如何使用匹配的r2c逆变换。请记住,您也可以在傅里叶域中分析您的问题。如果脉冲响应在时域中看起来是h[n]+h[-n]
,则它是h(f)+h(-f)
在频域中也是如此。加窗不会表现出类似的行为,也不会修复它。你将pad h归零到匹配的长度;现在,h是实值的,如果我理解正确的话;因此,你可能正在使用FFTW的real2complex变换之一?你确定你使用的是完整的对称DFT,而不是仅仅一半吗?你在做p吗使用复数运算的点式乘法?大家好,谢谢提问。顺序:@MSalters我的意思是说,我听到的声音是对称的h
所期望的声音;在调查包含h
的实际浮点数组后,它不是,看起来correct@Quintana,顺便说一句,你可以用这个作为参考nce实现:,其中有趣的部分是由FFTW计划完成的。但是,看看如何使用匹配的r2c逆变换。我们开始了,问题解决了。我正在搜索我的算法逻辑,而不是我的乘法函数!请注意,std::complex
有一个