AnSwEr's Blog
source link: https://answerywj.com/2022/01/06/wav/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
wav文件格式解析
本文将详细分析不同格式的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
文件头信息,我们可以计算出音频时长:
音频时长(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
- 本文作者: AnSwEr(Weijie Yuan)
- 本文链接: http://answerywj.com/2022/01/06/wav/
- 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明出处!
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK