关于wav文件格式的分析

 WAVE文件的格式,简单地说,就是文件头加上PCM数据。PCM数据已经是音频的裸数据,我们只需要搞清楚这个文件头的格式就行了。

解释代码如下:

        BYTE *pb = (BYTE *)_alloca(m_cbHeader);

        RIFFLIST  *pRiffWave = (RIFFLIST *)pb;
        RIFFCHUNK *pRiffFmt  = (RIFFCHUNK *)(pRiffWave + 1);
        RIFFCHUNK *pRiffData = (RIFFCHUNK *)(((BYTE *)(pRiffFmt + 1)) +
                               m_pInput->CurrentMediaType().FormatLength());

        pRiffWave->fcc = FCC('RIFF');
        pRiffWave->cb = m_cbWavData + m_cbHeader - sizeof(RIFFCHUNK);
        pRiffWave->fccListType = FCC('WAVE');

 

        pRiffFmt->fcc = FCC('fmt ');
        pRiffFmt->cb = m_pInput->CurrentMediaType().FormatLength();
        CopyMemory(pRiffFmt + 1, m_pInput->CurrentMediaType().Format(), pRiffFmt->cb);

   


 

        pRiffData->fcc = FCC('data');
        pRiffData->cb = m_cbWavData;

       

首先,一般是一个RIFFLIST数据结构,定义如下:
typedef   struct   _rifflist   {
      FOURCC   fcc;
      DWORD     cb;
      FOURCC   fccListType;
      }   RIFFLIST,   *   LPRIFFLIST;
其中,fcc赋值为FCC( 'RIFF '),fccListType赋值为FCC( 'WAVE '),cb表示为这个数据结构后面紧跟着的所有数据的总长度(不包括当前这个数据结构的大小,以字节为单位)。

接下去,是一个RIFFCHUNK数据结构,描述音频的格式,定义如下:
typedef   struct   _riffchunk   {
      FOURCC   fcc;
      DWORD     cb;
      }   RIFFCHUNK,   *   LPRIFFCHUNK;
其中,fcc赋值为FCC( 'fmt   '),cb表示为紧跟在这个数据结构后面的音频格式数据块的长度,一般为sizeof(WAVEFORMATEX)。

接下去,紧跟着一个音频格式数据块,一般为WAVEFORMATEX格式,定义如下:
typedef   struct   waveformat_extended_tag   {
        WORD     wFormatTag;            
        WORD     nChannels;              
        DWORD   nSamplesPerSec;    
        DWORD   nAvgBytesPerSec;  
        WORD     nBlockAlign;          
        WORD     wBitsPerSample;    
        WORD     cbSize;                    
}   WAVEFORMATEX;
这个数据结构中的各个成员大家应该很熟悉,主要描述音频的采样频率、通道数等属性。声卡根据这些信息才能正确解释后面的PCM数据。

再往下,紧跟着另一个RIFFCHUNK数据结构,定义同上。这个数据结构的fcc赋值为FCC( 'data '),cb表示为这个数据结构后面紧跟着的PCM数据的长度。

最后,紧跟着的,就都是PCM数据了。

 

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

WAVE 文件作为多媒体中使用的声音波形文件格式之一,它是以RIFF(Resource Interchange File Format)格式为标准的。每个WAVE文件的头四个字节便是“RIFF”。WAVE 文件由文件头和数据体两大部分组成。其中文件头又分为 RIFF/WAV 文件标识段和声音数据格式说明段两部分。WAVE文件各部分内容及格式见后文。

常见的声音文件主要有两种,分别对应于单声道(11.025KHz 采样率、8Bit 的采样值)和双声道(44.1KHz 采样率、16Bit 的采样值)。采样率是指:声音信号在“模→数”转换过程中单位时间内采样的次数。采样值是指每一次采样周期
内声音模拟信号的积分值。

对于单声道声音文件,采样数据为八位的短整数(short int 00H-FFH);而对于双声道立体声声音文件,每次采样数据为一个16位的整数(int),高八位和低八位分别代表左右两个声道。

WAVE 文件数据块包含以脉冲编码调制(PCM)格式表示的样本。WAVE 文件是由样本组织而成的。在单声道 WAVE 文件中,声道0代表左声道,声道1代表右声道。在多声道WAVE文件中,样本是交替出现的。

