如何理解音频频率分析中的傅里叶变换结果

2 投票
1 回答
632 浏览
提问于 2025-04-18 06:15

我正在用Python做音频分析。我的最终目标是得到一个频率和它们对应音量的列表,格式像这样 { frequency : volume (0.0 - 1.0) }

我把音频数据存成一个帧的列表,值在 -1.0+1.0 之间。我用numpy的傅里叶变换处理这个列表—— numpy.fftpack.fft()。但是结果对我来说一点意义都没有。

我知道傅里叶变换是把时间域的数据转换到频率域,但我不太明白它是怎么在数学上运作的。所以我对结果也搞不太懂。

  • numpy.fftpack.fft() 返回的列表里的值是什么意思?我该怎么处理这些值/理解它们呢?
  • 对上面描述的列表进行傅里叶变换后,最大值和最小值会是什么?
  • 我该如何得到我想要的那种字典,格式是 { frequency : volume (0.0 - 1.0) }

谢谢你。如果我对傅里叶变换的理解不够让你感到无奈,我很抱歉。

1 个回答

4

考虑一下一个正弦波的傅里叶变换(FFT):

>>> t = np.linspace(0, 2*np.pi, 100)
>>> x = np.sin(t)
>>> f = np.fft.rfft(x)
>>> np.round(np.abs(f), 0)
array([  0.,  50.,   1.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,
         0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,
         0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,
         0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,
         0.,   0.,   0.,   0.,   0.,   0.,   0.])

傅里叶变换会返回一个复杂数字的数组,这些数字表示不同频率的幅度和相位。如果你只关心幅度,我使用了 np.abs 来获取每个频率的大小,并用 np.round(__, 0) 将其四舍五入到最接近的整数。你可以看到在索引 1 处有一个尖峰,这表明找到了一个周期等于样本数量的正弦波。

现在让波形变得复杂一些

>>> x = np.sin(t) + np.sin(3*t) + np.sin(5*t)
>>> f = np.fft.rfft(x)
>>> np.round(np.abs(f), 0)
array([  0.,  50.,   1.,  50.,   0.,  48.,   4.,   2.,   2.,   1.,   1.,
         1.,   1.,   1.,   1.,   1.,   1.,   1.,   1.,   1.,   1.,   0.,
         0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,
         0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,   0.,
         0.,   0.,   0.,   0.,   0.,   0.,   0.])

我们现在在索引 1、3 和 5 处看到了尖峰,这些尖峰对应于我们的输入。它们分别代表周期为 nn/3n/5 的正弦波(其中 n 是输入样本的数量)。

编辑

这里有一个关于傅里叶变换的很好的概念解释: http://betterexplained.com/articles/an-interactive-guide-to-the-fourier-transform/

撰写回答