如何使用FFT或DFT重新采样音频


12

我首先通过执行FFT,然后仅获取所需结果的一部分,然后执行逆FFT,来对语音音频进行下采样。但是,只有当我使用两个都是2的幂的频率(例如从32768降到8192的下采样)时,它才能正常工作。我对32k数据执行FFT,丢弃数据的前3/4,然后执行对其余的1/4进行逆FFT。

但是,每当我尝试使用无法正确排列的数据来执行此操作时,就会发生以下两种情况之一:我使用的数学库(Aforge.Math)会产生拟合,因为我的样本不是2的幂。如果我尝试对样本进行零填充,以使它们成为二乘幂,则另一端会产生乱码。我还尝试使用DFT来代替,但最终会变得异常缓慢(这需要实时进行)。

在初始FFT和最后的逆FFT上,我如何正确地对FFT数据进行零填充?假设我有一个44.1khz的样本需要达到16khz,我目前正在尝试这样的样本,样本大小为1000。

  1. 将输入数据最后填充到1024
  2. 执行FFT
  3. 将前512个项目读入数组(我只需要前362个,但需要^ 2)
  4. 执行逆FFT
  5. 将前362个项目读入音频播放缓冲区

由此,我最后得到了垃圾。进行相同的操作,但由于样本已经是^ 2,而不必在步骤1和3进行填充,可以得出正确的结果。

c#  audio 

9
FFT确实不是执行此操作的正确方法。您想要一个多相滤波器组以实现最大效率,但是如果您只是想解决问题,请先对GCD进行上采样,然后对低通进行下采样,然后对下采样。
比约恩·罗奇

嗨,比约恩:什么是“ GCD”?
SpeedCoder5

Answers:


16

第一步是验证您的初始采样率和目标采样率均是有理数。由于它们是整数,因此它们自动是有理数。如果其中一个不是一个有理数,仍然可以改变采样率,但这是一个非常不同的过程,而且难度更大。

下一步是考虑两个采样率。在这种情况下,起始采样率为44100,这是因数。目标采样率16000是因数。因此,要从初始采样率转换为目标率,我们必须抽取并内插。2 7 * 5 3 3 2 * 7 2 2 5 * 52232527227533272255

无论您想如何对数据进行重新采样,都必须完成前面的步骤。现在让我们谈谈如何使用FFT。使用FFT进行重采样的技巧是选择FFT长度,以使所有工作顺利进行。这意味着选择的FFT长度是抽取率的倍数(在这种情况下为441)。在本例中,让我们选择FFT长度为441,尽管我们可以选择882或1323,或任何其他正数441。

了解其工作原理有助于对其进行可视化。您从一个音频信号开始,该音频信号在频域中看起来类似于下图。 44.1 kHz采样率

完成处理后,您希望将采样率降低到16 kHz,但希望失真尽可能小。换句话说,您只希望将上图中的所有内容都保持在-8 kHz至+8 kHz的范围内,并丢弃其他所有内容。结果如下图所示。 在此处输入图片说明

请注意,采样率并非按比例缩放,仅用于说明概念。

选择为抽取因子倍数的FFT长度的好处在于,您可以简单地通过删除部分FFT结果,然后对剩余的FFT求逆来进行重新采样。在我们的示例中,您对441个数据样本进行了FFT,从而在频域中获得了441个复数样本。我们想通过441进行抽取,然后以160()进行内插,因此我们保留了160个样本,它们代表从-8 kHz到+8 kHz的频率。然后,我们对这些样本进行逆FFT运算并保存!您有160个时域采样,采样频率为16 kHz。255