WAVE 文件除了前面一小段文件头对数据组织进行说明之外,Data 块就是声音的原始采样数据,WAVE 文件虽然可以压缩,但一般都使用不压缩的格式。44.1KHz 采样率、16Bit的分辨率、双声道,所以WAVE可以保存音质要求非常高的声音文件,CD 采用的也是这种格式,声音方面的专家或是音乐发烧友们应该非常熟悉。但这种文件的体积也非常大,以 44.1KHz 16bit 双声道的数据为例,一分钟的声音数据量为:4100*2byte*2channel*60s/1024/1024=10.09M 。所以不合适在网上传送。


 

下面我们具体地分析 WAVE 文件的格式

endian

field name

Size

 
bigChunkID4文件头标识,一般就是" RIFF" 四个字母
littleChunkSize4整个数据文件的大小,不包括上面ID和Size本身
bigFormat4一般就是" WAVE" 四个字母
bigSubChunk1ID4格式说明块,本字段一般就是"fmt "
littleSubChunk1Size4本数据块的大小,不包括ID和Size字段本身
littleAudioFormat2音频的格式说明
littleNumChannels2声道数
littleSampleRate4采样率
littleByteRate4比特率,每秒所需要的字节数
littleBlockAlign2数据块对齐单元
littleBitsPerSample2采样时模数转换的分辨率
bigSubChunk2ID4真正的声音数据块,本字段一般是"data"
littleSubChunk2Size4本数据块的大小,不包括ID和Size字段本身
littleDataN音频的采样数据

以下是对各个字段的详细解说:

ChunkID4bytesASCII 码表示的“RIFF”。(0x52494646)
ChunkSize4bytes36+SubChunk2Size,或是
4 + ( 8 + SubChunk1Size ) + ( 8 + SubChunk2Size ),
这是整个数据块的大小(不包括ChunkID和ChunkSize的大小)
Format4bytesASCII 码表示的“WAVE”。(0x57415645)
SubChunk1ID新的数据块(格式信息说明块)
ASCII 码表示的“fmt ”——最后是一个空格。(0x666d7420)
SubChunk1Size4bytes本块数据的大小(对于PCM,值为16)。
AudioFormat2bytesPCM = 1 (比如,线性采样),如果是其它值的话,则可能是一些压缩形式
NumChannels2bytes1 => 单声道  |  2 => 双声道
SampleRate4bytes采样率,如 8000,44100 等值
ByteRate4bytes等于: SampleRate * numChannels * BitsPerSample / 8
BlockAlign2bytes等于:NumChannels * BitsPerSample / 8
BitsPerSample2bytes采样分辨率,也就是每个样本用几位来表示,一般是 8bits 或是 16bits
   
SubChunk2ID4bytes新数据块,真正的声音数据
ASCII 码表示的“data ”——最后是一个空格。(0x64617461)
SubChunk2Size4bytes数据大小,即,其后跟着的采样数据的大小。
DataN bytes真正的声音数据

对于Data块,根据声道数和采样率的不同情况,布局如下(每列代表8bits):

1. 8 Bit 单声道:

采样1采样2
数据1数据2

2. 8 Bit 双声道

采样1采样2
声道1数据1声道2数据1声道1数据2声道2数据2

1. 16 Bit 单声道:

采样1采样2
数据1低字节数据1高字节数据1低字节数据1高字节

2. 16 Bit 双声道

采样1 
声道1数据1低字节声道1数据1高字节声道2数据1低字节声道2数据1高字节
采样2   
声道1数据2低字节声道1数据2高字节声道2数据2低字节声道2数据2高字节

 

下面我们看一个具体的例子,声音文件如下:

52 49 46 46 24 08 00 00 57 41 56 45 
66 6d 74 20 10 00 00 00 01 00 02 00 
22 56 00 00 88 58 01 00 04 00 10 00 
64 61 74 61 00 08 00 00 00 00 00 00 
24 17 1e f3 3c 13 3c 14 16 f9 18 f9 
34 e7 23 a6 3c f2 24 f2 11 ce 1a 0d 

对应的分析如下图所示:

untitled

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值