You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python绘制WAV文件音频频率曲线异常问题排查求助

问题原因分析与解决方案

核心问题排查

你遇到的情况并非fft()未执行或WAV文件不含时间序列,大概率是以下几个细节没处理到位:

  1. 多通道音频未转单通道
    scipy.io.wavfile.read读取立体声WAV时会返回二维数组(形状为(样本数, 通道数)),直接对二维数组做FFT会得到每个通道的频谱结果,叠加后可视化效果会类似时间序列波动。你可以先打印audio_time_series.shape确认是否为多通道。

  2. FFT结果未归一化导致可视化失真
    FFT的原始振幅值与样本数成正比,未归一化的数值过大,会让绘图自动缩放后细节丢失,看起来像时间序列的波形。

  3. 对频谱形态的误解
    语音的频谱本身就是由大量密集的谐波峰值组成,尤其是首秒的语音信号,密集的低频峰值可能会让你误以为是时间序列。

修正后的代码

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 18:35:27