📄 adpcm.c
字号:
/*File Name: Adpcm.c*/
/*********************************************/
const int index_adjust[16] = {-1, -1, -1, -1, 2, 4, 6, 8};
const 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 };
typedef struct adpcm_state {
short valprev; /* Previous output value */
short index; /* Index into stepsize table */
}S_AdpcmState;
S_AdpcmState f_sEnc;
S_AdpcmState f_sDec;
/*********************************************/
int loco_adpcmInit()
{
f_sEnc.valprev = 0;
f_sEnc.index = 0;
f_sDec.valprev = 0;
f_sDec.index = 0;
return 0;
}
void loco_adpcmResetDecoder()
{
f_sDec.valprev = 0;
f_sDec.index = 0;
}
void loco_adpcmResetEncoder()
{
f_sEnc.valprev = 0;
f_sEnc.index = 0;
}
void loco_adpcmFree()
{
f_sEnc.valprev = 0;
f_sEnc.index = 0;
f_sDec.valprev = 0;
f_sDec.index = 0;
}
inline char adpcm_encode(short sample)
{
int code, sb;
short delta;
int index;
int prev;
index = f_sEnc.index;
prev = f_sEnc.valprev;
sample *= 2;
/* 计算出和上一个的增量
sb 保存的是符号位
*/
delta = sample - prev;
if ( delta < 0 )
{
delta = -delta;
sb = 8;
}
else
sb=0;
/* 根据 steptable[] 得到一个 0~7 的值 */
code = 4*delta / step_table[index];
/* 它描述了声音强度的变化量 */
if (code > 7)
code = 7;
/* 根据声音强度调整下次取 steptable 的序号
便于下次得到更精确的变化量的描述
*/
index += index_adjust[code];
if (index < 0)
index = 0;
else if (index > 88)
index = 88;
/*保存sample*/
f_sEnc.valprev = sample;
f_sEnc.index = index;
/* 加上符号位返回 */
return (code|sb);
}
inline short adpcm_decode(char code)
{
int delta;
char sb;
int index;
int prev;
int c;
c = code;
index = f_sDec.index;
prev = f_sDec.valprev;
/* 将 code 分离为数据和符号 */
if ((c & 8) != 0)
sb=1;
else
sb=0;
c &= 7;
/* 后面加的一项是为了减少误差 */
delta = (step_table[index]*c)/4 + step_table[index]/8;
if (sb == 1)
delta = -delta;
/* 计算出当前的波形数据*/
prev += delta;
if (prev > 32767)
prev = 32767;
else if (prev < -32768)
prev = -32768;
index += index_adjust[c];
if (index < 0)
index = 0;
if (index > 88)
index = 88;
f_sDec.index = index;
f_sDec.valprev = prev;
return f_sDec.valprev;
}
int loco_adpcmEncode(unsigned char *psample,
int sample_size,
int sample_per_block,
int block_align,
unsigned char *pcode,
int code_size)
{
int i, j, index_c, index_s;
int code_block_count, block_count;
short sample;
unsigned char code, tmp_code, step;
int delta, sb;
block_count = (sample_size / 2) / sample_per_block;
code_block_count = code_size / block_align;
if (block_count > code_block_count)
block_count = code_block_count;
if (block_count == 0)
return 0;
index_c = 0;
index_s = 0;
i = 0;
for (j=0; j<block_count; j++)
{
pcode [index_c++] = psample[index_s++] & 0xFF ;
pcode [index_c++] = psample[index_s++] & 0xFF ;
pcode [index_c++] = f_sEnc.index ;
pcode [index_c++] = 0 ;
i += sample_per_block*2;
step = 0;
for (; index_s < i; )
{
step++;
sample = psample[index_s++] & 0xff;
sample |= (psample[index_s++] << 8) & 0xff00;
//编码操作
#if 0
tmp_code = adpcm_encode(sample);
#else
delta = sample - f_sEnc.valprev;
if ( delta < 0 )
{
delta = -delta;
sb = 8;
}
else
sb=0;
tmp_code = 4*delta / step_table[f_sEnc.index];
if (tmp_code > 7)
tmp_code = 7;
f_sEnc.index += index_adjust[tmp_code];
if (f_sEnc.index < 0)
f_sEnc.index = 0;
else if (f_sEnc.index > 88)
f_sEnc.index = 88;
f_sEnc.valprev = sample;
tmp_code = tmp_code|sb;
//编码结束
#endif
if (step == 1)
code = tmp_code & 0x0f;
else if (step == 2)
{
code |= (tmp_code << 4) & 0xf0;
pcode[index_c++] = code;
step = 0;
}
else
step = 0;
}
}
return block_count;
}
int loco_adpcmDecode(unsigned char *pcode,
int code_size,
int block_align,
unsigned char *psample,
int sample_size,
int sample_per_block)
{
int i, j, index_c, index_s;
int code_block_count, block_count;
short sample;
unsigned char code;
block_count = (sample_size / 2) / sample_per_block;
code_block_count = code_size / block_align;
if (block_count > code_block_count)
block_count = code_block_count;
if (block_count == 0)
return 0;
index_c = 0;
index_s = 0;
i = 0;
for (j=0; j<block_count; j++)
{
psample[index_s++] = pcode [index_c++];
psample[index_s++] = pcode [index_c++];
f_sDec.index = pcode [index_c++];
index_c++;
i += block_align;
for (; index_c < i; )
{
code = pcode[index_c] & 0x0f;
sample = adpcm_decode(code);
psample[index_s++] = sample & 0xff;
psample[index_s++] = (sample >> 8) & 0xff;
code = (pcode[index_c++] >> 4) & 0x0f;
sample = adpcm_decode(code);
psample[index_s++] = sample & 0xff;
psample[index_s++] = (sample >> 8) & 0xff;
}
}
return block_count;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -