天天看点

ADPCM 编码 及WAV解析 及实例

wav文件详解

  1. WAV头分析

WAV是微软公司(Microsoft)开发的一种声音文件格式,在多媒体中使用的声波文件格式之一,它是以RIFF(Resource Interchange File Format 资源交互文件格式) 格式为标准的。每个WAV文件的头四个字节就是“RIFF”。WAV文件由文件头和数据体两大部分组成。其中文件头又分为RIFF/WAV文件标识段和声音数据格式说明段两部分,文件头中还包含了音频流的编码参数。

如下图所示

ADPCM 编码 及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结构中的数据。

    1. RIFF结构如下,定义,

 typedef __packed struct

{

    u32 ChunkID;        //chunk id;这里固定为"RIFF",即0X46464952

    u32 ChunkSize ;         //集合大小;文件总大小-8

    u32 Format;            //格式;WAVE,即0X45564157

}ChunkRIFF ;

    1. 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编码格式,一般都是按块存储的,需要知道一个块内的采样数量。

    1. 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文件也不是必须的。

  1. 音频数据
    1. data结构

//data块

typedef __packed struct

{

    u32 ChunkID;        //chunk id;这里固定为"data",即0X5453494C

    u32 ChunkSize ;      // 音频数据块大小。(除去WAV头的所有数据)

}ChunkDATA;

    1. 数据块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文件实际例子:

ADPCM 编码 及WAV解析 及实例

IMA-ADPCM编码的WAV文件实际例子:

ADPCM 编码 及WAV解析 及实例
  1. ADPCM编解码

Windows自带的一个小工具

ADPCM 编码 及WAV解析 及实例

这个小工具我试过了,转换成不是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兼容性不好。

ADPCM 编码 及WAV解析 及实例

继续阅读