ADPCM压缩算法.docx
《ADPCM压缩算法.docx》由会员分享,可在线阅读,更多相关《ADPCM压缩算法.docx(21页珍藏版)》请在冰豆网上搜索。
![ADPCM压缩算法.docx](https://file1.bdocx.com/fileroot1/2023-2/22/c8cf2aa1-0201-455d-861d-38f1acd9532b/c8cf2aa1-0201-455d-861d-38f1acd9532b1.gif)
ADPCM压缩算法
ADPCM压缩算法
ADPCM(AdaptiveDifferentialPulseCodeModulation),是一种针对16bits(或8bits或者更高)声音波形数据的一种有损压缩算法,它将声音流中每次采样的16bit数据以4bit存储,所以压缩比1:
4.而且压缩/解压缩算法非常简单,所以是一种低空间消耗,高质量高效率声音获得的好途径。
保存声音的数据文件后缀名为.AUD的大多用ADPCM压缩。
ADPCM主要是针对连续的波形数据的,保存的是波形的变化情况,以达到描述整个波形的目的,由于它的编码和解码的过程却很简洁,列在后面,相信大家能够看懂。
8bits采样的声音人耳是可以勉强接受的,而16bit采样的声音可以算是高音质了。
ADPCM算法却可以将每次采样得到的16bit数据压缩到4bit。
需要注意的是,如果要压缩/解压缩得是立体声信号,采样时,声音信号是放在一起的,需要将两个声道分别处理。
ADPCM压缩过程
首先我们认为声音信号都是从零开始的,那么需要初始化两个变量
intindex=0,prev_sample=0;
下面的循环将依次处理声音数据流,注意其中的getnextsample()应该得到一个16bit的采样数据,而outputdata()可以将计算出来的数据保存起来,程序中用到的step_table[],index_adjust[]附在后面:
intindex=0,prev_sample:
=0;
while(还有数据要处理)
{
cur_sample=getnextsample(); //得到当前的采样数据
delta=cur_sample-prev_sample; //计算出和上一个的增量
if(delta<0)delta=-delta,sb=8; //取绝对值
elsesb=0; //sb保存的是符号位
code=4*delta/step_table[index]; (取余运算) //根据steptable[]得到一个0-7的值
if(code>7)code=7; //它描述了声音强度的变化量
index+=index_adjust[code]; //根据声音强度调整下次取steptable的序号
if(index<0)index=0; //便于下次得到更精确的变化量的描述
elseif(index>88)index=88;
prev_sample=cur_sample;
outputode(code|sb); //加上符号位保存起来
}
ADPCM解压缩过程
接压缩实际是压缩的一个逆过程,同样其中的getnextcode()应该得到一个编码,,而outputsample()可以将解码出来的声音信号保存起来。
这段代码同样使用了同一个的setp_table[]和index_adjust()附在后面:
intindex=0,cur_sample=0;
while(还有数据要处理)
{
code=getnextcode(); //得到下一个数据
if((code&8)!
=0)sb=1elsesb=0;
code&=7; //将code分离为数据和符号
delta=(step_table[index]*code)/4+step_table[index]/8; //后面加的一项是为了减少误差
if(sb==1)delta=-delta;
cur_sample+=delta; //计算出当前的波形数据
if(cur_sample>32767)output_sample(32767);
elseif(cur_sample<-32768)output_sample(-32768);
elseoutput_sample(cur_sample);
index+=index_adjust[code];
if(index<0)index=0;
if(index>88)index=88;
}
附表
intindex_adjust[8]={-1,-1,-1,-1,2,4,6,8};
intstep_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 }
TCPMP原代码赏析
/*****************************************************************************
*
*Thisprogramisfreesoftware;youcanredistributeitand/ormodify
*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby
*theFreeSoftwareFoundation;eitherversion2oftheLicense,or
*(atyouroption)anylaterversion.
*
*Thisprogramisdistributedinthehopethatitwillbeuseful,
*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe
*GNUGeneralPublicLicenseformoredetails.
*
*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense
*alongwiththisprogram;ifnot,writetotheFreeSoftware
*Foundation,Inc.,59TemplePlace,Suite330,Boston,MA 02111-1307USA
*
*$Id:
adpcm.h2712005-08-0908:
31:
35Zpicard$
*
*TheCorePocketMediaPlayer
*Copyright(c)2004-2005GaborKovacs
*
****************************************************************************/
#ifndef__ADPCM_H
#define__ADPCM_H
#defineADPCM_CLASS FOURCC('A','D','P','C')
#defineADPCM_MS_ID FOURCC('A','D','M','S')
#defineADPCM_IMA_IDFOURCC('A','D','I','M')
#defineADPCM_IMA_QT_IDFOURCC('A','D','I','Q')
#defineADPCM_G726_IDFOURCC('G','7','2','6')
externvoidADPCM_Init();
externvoidADPCM_Done();
#endif
/*****************************************************************************
*
*Thisprogramisfreesoftware;youcanredistributeitand/ormodify
*itunderthetermsoftheGNUGeneralPublicLicenseaspublishedby
*theFreeSoftwareFoundation;eitherversion2oftheLicense,or
*(atyouroption)anylaterversion.
*
*Thisprogramisdistributedinthehopethatitwillbeuseful,
*butWITHOUTANYWARRANTY;withouteventheimpliedwarrantyof
*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSE.Seethe
*GNUGeneralPublicLicenseformoredetails.
*
*YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense
*alongwiththisprogram;ifnot,writetotheFreeSoftware
*Foundation,Inc.,59TemplePlace,Suite330,Boston,MA 02111-1307USA
*
*$Id:
adpcm.c5652006-01-1214:
11:
44Zpicard$
*
*TheCorePocketMediaPlayer
*Copyright(c)2004-2005GaborKovacs
*
****************************************************************************/
#include"../common/common.h"
#include"adpcm.h"
#include"g726/g72x.h"
typedefstructstate
{
intPredictor;
intStepIndex;
intStep;
intSample1;
intSample2;
intCoEff1;
intCoEff2;
intIDelta;
}state;
typedefstructadpcm
{
codecCodec;
bufferData;
intChannel;//IMA_QT
int16_t*Buffer;
stateState[2];
g726_stateG726[2];
}adpcm;
staticconstintIndexTable[16]=
{
-1,-1,-1,-1,2,4,6,8,
-1,-1,-1,-1,2,4,6,8,
};
staticconstintStepTable[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
};
//AdaptationTable[],AdaptCoeff1[],andAdaptCoeff2[]arefromlibsndfile
staticconstintAdaptationTable[]=
{
230,230,230,230,307,409,512,614,
768,614,512,409,307,230,230,230
};
staticconstintAdaptCoeff1[]=
{
256,512,0,192,240,460,392
};
staticconstintAdaptCoeff2[]=
{
0,-256,0,64,0,-208,-232
};
static_INLINEintIMA_Calc(state*s,intv)
{
intStepIndex;
intPredictor;
intDiff,Step;
Step=StepTable[s->StepIndex];
StepIndex=s->StepIndex+IndexTable[v];
if(StepIndex<0)
StepIndex=0;
elseif(StepIndex>88)
StepIndex=88;
Diff=((2*(v&7)+1)*Step)>>3;
Predictor=s->Predictor;
if(v&8)
Predictor-=Diff;
else
Predictor+=Diff;
if(Predictor>32767)
Predictor=32767;
elseif(Predictor<-32768)
Predictor=-32768;
s->Predictor=Predictor;
s->StepIndex=StepIndex;
returnPredictor;
}
static_INLINEintMS_Calc(state*s,intv)
{
intPredictor;
Predictor=((s->Sample1*s->CoEff1)+(s->Sample2*s->CoEff2))>>8;
Predictor+=((v&0x08)?
v-0x10:
v)*s->IDelta;
if(Predictor>32767)
Predictor=32767;
elseif(Predictor<-32768)
Predictor=-32768;
s->Sample2=s->Sample1;
s->Sample1=Predictor;
s->IDelta=(AdaptationTable[v]*s->IDelta)>>8;
if(s->IDelta<16)
s->IDelta=16;
returnPredictor;
}
staticintProcess(adpcm*p,constpacket*Packet,constflowstate*State)
{
inti;
intPredictor;
constuint8_t*In;
constuint8_t*InEnd;
int16_t*Out=p->Buffer;
if(Packet)
{
if(Packet->RefTime>=0)
p->Codec.Packet.RefTime=Packet->RefTime;
BufferPack(&p->Data,0);
BufferWrite(&p->Data,Packet->Data[0],Packet->Length,1024);
}
else
p->Codec.Packet.RefTime=TIME_UNKNOWN;
if(!
BufferRead(&p->Data,&In,p->Codec.In.Format.Format.Audio.BlockAlign))
returnERR_NEED_MORE_DATA;
InEnd=In+p->Codec.In.Format.Format.Audio.BlockAlign;
switch(p->Codec.Node.Class)
{
caseADPCM_G726_ID:
{
g726_state*g1,*g2;
g1=g2=&p->G726[0];
if(p->Codec.In.Format.Format.Audio.Channels==2)
++g2;
switch(p->Codec.In.Format.Format.Audio.Bits)
{
case2:
for(;In {
Out[0]=(int16_t)g726_16_decoder(In[0]>>6,g1);
Out[1]=(int16_t)g726_16_decoder(In[0]>>4,g2);
Out[2]=(int16_t)g726_16_decoder(In[0]>>2,g1);
Out[3]=(int16_t)g726_16_decoder(In[0],g2);
}
break;
case3:
InEnd-=2;
for(;In {
Out[0]=(int16_t)g726_24_decoder(In[0]>>5,g1);
Out[1]=(int16_t)g726_24_decoder(In[0]>>2,g2);
Out[2]=(int16_t)g726_24_decoder((In[0]<<1)|(In[1]>>7),g1);
Out[3]=(int16_t)g726_24_decoder(In[1]>>4,g2);
Out[4]=(int16_t)g726_24_decoder(In[1]>>1,g1);
Out[5]=(int16_t)g726_24_decoder((In[1]<<2)|(In[2]>>6),g2);
Out[6]=(int16_t)g726_24_decoder(In[2]>>3,g1);
Out[7]=(int16_t)g726_24_decoder(In[2]>>0,g2);
}
break;
case4:
for(;In {
Out[0]=(int16_t)g726_32_decoder(In[0]>>4,g1);
Out[1]=(int16_t)g726_32_decoder(In[0],g2);
}
break;
case5:
InEnd-=4;
for(;In {
Out[0]=(int16_t)g726_40_decoder(In[0]>>3,g1);
Out[1]=(int16_t)g726_40_decoder((In[0]<<2)|(In[1]>>6),g2);
Out[2]=(int16_t)g726_40_decoder(In[1]>>1,g1);
Out[3]=(int16_t)g726_40_decoder((In[1]<<4)|(In[2]>>4),g2);
Out[4]=(int16_t)g726_40_decoder((In[2]<<1)|(In[3]>>7),g1);
Out[5]=(int16_t)g726_40_decoder(In[3]>>2,g2);
Out[6]=(int16_t)g726_40_decoder((In[3]<<3)|(In[4]>>5),g1);
Out[7]=(int16_t)g726_40_decoder(In[4]>>0,g2);
}
break;
}
break;
}
caseADPCM_IMA_QT