ADPCM算法

wochao 2001-04-25 01:33:00
请问ADPCM算法的原理及那有实现其的程序下载。谢谢。
...全文
217 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
wyly 2001-06-30
  • 打赏
  • 举报
回复
忘了说一声:上面g.721,g.723的ADPCM(可是我记得G.723不是ADPCM)
wyly 2001-06-30
  • 打赏
  • 举报
回复
www.avsuper.com上有ADPCM的辕马,不是IMA-ADPCM,是INTEL写的。
michaelh 2001-06-29
  • 打赏
  • 举报
回复
Ready to use,看我的厉害:

// adpcm.h
struct adpcm_state
{
short valprev; /* Previous output value */
char index; /* Index into stepsize table */
};

class G721 // ADPCM codec
{
public:
G721();
~G721();
void adpcm_coder(short* indata,char* outdata,int len,
adpcm_state* state);
void adpcm_decoder(char* indata,short* outdata,int len,
adpcm_state* state);
};

//adpcm.cpp
#include "stdafx.h"
#include "adpcm.h"
//#include "stdio.h"

static int indexTable[16] =
{
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8,
};

static int stepsizeTable[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
};

G721::~G721()
{

}

G721::G721()
{

}

void G721::adpcm_coder(short* indata,char* outdata,int len,adpcm_state* state)
{
short *inp; /* Input buffer pointer */
signed char *outp; /* output buffer pointer */
int val; /* Current input sample value */
int sign; /* Current adpcm sign bit */
int delta; /* Current adpcm output value */
int diff; /* Difference between val and valprev */
int step; /* Stepsize */
int valpred; /* Predicted output value */
int vpdiff; /* Current change to valpred */
int index; /* Current step change index */
int outputbuffer; /* place to keep previous 4-bit value */
int bufferstep; /* toggle between outputbuffer/output */

outp = (signed char *)outdata;
inp = indata;
valpred = state->valprev;
index = state->index;
step = stepsizeTable[index];
bufferstep = 1;

for ( ; len > 0 ; len-- )
{
val = *inp++;

/* Step 1 - compute difference with previous value */
diff = val - valpred;
sign = (diff < 0) ? 8 : 0;
if(sign) diff = (-diff);

/* Step 2 - Divide and clamp
** This code *approximately* computes:
** delta = diff*4/step;
** vpdiff = (delta+0.5)*step/4;
** but in shift step bits are dropped. The net result of this is
** that even if you have fast mul/div hardware you cannot put it to
** good use since the fixup would be too expensive.
*/
delta = 0;
vpdiff = (step >> 3);
if(diff >= step)
{
delta = 4;
diff -= step;
vpdiff += step;
}
step >>= 1;
if(diff >= step)
{
delta |= 2;
diff -= step;
vpdiff += step;
}
step >>= 1;
if(diff >= step)
{
delta |= 1;
vpdiff += step;
}
/* Step 3 - Update previous value */
if( sign )
valpred -= vpdiff;
else
valpred += vpdiff;
/* Step 4 - Clamp previous value to 16 bits */
if( valpred > 32767 )
valpred = 32767;
else if(valpred < -32768)
valpred = -32768;
/* Step 5 - Assemble value, update index and step values */
delta |= sign;
index += indexTable[delta];
if(index < 0) index = 0;
if(index > 88) index = 88;
step = stepsizeTable[index];
/* Step 6 - Output value */
if(bufferstep)
{
outputbuffer = (delta << 4) & 0xf0;
}
else
{
*outp++ = (delta & 0x0f) | outputbuffer;
}
bufferstep = !bufferstep;
}
/* Output last step, if needed */
if(!bufferstep)
*outp++ = outputbuffer;
state->valprev = valpred;
state->index = index;
}

