一、WAVE文件

  WAVE文件是计算机领域最常用的数字化声音文件格式之一,它是微软专门为Windows系统定义的波形文件格式(Waveform Audio),由于其扩展名为"*.wav"。最基本的WAVE文件是PCM(脉冲编码调制)格式的,这种文件直接存储采样的声音数据没有经过任何的压缩,是声卡直接支持的数据格式,要让声卡正确播放其它被压缩的声音数据,就应该先把压缩的数据解压缩成PCM格式,然后再让声卡来播放

1.Wave文件的内部结构

  WAVE文件是以RIFF(Resource Interchange File Format,“资源交互文件格式”)格式来组织内部结构的。RIFF文件结构可以看作是树状结构,其基本构成是称为"块"(Chunk)的单元,最顶端是一个“RIFF”块,下面的每个块有“类型块标识(可选)”、“标志符”、“数据大小”及“数据”等项所组成,块的结构如表1所示:

  上面说到的“类型块标识”只在部分chunk中用到,如“WAVE”chunk中,这时表示下面嵌套有别的chunk,当使用了“类型块标识”时,该chunk就没有别的项(如块标志符,数据大小等),它只作为文件读取时的一个标识。先找到这个“类型块标识”,再以它为起来读取它下面嵌套的其它chunk。

  非PCM格式的文件会至少多加入一个“fact”块,它用来记录数据解压缩后的大小。(注意是数据而不是文件)这个“fact”块一般加在“data”块的前面。

WAVE的基本结构WAVEFORMATEX结构定义如下:
typedef struct
{
WORD wFormatag; //编码格式,包括WAVE_FORMAT_PCM,//WAVEFORMAT_ADPCM等
WORD nChannls; //声道数,单声道为1,双声道为2;
DWORD nSamplesPerSec;//采样频率;
DWORD nAvgBytesperSec;//每秒的数据量;
WORD nBlockAlign;//块对齐;
WORD wBitsPerSample;//WAVE文件的采样大小;
WORD sbSize; //PCM中忽略此值
}WAVEFORMATEX;
PCM的结构就是基本结构;

IMAADPCMWAVEFORMAT结构定义如下:
Typedef struct
{
WAVEFORMATEX wfmt;
WORD nSamplesPerBlock;
}IMAADPCMWAVEFORMAT;

  IMA-ADPCM的wfmt->cbsize不能忽略,一般取值为2,表示此类型的WAVEFORMAT比一般的WAVEFORMAT多出2个字节。这两个字符也就是nSamplesPerBlock。

2.“fact”chunk的内部组织

   在非PCM格式的文件中,一般会在WAVEFORMAT结构后面加入一个“fact”chunk,结构如下:
typedef struct{
char[4]; //“fact”字符串
DWORD chunksize;
DWORD datafactsize; //数据转换为PCM格式后的大小。
}factchunk;
  datafactsize是这个chunk中最重要的数据,如果这是某种压缩格式的声音文件,那么从这里就可以知道他解压缩后的大小。对于解压时的计算会有很大的好处!

