使用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字节采样解析:
- 将原始字节转为
uint8数组,按3字节一组重排。 - 按小端模式组合成无符号24位整数,再通过判断最高位转换为有符号整数。
- 将原始字节转为
- 声道拆分:将总采样数组重塑为
(帧数, 声道数)的形状,直接按列提取左右声道,此时每个声道的长度等于帧数n_frames,和times数组长度完全匹配。
内容的提问来源于stack exchange,提问作者Jay
相关产品推荐
相关产品推荐

