jjj 发表于 2015-9-1 19:16:28

IMA-ADPCM 文件解析及编解码(参考了正点原子的录音例子)

本帖最后由 jjj 于 2015-9-1 19:23 编辑

wav文件详解
1.        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结构中的数据。

1.1.        RIFF结构如下,定义,
typedef __packed struct
{
    u32 ChunkID;                           //chunk id;这里固定为"RIFF",即0X46464952
    u32 ChunkSize ;                           //集合大小;文件总大小-8
    u32 Format;                                   //格式;WAVE,即0X45564157
}ChunkRIFF ;
1.2.        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.3.        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文件也不是必须的。

2.        音频数据
2.1.        data结构
//data块
typedef __packed struct
{
    u32 ChunkID;                           //chunk id;这里固定为"data",即0X5453494C
    u32 ChunkSize ;                // 音频数据块大小。(除去WAV头的所有数据)
}ChunkDATA;
2.2.        数据块BLOCK结构
IMA-ADPCM压缩的音频数据是以数据块存储的,存储格式如下:
//ADPCM压缩的数据块结构
typedef __packed struct
{
    u16 presample;                //第一个采样值16bit
    u8 index ;                           //上一个数据块的最后一个 index
    u8 rsv;                                   //保留
        u8 dat;
}DATA_BLOCK;
为了数据存储对齐,方便处理,一般一个音频BLOCK的大小是16的整数倍;如果设置BLOCK大小为256Byte,减去数据块头长度4字节,还剩252字节,4bit表示一个采样的话,可存储共252x2+1=505个采样点(加上数据头里的一个采样值)。
对于PCM编码的WAV文件,只需要按照顺序存储原始采样值即可,不需要分块。

PCM编码的WAV文件实际例子:



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

migrant 发表于 2015-9-1 19:53:50

收藏,谢谢共享

creep 发表于 2015-9-2 07:41:34

学习,感谢分享

Excellence 发表于 2015-9-2 08:32:27

下载,谢。

jjj 发表于 2021-1-7 11:25:59

这帖子居然是我写的,怎么那么陌生
页: [1]
查看完整版本: IMA-ADPCM 文件解析及编解码(参考了正点原子的录音例子)