ADPCM(Adaptive Differential Pulse Code Modulation),是一种针对 16bits( 或8bits或者更高) 声音波形数据的一种有损压缩算法,它将声音流中每次采样的 16bit 数据以 4bit 存储,所以压缩比 1:4. 而且压缩/解压缩算法非常简单,是一种低空间消耗,高质量高效率声音获得的好途径。保存声音的数据文件后缀名为 .AUD 的大多用ADPCM 压缩。
  ADPCM 主要是针对连续的波形数据的,保存的是波形的变化情况,以达到描述整个波形的目的。

  8bits采样的声音人耳是可以勉强接受的,而 16bit 采样的声音可以算是高音质了。ADPCM 算法却可以将每次采样得到的 16bit 数据压缩到 4bit。需要注意的是,如果要压缩/解压缩得是立体声信号,采样时,声音信号是放在一起的,需要将两个声道分别处理。

以上文字摘自http://blog.csdn.net/lxc1014/article/details/9316381

自己写该算法时参考了上述博客中的内容。但后来才知道STM32官方也有该算法的文档和程序,于是自己基于上面两份资料写了关于该算法的代码。当然还有很多不懂的,不对处望博友指正。我用的是STM32的ADC、DAC,它是12Bit采样,所以我稍微将传统的ADPCM给改了下。

typedef __packed struct
{int16_t valprev;

int8_t index;
}_s_ADPCM;

int8_t index_adjust[16] = {-1,-1,-1,-1,2,4,6,8,-1,-1,-1,-1,2,4,6,8};
uint16_t step_table[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
};

void ADPCM_Encoder(_s_ADPCM *state,int16_t* pInBuf,uint8_t *pOutBuf,uint8_t Len)

{
uint8_t i=0,j=0;
int16_t Index=0;
uint8_t code=0;
int32_t data=0,predata = 0 ,delta=0,prediff=0;
uint16_t step=0,tmpstep=0;
predata = (int32_t)state->valprev;

Index = (int16_t)state->index;
for(i=0;i<Len;i++)
{
data=(int32_t)*(pInBuf+i);
step = step_table[Index];

delta = data - predata;
if(delta<0)
{
delta=-delta;
code=8;
}
else
{
code=0;
}

#if 1
tmpstep = step;
prediff = (step >>3);
if(delta >= tmpstep)
{
code |= 0x04;
delta -= tmpstep;
prediff += step;
}

tmpstep = tmpstep>>1;

if(delta >= tmpstep)

{
code |= 0x02;
delta -= tmpstep;
prediff += (step >>1);
}
tmpstep = tmpstep>>1;
if(delta >= tmpstep)
{
code |= 0x01;
prediff += (step>>2);
}
#else
code = (delta<<2)/(step);
if(code >7) 
code = 7;

prediff = (delta * step)>>2;

#endif

if(code & 8)
{
predata -= prediff;
}
else
{
predata += prediff;
}

if(predata > 2047)
{
predata =2047;
}
else if(predata < -2048)
{
predata =-2048;
}

Index+=index_adjust[code];
if(Index < 0)
Index=0;
else if(Index >59)
Index=59;

if(i&0x01)
{
*(pOutBuf+j) |=(uint8_t)((code&0x0f)<<4);
j++;
}
else
{
*(pOutBuf+j) = (uint8_t)(code&0x0f);
}
}
state->valprev = (int16_t)predata;
state->index =(int8_t)Index;
}

void ADPCM_Decoder(uint8_t *pInBuf,int16_t *pOutBuf,uint8_t Len,_s_ADPCM *state)
{
uint8_t i=0,j=0,tmp_data=0,inCode=0;
uint16_t step=0;
int16_t Index=0;
int32_t predsample=0,diffq=0;

predsample = (int32_t)state->valprev;
Index = (int16_t)state->index;

for(i=0;i<(Len<<1);i++)
{
tmp_data=pInBuf[i>>1];
if(i&0x01)
inCode=(tmp_data&0xf0)>>4;
else
inCode=tmp_data&0x0f;
step = step_table[Index];

diffq = step>>3;
if(inCode & 0x04)
diffq += step;
if(inCode & 0x02)
diffq += (step>>1);
if(inCode & 0x01)
diffq += (step>>2);

if(inCode & 8)
predsample-= diffq;
else
predsample+=diffq;
if(predsample > 2047)
predsample =2047;
else if (predsample <-2048)
predsample = -2048;

Index+= index_adjust[inCode];
if(Index < 0)
Index=0;
if(Index >59)
Index = 59;

pOutBuf[j++] = (int16_t)predsample;
}
state->valprev = (int16_t)predsample;
state->index = (int8_t)Index;
}

对上述代码进行简单说明下:

编码时将16Bit压缩成4Bit,输出时是8Bit的数据,先接到的数据放在8Bit的低4位,第二次接到的数据放在高4位。

其中在编码函数中采用了条件编译,现在采用的即为算法介绍中编码方式。算法参考文档:http://www.mp3-tech.org/programmer/docs/adpcm.pdf

(当然也是STM32 ADPCM编码采用的方式)。另一个条件选择是一种粗略算法,我感觉没有前面一种编码效果好(我只验证了第一种编码方式,第二种没有试验)。

