ADPCM_DVI4音頻解碼

項目中要用到ADPCM_DVI4音頻格式,需要對DVI4做編解碼,在windows環境海思提供了庫,可以直接調用,近期需要移植到linux,海思沒有提供相關庫,只能自己想辦法了。找了很多資料,終於在RFC3551中找到DVI4的描述,見https://tools.ietf.org/html/rfc3551 4.5.1 。

總結下來只需要將IMA_ADPCM算法改兩部分就可以:

1.解碼代碼

/**************************************************************************************
* Function:    adpcm_decoder
*
* Description: decode ADPCM data in a long word to 8 16-bit PCM
*
* Argument:    char *outdata; [I] ADPCM output
*              short *indata; [0] PCM input
*              adpcm_state *state; [I/O] save previous info (output value and index into stepsize table)
*
* Return:      void
*
* Notes:       quantize the difference (diff)
*              predict the valpred for next sample
**************************************************************************************/
void adpcm_decoder(char *indata, short *outdata, struct adpcm_state *state, int input_len)
{
	//    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 */
	int len;
	//   outp = outdata;   
   //    inp = (signed char *)indata;   

	valpred = (int)state->valprev;
	index = state->index;
	step = stepsizeTable[index];

	bufferstep = 0;
	inputbuffer = 0;


	//int i  = 0;   
	for (len = 0; len < input_len * 2; len++) {

		/* Step 1 - get the delta value */
		if (bufferstep) {
			//delta = (inputbuffer >> 4) & 0xf;
			//再解低4bit
			delta = (inputbuffer) & 0xf;
		}
		else {
			inputbuffer = *indata++;
			//delta = (inputbuffer) & 0xf;
			//先解高4bit
			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 */
		*outdata++ = (valpred >> TRUCATE_BIT);  // convert to 15 bit output   
	}

	state->valprev = valpred;
	state->index = index;
}

修改部分 主要是對調了每個字節的4bit順序

if (bufferstep) {
			//delta = (inputbuffer >> 4) & 0xf;
			//再解低4bit
			delta = (inputbuffer) & 0xf;
		}
		else {
			inputbuffer = *indata++;
			//delta = (inputbuffer) & 0xf;
			//先解高4bit
			delta = (inputbuffer >> 4) & 0xf;
		}

 

2.調用與IMA不同的是 前4個字節是predict和index  也就是上面方法中的adpcm_state 

        pst->valprev = ((short)data[1] << 8) + data[0];
		//pst->index = ((short)data[3] << 8) + data[2];
		pst->index = data[2];
		data += 4;

		adpcm_decoder(data, outdata, pst, data_len);

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章