我正在使用 FFT 从音频文件中提取每个频率分量的幅度。实际上,Audacity 中已经有一个叫做 Plot Spectrum 的功能可以帮助解决这个问题。以这个由 3kHz sine 和 6kHz sine 组成的音频文件为例,频谱结果如下图所示。你可以看到峰值在 3KHz 和 6kHz,没有额外的频率。
现在我需要实现相同的函数并在 Python 中绘制类似的结果。在 的帮助下,我已接近 Audacity 结果,rfft
但在获得此结果后我仍有问题需要解决。
- 第二张图片中幅度的物理意义是什么?
- 如何像 Audacity 中的那样将幅度标准化为 0dB?
- 为什么超过 6kHz 的频率具有如此高的幅度(≥90)?我可以将这些频率缩放到相对较低的水平吗?
相关代码:
import numpy as np
from pylab import plot, show
from scipy.io import wavfile
sample_rate, x = wavfile.read('sine3k6k.wav')
fs = 44100.0
rfft = np.abs(np.fft.rfft(x))
p = 20*np.log10(rfft)
f = np.linspace(0, fs/2, len(p))
plot(f, p)
show()
更新
我将汉宁窗乘以整个长度信号(正确吗?)并得到这个。大部分裙子的振幅都在40以下。
正如@Mateen Ulhaq所说,将 y 轴缩放到分贝。结果更接近于 Audacity。我可以将低于-90dB的幅度处理得如此之低以至于可以忽略吗?
更新代码:
fs, x = wavfile.read('input/sine3k6k.wav')
x = x * np.hanning(len(x))
rfft = np.abs(np.fft.rfft(x))
rfft_max = max(rfft)
p = 20*np.log10(rfft/rfft_max)
f = np.linspace(0, fs/2, len(p))
关于赏金
使用上面更新中的代码,我可以测量以分贝为单位的频率分量。最高可能值为 0dB。但是该方法仅适用于特定的音频文件,因为它使用rfft_max
了该音频。我想像 Audacity 一样在一个标准规则中测量多个音频文件的频率分量。
我也在Audacity 论坛上开始讨论,但我仍然不清楚如何实现我的目的。