void G721::adpcm_decoder(char* indata,short* outdata,int len,adpcm_state* state)
{
signed char *inp; /* Input buffer pointer */
short *outp; /* output buffer pointer */
int sign; /* Current adpcm sign bit */
int delta; /* Current adpcm output value */
int step; /* Stepsize */
int valpred; /* Predicted value */
int vpdiff; /* Current change to valpred */
int index; /* Current step change index */
int inputbuffer; /* place to keep next 4-bit value */
int bufferstep; /* toggle between inputbuffer/input */

outp = outdata;
inp = (signed char *)indata;
valpred = state->valprev;
index = state->index;
step = stepsizeTable[index];
bufferstep = 0;
for( ; len > 0 ; len--)
{
/* Step 1 - get the delta value */
if(bufferstep)
{
delta = inputbuffer & 0xf;
}
else
{
inputbuffer = *inp++;
delta = (inputbuffer >> 4) & 0xf;
}
bufferstep = !bufferstep;
/* Step 2 - Find new index value (for later) */
index += indexTable[delta];
if(index < 0 ) index = 0;
if(index > 88) index = 88;
/* Step 3 - Separate sign and magnitude */
sign = delta & 8;
delta = delta & 7;
/* Step 4 - Compute difference and new predicted value */
/*
** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
** in adpcm_coder.
*/
vpdiff = step >> 3;
if(delta & 4) vpdiff += step;
if(delta & 2) vpdiff += step>>1;
if(delta & 1) vpdiff += step>>2;
if(sign)
valpred -= vpdiff;
else
valpred += vpdiff;
/* Step 5 - clamp output value */
if(valpred > 32767)
valpred = 32767;
else if ( valpred < -32768 )
valpred = -32768;
/* Step 6 - Update step value */
step = stepsizeTable[index];
/* Step 7 - Output value */
*outp++ = valpred;
}
state->valprev = valpred;
state->index = index;
}
请加分.
青润 2001-05-16
  • 打赏
  • 举报
回复
这些资料我手中到是有一些,不过我很忙,其实大部份资料你们自己也可以收集到的,
给你们一个搜索引擎:www.google.com
自己去找找吧。
mmmyyyaaa 2001-05-15
  • 打赏
  • 举报
回复
太感谢你了
bestone 2001-04-28
  • 打赏
  • 举报
回复
谢谢。我也在找这个呢。楼上的朋友,有没有其他的比如;DM,ADM,DPCM,ADPCM.LP,PARCAR等的算法,如有请跟我联系一下。最好有源码,我在做毕设,先谢了。
青润 2001-04-26
  • 打赏
  • 举报
回复
IMA-ADPCM 算法

--------------------------------------------------------------------------------

  IMA-ADPCM (ADPCM Adaptive Differential Pulse Code Modulation), 是一种针对 16bit (或者更高?) 声音波形数据的一种有损压缩算法, 它将声音流中每次采样的 16bit 数据以 4bit 存储, 所以压缩比 1:4. 而压缩/解压缩算法非常的简单, 所以是一种低空间消耗,高质量声音获得的好途径. 著名的 WestWood 在它的许多游戏里都使用了这个技术, DUNE II, C&C, RA 等等, 保存声音的数据文件后缀名为 .AUD 的大多用 IMA-ADPCM 压缩. (不过 WestWood 的游戏数据文件大多经过打包, 这些小文件统统放进了一个 .MIX 文件包中, 关于解开 .MIX 文件包, 见 http://www.geocities.com/SiliconValley/8682)

  ADPCM 主要是针对连续的波形数据的, 保存的是波形的变化情况, 以达到描述整个波形的目的. 本文并不想详细介绍 ADPCM 算法原理, 那些是数学知识,有高等数学基础的朋友可以自己研究, 云风数学马马虎虎, 这里也讲不清楚, 但是它的编码和解码的过程却很简洁, 列在后面, 相信大家能够看明白.

  先给不熟悉声音信号的储存的朋友补一课, 不想看就跳过吧 ^_^: 一般游戏中用到的声音有两种不同性质的, 一是波形数据, 是经过事先声音采样录制下来的, 采样时一般按每秒 8千到 4 万次的频率(8Khz ~44.4Khz)记录每次采样时的声音强度, 在播放时, 再以同一频率, 按样本声音的强弱变化触发扬声器, 声音就被重现了, 如果你将采样数据流标在坐标纸上,就会发现是一条波形曲线, 如果采样时将声音信号强弱分为 256 级, 就是我们说的 8bit 采样, 如果分为 65536 级, 就是 16bit 采样了; 另一是 MIDI 类的, 它是将各种乐器的声学性质都事先记录下来, 而数据流中仍旧是按一定频率记录, 但不是每秒数千上万次了, 大约只有几 Hz 到几十 Hz, 将几种乐器按某一音频和强度触发描述下来, 经过声卡合成为波形信号就可以播放了.

  8bit 采样的声音人耳是可以接受的, 比如 Win95 启动的音乐, 而 16bit 采样的声音可以算是高音质了, 现代游戏中也多采用它. (将声音强度分的更细没有太多的意义, 通常都是提高采样频率来近一步提高音质) ADPCM 算法却可以将每次采样得到的 16bit 数据压缩到 4bit ;-) 需要注意的是, 如果要压缩/接压缩立体声信号, 请注意采样时, 声音信号是放在一起的, 需要将两个声道分别处理. OK, 下面列出了其中的奥妙, 请细细品味:


