【问题标题】:How do fourier processing algorithms deal with "data edges"傅立叶处理算法如何处理“数据边缘”
【发布时间】:2016-08-09 17:42:40
【问题描述】:

我正在对音频和图像文件以及快速傅里叶变换 (FFT) 进行一些有趣的实验。

快速傅里叶变换用于信号处理而不是其他傅里叶变换算法,因为对于大量数据,它们是唯一(或唯一)可行的算法变体之一,因为它们的规模为 O(n log(n )),而不是像天真的实现那样 n^2。

缺点是数据必须存储在一个有 2^n 个元素的数组中,对于 n 个整数。

当处理一些没有 2^n 元素的数据时,简单的方法是将数组扩展为长度 2^n 并用零填充“空”元素。 (假设输入信号的平均值为零。)

我编写了一个程序来处理从 WAV 文件中提取的一些音频样本。我尝试实现诸如低切滤波器之类的东西。在这种情况下,我发现我的输出信号(在进行了逆变换之后)在一定的 时间 之后会降低到零幅度。这显然不是人们所期望的低通滤波器。

此时我可以转储我的代码,但这既无用也不合法,因为我的算法的来源是一本封闭源代码的教科书。

我将提出以下问题。

用零填充数组是最好的办法吗?这会导致我的程序产生我看到的意外结果吗?如果我正确理解傅立叶数学,在我的数组末尾有一堆零将引入大量低频和高频内容,因为这基本上看起来像一个阶跃函数(低频方波)。我是否应该做其他事情,例如以不同的方式实现我的带通滤波器,例如,将数据分成较小的组,例如 1024 个样本,并将 FT、滤波器和 IFT(逆 FT)应用于这些小组?

这个问题已被标记为理论,因为它与任何特定的编程语言无关。 (我认为这是要使用的正确标签?)

编辑:它现在运行良好,谢谢大家,我能够使用以下信息查明我犯的 2 个错误。

【问题讨论】:

  • 许多 FFT 库支持混合基数大小,而不仅仅是 2^n,但零填充很好。

标签: algorithm signal-processing fft theory


【解决方案1】:

所有有限长度的 DFT 和 FFT 将更长的数据(比 FFT 更长的源数据或 wav 文件)与矩形窗口相乘,矩形窗口将频谱与(周期性)Sinc 函数进行卷积。零填充使用更短的矩形窗口,这导致频谱与更宽的 Sinc 函数进行卷积。

通过乘以 FFT 进行滤波会产生循环卷积,它将滤波器的脉冲响应包裹在 FFT/IFFT 结果周围(例如,滤波信号的结尾会干扰 IFFT 结果中滤波信号的开头)。因此,您希望在 FFT 之前对数据进行零填充,然后在过滤结果结束时或之前看到滤波器的脉冲响应变为零(例如,不回绕)。查找重叠相加和重叠保存算法,使用短 FFT 对较长信号进行快速卷积滤波,该算法负责将滤波器脉冲响应扩展到零填充部分。

您还可以使用长度不是 2 的幂的 FFT。任何可以分解为小素数的长度都适用于大多数现代 FFT 库。

【讨论】:

  • 因此我应该对输出数据进行反卷积吗?这可能是我看到的效果的原因吗? (我的直觉是答案是否定的。)
  • 您应该重叠添加或重叠保存。如果你过滤,你已经在卷积,不想撤消。
  • 您能向我解释一下重叠添加/保存相对于整个 FFT 的优势是什么?它会产生“更正确的输出”还是更有效,或者其他什么?
  • @user3728501 重叠添加/重叠保存要快得多,并且应该给您与基于单次 FFT 的卷积时域卷积完全相同的结果(慢)。 en.wikipedia.org/wiki/… 看那里的等高线图。
【解决方案2】:

这取决于你对什么感兴趣。

如果您只对频谱幅度感兴趣,那么将真实数据放在要处理的窗口中间。只要知道这个时间偏移会在频谱结果中产生一个相移。

无论点数如何,都不要忘记在数据上放置一个窗口。 Wikipedia 在https://en.wikipedia.org/wiki/Window_function 上有一篇很好的关于窗口函数的文章。

