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

使用Python绘制WAV信号振幅遇维度不匹配错误的解决咨询

处理3字节采样宽度的WAV文件并绘制波形

问题根源

你用np.int16解析3字节采样的WAV文件,导致数组长度计算错误。每个采样占3字节,而np.int16按2字节解析,最终生成的数组长度是总字节数/2,远大于实际的声道采样数,和times数组长度不匹配,触发维度错误。

解决方案

需要手动处理3字节采样的解析,将其转换为合适的有符号整数,再拆分声道:

完整修正代码

import wave
import matplotlib.pyplot as plt
import numpy as np

wav_obj = wave.open("loop.wav", "rb")

sample_freq = wav_obj.getframerate()
n_frames = wav_obj.getnframes()  # 总帧数,每帧对应一个时间点的所有声道采样
t_audio = n_frames / sample_freq
n_channels = wav_obj.getnchannels()
sample_width = wav_obj.getsampwidth()  # 获取采样宽度(字节数)

signal_wave = wav_obj.readframes(n_frames)

# 处理3字节采样的情况
if sample_width == 3:
    # 将字节数据转为uint8数组
    bytes_array = np.frombuffer(signal_wave, dtype=np.uint8)
    # 按3字节一组重新排列,形状为(总采样数, 3)
    reshaped = bytes_array.reshape(-1, 3)
    # 小端模式组合成24位有符号整数
    unsigned = reshaped[:, 0] | (reshaped[:, 1] << 8) | (reshaped[:, 2] << 16)
    # 处理符号位:24位有符号数范围是-2^23到2^23-1
    signal_array = np.where(unsigned >= 2**23, unsigned - 2**24, unsigned).astype(np.int32)
else:
    # 其他常见采样宽度的默认处理
    dtype_map = {1: np.int8, 2: np.int16, 4: np.int32}
    signal_array = np.frombuffer(signal_wave, dtype=dtype_map[sample_width])

# 将采样数组按声道拆分,形状变为(n_frames, n_channels)
signal_array = signal_array.reshape(-1, n_channels)
l_channel = signal_array[:, 0]
r_channel = signal_array[:, 1]

times = np.linspace(0, t_audio, num=n_frames)

plt.figure(figsize=(15, 5))
plt.plot(times, l_channel)
plt.title('Left Channel')
plt.ylabel("Signal Value")
plt.xlabel("Time in seconds")
plt.xlim(0, t_audio)
plt.show()

关键步骤说明

  • 获取采样宽度:通过getsampwidth()确认每个采样的字节数,针对3字节做特殊处理。
  • 3字节采样解析:
    1. 将原始字节转为uint8数组,按3字节一组重排。
    2. 按小端模式组合成无符号24位整数,再通过判断最高位转换为有符号整数。
  • 声道拆分:将总采样数组重塑为(帧数, 声道数)的形状,直接按列提取左右声道,此时每个声道的长度等于帧数n_frames,和times数组长度完全匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 01:37:46