wav文件详解
- WAV头分析
WAV是微软公司(Microsoft)开发的一种声音文件格式,在多媒体中使用的声波文件格式之一,它是以RIFF(Resource Interchange File Format 资源交互文件格式) 格式为标准的。每个WAV文件的头四个字节就是“RIFF”。WAV文件由文件头和数据体两大部分组成。其中文件头又分为RIFF/WAV文件标识段和声音数据格式说明段两部分,文件头中还包含了音频流的编码参数。
如下图所示
//wav头
typedef __packed struct
{
ChunkRIFF riff; //riff块
ChunkFMT fmt; //fmt块
ChunkFACT fact; //fact块 线性PCM,没有这个结构体
ChunkDATA data; //data块
}__WaveHeader;
WAV文件头包含三部分,RIFF,fmt,fact,数据存储大小端定义按上图中的定义,规律大概是这样的,如果是字符串常量,则按阅读习惯,采用大端存储模式,如果是十六进制数据的纯数据,则按一般处理器处理规律小端模式存储。
WAV文件是非常简单的一种RIFF文件,它的格式类型为“WAVE ”。RIFF块包含两个子块,这两个子块的ID分别是“fmt ”和“data ” 。其中“fmt ”子块由结构PCMWAVEFORMAT所组成,其子块的大小就是sizeof(PCMWAVEFORMAT),数据组成就是PCMWAVEFORMAT结构中的数据。
-
- RIFF结构如下,定义,
typedef __packed struct
{
u32 ChunkID; //chunk id;这里固定为"RIFF",即0X46464952
u32 ChunkSize ; //集合大小;文件总大小-8
u32 Format; //格式;WAVE,即0X45564157
}ChunkRIFF ;
-
- fmt结构
//fmt块
typedef __packed struct
{
u32 ChunkID; //chunk id;这里固定为"fmt ",即0X20746D66
u32 ChunkSize ; //子集合大小(不包括ID和Size);这里为:20.
u16 AudioFormat; //音频格式;0X01,表示线性PCM;0X11表示IMA ADPCM
u16 NumOfChannels; //通道数量;1,表示单声道;2,表示双声道;
u32 SampleRate; //采样率;0X1F40,表示8Khz
u32 ByteRate; //字节速率;
u16 BlockAlign; //块对齐(字节);
u16 BitsPerSample; //单个采样数据大小;4位ADPCM,设置为4
u16 ByteExtraData; //附加的数据字节;2个; 线性PCM,没有这个参数
u16 sampleperblock; //一般是一个数据块中的采样数量 如:0x01F9
}ChunkFMT;
ByteExtraData这个数据重点说一下,在原始线性PCM编码格式,不需要这个参数,只有压缩的PCM编码格式,一般都是按块存储的,需要知道一个块内的采样数量。
-
- fact结构
//fact块
typedef __packed struct
{
u32 ChunkID; //chunk id;这里固定为"fact",即0X74636166;
u32 ChunkSize ; //子集合大小(不包括ID和Size);这里为:4.
u32 NumOfSamples; //采样的数量;
}ChunkFACT;
“All (compressed) non-PCM formats must have a Fact chunk (Rev. 3documentation). The chunk contains at least one value, the number of samples in the file.”
虽然标准协议要求”所有非PCM编码的WAV文件要求有fact块”,但实际分析了两个wav文件的文件头,一种PCM编码,一种IMA-ADPCM编码,这两个文件都没有fact块,但是window可以正常播放;说明fact块对这两种类型的wav文件也不是必须的。
- 音频数据
- data结构
//data块
typedef __packed struct
{
u32 ChunkID; //chunk id;这里固定为"data",即0X5453494C
u32 ChunkSize ; // 音频数据块大小。(除去WAV头的所有数据)
}ChunkDATA;
-
- 数据块BLOCK结构
IMA-ADPCM压缩的音频数据是以数据块存储的,存储格式如下:
//ADPCM压缩的数据块结构
typedef __packed struct
{
u16 presample; //第一个采样值16bit
u8 index ; //上一个数据块的最后一个 index
u8 rsv; //保留
u8 dat[sampleperblock-1];
}DATA_BLOCK;
为了数据存储对齐,方便处理,一般一个音频BLOCK的大小是16的整数倍;如果设置BLOCK大小为256Byte,减去数据块头长度4字节,还剩252字节,4bit表示一个采样的话,可存储共252x2+1=505个采样点(加上数据头里的一个采样值)。
对于PCM编码的WAV文件,只需要按照顺序存储原始采样值即可,不需要分块。
PCM编码的WAV文件实际例子:
IMA-ADPCM编码的WAV文件实际例子:
- ADPCM编解码
Windows自带的一个小工具
这个小工具我试过了,转换成不是ima-adpcm格式, 而是转换成microsoft adpcm格式,这2种格式之间有什么区别 我不知道 ,但是市面上大多数是ima-adpcm格式,所以我就不研究这个microsoft adpcm格式了。
兼容性问题:
1, cooledit生成的IMA ADPCM 编译的WAV文件, foobar.exe不能播放,
2. 录音笔录制的 ADPCM WAV就可以播放,
对比发现, cooledit生成的wav文件好像更符合标准,有fact部分,而录音笔录音的wav没有fact部分,标准规定如果是压缩的wav格式的话,要求有fact部分,但实际是有这部分播放器就不识别,放不出来,而没有这部分,大多数播放器就可以很好的播放。 或许是cooledit兼容性不好。