使用基于 FFT 的卷积正确处理数据

Posted

技术标签:

【中文标题】使用基于 FFT 的卷积正确处理数据【英文标题】:Properly manipulating data with FFT based convolution 【发布时间】:2014-12-27 04:34:32 【问题描述】:

我已经阅读 DSP 指南已有 3 年了。直到最近对编程足够熟悉后,我才决定开始尝试基于 FFT 的卷积,确切地说是一维,一实进,一复出。

我偶然发现了一些用于获取 FFT 和 IFFT 的代码并让它工作,我在复频域中得到了一个正确的 DFT,经过一点位操作(将复数数组分离回两个单独的实数和虚数数组)并通过 IFFT 运行它,然后再次进行更多位操作,从而得到预期的原始输入。

现在,也许我对卷积的概念完全错误,但简单地将复杂数组的相似元素相乘,然后通过 IFFT 将结果返回给虚假数字。 为了进行测试,我只是制作了一个斜坡内核,一个狄拉克三角函数作为输入并将结果插入 IFFT,代码没有按预期给出原始内核 .

public void convolution(double [] xReal, double [] xImag,
                        double [] hReal, double [] hImag)

    for (int i = 0; i < n; i++)
        xReal[i] *= hReal[i];
        xImag[i] *= hImag[i];
    

我的问题是:这个用于将复杂 DFT 的元素相乘的代码是否正确。

我一直在寻找简单的卷积代码或只是其背后的数学,但没有这样的运气。我发现的一切都是“频域中的乘法等于时域中的卷积”。

【问题讨论】:

如果您的问题直截了当并提出明确的问题,您更有可能获得帮助。事实上,很难说出你在问什么。 我在问我用于计算卷积的代码是否给定频域中的复杂 DFT。 【参考方案1】:

频域中的乘法执行的是循环卷积,而不是直线卷积,除非您将 FFT 和 IFFT 零填充到比时域信号长度与全时域脉冲响应的总和更长的时间。 (零填充,因为全零的圆形环绕/环绕与不环绕相同)。

此外,对于卷积,您需要乘以零填充脉冲响应(其频率响应)的变换 (FFT),而不是脉冲响应本身。

此外,乘法必须是复数乘法,而不是仅对 2 个分离的分量向量进行乘法。

【讨论】:

因此,在您通过 FFT 运行输入和脉冲之后,您填充结果然后使用复数乘法,然后通过 IFFT 运行该结果。由于填充了零,进入 IFFT 的数据会比进入 FFT 的数据大吗?还是在 FFT 之前填充零并在 IFFT 之前再次填充? 在两个 FFT 之前填充,然后为 IFFT 保持较长的长度相同。无论如何,卷积都会增加结果长度。 查看 FFT 计算器后,我发现这是我使用的 FFT 库,要么是错误的,要么是我没有正确实现它。我搬到了 FFT Columbia,得到了我想要的结果;我什至不需要用它填充零。我使用的旧库如果填充零,它实际上改变了我认为不应该发生的 FFT 的结果,我使用的计算器证明了这一点。

以上是关于使用基于 FFT 的卷积正确处理数据的主要内容,如果未能解决你的问题,请参考以下文章

FFT的使用方法有哪些?

与实施库利FFT的故障

如何正确 FFT 声音阵列?

如何使用 iOS Accelerate 框架正确填充 FFT 的二维数组

FFT 频谱未正确显示

在 fft 中应用窗口函数的正确方法