【问题标题】:Creating an amplitude vs frequency spectrogram of an audio file in Python在 Python 中创建音频文件的幅度与频谱图
【发布时间】:2026-01-11 21:25:02
【问题描述】:

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

【问题讨论】:

标签: python audio transform fft spectrogram


【解决方案1】:

简单光谱

获得均匀采样信号x 的幅度与频率关系的最简单方法是通过有效的Fast Fourier Transform 算法计算其Discrete 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 方法获得的频谱产生的频谱看起来非常嘈杂(即有很多尖峰)。 为了获得更准确的估计,更复杂的方法是使用periodograms(由scipy.signal.periodogram 实现)和Welch's method(由scipy.signal.welch 实现)等技术计算power spectrum estimate。但请注意,在这些情况下,计算的频谱与幅度的平方成正比,因此其平方根提供了均方根 (RMS) 幅度的估计值。

回到以常规采样率fs 采样的信号x,因此可以获得这样的功率谱估计,如 scipy 文档中的示例所述,如下所示:

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

相应的频率f也在此过程中计算,因此您可以绘制结果

plt.plot(f, A_rms)

使用scipy.signal.welch 非常相似,但使用的实现略有不同,提供了不同的精度/分辨率折衷。

【讨论】:

    【解决方案2】:
    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

    【讨论】:

    • 上面的代码是频率与时间的关系。我正在寻找幅度与频谱图。