您可能会怀疑,有两个潜在的问题。我将逐一介绍并解释如何克服它们。

  1. 如果数据不是抽取因子的整数倍,该怎么办?您可以通过在数据末尾填充足够的零以使其成为抽取因子的倍数来轻松克服这一问题。在对数据进行FFT处理之前将其填充。

  2. 尽管我介绍的方法非常简单,但它也不理想,因为它会在时域中引入振铃和其他令人讨厌的伪影。您可以通过在删除高频数据之前对频域数据进行过滤来避免这种情况。您可以通过FFT'ing你长的过滤器做到这一点至少,填充数据(FFT'ing之前)l 1ll1零(请注意,数据样本的数量和填充样本的数量都必须是抽取因子的正数-您可以增加填充长度来满足此约束),对填充的数据进行FFT,并乘以频域数据和滤波器,然后将高频(> 8 kHz)结果混叠为低频(<8 kHz)结果,然后再丢弃高频结果。不幸的是,由于频域中的滤波本身就是一个大话题,因此,我将无法在此答案中更详细地介绍。不过,我要说的是,如果您要过滤并处理多个块中的数据,则需要实现Overlap-and-AddOverlap-and-Save以使过滤连续进行。

我希望这有帮助。

编辑:频域样本的起始数量与目标频域样本的数量之间的差异必须是偶数,以便您可以从结果的正侧除去与结果的负侧相同数目的样本。在我们的示例中,样本的起始数量是抽取率(即441),目标样本的数量是内插率(即160)。两者之差为279,不是偶数。解决方案是将FFT长度增加一倍至882,这会使目标样本数也增加一倍至320。现在两者之间的差异是偶数,并且可以毫无问题地丢弃适当的频域样本。


非常好。吉姆,你如何在飞行中做出如此出色的人物?
Spacey 2012年

@Mohammad我通常使用Powerpoint。在这种情况下,我使用了Powerpoint的Libre Office版本,我认为它称为“ Impress”。
Jim Clay 2012年

您好,我对您的问题有疑问(2)。您在此步骤中的确切含义是:“ ...然后将高频(> 8 kHz)的结果混叠为低频(<8 kHz)的结果,然后再丢弃高频结果。” 我了解之前的步骤。将我的f域数据与过滤器的f域相乘之后,那又如何呢?另外,如果您也想对数据进行上采样,此方法是否有效?谢谢。
TheGrapeBeyond'Mar

@TheGrapeBeyond在时域中使用别名时,会将所有Nyquist区域加在一起。所有奈奎斯特区的第一个元素加在一起,成为第一个奈奎斯特区的新的第一个元素。所有的奈奎斯特区域的第二个元素被添加在一起,成为第一奈奎斯特区域等的新的第二元素
吉姆·克莱

嗯,我不确定我是否了解您如何进行基于FFT的重采样,因为当我在此处尝试时,会得到非常奇怪的结果。我会问一个问题。
TheGrapeBeyond'Mar

3

虽然以上答案确实很完整:

这是要点:

  1. 对信号进行下采样时,它必须是整数。在向下采样信号之前,您需要过滤信号。
  2. 您可以通过先对信号进行上采样/内插来实现有理数下采样。
  3. 上采样只是插入零,然后过滤信号。
  4. 因此可以达到3/4的采样率 通过在每个信号采样之间插入4个零来对信号进行升采样。应用过滤器。然后过滤信号并每4个信号样本中的每3个删除一次。

详细信息:

http://www.ws.binghamton.edu/fowler/fowler%20personal%20page/EE523_files/Ch_14_1%20Subband%20Intro%20&%20Multirate%20(PPT).pdf

另外:除非绝对必要,否则请勿计算机化FFT,然后再计算IFFT。这是一个极其缓慢的过程,并且被认为不适用于大多数信号处理任务。FFT通常仅在频域中用于分析问题或进行信号处理。


1

正如Bjorn Roche所说的那样,使用FFT绝对是无效的。但是这里使用频域中的上采样滤波器和下采样方法以非常非常简单的方式进行。

1-取所需的长度为N的矢量信号。

2-执行N点FFT。

3-在FFT向量的中间对FFT进行160 * N零填充。

4-执行IFFT

5-从441个样本中选择一个,丢弃另一个440。

您将得到一个长度为N * 160/441的向量,它将是您的重采样信号。

如您所见,您正在执行许多无意义的计算,因为大多数结果将被丢弃。但是,如果您可以访问执行FFT的代码,则实际上可以对其进行一些调整,以便仅计算最终得到的IFFT结果,而不计算将被丢弃的结果。

希望能帮助到你。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.