一、综述
WAVE文件作为多媒体中使用的声波文件格式之一,它是以RIFF格式为标准的。
RIFF是英文Resource Interchange File Format的缩写,每个WAVE文件的头四个
字节便是“RIFF”。
WAVE文件是由若干个Chunk组成的。按照在文件中的出现位置包括:RIFF WAVE
Chunk, Format Chunk, Fact Chunk(可选), Data Chunk。具体见下图:
------------------------------------------------
| RIFF WAVE Chunk
| ID = 'RIFF'
| RiffType = 'WAVE'
------------------------------------------------
| Format Chunk
| ID = 'fmt '
------------------------------------------------
| Fact Chunk(optional)
| ID = 'fact'
------------------------------------------------
| Data Chunk
| ID = 'data'
------------------------------------------------
图1 Wav格式包含Chunk示例
其中除了Fact Chunk外,其他三个Chunk是必须的。每个Chunk有各自的ID,位
于Chunk最开始位置,作为标示,而且均为4个字节。并且紧跟在ID后面的是Chunk大
小(去除ID和Size所占的字节数后剩下的其他字节数目),4个字节表示,低字节
表示数值低位,高字节表示数值高位。下面具体介绍各个Chunk内容。
PS:
所有数值表示均为低字节表示低位,高字节表示高位。
二、具体介绍
RIFF WAVE Chunk
==================================
| |所占字节数| 具体内容 |
==================================
| ID | 4 Bytes | 'RIFF' |
----------------------------------
| Size | 4 Bytes | | //除去id , size剩下的字节数(文件大小-8)
----------------------------------
| Type | 4 Bytes | 'WAVE'|
----------------------------------
图2 RIFF WAVE Chunk
以'FIFF'作为标示,然后紧跟着为size字段,该size是整个wav文件大小减去ID
和Size所占用的字节数,即FileLen - 8 = Size。然后是Type字段,为'WAVE',表
示是wav文件。
结构定义如下:
struct RIFF_HEADER
{
char szRiffID[4]; // 'R','I','F','F'
DWORD dwRiffSize; //减去id , size占的字节数 ,对应的就是整个文件wav的大小,下面的format chunk的大小就不是整个wav的大小了.
char szRiffFormat[4]; // 'W','A','V','E'
};
在Format chunk中,除了有音频的数据的采样率、声道等音频的属性外,另一个比较主要的字段就是format_tag,该字段表示音频数据是以何种方式编码存放的。其具体的取值可以为以下:
1(0x0001) | PCM/非压缩格式 | 16 | |
2(0x0002 | Microsoft ADPCM | 18 | √ |
3(0x0003) | IEEE float | 18 | √ |
6(0x0006) | ITU G.711 a-law | 18 | √ |
7(0x0007) | ITU G.711 μ-law | 18 | √ |
49(0x0031) | GSM 6.10 | 20 | √ |
64(0x0040) | ITU G.721 ADPCM | √ | |
65,534(0xFFFE) | 见子格式块中的编码格式 | 40 |
Format Chunk
====================================================================
| | 字节数 | 具体内容 |
====================================================================
| ID | 4 Bytes | 'fmt ' |
--------------------------------------------------------------------
| Size | 4 Bytes | 数值为16或18,18则最后又附加信息 | //本chunk大小-8
--------------------------------------------------------------------
| FormatTag | 2 Bytes | 编码方式,一般为0x0001 |
-------------------------------------------------------------------- |
| Channels | 2 Bytes | 声道数目,1--单声道;2--双声道 |
--------------------------------------------------------------------
| SamplesPerSec | 4 Bytes | 采样频率 |
--------------------------------------------------------------------
| AvgBytesPerSec| 4 Bytes | 每秒所需字节数 |===> WAVE_FORMAT
-------------------------------------------------------------------- |
| BlockAlign | 2 Bytes | 数据块对齐单位(每个采样需要的字节数)|
-------------------------------------------------------------------- |
| BitsPerSample | 2 Bytes | 每个采样需要的bit数 |
-------------------------------------------------------------------- |
| | 2 Bytes | 附加信息(可选,通过Size来判断有无) |
--------------------------------------------------------------------
图3 Format Chunk
以'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; //16或者18
WAVE_FORMAT wavFormat;
};
例子说明:44头,无附加信息
-rwxrwxrwx 1 root root 739160 Aug 8 17:47 115.wav*
例子说明:
位置 | 字节 | 数值 | 描述 | 类型 | 大小端 |
1-4 | 4 | STR | 固定格式 "RIFF" | 52 49 46 46 |
大 |
5 - 8 | 4 | U32 | 文件长度-8 739152(00 0b 47 50) | 50 47 0b 00 | 小 |
9 -12 | 4 | STR | 文件类型 "WAVE" | 41 57 45 56 | 大 |
13-16 | 4 | STR | 格式表示符 "fmt " | 66 6d 74 20 | 大 |
17-20 | 4 | U32 | "10 00 00 00 "表示PCM数据 | 10 00 00 00 | 小 |
21-22 | 2 | U16 | 数据类型,"01 00"表示 PCM | 01 00 | 小 |
23-24 | 2 | U16 | 通道数 2 | 02 00 | 小 |
25-28 | 4 | U32 | 采样率 44100 (00 00 ac 44) | 44 ac 00 00 | 小 |
29-32 | 4 | U32 | 码率: 采样率x位深度x通道数/8 44100*16*2/8 = 176400 (00 02 b1 10) |
10 b1 02 00 | 小 |
33-34 | 2 | U32 | 采样一次,占内存大小 :位深度x通道数/8 =16*2/8=4 | 04 00 | 小 |
35-36 | 2 | U16 | 采样深度 16bit |
10 00 | 小 |
37-40 | 4 | STR | 表述payload数据开头 "data" | 64 61 74 61 | 大 |
41-44 | 4 | U32 | 数据部分的长度 739116 (00 0b 47 2c) | 2c 47 0b 00 | 小 |
文件格式中关于SIZE之间的关系:
FileSize = 739160
RiffSize = 739152
DataSize = 739116
关系:FileSize = 739160
= RiffSize + 8 = 739152 + 8
= DataSize + 44 = 739116 + 44
Fact Chunk
==================================
| |所占字节数| 具体内容 |
==================================
| ID | 4 Bytes | 'fact' |
----------------------------------
| Size | 4 Bytes | 数值为4 |
----------------------------------
| data | 4 Bytes | |
----------------------------------
图4 Fact Chunk
Fact Chunk是可选字段,一般当wav文件由某些软件转化而成,则包含该Chunk。
结构定义如下:
struct FACT_BLOCK
{
char szFactID[4]; // 'f','a','c','t'
DWORD dwFactSize; //同理就是减去id, size的本chunk的大小
};
Data Chunk
==================================
| |所占字节数| 具体内容 |
==================================
| ID | 4 Bytes | 'data' |
----------------------------------
| Size | 4 Bytes | |
----------------------------------
| data | | |
----------------------------------
图5 Data Chunk
Data Chunk是真正保存wav数据的地方,以'data'作为该Chunk的标示。然后是
数据的大小。紧接着就是wav数据。根据Format Chunk中的声道数以及采样bit数,
wav数据的bit位置可以分成以下几种形式:(即和 format chunk有关系)
---------------------------------------------------------------------
| 单声道 | 取样1 | 取样2 | 取样3 | 取样4 |
|--------------------------------------------------------------------
| 8bit量化 | 声道0 | 声道0 | 声道0 | 声道0 |
---------------------------------------------------------------------
| 双声道 | 取样1 | 取样2 |
|--------------------------------------------------------------------
| 8bit量化 | 声道0(左) | 声道1(右) | 声道0(左) | 声道1(右) |
----------------------------------------------------------------------
| 单声道 | 取样1 | 取样2 |
|---------------------------------------------------------------------
| 16bit量化 | 声道0 | 声道0 | 声道0 | 声道0 |
| | (低位字节) | (高位字节) | (低位字节) | (高位字节)|
-----------------------------------------------------------------------
| 双声道 | 取样1 | 取样2 |
|-------------------------------------------------------------------------------
| 16bit量化 | 声道0(左) | 声道1(右) | 声道0(左) | 声道1(右)|
| | (低位字节) | (高位字节) | (低位字节) | (高位字节) |
---------------------------------------------------------------------------------
图6 wav数据bit位置安排方式
Data Chunk头结构定义如下:
struct DATA_BLOCK
{
char szDataID[4]; // 'd','a','t','a'
DWORD dwDataSize;
};
其他情况:
1、如果Format Chunk Size等于0x10(16),表示头部不包含附加信息,即WAV头部信息长度为44;如果等于0x12(18),则包含附加信息,此时头部信息长度大于44
2、如果RIFFSize - DataSize > (FormatSize + FactSize) 说明数据部分有其他类型数据,在取出数据部分的时候要去掉这部分信息
参考:
wave文件格式以及代码 - Red_Point - 博客园 (cnblogs.com)