WAV音频文件解析与Python读取
WAV音频文件解析与Python读取
WAV(波形声音文件)是最常见的声音文件格式之一,是微软公司专门为Windows开发的一种标准数字音频文件,该文件能记录各种单声道或立体声的声音信息,并能保证声音不失真。
1. WAV文件格式
通常在ASR(语音识别)等使用的PCM音频文件
PCM(脉冲编码调制,PulseCodeModulation)是对连续变化的模拟信号进行抽样、量化和编码产生的数字信号。
在读取前需要通过FFmpeg工具转换
# MP3转WAV例子
ffmpeg -i input.mp3 -acodec pcm_s16le -ar 16000 -ac 1 output.wav
s(signed)代表有符号,16代表量化位数为16位,le(little endian)为小端存储(先存低字节,再存高字节)
1.1 WAV文件格式解析
具体内容:
第一块RIFF(共12字节):
ChunkID:4字节,值为b’RIFF’
ChunkSize:4字节,值为文件总字节数减8
Format:4字节,值为b’WAVE’
(注:RIFF(Resource Interchange File Format)是指资源互换文件格式)
第二块fmt(共24字节):
Subchunk1ID:4字节,值为b’fmt’
Subchunk1Size:4字节,值为16,实际为后面这块内容所占的字节数即24-8=16
AudioFormat:2字节,值为1,表示为PCM格式
NumChannels:2字节,声道数,值为1,表示为单声道
SampleRate:4字节,采样率,值为16000,
ByteRate:4字节,音频码率,值为32000,音频码率=声道数*采样率*量化位数/8
BlockAlign:2字节,值为2,表示为每个采样点的字节数=声道数*量化位数/8
BytePerSample:2字节,量化位数,值为16
(注:AudioFormat有4种:
值 | 文件格式 |
---|---|
0x0001 | PCM |
0x0002 | ADPCM |
0x0006 | AKAW |
0x0007 | MULAM |
0xFFFE | EXTENSIBLE |
)
第三块data(共8+SubChunkSize2字节):
Subchunk2ID:4字节,值为b’data’
Subchunk2Size:4字节,音频数据长度
data:Subchunk2Size字节
2. Python读取WAV文件方式
2.1 通过wave模块读取
import wave
with wave.open("example.wav", "rb") as wav_file:
params = wav_file.getparams()
print(params)
frames = wav_file.readframes(params.nframes)
print(len(frames), frames[:10])
测试结果
读取WAV音频函数定义:
def readframes(self, nframes):
......
return data
因此也可以通过一下方式直接读取音频
with wave.open("example.wav", "rb") as wav_file:
frames = wav_file.readframes(wav_file.getnframes())
2.2 通过struct模块解析二进制文件
import struct
with open("example.wav", "rb") as wav_file:
data = wav_file.read()
riff_header = data[:12]
riff_id, riff_size, format = struct.unpack('<4sI4s', riff_header)
print(riff_id, riff_size, format)
format_chuck = data[12:20]
fmt, fmt_size = struct.unpack('<4sI', format_chuck)
print(fmt, fmt_size)
assert fmt_size == 16
format_data = data[20:36]
audio_format, channels, sample_rate, bytes_per_sec, block_align, bytes_per_sample = struct.unpack('<HHIIHH', format_data)
print(audio_format, channels, sample_rate, bytes_per_sec, block_align, bytes_per_sample)
assert audio_format == 1
data_chuck = data[36:44]
data_id, data_size = struct.unpack('<4sI', data_chuck)
print(data_id, data_size)
frames = data[44:44+data_size]
print(len(frames), frames[:10])
运行结果
作者:莽夫搞战术