在 Python 中创建音频文件的幅度与频谱图

Creating an amplitude vs frequency spectrogram of an audio file in Python

我正在尝试在 Python 中创建音频文件的幅度与频率频谱图。这样做的程序是什么? 一些示例代码会有很大帮助。

from scipy import signal
import matplotlib.pyplot as plt
fs = 10e3
N = 1e5
amp = 2 * np.sqrt(2)
noise_power = 0.01 * fs / 2  
time = np.arange(N) / float(fs)
mod = 500*np.cos(2*np.pi*0.25*time)
carrier = amp * np.sin(2*np.pi*3e3*time + mod)
noise = np.random.normal(scale=np.sqrt(noise_power), size=time.shape)
noise *= np.exp(-time/5)
x = carrier + noise
f, t, Sxx = signal.spectrogram(x, fs)
plt.pcolormesh(t, f, Sxx)
plt.ylabel('Frequency [Hz]')
plt.xlabel('Time [sec]')
plt.show()

这是从 scipy 文档中提取的,因为您需要科学计算来创建频谱图。 如果您还没有安装 scipy,请在您的计算机上安装它并阅读其文档:

https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.spectrogram.html

简谱

获得均匀采样信号 x 的振幅与频率关系的最简单方法是计算其 Discrete Fourier Transform through the efficient Fast Fourier Transform 算法。给定以常规采样率 fs 采样的信号 x,您可以使用:

import numpy as np
Xf_mag = np.abs(np.fft.fft(x))

Xf_mag 数组的每个 index 将包含一个频率仓的振幅,其频率由 index * fs/len(Xf_mag) 给出。这些频率可以使用以下方法方便地计算:

freqs = np.fft.fftfreq(len(Xf_mag), d=1.0/fs)

终于可以使用 matplotlib 绘制频谱了:

import matplotlib.pyplot as plt
plt.plot(freqs, Xf_mag)

优化频谱估计

您可能会注意到,使用简单的 FFT 方法获得的频谱产生的频谱看起来非常嘈杂(即有很多尖峰)。 为了获得更准确的估计,更复杂的方法是计算 power spectrum estimate using techniques such as periodograms (implemented by scipy.signal.periodogram) and Welch's method (implemented by scipy.signal.welch)。但是请注意,在这些情况下,计算出的频谱与振幅的平方成正比,因此其平方根提供了 Root-Mean-Squared (RMS) 振幅的估计值。

回到以常规采样率 fs 采样的信号 x,因此可以按照 scipy 文档中示例中的描述获得这样的功率谱估计具有以下内容:

f, Pxx = signal.periodogram(x, fs)
A_rms = np.sqrt(Pxx)

相应的频率f也在这个过程中计算出来,所以你可以用

绘制结果
plt.plot(f, A_rms)

使用 scipy.signal.welch 非常相似,但使用略有不同的实现,提供了不同的 accuracy/resolution 权衡。