--------------------------------------------------------------------------------

IMA-ADPCM 压缩过程

首先我们认为声音信号都是从零开始的,那么需要初始化两个变量

int index=0,prev_sample:=0;

下面的循环将依次处理声音数据流, 注意其中的 getnextsample() 应该得到一个 16bit 的采样数据, 而 outputdata() 可以将计算出来的数据保存起来,程序中用到的 step_table[], index_adjust[] 附在后面:
int index=0,prev_sample:=0;

while (还有数据要处理) {
cur_sample=getnextsample(); // 得到当前的采样数据
delta=cur_sample-prev_sample; // 计算出和上一个的增量
if (delta<0) delta=-delta,sb=8;
else sb=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; // 便于下次得到更精确的变化量的描述
else if (index>88) index=88;

prev_sample=cur_sample;

outputode(code|sb); // 加上符号位保存起来
}





--------------------------------------------------------------------------------

IMA-ADPCM 解压缩过程

  接压缩实际是压缩的一个逆过程, 同样其中的 getnextcode() 应该得到一个编码, 而 outputsample() 可以将解码出来的声音信号保存起来. 这段代码同样使用了同一个的 setp_table[] 和 index_adjust() 附在后面:

int index=0,cur_sample:=0;

while (还有数据要处理) {
code=getnextcode(); // 得到下一个数据

if ((code & 8) != 0) sb=1 else sb=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) cur_sample=32767;
else if (cur_sample<-32768) cur_sample:=-32768;

output_sample(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 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 };


--------------------------------------------------------------------------------
  关于 WestWood 的 .AUD 文件,结构比较简单, 这里顺带提一下, 有兴趣可以自己写处理 AUD 文件的程序 ;-) 其 8bit 的声音压缩算法尚不知晓, 但用的最广泛的 16bit 声音正是用 IMA-ADPCM 压缩, 每个 AUD 文件都有一个文件头, 结构如下:

struct {
unsigned short int samplespersec; // 频率
long int size; // 除掉文件头的大小
long int outsize; // 输出数据大小 (通常是 4 倍)
unsigned char flags; // 位 0 描述是否立体声, 位 1 描述是否 16 bit
unsigned char type; // 1=WW 压缩, 99=IMA ADPCM
}

AUD 文件的声音信号是按块存放的, 每块大约 512 字节, 没一块都有一个块头结构:

struct {
unsigned short int size; // 压缩过的数据大小
unsigned short int outsize; // 输出数据大小 (通常是 4 倍)
long int id; // 永远是 0x0000DEAF
}


--------------------------------------------------------------------------------
本文参考了 Vladan Bato 写的 AUD 文件格式描述. 可以去他的网页 http://www.geocities.com/SiliconValley/8682 找到原文和他写的 AUD,WAV 转换程序.另外, Allegro 的爱好者可能想自己加入 AUD 的支持(Allegro 3.1 新增 Plug-In 支持, 增加新文件类型很方便), 不妨看看 http://www.alphalink.com.au/~tjaden, 这里有完成了的 AUD 支持库.

33,007

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