我正在进行一些有趣的音频和图像文件以及快速傅立叶变换(FFT)实验。
快速傅里叶变换用于信号处理而不是其他傅里叶变换算法,因为对于大量数据,它们是唯一(或唯一的)可行的算法变体,因为它们可以扩展为O(n log(n) )),而不是天真实现的n ^ 2。
缺点是数据必须存储在一个包含2 ^ n个元素的数组中,用于n个整数。
当处理一些没有2 ^ n个元素的数据时,简单的方法是将数组扩展为长度为2 ^ n并用零填充“空”元素。 (假设输入信号的平均值为零。)
我编写了一个程序来处理从WAV文件中获取的一些音频样本。我尝试过诸如低切滤波器之类的东西。在这种情况下,我发现我的输出信号(在进行反向变换之后)在一段时间之后切换到零幅度。这显然不是人们对低通滤波器的期望。
我可以在此时转储我的代码,但这既无用,也不合法,因为我的算法源是带有封闭源代码的教科书。
相反,我会问下面的问题。
用零填充数组是最好的事情吗?这会导致我的程序产生我所看到的意外结果吗?如果我正确理解傅立叶数学,在我的数组末尾有一堆零会引入大量的低频和高频内容,因为它基本上看起来像一个阶跃函数(低频方波)。我是否应该采取其他措施,例如以不同的方式实施我的带通滤波器,例如,将数据拆分为较小的1024个采样组,并将FT,滤波器和IFT(反FT)应用于这些小组? / p>
这个问题已被理论标记,因为它与任何特定的编程语言无关。 (我认为这是正确的标签?)
编辑:它现在工作得非常好,谢谢大家,我能够使用以下信息查明我犯的两个错误。
答案 0 :(得分:2)
所有有限长度DFT和FFT都使用矩形窗口乘以较长的数据(比FFT更长的源数据或wav文件),该窗口将频谱与(周期性)Sinc函数进行卷积。零填充使用较短的矩形窗口,这导致频谱的卷积与更宽的Sinc函数。
通过FFT的乘法进行滤波导致循环卷积,其围绕FFT / IFFT结果包围滤波器的脉冲响应(例如,滤波信号的结束将干扰IFFT结果内的滤波信号的开始)。因此,您希望在FFT之前对数据进行零填充,然后在滤波结果的最后或之前(例如,不环绕)看到滤波器的脉冲响应变为零。查找重叠相加和重叠保存算法,使用短FFT对较长信号进行快速卷积滤波,从而处理延伸到零填充部分的滤波器脉冲响应。
您也可以使用长度不是2的幂的FFT。任何可以考虑到小素数的长度都适用于大多数现代FFT库。
答案 1 :(得分:1)
这取决于你感兴趣的内容。
如果您只对频谱幅度感兴趣,请将实际数据放在要处理的窗口中间。只要知道这个时间偏移会将相移转移到频谱结果中。
无论点数多少,都不要忘记在数据上放置一个窗口。维基百科对https://en.wikipedia.org/wiki/Window_function的窗口函数有很好的描述。
如果你没有对你的真实世界数据进行某种窗口化,填充信号似乎会在有效数据结束时加速并逐步降低(这会给你的频谱带来很多噪音)你的错误印象是你有噪声)。
所以,我的建议,如果你主要关心幅度: - 为您拥有的有效数据点开发一个汉明窗口。 - 将汉明窗口应用于您拥有的数据
之后你有OPTIONS:
A)如果您的样本略高于基数2,请使用较低的基数2(即如果您有1400个点,则执行两个1024点重叠的FFT)。这两个FFT的结果可以“巧妙地”和#34;合并为一个聚合光谱。根据您的保真度需求,您可以使用更多具有较大部分重叠数据的FFT来执行此操作。尝试将重叠率保持在10%以下,以便考虑窗口边缘,窗口边缘会因窗口函数的开始和结束而衰减。
B)将您的窗口数据放在FFT输入向量的任何位置(开始,中间或结尾,它应该只影响您的相位结果 - 这就是我询问相位是否重要的原因。)
如果事实证明相位很重要,请在FFT矢量的开头开始有效的窗口数据。
关于你的频谱观察(两周前我刚刚做了同样的事情)。如果您正在查看从有损压缩转换的波形文件,您将开始使用带限信号,因此期望频谱突然下降。我的第一个无损波文件图有一个巨大的光点来自Fs / 10 - > 9Fs / 10(预计)。对于你的情节 - 也用对数分档显示你的数据(线性分档会给你误导信息并压缩低频率元素,它们是压缩音乐文件中大部分信号)。
仅供参考 - 我推荐汉明(因为我做了同样的事情)。解码的压缩音频信号仅使用一部分频谱(解码320kbps流以10Khz采样),即使解码为44.1Khz表示,所有有趣的数据也应低于5Khz。
祝你好运
J.R。
P.S。这是我在这里的第一篇文章,如果你想要TeraPlot的漂亮照片,请回复一下。
答案 2 :(得分:0)
这是http://dsp.stackexchange.com的问题,但是,零填充在这里完全合法。
这就是为什么滤波后的信号(一旦它回到时域中)在一段时间后变为零的原因:想象一下使用低通滤波器的脉冲响应对零填充信号进行线性卷积(使用慢速O(N ^) 2)时域过滤器实现)。原始信号完成后输出将变为零,当滤波器刚刚被零提供时,对吗?该结果与基于FFT的快速卷积的输出相同。这是完全正常的。只需将输出信号裁剪为与输入相同的长度,然后继续使用。
对FFT顺序的警告:仅仅因为两个FFT的长度在操作计数方面“最快”,而具有低素数因子(3,5,7)的长度的FFT具有稍高的操作计数,可能会发现,由于内存成本的原因,在实际运行时方面,零填充到低素数因子的速度更快。一个病态的例子:如果你有一个1025长的信号,你可能不想零填充到2048并且花费分配近2倍内存缓冲的成本,并运行近2倍的FFT。您可以尝试使用1080长度的FFT或其他内容(1080 = 2^3 * 3^3 * 5
:nextprod
是您的朋友),如果它的完成速度比二次幂快得多,也不会感到惊讶。