详解WAVE音频文件格式

详解WAVE音频文件格式

WAVE声音文件格式是目前Windows最直接保存声音数据的文件格式.在涉及声音信号处理时大多是对WAV文件直接操作,有必要搞清楚所研究声音的文件格式.

1 RIFF文件与WAV文件

在Windows环境下,大部分多媒体文件都依循着一种结构来存放信息,称为资源互换文件格式(Resources Interchange File Format),简称RIFF。比如声音的WAV文件,视频的AVI文件,动画的MMM文件等均是由此结构衍生出来的.所以,要掌握多媒体文件格式,首先得认识RIFF的结构.

RIFF是一种树状结构,其基本组成单位是chunk(即块),每个chunk由辨识码,数据大小和数据组成,如下图。可以看出,一个chunk的长度,就是数据的大小加上8Byte.

详解WAVE音频文件格式_第1张图片

一般而言,chunk本身不允许内部再包含chunk,但有两个例外:以"RIFF"和以"UST"为辨识码的chunk。针对这两种chunk,RIFF又从原先的"裸数据"中切出4Byte作为"格式辨别码",如下图所示.

详解WAVE音频文件格式_第2张图片

对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字节),定义如下:

详解WAVE音频文件格式_第3张图片

 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>.

详解WAVE音频文件格式_第4张图片

2.2 58字节文件头

如果不是Windows的标准WAV文件,而是经过了一些软件处理的,往往就是58字节的文件头,如下图所示.

详解WAVE音频文件格式_第5张图片

它比44字节的多了一个fact子块.<fact—ck>储存了关于WAV文件内容的重要信息.该子块定义如下:

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;
 };

3 "data"子块数据安排方式

"data"子块中装的是真正的声音数据.除非安装其它特殊软件,否则Windows目前仅提供WAVE_FORMAT_PCM一种数据格式,即脉冲编码调制(Pulse Code Modulation).针对此惭式,Windows中"data"子块中数据存放的形式如下图所示,根据声道数不同及取样位数的不同,安排4位的位置.

详解WAVE音频文件格式_第6张图片

    Data Chunk头结构定义如下:

struct DATA_BLOCK
 {
	char szDataID[4]; // 'd','a','t','a'
	DWORD dwDataSize;
 };

注意:Windows中将16位值的范围定为[-32768,32767].另外,0并不一定代表无声,而是由中间数值来决定,即8位的时候为128,l6位时0才是无声.所以,编程中需要放入无声的数据时,必须先认清声音格式是l6位还是8位.
通常解压缩后得到的文件仅仅是裸数据,不能正常播放声音.了解了WAV文件格式后,就可以按照标准的44字节格式,在解码数据前编写一个正确的WAV文件头,使其成为一个有效的WAV文件.

4 实例文件分析

下面我们来分析一个真正的WAVE文件(http://download.csdn.net/detail/ce123/5771797).
详解WAVE音频文件格式_第7张图片

对照前面的讲解,看懂这个文件的结构应该非常容易大笑.

你可能感兴趣的:(详解WAVE音频文件格式)