首页 > 代码库 > WAVE文件格式解析

WAVE文件格式解析

WAVE 文件作为Windows多媒体中使用的声音波形文件格式之一,它是以RIFF(Resource Interchange File Format)格式为标准的。这里不针对RIFF文件格式做介绍,不太了解的可以参考“RIFF格式简介”一文。

WAVE文件构成

每个WAVE文件的头四个字节便是“RIFF”。WAVE 文件由文件头和数据体两大部分组成。其中文件头又分为 RIFF/WAV 文件标识段和声音数据格式说明段两部分。相对于RIFF文件,只是将“RIFF”chunk的form id替换为“WAVE”。下表是一个典型的WAVE文件各部分构成及其长度字段。注意所有数据采用windows默认的小端存储。(FOURCC是一个特殊的四字节码,判断时按照字符顺序判断即可。)

长度内容说明
chunkID4Chunk ID: "RIFF",FOURCC四字节码
chunksize4Chunk size: 4+n
 WAVEID4WAVE ID: "WAVE",FOURCC四字节码
WAVE chunksnWave chunks包含格式信息和音频采样数据,分为“format” chunk和“data”chunk两部分。

 Format chunk

Format chunk用于说明data chunk中PCM数据的格式。主要三种不同的format chunk格式(不同的格式码)。如下表:

长度内容说明
ckID4Chunk ID: "fmt ",FOURCC四字节码,注意最后一个填充是空格。
cksize4Chunk size: 16 or 18 or 40
 wFormatTag2Format code,格式码
nChannels2Number of interleaved channels,采样声道数(交织存储)
nSamplesPerSec4Sampling rate (blocks per second),音频采样率
nAvgBytesPerSec4Data rate,音频码率
nBlockAlign2Data block size (bytes),音频数据块大小(单位字节)
wBitsPerSample2Bits per sample,量化位数(比如8bits、16bits、32bits)

cbSize2Size of the extension (0 or 22),扩展字段长度

wValidBitsPerSample2Number of valid bits,有效的位长度
dwChannelMask4Speaker position mask,声道描述掩码,比如左声道、右声道等
SubFormat16GUID, including the data format code,数据格式码

 标准中定义的wFormatTag(Format code)可取值范围如下表:

Format CodePreProcessor SymbolData
0x0001WAVE_FORMAT_PCMPCM
0x0003WAVE_FORMAT_IEEE_FLOATIEEE float,[-1.0f,1.0f]
0x0006WAVE_FORMAT_ALAW8-bit ITU-T G.711 A-law
0x0007WAVE_FORMAT_MULAW8-bit ITU-T G.711 µ-law
0xFFFEWAVE_FORMAT_EXTENSIBLEDetermined by SubFormat

PCM格式

当wFormatTag为0x0001时,表示WAVE文件中存储的是PCM格式的音频数据。

在数据域中除了单声道-量化位数为8音频数据之外PCM存储格式按照补码的形式存放。对于单声道、量化位数为8的情况,使用offset binary(偏移二进制码),有兴趣的可以查看下对应的标准。

非PCM格式

对于非PCM格式的数据,使用扩展字段,扩展字段长度由cbSize指定。需要说明以下几点:

  • 对于非PCM格式,必须有扩展字段,字段长度cbSize可以为0,但是扩展字段不可省略。
  • 对于浮点数据,最大峰值为1,量化位数(bits/sample)取值可以是32或64。
  • 对于 log-PCM formats (µ-law and A-law)的格式,量化位数(bits/sample)取值为8。
  • 对于非PCM格式,必须包含“FACT”chunk。

 扩展格式

当FormatTag为WAVE_FORMAT_EXTENSIBLE(0xFFFE)时,表示format chunk有扩展字段,其中包括有效量化位数(wValidBitsPerSample)、声道位置掩码、以及额外的GUID(SubFormat)。

  • 在正常PCM数据中量化位数(wBitsPerSample)必须是8的倍数,在WAVE_FORMAT_EXTENSIBLE下量化位数可以使用wValidBitsPerSample来描述,也就是会所wValidBitsPerSample有可能小于wBitsPerSample。
  • 对于声道位置掩码的信息,可参考如下文章:Multi-channel / high bit resolution formats, 2001-12-04: Multiple Channel Audio Data and WAVE Files。
  • SubFormat代表的GUID前两个字节是由PCM数据格式填充的,例如WAVE_FORMAT_EXTENSIBLE。后续的14个字节是固定的,"\x00\x00\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71"。

