详解WAVE音频文件格式
WAVE声音文件格式是目前Windows最直接保存声音数据的文件格式.在涉及声音信号处理时大多是对WAV文件直接操作,有必要搞清楚所研究声音的文件格式.
1 RIFF文件与WAV文件
在Windows环境下,大部分多媒体文件都依循着一种结构来存放信息,称为资源互换文件格式(Resources Interchange File Format),简称RIFF。比如声音的WAV文件,视频的AVI文件,动画的MMM文件等均是由此结构衍生出来的.所以,要掌握多媒体文件格式,首先得认识RIFF的结构.
RIFF是一种树状结构,其基本组成单位是chunk(即块),每个chunk由辨识码,数据大小和数据组成,如下图。可以看出,一个chunk的长度,就是数据的大小加上8Byte.
一般而言,chunk本身不允许内部再包含chunk,但有两个例外:以"RIFF"和以"UST"为辨识码的chunk。针对这两种chunk,RIFF又从原先的"裸数据"中切出4Byte作为"格式辨别码",如下图所示.
对RIFF的树状结构有所了解之后,可以知道它相当于一个根目录,而格式辨识码则相当于具体的盘符如C:,D:等等.Windows下的各种多媒体文件格式就如同在磁盘机下规定只能存放怎样的目录,而在该目录下仅能存放何种数据.
2 WAV文件头
顾名思义,WAV就是波形音频文件(Wave Audio),是Windows中用来表示数字化声音的一种标准格式,其文件扩展名为.wav,是一种非常简单的RIFF文件,格式辨识码为"WAVE".整个WAV文件分成两部分:文件头和数据块.WAV格式文件主要有两种文件头.
2.1标准的44字节文件头
这种WAV是最简单的一种RIFF格式,包含两个chunk:<fmt—chunk>,<wave—data>,这两个子块都是一个WAV文件必须包含的.
<fmt—chunk>子块,描述了波形数据<wave~data>的格式,对于44字节文件头,它由结构PCMWAVEF0RMAT组成,其子块大小是sizeof(PCMWAVEF0RMAT),数据是PCMWAVEF0RMAT的数据,如下图所示,其中PCMWAVEF0RMAT是PCM波形音频数据的数据格式结构,大小是l6字节(少数为18字节),定义如下:
RIFF WAVE Chunk
=======================
|名称 |所占字节数 | 具体内容
=======================
| ID | 4 Bytes | 'RIFF'
----------------------------------------
| Size | 4 Bytes |
----------------------------------------
| Type | 4 Bytes | 'WAVE'
----------------------------------------
以'RIFF'作为标示,然后紧跟着为size字段,该size是整个wav文件大小减去ID和Size所占用的字节数,即FileLen - 8 =Size.然后是Type字段,为'WAVE',表示是wav文件.结构定义如下:
struct RIFF_HEADER
{
char szRiffID[4]; // 'R','I','F','F'
DWORD dwRiffSize;
char szRiffFormat[4]; // 'W','A','V','E'
};
Format Chunk
====================================================
| 名称 | 字节数 | 具体内容
====================================================
|ID | 4Bytes | 'fmt'
-----------------------------------------------------------------------------------------------
| Size | 4 Bytes | 数值为16或18,18则最后又附加信息
-----------------------------------------------------------------------------------------------
| FormatTag | 2 Bytes | 编码方式,一般为0x0001(WAVE—FORMAT_PCM)
-----------------------------------------------------------------------------------------------
| Channels | 2Bytes | 声道数目,1--单声道;2--双声道
----------------------------------------------------------------------------------------------
| SamplesPerSec | 4 Bytes | 采样频率
-----------------------------------------------------------------------------------------------
| AvgBytesPerSec | 4 Bytes | 每秒所需字节数 ===> WAVE_FORMAT
-------------------------------------------------------------------------------------------------
| BlockAlign | 2 Bytes | 数据块对齐单位(每个采样需要的字节数)
-------------------------------------------------------------------------------------------------
| BitsPerSample | 2 Bytes | 每个采样需要的bit数
-------------------------------------------------------------------------------------------------
| | 2 Bytes | 附加信息(可选,通过Size来判断有无)
------------------------------------------------------------------------------------------------
以'fmt '作为标示.一般情况下Size为16,此时最后附加信息没有;如果为18则最后多了2个字节的附加信息.主要由一些软件制成的wav格式中含有该2个字节的
附加信息.结构定义如下:
struct WAVE_FORMAT
{
WORD wFormatTag;
WORD wChannels;
DWORD dwSamplesPerSec;
DWORD dwAvgBytesPerSec;
WORD wBlockAlign;
WORD wBitsPerSample;
};
struct FMT_BLOCK
{
char szFmtID[4]; // 'f','m','t',' '
DWORD dwFmtSize;
WAVE_FORMAT wavFormat;
};
为了产生出能够正确读出的WAV文件,必须严格注意以下几个分量间的特定关系,否则产生出的文件将无法正常播放:
nAvgBytesPerSec = nSamplesPerSec*nChannels*wBitsPerSample/8
nBlockAlign = nChannels*wBitsPerSample/8
根据以上规则,下图给出一个8kHz采样,16bit量化的声音文件的<fmt—chunk>.