如果您不对真实世界的数据执行某种加窗,则填充信号会在有效数据的末尾出现一个上升和一个下降(这会在您的频谱中产生大量噪声你有一个错误的印象,你有一个本底噪声)。

所以,如果您主要关心幅度,我的建议是: - 为您拥有的有效数据点数开发一个汉明窗口。 - 将汉明窗口应用于您拥有的数据

之后你有选项:

A)如果您的样本略高于以二为底的数字,请使用较低的以二为底的数字(即,如果您有 1400 个点,请执行两个重叠的 1024 点 FFT)。这两个 FFT 的结果可以“巧妙地”组合成一个聚合频谱。根据您的保真度需求,您可以使用更多 FFT 和更多重叠数据来执行此操作。尝试将重叠保持在 10% 以下,以解决窗口边缘会因窗口函数的开始和结束而衰减的问题。

B) 将您的窗口数据放在 FFT 输入向量中的任何位置(开始、中间或结束,它只会影响您的相位结果 - 这就是为什么我问相位是否重要)。

如果结果表明相位很重要,请在 FFT 向量的开头开始您的有效窗口数据。

关于您的频谱观察(两周前我刚刚经历了同样的事情)。如果您正在查看从有损压缩转换的波形文件,您将从频带受限信号开始,因此预计频谱会突然下降。我的第一个无损波形文件图有一个从 Fs/10 -> 9Fs/10 的巨大光秃点(这是预期的)。对于您的绘图 - 还可以在对数 bin 中显示您的数据(线性 bin 会给您提供误导性信息并挤压作为压缩音乐文件中大部分信号的低频元素)。

仅供参考 - 我推荐汉明(因为我做了同样的事情)。解码后的压缩音频信号将仅使用您的一部分频谱(解码 320kbps 流以 10Khz 采样),即使解码为 44.1Khz 表示,所有有趣的数据也应低于 5Khz。

祝你好运

J.R.

附:这是我在这里的第一篇文章,如果你想要一些来自 TeraPlot 的漂亮图片,请回复。

【讨论】:

  • 当然图片听起来很有趣 - 有趣的信息在这里,有一个投票
【解决方案3】:

这是http://dsp.stackexchange.com 的问题,但是是的,零填充在这里是完全合法的。

这就是为什么滤波后的信号(一旦它回到时域)在一段时间后变为零:想象一下将零填充信号与低通滤波器的脉冲响应线性卷积(使用慢 O(N^ 2)时域滤波器实现)。原始信号完成后,输出将变为零,此时滤波器刚刚被输入零,对吗?该结果将与基于 FFT 的快速卷积的输出相同。这是完全正常的。只需将输出信号裁剪为与输入相同的长度,然后继续您的生活。

关于 FFT 订单的警告:仅仅因为 2 次方 FFT 长度在运算次数方面是“最快的”,而具有低素因数(3、5、7)长度的 FFT 运算次数略高,您可能会发现,由于内存成本,就实际运行时间而言,对低质因子进行零填充更快。一个病态的例子:如果你有一个 1025 长的信号,你可能不想零填充到 2048 并吃掉分配近 2 倍内存缓冲区和运行近 2 倍长 FFT 的成本。你会尝试 1080 长度的 FFT 或其他东西(1080 = 2^3 * 3^3 * 5:nextprod 是你的朋友),如果它完成的速度比二次方快得多,也不会感到惊讶。

【讨论】:

  • “只需将输出信号裁剪为与输入相同的长度,然后继续你的生活。” - 我对此感到困惑 - 想象一下我正在处理一个音频文件 - 输出信号在音频文件的中途变为零,而不是在开头或结尾,所以我无法裁剪“开头或结尾”关”
  • 如果您的 FFT/IFFT 滤波器的输出在输入之前变为全零,那么您的代码中可能存在与 FFT 长度选择或零填充无关的其他严重错误。
  • 如果正好是一半,可能是 FFTSHIFT 的问题。您是否可以尝试用 Julia 或 Python/Numpy 之类的东西编写过滤器,这样您就可以看到“正确”的答案是什么,然后在您更好地理解这些概念后用您选择的语言实现它?
  • 还可以考虑绘制您的输入信号(WAV 文件幅度)和输出,并显示它。再次,一个非常 dsp.stackexchange.com 的问题。
猜你喜欢
  • 2017-05-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-11-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多