解码时就要将压缩后的数据给分开来。即假如编码数量为32个16Bit的数据,经过压缩可得到16个8Bit的数据,再经过解压缩可得到32个16Bit数据。编解码局限性在于编码数量我只考虑了偶数情况,奇数情况我还没考虑。

当然上述算法还有待优化~~时间允许的话,一定仔细研究下,从而优化自己的代码。

ADPCM 音频压缩算法相关推荐

  1. ADPCM音频格式详解 ADPCM_IMA ADPCM_DIV4

    网上帖子一大推,都是照搬adpcm音频算法代码,实际使用时需要注意没有相关细节,我在这里补充一片防止大家走弯路 //ADPCM-DIV4 音频帧标识头 struct adpcm_state {    ...

  2. ADPCM音频编解码

    前言 参考 所谓ADPCM编码是一种自适应差分脉码调制技术.它可以对音频数据在毫无损失的前提下,将数据量压缩为原来的1/4,这对于音频来说,意义是重大的. ADPCM源于微软的Windows,一般的W ...

  3. Zigbee音频, 6LowPAN, IEEE 802

    http://antkillerfarm.github.io/ Zigbee音频 前言 本文是对Zigbee传输音频数据功能的一个资源汇总分析贴. 网上解决方案分析 基于MCF5213及Zigbee技 ...

  4. 第二部分 音频压缩编码

    第二部分    音频压缩编码 一.有损 ( lossy )/无损 ( lossless )/未压缩 ( uncompressed )音频格式 未压缩音频是一种没经过任何压缩的简单音频.未压缩音频通常用 ...

  5. CSR867x — 说说蓝牙音频常用的编解码格式

    XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XX  作       者:文化人 XX  联系方式: XX  版权声明:原创文章,欢迎 ...

  6. CSR8670 — 说说蓝牙音频常用的编解码格式

    SBC (Sub-band coding,子带编码) 最早的格式应该是SBC,SBC是A2DP(Advanced Audio DistribuTIon Profile,蓝牙音频传输协议)协议强制规定的 ...

  7. 音频处理与压缩的一些技术点和算法

    音频处理的方法主要包括: 降噪.回声消除.自动增益.静音检测.噪声控制 音频压缩算法需要看音频编码的格式: G.7xx.iLBC.SILK.OPUS.AAC.AC3.apt-x(ADPCM)等等 降噪 ...

  8. 各种音频视频编码方法

    编解码学习笔记(一):基本概念 媒体业务是网络的主要业务之间.尤其移动互联网业务的兴起,在运营商和应用开发商中,媒体业务份量极重,其中媒体的编解码服务涉及需求分析.应用开发.释放license收费等等 ...

  9. 蓝牙 A2DP 音频传输格式-全面解析

    1. 蓝牙 A2DP 音频传输格式 达到 CD 音质需要 1411.2 kbit/s 的带宽,显然 A2DP 无法允许,所以音频数据需要经过压缩.我们知道同样的比特率下,不同的编码格式音质是不同的.A ...

  10. ADPCM编解码的使用

    网上有很多讲解Adpcm编解码的,但是就没有详细说明其是需要如何使用的. 这里就记录下是如何使用代码的,即是函数的参数需要填写什么,要注意的要点. ADPCM(Adaptive Differentia ...

最新文章

  1. ES Segment Memory——本质上就是segment中加到内存的FST数据,因此segment越多,该内存越大...
  2. 如何在命令行模式下升级的你Visual Studio的Solution文件
  3. redis快照文件dump.rdb解析工具--redis-rdb-tools
  4. Latex 调整表格大小 表格过大 表格过小
  5. 7-8 字符串字母大小写转换 (15 分)
  6. 获取设备和 App 信息
  7. Android MediaPlayer的生命周期
  8. c语言程序原版PDF,正式版C语言程序设计.pdf
  9. 静态网页HTML知识点归纳
  10. 微信扫码跳转浏览器下载app
  11. drive翻译成中文_drive是什么意思_drive翻译_读音_用法_翻译
  12. 什么是设备管理系统,包括哪些内容?一文读懂
  13. SAP物料主数据编码范围配置
  14. django 发送邮件验证码
  15. 机器学习中的矩阵向量求导(五) 矩阵对矩阵的求导
  16. 7-13 大家一起来玩游戏 (20 分)
  17. thinkphp6 验证码总是提示不正确
  18. C#工控上位机——框架
  19. VS2015 0xc000007b应用程序无法正常启动 解决办法
  20. 2023青海大学计算机考研信息汇总

热门文章

  1. 经典算法详解(2):费氏数列
  2. Word 2003的基本使用
  3. 《你和你的研究》全文
  4. 基于单片机的心率监测系统设计(#0403)
  5. C++统计输入字符串各个大写字母的个数
  6. Android 项目使用 Jenkins 打包时的异常问题 AAPT: C:\Windows\System32\config\systemprofile\.gradle\caches
  7. 通过命令行安装egret引擎
  8. 计算机网络——数据从网卡到应用的过程
  9. 解决Word无响应崩溃的问题
  10. 04、CONSTANT-ROUND CZK PROOFS for NP--Alon Rosen[对于NP的常数轮CZK证明]