3.“data”chunk的内部组织

   从“data”chunk的第9个字节开始,存储的就是声音信息的数据了,(前八个字节存储的是标志符“data”和后接数据大小size(DWORD)。这些数据可能是压缩的,也可能是没有压缩的。
   PCM中的声音数据没有被压缩,如果是单声道的文件,采样数据按时间的先后顺序依次存入。(它的基本组织单位是BYTE(8bit)或WORD(16bit))如果是双声道的文件,采样数据按时间先后顺序交叉地存入。如图所示:

   IMA-ADPCM是压缩格式,它是从PCM的16位采样压缩成4位的。对于单声道的IMA-ADPCM来说,它是将PCM的数据按时间次序依次压缩并写入文件中的,每个byte中含两个采样,低四位对应第一个采样,高四位对应第二个采样。而对于双声道的IMA-ADPCM来说,它的存储相对就麻烦一些了,它是将PCM的左声道的前8个采样依次压缩并写入到一个DWORD中,然后写入“data”chunk里。紧接着是右声道的前8个采样。以此循环,当采样数不足8时(到数据尾端),应该把多出来的采样用0填充。其示意图如下:

特别注意:
   在IMA-ADPCM中,“data”chuck中的数据是以block形式来组织的,我把它叫做“段”,也就是说在进行压缩时,并不是依次把所有的数据进行压缩保存,而是分段进行的,这样有一个十分重要的好处:那就是在只需要文件中的某一段信息时,可以在解压缩时可以只解所需数据所在的段就行了,没有必要再从文件开始起一个一个地解压缩。这对于处理大文件将有相当的优势。同时,这样也可以保证声音效果。
   Block一般是由block header (block头) 和 data 两者组成的。其中block header是一个结构,它在单声道下的定义如下:
Typedef struct
{
short sample0; //block中第一个采样值(未压缩)
BYTE index; //上一个block最后一个index,第一个block的index=0;
BYTE reserved; //尚未使用
}MonoBlockHeader;
  有了blockheader的信息后,就可以不需要知道这个block前面和后面的数据而轻松地解出本block中的压缩数据。对于双声道,它的blockheader应该包含两个MonoBlockHeader其定义如下:
typedaf struct
{
MonoBlockHeader leftbher;
MonoBlockHeader rightbher;
}StereoBlockHeader;
  在解压缩时,左右声道是分开处理的,所以必须有两个MonoBlockHeader;
注1:上述的index是解压缩算法中必须用到的一个参数。详见后面。
注2: 关于block的大小,通常会有以下几种情况:

  对于单声道,大小一般为512byte,显然这里面可以保存的sample个数为(512-sizeof(MonoBlockHeader))/4 + 1 = 1017个<其中"+1"是第一个存在头结构中的没有压缩的sample.
  对于双声道,大小一般为1024byte,按上面的算法可以得出,其中的sample个数也是1017个.

4.读取WAVE文件的方法.

  在知道了WAVE文件的内部数据组织后,可以直接通过FILE或HFILE来实现文件的读取。但由于WAVE文件是以RIFF格式来组织的,所以用多媒体输入输出流来操作将更加方便,可以直接在文件中查找chunk并定位数据。

二、IMA-ADPCM 编码和解码算法

  IMA-ADPCM 是Intel公司首先开发的是一种主要针对16bit采样波形数据的有损压缩算法, 压缩比为 4:1.它与通常的DVI-ADPCM是同一算法。 (对8bit数据压缩时是3.2:1,也有非标准的IMA-ADPCM压缩算法,可以达到5:1甚至更高的压缩比)4:1的压缩是目前使用最多的压缩方式。
  ADPCM(Adaptive Differential Pulse Code Modulation 差分脉冲编码调制)主要是针对连续的波形数据的, 保存的是相临波形的变化情况, 以达到描述整个波形的目的。算法中必须用到两个一维数组,setptab[] 和 index_adjust[],附在下面的代码之后。

1.IMA-ADPCM 压缩过程

首先我们认为声音信号都是从零开始的,那么需要初始化两个变量
int index = 0,prev_sample = 0;
但在实际使用中,prev_sample的值是每个block中第一个采样的值。(这点在后面的block中会详细介绍)
假设已经写好了两个函数:
GetNextSamp() —— 得到一个 16bit 的采样数据;
SaveComCode() —— 保存一个 4bit 的压缩样品;
下面的循环将依次压缩声音数据流:

while (还有数据要处理) {
cur_sample = GetNextSamp(); // 得到PCM中的当前采样数据
diff = cur_sample-prev_sample; // 计算出和上一个的增量
if (diff<0)
{
diff=-diff;
fg=8;
}
else fg=0; // fg 保存的是符号位

code = 4*diff / steptab[index];
if (code>7) code=7;                 // 根据 steptab[] 得到一个 0~7 的值,它描述了采样振幅的变化量index+=index_adjust[code];          // 根据声音强度调整下次取 steptab 的序号,便于下次得到更精确的变化量的描述
if (index<0) index=0;               // 调整index的值
else if (index>88) index=88;prev_sample=cur_sample;SaveComCode(code|fg);                 // 加上符号位保存起来
}

2.IMA-ADPCM 解压缩过程

解压缩实际是压缩的一个逆过程,假设写好了以下两个函数:
GetNextCode() —— 得到一个编码(4bit)
OutputSamp() —— 将解码出来的声音信号保存起来( 16bit).
int index=0,cur_sample=0;
while (还有数据要处理) {
code=GetNextCode(); // 得到下一个压缩样品Code 4bit

if ((code & 8) != 0) fg=1 else fg=0;
code&=7;                      // 将 code 分离为数据和符号diff = (steptab[index]*code) /4 + steptab[index] / 8;   // 后面加的一项是为了减少误差    if (fg==1) diff=-diff;cur_sample+=diff;            // 计算出当前的波形数据
if (cur_sample>32767) OutputSamp(32767);
else if (cur_sample<-32768) OutputSamp(-32768);else OutputSamp(cur_sample);index+=index_adjust[code];
if (index<0) index=0;
if (index>88) index=88;

}

附表
int index_adjust[8] = {-1,-1,-1,-1,2,4,6,8};
int steptab[89] = { 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767 };

ADPCM WAVE文件的压缩与解压缩相关推荐

  1. Linux命令(9)—— 文件的压缩与解压缩

    .gz..bz2..zip文件均可以在linux操作系统下进行解压缩和压缩 tar命令 适用于 .gz..bz2类型文件 tar命令有很多选项 选项 作用 -c 创建出你要打包的文件 -j 压缩或解压 ...

  2. Linux下文件的压缩、解压缩、打包以及提取

    文章目录 Linux下文件的压缩.解压缩.打包以及提取 一.单个文件的解压缩 1.压缩文件: 2.文件的压缩 3.压缩文件的查看: 4.文件的解压:gunzip [选项] 文件名 二.多个文件的打包和 ...

  3. 哈夫曼树实现文件的压缩与解压缩

    利用哈夫曼树实现文件的压缩与解压缩 压缩: 1.统计出文件中相同字符出现的次数 2.获取哈夫曼编码 次数作为权值构建哈夫曼树 3.重新编码,写回压缩文件 保存头文件: 源文件后缀 编码信息的行数 每个 ...

  4. 数据压缩及解压缩算法,多种文件的压缩与解压缩-java android

    > 数据压缩算法,文本压缩算法 几种压缩算法原理介绍- https://blog.csdn.net/clevercode/article/details/46691645 文本压缩算法的对比和选 ...

  5. 对rar文件的解压缩,对zip文件的压缩与解压缩

    一.对rar文件的解压缩 1.maven <dependency><groupId>com.github.junrar</groupId><artifactI ...

  6. Linux下文件的压缩与解压缩

    Linux下文件的压缩与解压缩与Windows环境下有较大的区别,在Windows下只需要安装类似Winrar工具就能解压缩大部分文件,而在Linux命令行下每一种文件都有不同的压缩和解压缩方法. 使 ...

  7. sudo mysql压缩备份解压操作_高效管理文件之压缩及解压缩 .bz2 文件

    对文件进行压缩,可以通过使用较少的字节对文件中的数据进行编码来显著地减小文件的大小,并且在跨网络的文件的备份和传送时很有用. 另一方面,解压文件意味着将文件中的数据恢复到初始状态.Linux 中有几个 ...

  8. C# 文件的压缩与解压缩

    依赖:.NET Framework 4.5及以上,引用 - 添加引用 - 程序集 System.IO.Compression System.IO.Compression.FileSystem ---- ...

  9. 如何使用Python对文件进行压缩与解压缩

    前言 我们在日常工作中,除了会涉及到使用Python处理文本文件,有时候还会涉及对压缩文件的处理. 通常会涉及到的压缩文件格式有: •rar:Windows 环境下用的比较多的压缩,比较著名的GUI工 ...

最新文章

  1. android notification 定时显示,Android编程使用Service实现Notification定时发送功能示例...
  2. rmi远程代码执行漏洞_【漏洞通告】Apache Solr远程代码执行漏洞
  3. 归算法及经典递归例子代码实现
  4. 骨骼捏脸功能的实现方法
  5. c#语言中代替指针,如何在C#中使指针通用?
  6. 我的计算机怎么打不开怎么办理,我的电脑打不开,怎么办【解决方法】
  7. ios业务模块间互相跳转的解耦方案
  8. 13 款 JavaScript 模板引擎
  9. jquery 获取系统默认年份_你没有看错,爬网页数据,C# 也可以像 Jquery 那样
  10. django设置models.Model数据可以为空
  11. 自建lol服务器,终于干正事了?英雄联盟宣布:艾欧尼亚服务器将进行扩容
  12. Python简洁的出入库系统(模块化)
  13. day08面向对象+
  14. Android-导航栏特效-新闻类APP(仿iOS版网易新闻今日头条的文字渐变缩放特效)
  15. 吐血推荐珍藏的Chrome插件
  16. Java DES 加密解密工具类实现
  17. 基于 CherryUSB 调试 dwc2 usb host 笔记
  18. 浅析数据中心布线系统的绿色环保与节能
  19. Windows 版本说明,Enterprise、Ultimate、Home、Professional知多少?
  20. 比 Bloom Filter 节省25%空间!Ribbon Filter 在 Lindorm中的应用

热门文章

  1. 【OpenCV图像处理16】课程总结
  2. Golang实现的[]byte和int转化
  3. 利用Python爬取全国250m精度的人口数据
  4. 【强化学习实践】 打乒乓球Pong
  5. RPA自动化办公04——软件自动化(excel,word,浏览器)
  6. [MSSQL]汉字转全拼音函数优化方案(SQLServer),值得你看看
  7. 杰理AC692N系列增加编码器通过AD检测方式
  8. CiteSeer统计的计算机领域的期刊和会议的影响因子(2005)
  9. Oracle数据库安装先决条件检查失败解决方案
  10. 同时介绍两个对象怎么办_“相亲对象好着急,认识第一天就干出这事?”哈哈哈哈哈我该怎么办|哈哈哈哈哈|相亲|情侣|借钱|电子厂...