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

如何用Matplotlib渲染具有正确音量水平的音频波形图?

修复Matplotlib生成音频波形图的电平与截断问题

问题说明

以下为同一音频文件的波形对比:

  • 左侧:正确的原始未归一化音频波形
  • 右侧:Matplotlib生成的存在问题的波形

需要解决两个核心问题:

  1. 修正音频电平的显示精度
  2. 解决Y轴高度截断问题
    • Y轴上下存在无意义的空白间隙
    • 测试不同采样率的归一化文件后发现,无论音频电平如何,间隙都会出现

原使用代码

import numpy as np
import wave, sys, os
import matplotlib.pyplot as plt

File_Name = os.path.basename(sys.argv[1])
plt.rcParams["axes.xmargin"] = 0

#-=-=-=-#

try:
    Audio = wave.open(sys.argv[1], "r")
except Exception:
    raise SystemExit("WAV format not integer, exiting.")

if Audio.getnchannels() > 1:
    raise SystemExit("Not a mono file, exiting.")

Signal = Audio.readframes(-1)
Signal = np.fromstring(Signal, "int16")
Time = np.linspace(0, len(Signal) / Audio.getframerate(), num = len(Signal))

#-=-=-=-#

plt.plot(Time, Signal, color = "#000000")
#plt.axis("off")
#plt.savefig(os.path.splitext(File_Name)[0] + ".png",
#   bbox_inches = "tight", transparent = 1, pad_inches = 0
#)
plt.show()

问题根源与解决方案

问题1:音频电平显示偏差

int16格式的WAV音频信号取值范围为**-32768 ~ 32767**,Matplotlib默认Y轴会自动缩放并留有余量,导致电平显示不匹配原始信号幅度。

问题2:Y轴空白间隙

Matplotlib的plot方法默认会为Y轴添加5%左右的padding,即使数据已经占满理论范围,也会出现上下空白。


修改后的代码

import numpy as np
import wave, sys, os
import matplotlib.pyplot as plt

File_Name = os.path.basename(sys.argv[1])
plt.rcParams["axes.xmargin"] = 0

try:
    Audio = wave.open(sys.argv[1], "r")
except Exception:
    raise SystemExit("WAV格式非整数类型,程序退出。")

if Audio.getnchannels() > 1:
    raise SystemExit("不是单声道文件,程序退出。")

Signal = Audio.readframes(-1)
# 替换已废弃的np.fromstring,使用更规范的np.frombuffer
Signal = np.frombuffer(Signal, dtype=np.int16)
Time = np.linspace(0, len(Signal) / Audio.getframerate(), num=len(Signal))

plt.plot(Time, Signal, color="#000000")
# 强制Y轴覆盖int16音频的完整取值范围,消除间隙并修正电平
plt.ylim(-32768, 32767)

# 若需将电平归一化到-1~1范围,取消以下两行注释
# Signal_normalized = Signal / 32767.0
# plt.ylim(-1, 1)

# plt.axis("off")
# plt.savefig(os.path.splitext(File_Name)[0] + ".png",
#    bbox_inches="tight", transparent=True, pad_inches=0
# )
plt.show()

关键修改点

  1. 替换废弃API:用np.frombuffer替代np.fromstring,后者在NumPy 1.16+版本已被标记为废弃,前者更安全且符合现代NumPy规范
  2. 锁定Y轴范围:通过plt.ylim(-32768, 32767)强制Y轴覆盖int16信号的完整取值范围,彻底消除上下空白间隙,同时让电平显示完全匹配原始信号
  3. 可选归一化:如果需要标准化电平到-1~1范围,只需将信号除以32767.0并设置对应的Y轴极限即可

内容的提问来源于stack exchange,提问作者kubinka0505

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 10:20:35