Python绘制WAV文件音频频率曲线异常问题排查求助
问题原因分析与解决方案
核心问题排查
你遇到的情况并非fft()未执行或WAV文件不含时间序列,大概率是以下几个细节没处理到位:
多通道音频未转单通道
scipy.io.wavfile.read读取立体声WAV时会返回二维数组(形状为(样本数, 通道数)),直接对二维数组做FFT会得到每个通道的频谱结果,叠加后可视化效果会类似时间序列波动。你可以先打印audio_time_series.shape确认是否为多通道。FFT结果未归一化导致可视化失真
FFT的原始振幅值与样本数成正比,未归一化的数值过大,会让绘图自动缩放后细节丢失,看起来像时间序列的波形。对频谱形态的误解
语音的频谱本身就是由大量密集的谐波峰值组成,尤其是首秒的语音信号,密集的低频峰值可能会让你误以为是时间序列。
修正后的代码
import matplotlib.pyplot as plt import numpy as np from scipy.fftpack import fft from scipy.io import wavfile # 读取音频 sample_rate, audio_time_series = wavfile.read(audio_path) # 转换为单通道(处理立体声情况) if len(audio_time_series.shape) > 1: audio_time_series = audio_time_series.mean(axis=1).astype(np.int16) # 截取首1秒数据 single_sample_data = audio_time_series[:sample_rate] def fft_plot(audio, sample_rate): N = len(audio) # 样本数量 T = 1 / sample_rate # 采样周期 # 执行FFT并计算归一化振幅 y_freq = fft(audio) domain = N // 2 # 归一化振幅(直流分量单独处理,其余频率乘以2以补偿FFT的对称特性) y_freq_amp = 2.0 / N * np.abs(y_freq[:domain]) y_freq_amp[0] = np.abs(y_freq[0]) / N # 生成频率轴 x_freq = np.linspace(0, sample_rate / 2, domain) # 绘图 plt.plot(x_freq, y_freq_amp) plt.xlabel("Frequency [Hz]") plt.ylabel("Normalized Amplitude") # 可选:限制X轴到5kHz,符合你的预期 plt.xlim(0, 5000) plt.show() fft_plot(single_sample_data, sample_rate)
额外验证步骤
- 先单独绘制时间序列确认数据正常:
plt.plot(single_sample_data); plt.show(),对比频谱图的形态差异。 - 打印
sample_rate确认采样率正确(通常语音是44100Hz或16000Hz)。 - 检查
y_freq.dtype,确认FFT返回的是复数数组(complex128),说明FFT已正常执行。
内容的提问来源于stack exchange,提问作者Marco Acea
相关产品推荐
相关产品推荐

