【问题标题】:Python NumPy - FFT and Inverse FFT?Python NumPy - FFT 和逆 FFT?
【发布时间】:2012-04-30 15:45:49
【问题描述】:

我一直在使用 FFT,目前正在尝试使用 FFT 从文件中获取声音波形(最终修改它),然后将修改后的波形输出回文件。我得到了声波的 FFT,然后在其上使用了逆 FFT 函数,但输出文件听起来根本不对。我没有对波形进行任何过滤——我只是在测试获取频率数据,然后将其放回文件中——听起来应该是一样的,但听起来却大不相同。

从那以后,我一直在研究这个项目,但还没有得到想要的结果。输出的声音文件很嘈杂(更大声,以及原始文件中不存在的额外噪音),并且来自一个通道的声音泄漏到另一个通道(之前是静音的)。输入声音文件是立体声、2 声道文件,声音仅来自一个声道。这是我的代码:

import scipy
import wave
import struct
import numpy
import pylab

from scipy.io import wavfile

rate, data = wavfile.read('./TriLeftChannel.wav')

filtereddata = numpy.fft.rfft(data, axis=0)
print(data)

filteredwrite = numpy.fft.irfft(filtereddata, axis=0)
print(filteredwrite)

wavfile.write('TestFiltered.wav', rate, filteredwrite)

我不太明白为什么这不起作用。

我已经压缩了问题 .py 文件和音频文件,如果这可以帮助解决问题here

【问题讨论】:

  • 在保存之前尝试添加filteredwrite = numpy.round(filteredwrite).astype('int16')
  • @Bago - 非常感谢!这完全解决了问题。我想知道,将过滤后的 ifft 强制为“int16”是否意味着它将是一个 16 位深度的声音文件?
  • 我对 wav 文件了解不多,我一直认为它们是未压缩的原始数据,但您必须阅读 wav 格式规范才能确定。
  • @Bago - 我明白了。好的,非常感谢!

标签: python audio numpy fft audio-processing


【解决方案1】:
  1. 您似乎没有在此处应用任何过滤器
  2. 您可能希望获取fft(后滤波)的ifft,而不是输入波形。

【讨论】:

    【解决方案2】:
    >>> import numpy as np
    >>> a = np.vstack([np.ones(11), np.arange(11)])
    
    # We have two channels along axis 0, the signals are along axis 1
    >>> a
    array([[  1.,   1.,   1.,   1.,   1.,   1.,   1.,   1.,   1.,   1.,   1.],
           [  0.,   1.,   2.,   3.,   4.,   5.,   6.,   7.,   8.,   9.,  10.]])
    >>> np.fft.irfft(np.fft.rfft(a, axis=1), axis=1)
    array([[  1.1       ,   1.1       ,   1.1       ,   1.1       ,
              1.1       ,   1.1       ,   1.1       ,   1.1       ,
              1.1       ,   1.1       ],
           [  0.55      ,   1.01836542,   2.51904294,   3.57565618,
              4.86463721,   6.05      ,   7.23536279,   8.52434382,
              9.58095706,  11.08163458]])
    # irfft returns an even number along axis=1, even though a was (2, 11)
    
    # When a is even along axis 1, we get a back after the irfft.
    >>> a = np.vstack([np.ones(10), np.arange(10)])
    >>> np.fft.irfft(np.fft.rfft(a, axis=1), axis=1)
    array([[  1.00000000e+00,   1.00000000e+00,   1.00000000e+00,
              1.00000000e+00,   1.00000000e+00,   1.00000000e+00,
              1.00000000e+00,   1.00000000e+00,   1.00000000e+00,
              1.00000000e+00],
           [  7.10542736e-16,   1.00000000e+00,   2.00000000e+00,
              3.00000000e+00,   4.00000000e+00,   5.00000000e+00,
              6.00000000e+00,   7.00000000e+00,   8.00000000e+00,
              9.00000000e+00]])
    
    # It seems like you signals are along axis 0, here is an example where the signals are on axis 0
    >>> a = np.vstack([np.ones(10), np.arange(10)]).T
    >>> a
    array([[ 1.,  0.],
           [ 1.,  1.],
           [ 1.,  2.],
           [ 1.,  3.],
           [ 1.,  4.],
           [ 1.,  5.],
           [ 1.,  6.],
           [ 1.,  7.],
           [ 1.,  8.],
           [ 1.,  9.]])
    >>> np.fft.irfft(np.fft.rfft(a, axis=0), axis=0)
    array([[  1.00000000e+00,   7.10542736e-16],
           [  1.00000000e+00,   1.00000000e+00],
           [  1.00000000e+00,   2.00000000e+00],
           [  1.00000000e+00,   3.00000000e+00],
           [  1.00000000e+00,   4.00000000e+00],
           [  1.00000000e+00,   5.00000000e+00],
           [  1.00000000e+00,   6.00000000e+00],
           [  1.00000000e+00,   7.00000000e+00],
           [  1.00000000e+00,   8.00000000e+00],
           [  1.00000000e+00,   9.00000000e+00]])
    

    【讨论】:

      【解决方案3】:

      不应该这样吗?

      filtereddata = numpy.fft.fft(data)
      # do fft stuff to filtereddata
      filteredwrite = numpy.fft.ifft(filtereddata)
      wavfile.write('TestFiltered.wav', rate, filteredwrite)
      

      【讨论】:

      • @wim - 对此感到抱歉 - 编辑了我的原始帖子以获得更多信息。
      【解决方案4】:

      两个问题。

      您正在对 2 通道数据进行 FFT。您应该只 FFT 1 通道的单声道数据,以使 FFT 结果具有一般意义。如果要处理 2 个声道的立体声数据,则应分别对每个声道进行 IFFT(FFT())。

      您使用的是真正的 fft,它会丢弃信息,从而使 fft 不可逆。

      如果要反转,则需要使用产生复数结果的 FFT,然后将这个复数频域矢量 IFFT 回时域。如果您修改频域矢量,如果您想要一个严格的实数结果(减去数值噪声),请确保它保持共轭对称。

      【讨论】:

      • 你可以fft多通道数据,你只需要使用一个二维数组并确保axis关键字设置正确(默认为-1),irfft(rfft(n))应该返回n(在机器内精度)。
      • * irfft(rfft(n)) 如果 n.shape[axis] 是偶数,似乎表现最好。
      • @Bago - 很抱歉花了这么长时间才解决这个问题,但你能详细说明一下你的意思吗? “使用二维数组”是什么意思?你的意思是一个 NumPy 数组,对吧?
      • @Bago - 我认为我做对了,但很难说。正在使用 wavfile.read('./TriLeftChannel.wav') 读取数组,但形状为 (x, 2),其中 x 是大量样本。所以,它已经是一个二维数组了。我在使用 FFT 和 IFFT 时指定了轴,但它并没有改变输出...
      • @SolarLune,在这种情况下,一个简短的例子真的很有帮助。我想你会发现,如果你提供足够的关于 SO 的信息来帮助其他人重现你的问题,你会得到更多的反馈。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-12
      • 2015-08-20
      • 2013-05-22
      • 2015-11-15
      • 2018-03-16
      • 1970-01-01
      相关资源
      最近更新 更多