在以下几种情况下必须使用WAVE_FORMAT_EXTENSIBLE格式:

  1. PCM数据的量化位数(wBitsPerSample)大于16。
  2. 音频采样声道数大于2。
  3. 实际量化位数不是8的倍数。
  4. 存储顺序和播放顺序不一致,需要指定从声道顺序到声卡播放顺序映射的情况。

FACT chunk

通常PCM数据是不压缩的,对于所有压缩的非PCM格式都需要有FACT chunk。具体可参考:WAVE update (Revision: 3.0), 1994-04-15: Multimedia Registration Kit Revision 3.0 (Q120253))。FACT chunk至少定义一个字段,实际采样数dwSampleLength。

关于FACT chunk可以了解,但是很少用到,如果有这种格式的wav文件,建议参考上述标准解析。

DATA chunk

data chunk中包含采样数据。格式如下:

长度内容说明
ckID4Chunk ID: "data"
cksize4Chunk size: n
 sampled datanSamples,音频采样数据,交织存储
pad byte0 or 1Padding byte if n is odd,填充字节

 

实例

由于微软将多媒体输入输出函数废弃了(Using Multimedia File I/O),这里不给出专门读写的代码,而是直接使用二进制形式分析。

先做如下假定:

  • Nc 表示channels,声道数
  • Ns表示文件中包含的实际采样块数目,每个采样块包括Nc 个独立采样
  • 采样率为 F (blocks per second,单位Hz)
  • 每个采样的长度为M字节。

PCM文件格式如下表:

FieldLengthContents
ckID4Chunk ID: "RIFF"
cksize4Chunk size: 4 + 24 +
(8 + Nc * Ns + (0
 or 1))
 WAVEID4WAVE ID: "WAVE"

ckID4Chunk ID: "fmt "
cksize4Chunk size: 16
 wFormatTag2WAVE_FORMAT_PCM
nChannels2Nc
nSamplesPerSec4F
nAvgBytesPerSec4F * M * Nc
nBlockAlign2Nc
wBitsPerSample2rounds up to 8 * M

ckID4Chunk ID: "data"
cksize4Chunk size: M * Nc* Ns
 sampled dataM * Nc * NsNc * Ns channel-interleaved M-byte samples
pad0 or 1Padding byte if M * Nc * Nis odd

注意WAVE文件可能附加information chunk。所以程序解析是最好按照上述标准定义,不要认为去掉wav fmt chunk之后全是data chunk。

Extensible Format如下表:

FieldLengthContents
ckID4Chunk ID: "RIFF"
cksize4Chunk size: 4 + 48 + 12 +
(8 + M * Nc * Ns + (0 
or 1))
 WAVEID4WAVE ID, "WAVE"

ckID4Chunk ID: "fmt "
cksize4Chunk size: 40
 wFormatTag2WAVE_FORMAT_EXTENSIBLE
nChannels2Nc
nSamplesPerSec4F
nAvgBytesPerSec4F * M * Nc
nBlockAlign2M * Nc
wBitsPerSample28 * M
cbSize2Size of the extension: 22
wValidBitsPerSample2at most 8 * M
dwChannelMask4Speaker position mask: 0
SubFormat16GUID (first two bytes are the data format code)

ckID4Chunk ID: "fact"
cksize4Chunk size: 4
 dwSampleLength4Nc * Ns

ckID4Chunk ID: "data"
cksize4Chunk size: M * Nc * Ns
 sampled dataM * Nc *NsNc * Ns channel-interleaved M-byte samples
pad0 or 1Padding byte if M * Nc * Ns is odd

本文主要参考:Audio File Format Specifications,相关测试wav文件及标准也从其链接下载。

写作本文的目的主要是学习下wave文件格式,并能够将音频数据解析出来。

以上介绍的内容中针对WAVE文件我们可以只关心,fmt chunk、data chunk数据,其他数据chunk可以忽略,如果你对其他chunk感兴趣,建议查看rfc2361及Microsoft提供的标准文档。

 

WAVE文件格式解析