详解WAVE音频文件格式

来源:互联网 发布:mycat 优化 编辑:程序博客网 时间:2024/06/06 15:49

介绍WAVEFORMATEX结构体的含义:

 
[cpp] view plain copy
  1. typedef struct {     
  2.   WORD wFormatTag;    //波形声音的格式,单声道双声道使用WAVE_FORMAT_PCM.当包含在WAVEFORMATEXTENSIBLE结构中时,使用WAVE_FORMAT_EXTENSIBLE.    
  3.   WORD nChannels;    //声道数量    
  4.   DWORD nSamplesPerSec;  //采样率.wFormatTag为WAVE_FORMAT_PCM时,有8.0kHz,11.025kHz,22.05kHz,和44.1kHz.    
  5.   DWORD nAvgBytesPerSec;  //每秒的采样字节数.通过nSamplesPerSec * nChannels * wBitsPerSample / 8计算    
  6.   WORD nBlockAlign;    //每次采样的字节数.通过nChannels * wBitsPerSample / 8计算    
  7.   WORD wBitsPerSample;  //采样位数.wFormatTag为WAVE_FORMAT_PCM时,为8或者16    
  8.   WORD cbSize;      //wFormatTag为WAVE_FORMAT_PCM时,忽略此参数    
  9. } WAVEFORMATEX;    



详解WAVE音频文件格式


    WAVE声音文件格式是目前Windows最直接保存声音数据的文件格式.在涉及声音信号处理时大多是对WAV文件直接操作,有必要搞清楚所研究声音的文件格式.
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下的各种多媒体文件格式就如同在磁盘机下规定只能存放怎样的目录,而在该目录下仅能存放何种数据.

WAV文件头

顾名思义,WAV就是波形音频文件(Wave Audio),是Windows中用来表示数字化声音的一种标准格式,其文件扩展名为.wav,是一种非常简单的RIFF文件,格式辨识码为"WAVE".整个WAV文件分成两部分:文件头和数据块.WAV格式文件主要有两种文件头.

标准的44字节文件头

这种WAV是最简单的一种RIFF格式,包含两个chunk:<fmt—chunk>,<wave—data>,这两个子块都是一个WAV文件必须包含的.

RIFF WAVE Chunk

以'RIFF'作为标示,然后紧跟着为size字段,该size是整个wav文件大小减去ID和Size所占用的字节数,即FileLen - 8 =Size.然后是Type字段,为'WAVE',表示是wav文件.结构定义如下:

[cpp] view plain copy
  1. struct RIFF_HEADER  
  2. {  
  3.     char szRiffID[4];  // 'R','I','F','F'  
  4.     DWORD dwRiffSize;  
  5.     char szRiffFormat[4]; // 'W','A','V','E'  
  6. };  

Format Chunk

以'fmt '作为标示.一般情况下Size为16,此时最后附加信息没有;如果为18则最后多了2个字节的附加信息.主要由一些软件制成的wav格式中含有该2个字节的

[cpp] view plain copy
  1. struct WAVE_FORMAT  
  2. {  
  3.     WORD wFormatTag;  
  4.     WORD wChannels;  
  5.     DWORD dwSamplesPerSec;  
  6.     DWORD dwAvgBytesPerSec;  
  7.     WORD wBlockAlign;  
  8.     WORD wBitsPerSample;  
  9. };  
  10. struct FMT_BLOCK  
  11. {  
  12.     char  szFmtID[4]; // 'f','m','t',' '  
  13.     DWORD  dwFmtSize;  
  14.     WAVE_FORMAT wavFormat;  
  15. };   

为了产生出能够正确读出的WAV文件,必须严格注意以下几个分量间的特定关系,否则产生出的文件将无法正常播放:
58字节文件头如果不是Windows的标准WAV文件,而是经过了一些软件处理的,往往就是58字节的文件头,如下图所示.

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

Fact Chunk

Fact Chunk是可选字段,一般当wav文件由某些软件转化而成,则包含该Chunk.结构定义如下:

[cpp] view plain copy
  1. struct FACT_BLOCK  
  2. {  
  3.       char  szFactID[4]; // 'f','a','c','t'  
  4.       DWORD  dwFactSize;  
  5. };  

"data"子块数据安排方式

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

Data Chunk头结构定义如下:

[java] view plain copy
  1. struct DATA_BLOCK  
  2.  {  
  3.        char szDataID[4]; // 'd','a','t','a'  
  4.        DWORD dwDataSize;  
  5.  };  

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

原创粉丝点击