详解WAVE音频文件格式
WAVE声音文件格式是目前Windows最直接保存声音数据的文件格式.在涉及声音信号处理时大多是对WAV文件直接操作,有必要搞清楚所研究声音的文件格式.
RIFF是一种树状结构,其基本组成单位是chunk(即块),每个chunk由辨识码,数据大小和数据组成,如下图。可以看出,一个chunk的长度,就是数据的大小加上8Byte.
一般而言,chunk本身不允许内部再包含chunk,但有两个例外:以"RIFF"和以"UST"为辨识码的chunk。针对这两种chunk,RIFF又从原先的"裸数据"中切出4Byte作为"格式辨别码",如下图所示.
对RIFF的树状结构有所了解之后,可以知道它相当于一个根目录,而格式辨识码则相当于具体的盘符如C:,D:等等.Windows下的各种多媒体文件格式就如同在磁盘机下规定只能存放怎样的目录,而在该目录下仅能存放何种数据.
顾名思义,WAV就是波形音频文件(Wave Audio),是Windows中用来表示数字化声音的一种标准格式,其文件扩展名为.wav,是一种非常简单的RIFF文件,格式辨识码为"WAVE".整个WAV文件分成两部分:文件头和数据块.WAV格式文件主要有两种文件头.
这种WAV是最简单的一种RIFF格式,包含两个chunk:
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文件,必须严格注意以下几个分量间的特定关系,否则产生出的文件将无法正常播放:它比44字节的多了一个fact子块.
Fact Chunk
======================
|名称 |所占字节数| 具体内容
======================
| ID | 4 Bytes | 'fact'
---------------------------------------
| Size | 4 Bytes | 数值为4
-------------------------------------
| data | 4 Bytes |
-------------------------------------
Fact Chunk是可选字段,一般当wav文件由某些软件转化而成,则包含该Chunk.结构定义如下:
struct FACT_BLOCK
{
char szFactID[4]; // 'f','a','c','t'
DWORD dwFactSize;
};
"data"子块中装的是真正的声音数据.除非安装其它特殊软件,否则Windows目前仅提供WAVE_FORMAT_PCM一种数据格式,即脉冲编码调制(Pulse Code Modulation).针对此惭式,Windows中"data"子块中数据存放的形式如下图所示,根据声道数不同及取样位数的不同,安排4位的位置.
Data Chunk头结构定义如下:
struct DATA_BLOCK
{
char szDataID[4]; // 'd','a','t','a'
DWORD dwDataSize;
};
对照前面的讲解,看懂这个文件的结构应该非常容易.