wav数据格式详解
简述
WAV 文件是在 PC 机平台上很常见的、最经典的多媒体音频文件, 是 WaveForm 的简写,也称为波形文件,可直接存储声音波形,还原的波形曲线十分逼真。
WAV 的特点如下:真实记录自然声波形,基本无数据压缩,数据量大。
文件结构
WAV 文件遵循 RIFF 规则,其内容以区块(chunk)为最小单位进行存储。WAV文件一般由3个区块组成:RIFF chunk、Format chunk 和 Data chunk。
CHUNK
每个 CHUNK 的格式都是:
名称 | 字节数 | 说明 |
---|---|---|
ID | 4 | 标识 |
Size | 4 | 该块的数据长度 |
Data | Size | 该块的数据 |
以下是存在的 CHUNK 类型:
数据块符号 | 数据块名称 | 可选否 |
---|---|---|
RIFF chunk |
文件头数据块 | 否 |
Format chunk |
格式数据块 | 否 |
Data chunk |
波形数据块 | 否 |
Fact chunk |
是 | |
Cue points chunk |
是 | |
Playlist chunk |
是 | |
Associated data list chunk |
是 |
RIFF chunk
名称 | 字节数 | 端序 | 内容 |
---|---|---|---|
ID | 4 | 大端 | RIFF (0x52494646) |
Size | 4 | 小端 | fileSize - 8 (文件大小 - 8) |
Type | 4 | 大端 | WAVE (0x57415645) |
当 Type 是 WAVE
时,表示后面需要两个子块:Format chunk
和
Data chunk
。
Format chunk
名称 | 字节数 | 端序 | 内容 |
---|---|---|---|
ID | 4 | 大端 | fmt (0x666D7420) |
Size | 4 | 小端 | 16 |
AudioFormat | 2 | 小端 | 音频格式 |
NumChannels | 2 | 小端 | 声道数 (1 or 2) |
SampleRate | 4 | 小端 | 采样率 |
ByteRate | 4 | 小端 | 每秒数据字节数 |
BlockAlign | 2 | 小端 | 数据块对齐 |
BitsPerSample | 2 | 小端 | 采样位数 (8, 16 or 32) |
需要注意的是,ByteRate 和 BlockAlign 是可以计算出来的,如果不满足公式可能导致读取文件错误:
ByteRate = SampleRate * NumChannels * BitsPerSample / 8
BlockAlign = NumChannels * BitsPerSample / 8
BitsPerSample 代表的是采样位数,即接下来的 Data chunk 中的每个波形数据有几个字节。
Data chunk
名称 | 字节数 | 端序 | 内容 |
---|---|---|---|
ID | 4 | 大端 | data (0x64617461) |
Size | 4 | 小端 | N |
Data | Size | 小端 | 波形数据 |
需要注意的是,Size = ByteRate * seconds
如果声道数为 2,即多声道音频,在 Data 中每次采样依次排列,即例如 8bit 双声道的数据存放为:
采样1 | 采样2 | ||
---|---|---|---|
声道1数据 (1 byte) | 声道2数据 (1 byte) | 声道1数据 (1 byte) | 声道2数据 (1 byte) |
音频处理
python3&wave
这里使用 Python3 对 wav 文件进行处理。
在 Python3 中自带一个 wave
模块支持对 wav
格式的音频数据进行处理,结合 numpy
可以自由操作所有 wav
的波形数据。
常用的操作有:
函数 | 作用 |
---|---|
wave.open(filename, "r") |
打开一个音频文件,返回 Wave_read 对象 |
Wave_read.close() |
关闭一个 Wave_read 对象 |
Wave_read.getnchannels() |
返回声道数量,1为单声道,2为立体声 |
Wave_read.getsampwidth() |
返回采样位数 |
Wave_read.getframerate() |
返回采样频率 |
Wave_read.getnframes() |
返回音频总帧数 |
Wave_read.readframes(n) |
读取 n 帧波形数据,如果参数为 -1 则读取所有 |
将波形数据转化为成 ndarray
的示例代码:
1 | import wave |
python3&soundfile
但这里更推荐使用第三方库
soundfile
,可以更轻松的将音频数据读取并转换为
ndarray
,示例代码如下:
1 | data, samplerate = sf.read("attachment.wav") |
其中,samplerate
是音频的采样率。
但默认读取类型是 float
,如果觉得不好看,可以通过
dtype
参数控制输出的 numpy
数组的
dtype
。
1 | data, samplerate = sf.read("attachment.wav", dtype = np.int16) |
同时如果是多声道的音频文件,它将转换出多个 ndarray
数组来保存不同声道的数据。