本文将详细分析不同格式的wav文件。
简介wav即wave(下文统称为wav), 该文件格式是由微软开发的用于音频数字存储的标准,可应用于Windows、Linux和MacOS等多种操作系统,文件扩展名为.wav,是waveform的简写。
wav文件结构在Windows下,大部分多媒体文件都遵循RIFF(Resource Interchange File Format,资源互换文件格式)格式来存储数据。
RIFF文件的基本存储单位称为块(chunk),一个遵循RIFF格式的文件由若干个chunk组成,每个chunk又由块标识、块长度和块数据三部分构成,其基本结构见表1:
Field
Size(bytes)
Type
块标识
4
S8 *
块长度
4
U32
块数据
S8 *
**表1** `chunk`基本结构
块标识:用于标识块中的数据,由4个ASCII字符组成,如不满4个字符则在右边以空格充填,如:RIFF、LIST、fmt 和data等;
块长度:用于标识块数据域中的数据长度,块标识域和块长度域不包括在其中,所以一个chunk的实际长度为该值加8;
块数据:存储块数据,若数据长度为奇数,则在最后添加一个NULL;
特别需要注意的是,RIFF格式规定只有块标识为RIFF或LIST的块可以含有子块(subChunk),而其它块只可以包含数据。块标识为RIFF或LIST的块的结构与表1大致相同,只不过其块数据域分为两部分:
type:由4个ASCII字符组成,代表RIFF文件的类型,如WAVE和AVI ,或者代表LIST块的类型,如avi文件中的列表hdrl和movi;
data:实际的块内容,包含若干subChunk;
wav文件是非常简单的一种RIFF文件,其本身就是由一个块标识为RIFF的chunk和多个subChunk组成的一个chunk,其组成如下:
RIFF chunk:主块,必选,块标识为RIFF,说明这是一个RIFF文件,RIFF文件的第一个块标识必须是RIFF;
Format chunk:子块,必选,块标识为fmt ,用于存储文件的一些参数信息,比如采样率、通道数和编码格式等;
Fact chunk:子块,可选,块标识为fact,基于压缩编码的wav文件必须含有fact块;
List chunk:子块,可选,块标识为LIST,用于记录文件版权和创建时间信息;
Data chunk:子块,必选,块标识为data,用于存储音频数据;
目前业界标准的wav文件仅由RIFF chunk、Format chunk和Data chunk组成:
wav文件头格式wav文件从数据类型上看,主要由文件头和数据体两部分组成:
文件头:由RIFF chunk、Format chunk、List chunk和Fact chunk等组成,用于存储一些文件信息;
数据体:由Data chunk组成,用于存储音频数据;
标准格式标准的wav文件头仅由RIFF chunk和Format chunk组成,长度为44个字节,格式见表2:
file offset(bytes)
Field name
Field size(bytes)
type
endian
description
0
Chunk ID
4
S8 *
big
“RIFF”,表明为RIFF文件
4
Chunk Size
4
U32
little
除了RIFF及自己之外,整个文件的长度,即文件总字节数减去8字节
8
Format
4
S8 *
big
“WAVE”,表明为wav格式
12
Subchunk1 ID
4
S8 *
big
“fmt “
16
Subchunk1 Size
4
U32
little
表示fmt数据块即subchunk1除了Subchunk1 ID和Subchunk1 Size之后剩下的长度,一般为16, 大于16表示存在扩展区域,可选值为16、18、20、40等
20
AudioFormat
2
U16
little
编码格式,即压缩格式,0x01表示pcm格式,无压缩,参见表3
22
NumChannels
2
U16
little
音频通道数,单声道为1,立体声或双声道为2
24
SampleRate
4
U32
little
采样频率,每个通道单位时间采样次数,可选值为16000kHz和44100kHz等
28
ByteRate
4
U32
little
数据传输速率,可用此估算缓冲区长度,ByteRate = SampleRate * NumChannels * (BitsPerSample / 8)
32
BlockAlign
2
U16
little
采样一次的字节数,即一帧的字节数,表示块对齐的内容(数据块的调整数),播放软件一次处理多少个该长度的字节数据,以便将其用于缓冲区的调整,BlockAlign = NumChannels * (BitsPerSample / 8)
34
BitsPerSample
2
U16
little
采样位宽,即每个采样点的bit数,可选值8、16或32等
36
Subchunk2 ID
4
S8 *
big
“data”
40
Subchunk2 Size
4
U32
little
音频数据的总长度,即文件总字节数减去wav文件头的长度
44
Data
little
音频数据
**表2** 标准的`wav`文件头格式
通过wav文件头信息,我们可以计算出音频时长:
1音频时长(s) = Subchunk2 Size / ByteRate
压缩编码格式wav文件几乎支持所有ACM规范的编码格式,其信息存储在wav文件头偏移20、21两个字节中,常见的压缩编码格式见表3:
格式代码
格式名称
Format chunk 长度
是否有Fact chunk
0 (0x0000)
unknown
unknown
unknown
1 (0x0001)
PCM/uncompressed
16
无
2 (0x0002)
Microsoft ADPCM
18
有
3(0x0003)
IEEE float
18
有
6 (0x0006)
ITU G.711 a-law
18
有
7 (0x0007)
ITU G.711 µ-law
18
有
17 (0x0011)
IMA ADPCM
unknown
unknown
20 (0x0016)
ITU G.723 ADPCM (Yamaha)
unknown
unknown
49 (0x0031)
GSM 6.10
20
有
64 (0x0040)
ITU G.721 ADPCM
unknown
有
80 (0x0050)
MPEG
unknown
unknown
65,534 (0xFFFE)
扩展格式标识
40
unknown
65,536 (0xFFFF)
Experimental
unknown
unknown
**表3** 常见的压缩编码格式
扩展格式当然,也不是所有的wav文件头都是44个字节的,比如通过FFmpge编码而来的wav文件头通常大于44个字节,目前比较常见的wav文件头长度有44字节、46字节、58字节和98字节。
Format chunk扩展当wav文件采用非PCM编码即压缩格式时,会扩展Format chunk,在其之后扩充了一个数据结构,见表4:
file offset(bytes)
Field name
Field size(bytes)
type
description
24
extand size
2
U16
除其自身外的扩展区域长度
26
extand area
包含扩展的格式信息,其长度取决于压缩编码类型。当某种编码格式(如ITU G.711 a-law)使扩展区的长度为0时,该字段还必须保留,只是长度字段的数值为0。
**表4** 标准Format chunk扩展格式
由此可以得出,如果Subchunk1 Size等于0x10(16),表示不包含Format chunk扩展,wav文件头长度为44字节;如果大于0x10(16),则包含Format chunk扩展,扩展长度的最小值为18(16+2),此时wav文件头大于44字节。
当编码格式代码为0xFFFE时,Format chunk扩展长度为24字节,格式见表5。
file offset(bytes)
Field name
Field size(bytes)
type
description
24
扩展区长度
2
U16
值为22
26
有效采样位数
2
U16
最大值为 每个采样字节数 * 8
28
扬声器位置
4
U32
声道号与扬声器位置映射的二进制掩码
32
编码格式
2
U16
真正的编码格式代码
34
14
值为{\x00, \x00, \x00, \x00, \x10, \x00, \x80, \x00, \x00, \xAA, \x00, \x38, \x9B, \x71}
**表5** 编码为0xFFFE的Format chunk扩展格式
Fact chunk采用压缩编码(修订版Rev.3以后出现的编码格式)的wav文件必定有含有Fact chunk,其结构符合标准chunk结构,参见表1。
Fact chunk的块标识符为”fact“,块长度至少为4个字节,目前其只有一个块数据内容,即每个声道采样总数,或采样帧总数。该值等于Subchunk2 Size / BlockAlign。
值得注意的是,在实测中发现,将压缩编码格式文件转换成PCM编码格式后,原Fact chunk仍然存在。
wav文件动态解析库wav文件格式是一种极其简单的文件格式,如果对其结构足够熟悉,完全可以通过代码正确读写,从而免去引入一些复杂的中间库,降低复杂度,提高工作效率。
这里提供了一个wav文件动态解析库,欢迎使用。
Reference
WAVE PCM soundfile format
wav音频文件头动态解析–java语言
史上全最的WAV格式详解
wav文件格式分析与详解