1. 音频文件读取与基础信息提取
任务目标
读取一个WAV音频文件,提取采样率、位深、通道数、采样点数与时长等基础信息,并绘制波形图以直观验证读取结果。本案例使用Python标准库wave与struct完成WAV解析,不依赖第三方音频库,确保最小可复现。
环境依赖
- Python 3.8+(仅标准库)
- matplotlib(用于波形绘制,需单独安装:
pip install matplotlib)
完整实现代码
import wave
import struct
import matplotlib.pyplot as plt
def read_wav_info(filepath):
"""读取WAV文件并返回基本信息与音频数据"""
with wave.open(filepath, 'rb') as wf:
channels = wf.getnchannels()
sampwidth = wf.getsampwidth() # 字节数
framerate = wf.getframerate()
nframes = wf.getnframes()
comptype = wf.getcomptype()
# 读取全部帧数据(bytes)
raw_data = wf.readframes(nframes)
# 位深 = 采样宽度(字节) * 8
bit_depth = sampwidth * 8
duration = nframes / framerate
# 解析PCM数据为整数列表(仅支持16位PCM,WAV最常见格式)
if sampwidth == 2:
fmt = f'<{nframes * channels}h' # 小端16位有符号
samples = struct.unpack(fmt, raw_data)
else:
raise ValueError(f"当前仅支持16位PCM,实际位深为{bit_depth}bit")
# 按通道分离
channel_data = []
for ch in range(channels):
channel_data.append(list(samples[ch::channels]))
info = {
'channels': channels,
'sampwidth_bytes': sampwidth,
'bit_depth': bit_depth,
'framerate': framerate,
'nframes': nframes,
'duration_sec': round(duration, 3),
'compression': comptype
}
return info, channel_data
def plot_waveform(channel_data, framerate, title="Waveform"):
"""绘制波形图(最多显示前2个通道)"""
n_channels = len(channel_data)
fig, axes = plt.subplots(n_channels, 1, figsize=(10, 3*n_channels), squeeze=False)
for ch in range(n_channels):
data = channel_data[ch]
time_axis = [i / framerate for i in range(len(data))]
axes[ch][0].plot(time_axis, data, linewidth=0.3)
axes[ch][0].set_xlabel("Time (s)")
axes[ch][0].set_ylabel(f"Amplitude (ch{ch+1})")
axes[ch][0].set_title(f"{title} - Channel {ch+1}")
axes[ch][0].grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
if __name__ == "__main__":
# 使用正弦波生成测试WAV文件(16位单声道,44.1kHz,1秒)
import math
test_file = "test_tone.wav"
sample_rate = 44100
freq = 440.0
amplitude = 0.6
n_samples = sample_rate # 1秒
with wave.open(test_file, 'w') as wf:
wf.setnchannels(1)
wf.setsampwidth(2)
wf.setframerate(sample_rate)
for i in range(n_samples):
value = int(amplitude * 32767 * math.sin(2 * math.pi * freq * i / sample_rate))
wf.writeframes(struct.pack('<h', value))
# 读取并显示信息
info, ch_data = read_wav_info(test_file)
print("=== WAV 文件基本信息 ===")
for key, val in info.items():
print(f"{key}: {val}")
# 绘制波形
plot_waveform(ch_data, info['framerate'], title=test_file)
运行与验证
- 将上述代码保存为
wav_reader.py,在终端执行:python wav_reader.py - 程序会先自动生成一个440Hz、1秒、16位单声道的测试文件
test_tone.wav,然后读取并打印其信息。 - 预期输出(与代码逻辑严格一致):
channels: 1
sampwidth_bytes: 2
bit_depth: 16
framerate: 44100
nframes: 44100
duration_sec: 1.0
compression: NONE - 波形验证:应弹出matplotlib窗口,显示一条频率为440Hz的正弦波曲线,横轴时间范围约0~1秒,纵轴幅度在-0.6~0.6之间(归一化后)。若波形正确显示且信息与预期一致,则案例验证通过。
关键说明
- 代码仅支持16位PCM WAV(最常见格式)。若需处理其他位深,需扩展
struct解包格式。 - 波形绘制使用
matplotlib,若需在无图形界面环境运行,可将plt.show()替换为plt.savefig('waveform.png')保存图片。 - 读取大文件时
readframes(nframes)会一次性载入全部数据,本案例适用于教学演示的小文件;处理大文件时应分块读取。