⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 adpcm.c

📁 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 + -