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

📄 g72x.c

📁 zigbee 飞思卡尔 音频传输 基于ucos的所有源码
💻 C
字号:
/*
 * This source code is a product of Sun Microsystems, Inc. and is provided
 * for unrestricted use.  Users may copy or modify this source code without
 * charge.
 *
 * SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
 * THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
 *
 * Sun source code is provided with no support and without any obligation on
 * the part of Sun Microsystems, Inc. to assist in its use, correction,
 * modification or enhancement.
 *
 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
 * OR ANY PART THEREOF.
 *
 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
 * or profits or other special, indirect and consequential damages, even if
 * Sun has been advised of the possibility of such damages.
 *
 * Sun Microsystems, Inc.
 * 2550 Garcia Avenue
 * Mountain View, California  94043
 */

/*
 * g72x.c
 *
 * Common routines for G.721 and G.723 conversions.
 */

//#include <audiofmt/st.h>
#include "g72x.h"
//#include <audiofmt/libst.h>
//#include <math.h>

static int power2[15] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80,
			0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000};
static int abs(int d)
{
	if(d>0)
	{
		return d;
	}
	else
	{
		return -d;
	}
}
/*
 * g72x_init_state()
 *
 * This routine initializes and/or resets the g72x_state structure
 * pointed to by 'state_ptr'.
 * All the initial state values are specified in the CCITT G.721 document.
 */
void
g72x_init_state(struct g72x_state* state_ptr)
{
asm
	{
	    move.l state_ptr,a4
	    move.l #34816,(a4)+   //yl
	    move.l #544,(a4)+     //yu 
	    move.l #0,(a4)+       //dms
	    move.l #0,(a4)+       //dml
	    move.l #0,(a4)+       //ap
	    move.l #0,(a4)+       //a
		move.l #0,(a4)+
		move.l #0,(a4)+      //b
		move.l #0,(a4)+
		move.l #0,(a4)+
		move.l #0,(a4)+
		move.l #0,(a4)+
		move.l #0,(a4)+
		move.l #0,(a4)+    //pk        
		move.l #0,(a4)+    
		move.w #32,(a4)+    //dq
		move.w #32,(a4)+
		move.w #32,(a4)+
		move.w #32,(a4)+
		move.w #32,(a4)+
		move.w #32,(a4)+
		move.l #32,(a4)+   //sr
		move.l #32,(a4)+
		move.l #0,(a4)     //td
	}
/*	int		cnta;

	state_ptr->yl = 34816;
	state_ptr->yu = 544;
	state_ptr->dms = 0;
	state_ptr->dml = 0;
	state_ptr->ap = 0;
	for (cnta = 0; cnta < 2; cnta++) {
		state_ptr->a[cnta] = 0;
		state_ptr->pk[cnta] = 0;
		state_ptr->sr[cnta] = 32;
	}
	for (cnta = 0; cnta < 6; cnta++) {
		state_ptr->b[cnta] = 0;
		state_ptr->dq[cnta] = 32;//short
	}
	state_ptr->td = 0;*/
}

/*
 * predictor_zero()
 *
 * computes the estimated signal from 6-zero predictor.
 *
 */
/*int
predictor_zero(struct g72x_state* state_ptr)
{
	int		i;
	int		sezi;
	
	sezi = state_ptr->b[0] * state_ptr->dq[0];
	for (i = 1; i < 6; i++)			/* ACCUM */
/*		sezi += state_ptr->b[i] * state_ptr->dq[i];
	return (sezi >>13);*/
	
/*	sezi = fmult(state_ptr->b[0] >> 2, state_ptr->dq[0]);
	for (i = 1; i < 6; i++)			
		sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]);
	return (sezi);
}
*/

/*
 * predictor_pole()
 *
 * computes the estimated signal from 2-pole predictor.
 *
 */
/*int
predictor_pole( struct g72x_state* state_ptr )
{
	 return((state_ptr->a[1] * state_ptr->sr[1] +
	    state_ptr->a[0] * state_ptr->sr[0]) >> 13);*/
/*	return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) +
	    fmult(state_ptr->a[0] >> 2, state_ptr->sr[0]));
	    
}
*/

/*
 * step_size()
 *
 * computes the quantization step size of the adaptive quantizer.
 *
 */
int
step_size(struct g72x_state *state_ptr)
{
asm
	{
	move.l	state_ptr,a0
	add.l	#16,a0
	move.l	(a0),d0
	sub.l	#12,a0
	move.l	(a0),d1
	cmp.l	#256,d0
	ble		else1
	move.l	d1,d0
	jmp		exit
	else1:
	sub.l	#4,a0
	move.l	(a0),d2
	asr.l	#6,d2	//y,d2
	sub.l	d2,d1	//dif,d1
	asr.l	#2,d0	//al,d0
	cmp.l	#0,d1
	bgt		gt1
	cmp.l	#0,d1
	blt		lt1
	move.l	d2,d0
	jmp		exit
	gt1:
	muls.l	d1,d0
	asr.l	#6,d0
	add.l	d2,d0
	jmp		exit
	lt1:
	muls.l	d1,d0
	add.l	#0x3F,d0
	asr.l	#6,d0
	add.l	d2,d0
	exit:	
	
	}
/*	int		y;
	int		dif;
	int		al;

	if (state_ptr->ap >= 256)
		return (state_ptr->yu);
	else {
		y = state_ptr->yl >> 6;
		dif = state_ptr->yu - y;
		al = state_ptr->ap >> 2;
		if (dif > 0)
			y += (dif * al) >> 6;
		else if (dif < 0)
			y += (dif * al + 0x3F) >> 6;
		return (y);
	}*/
}

/*
 * quantize()
 *
 * Given a raw sample, 'd', of the difference signal and a
 * quantization step size scale factor, 'y', this routine returns the
 * ADPCM codeword to which that sample gets quantized.  The step
 * size scale factor division operation is done in the log base 2 domain
 * as a subtraction.
 */
int
quantize(
	int d,			                    // Raw difference signal sample
	int y,								// Step size multiplier
	int * table,						// quantization table
	int size							// table size of short integers
)
{
//	short		dqm;	/* Magnitude of 'd' */
//	short		exp;	/* Integer part of base 2 log of 'd' */
//	short		mant;	/* Fractional part of base 2 log */
//	short		dl;	/* Log of magnitude of 'd' */
//	short		dln;	/* Step size scale factor normalized log */
//	int		i;

	/*
	 * LOG
	 *
	 * Compute base 2 log of 'd', and store in 'dl'.
	 */
//	dqm = abs(d);
/*	if(d>=0)
	{
		dqm = d;
	}
	else
	{
		dqm = -d;
	}
	exp = quan(dqm >> 1, power2, 15);
	mant = ((dqm << 7) >> exp) & 0x7F;	// Fractional portion.
	dl = (exp << 7) + mant;*/
	asm
	{
	move.l d,d3
	move.l d3,d5      //d5--d
	cmp.l #0,d3
	bge good_d
	neg.l d3
good_d:
	move.l d3,d1    //d1 dqm
	
	move.l #0,d0
	move.l #15,d2
	asr.l #1,d3
	lea power2,a1
next_q3:
	move.l (a1)+,d4
	cmp.l d4,d3
	blt exit_q3
	addi.l #1,d0
	cmp.l d2,d0
	blt next_q3
exit_q3:
	asl.l #7,d1
	asr.l d0,d1
	and.l #0x7f,d1  //d1 mant
	asl.l #7,d0
	add.l d1,d0  //d0--dl
	move.l y,d1
	asr.l #2,d1
	sub.l d1,d0   //d0--dln

	/*
	 * SUBTB
	 *
	 * "Divide" by step size multiplier.
	 */
//	dln = dl - (y >> 2);
	move.l #0,d1
	move.l size,d2
	move.l d0,d3
	move.l table,a1
next_q:
	move.l (a1)+,d4
	ext.l d4
	cmp.l d4,d3
	blt exit_q
	addi.l #1,d1
	cmp.l d2,d1
	blt next_q
exit_q:       //d1--i
	cmp.l #0,d5
	blt end_d
	cmp.l #0,d1
	bne end_all
	move.l #0,d1
end_d:
	asl.l #1,d2
	add.l #1,d2
	sub.l d1,d2	
	move.l d2,d1
end_all:
	move.l d1,d0
	}
	/*
	 * QUAN
	 *
	 * Obtain codword i for 'd'.
	 */
/*	i = quan(dln, table, size);
	if (d < 0)			/* take 1's complement of i */
/*		return ((size << 1) + 1 - i);
	else if (i == 0)		/* take 1's complement of 0 */
/*		return ((size << 1) + 1); /* new in 1988 */
/*	else
		return (i);*/
}


/*
 * reconstruct()
 *
 * Returns reconstructed difference signal 'dq' obtained from
 * codeword 'i' and quantization step size scale factor 'y'.
 * Multiplication is performed in log base 2 domain as addition.
 */
int
reconstruct(int sign, int dqln, int y)
{
/*	short		dql;	// Log of 'dq' magnitude 
	short		dex;	// Integer part of log 
	short		dqt;
	short		dq;	// Reconstructed difference signal sample 

	dql = dqln + (y >> 2);	// ADDA 

	if (dql < 0) {
		return ((sign) ? -0x8000 : 0);
	} else {		// ANTILOG 
		dex = (dql >> 7) & 15;
		dqt = 128 + (dql & 127);
		dq = (dqt << 7) >> (14 - dex);
		return ((sign) ? (dq - 0x8000) : dq);
	}*/
	asm
{
	move.l y,d1
	asr.l #2,d1
	move.l dqln,d2
	add.l d2,d1  //d1--dql
	cmp.l #0,d1
	bge next_dql
	move.l sign,d3
	cmp.l #0,d3
	beq retu_0
	move.l #0x8000,d0
	neg.l d0
	bra end_re
retu_0:
	move.l #0,d0
	bra end_re
next_dql:
    move.l sign,d3
	move.l d1,d4
	asr.l #7,d4
	and.l #15,d4  //d4 dex
	and.l #127,d1
	add.l #128,d1  //d1 dqt
	asl.l #7,d1
	move.l #14,d2
	sub.l d4,d2
	asr.l d2,d1 //d1--dq
	ext.l d1
	cmp.l #0,d3
	beq next_n0
	move.l #0x8000,d2
	sub.l d2,d1
next_n0:
	move.l d1,d0
end_re:	
}
}


/*
 * update()
 *
 * updates the state variables for each output code
 */
void
update(int y, int wi, int fi, int dq, int sr, int dqsez, struct g72x_state* state_ptr)
{
	int		cnt;
	int		mag, exp, mant;	/* Adaptive predictor, cbFLOAT A */
	int		a2p = 0;		/* LIMC */
	int		a1ul;		/* UPA1 */
	int		ua2, pks1;	/* UPA2 */
	int		uga2a, fa1;
	int		uga2b;
	int		tr;		/* tone/transition detector */
	int		ylint, thr2, dqthr;
	int  		ylfrac, thr1;
	int		pk0;

	pk0 = (dqsez < 0) ? 1 : 0;	/* needed in updating predictor poles */

	mag = dq & 0x7FFF;		/* prediction difference magnitude */
	/* TRANS */
	ylint = state_ptr->yl >> 15;	/* exponent part of yl */
	ylfrac = (state_ptr->yl >> 10) & 0x1F;	/* fractional part of yl */
	thr1 = (32 + ylfrac) << ylint;		/* threshold */
	thr2 = (ylint > 9) ? 31 << 10 : thr1;	/* limit thr2 to 31 << 10 */
	dqthr = (thr2 + (thr2 >> 1)) >> 1;	/* dqthr = 0.75 * thr2 */
	if (state_ptr->td == 0)		/* signal supposed voice */
		tr = 0;
	else if (mag <= dqthr)		/* supposed data, but small mag */
		tr = 0;			/* treated as voice */
	else				/* signal is data (modem) */
		tr = 1;

	/*
	 * Quantizer scale factor adaptation.
	 */

	/* FUNCTW & FILTD & DELAY */
	/* update non-steady state step size multiplier */
	state_ptr->yu = y + ((wi - y) >> 5);

	/* LIMB */
	if (state_ptr->yu < 544)	/* 544 <= yu <= 5120 */
		state_ptr->yu = 544;
	else if (state_ptr->yu > 5120)
		state_ptr->yu = 5120;

	/* FILTE & DELAY */
	/* update steady state step size multiplier */
	state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6);

	/*
	 * Adaptive predictor coefficients.
	 */
	if (tr == 1) {			/* reset a's and b's for modem signal */
		state_ptr->a[0] = 0;
		state_ptr->a[1] = 0;
		state_ptr->b[0] = 0;
		state_ptr->b[1] = 0;
		state_ptr->b[2] = 0;
		state_ptr->b[3] = 0;
		state_ptr->b[4] = 0;
		state_ptr->b[5] = 0;
	} else {			/* update a's and b's */
		pks1 = pk0 ^ state_ptr->pk[0];		/* UPA2 */

		/* update predictor pole a[1] */
		a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7);
		if (dqsez != 0) {
			fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0];
			if (fa1 < -8191)	/* a2p = function of fa1 */
				a2p -= 0x100;
			else if (fa1 > 8191)
				a2p += 0xFF;
			else
				a2p += fa1 >> 5;

			if (pk0 ^ state_ptr->pk[1])
				/* LIMC */
				if (a2p <= -12160)
					a2p = -12288;
				else if (a2p >= 12416)
					a2p = 12288;
				else
					a2p -= 0x80;
			else if (a2p <= -12416)
				a2p = -12288;
			else if (a2p >= 12160)
				a2p = 12288;
			else
				a2p += 0x80;
		}

		/* TRIGB & DELAY */
		state_ptr->a[1] = a2p;

		/* UPA1 */
		/* update predictor pole a[0] */
		state_ptr->a[0] -= state_ptr->a[0] >> 8;
		if (dqsez != 0)
			if (pks1 == 0)
				state_ptr->a[0] += 192;
			else
				state_ptr->a[0] -= 192;

		/* LIMD */
		a1ul = 15360 - a2p;
		if (state_ptr->a[0] < -a1ul)
			state_ptr->a[0] = -a1ul;
		else if (state_ptr->a[0] > a1ul)
			state_ptr->a[0] = a1ul;

		/* UPB : update predictor zeros b[6] */
/*		for (cnt = 0; cnt < 6; cnt++) {
				state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8;
			if (dq & 0x7FFF) {			/* XOR */
/*				if ((dq ^ state_ptr->dq[cnt]) >= 0)
					state_ptr->b[cnt] += 128;
				else
					state_ptr->b[cnt] -= 128;
			}
		}
	}*/
		asm
		{
			move.l state_ptr,a0
			add.l  #28,a0
			move.l (a0),d1
			move.l d1,d2
			asr.l  #8,d2
			sub.l  d2,d1
			move.l d1,(a0)+
			move.l (a0),d1
			move.l d1,d2
			asr.l  #8,d2
			sub.l  d2,d1
			move.l d1,(a0)+
			move.l (a0),d1
			move.l d1,d2
			asr.l  #8,d2
			sub.l  d2,d1
			move.l d1,(a0)+
			move.l (a0),d1
			move.l d1,d2
			asr.l  #8,d2
			sub.l  d2,d1
			move.l d1,(a0)+
			move.l (a0),d1
			move.l d1,d2
			asr.l  #8,d2
			sub.l  d2,d1
			move.l d1,(a0)+
			move.l (a0),d1
			move.l d1,d2
			asr.l  #8,d2
			sub.l  d2,d1
			move.l d1,(a0)+
		check2:
			move.l dq,d3
			andi.l #0x7fff,d3
			cmp.l  #0,d3
			beq		exit1
			move.l state_ptr,a0
			add.l  #28,a0
			move.l a0,a1
			add.l #32,a1
			
			move.l dq,d2
			move.l (a0),d3
			move.w (a1)+,d4
			ext.l	d4
			eor.l d2,d4
			cmp.l  #0,d4
			blt    else2
			add.l  #128,d3
			move.l d3,(a0)+
			jmp    next2
			else2:
			sub.l  #128,d3
			move.l d3,(a0)+
			next2:	   
			
			move.l (a0),d3
			move.w (a1)+,d4
			ext.l	d4
			eor.l d2,d4
			cmp.l  #0,d4
			blt    else3
			add.l  #128,d3
			move.l d3,(a0)+
			jmp    next3
			else3:
			sub.l  #128,d3
			move.l d3,(a0)+
			next3:	   
			
			move.l (a0),d3
			move.w (a1)+,d4
			ext.l	d4
			eor.l d2,d4
			cmp.l  #0,d4
			blt    else4
			add.l  #128,d3
			move.l d3,(a0)+
			jmp    next4
			else4:
			sub.l  #128,d3
			move.l d3,(a0)+
			next4:	   
			
			move.l (a0),d3
			move.w (a1)+,d4
			ext.l	d4
			eor.l d2,d4
			cmp.l  #0,d4
			blt    else5
			add.l  #128,d3
			move.l d3,(a0)+
			jmp    next5
			else5:
			sub.l  #128,d3
			move.l d3,(a0)+
			next5:	   
			
			
			move.l (a0),d3
			move.w (a1)+,d4
			ext.l	d4
			eor.l d2,d4
			cmp.l  #0,d4
			blt    else6
			add.l  #128,d3
			move.l d3,(a0)+
			jmp    next6
			else6:
			sub.l  #128,d3
			move.l d3,(a0)+
			next6:	   
			
			move.l (a0),d3
			move.w (a1)+,d4
			ext.l	d4
			eor.l d2,d4
			cmp.l  #0,d4
			blt    else7
			add.l  #128,d3
			move.l d3,(a0)+
			jmp    next7
			else7:
			sub.l  #128,d3
			move.l d3,(a0)+
			next7:	   
			exit1:
		}
	
	}
    asm
    {
    	move.l	state_ptr,a0
    	add.l	#70,a0
    	move.l	a0,a1
    	add.l	#2,a1
    	move.w	-(a0),d0
    	move.w	d0,-(a1)
    	
    	move.w	-(a0),d0
    	move.w	d0,-(a1)
    	
    	move.w	-(a0),d0
    	move.w	d0,-(a1)
    	
    	move.w	-(a0),d0
    	move.w	d0,-(a1)
    	
    	move.w	-(a0),d0
    	move.w	d0,-(a1)	
    }
/*	for (cnt = 5; cnt > 0; cnt--)
		state_ptr->dq[cnt] = state_ptr->dq[cnt-1];*/

	if(dq < 0){
		dq = 32768 + dq;
		dq = -dq;
	}	
	state_ptr->dq[0] = dq;

	
	state_ptr->sr[1] = state_ptr->sr[0];
	state_ptr->sr[0] = sr;
		
	/* DELAY A */
	state_ptr->pk[1] = state_ptr->pk[0];
	state_ptr->pk[0] = pk0;

	/* TONE */
	if (tr == 1)		/* this sample has been treated as data */
		state_ptr->td = 0;	/* next one will be treated as voice */
	else if (a2p < -11776)	/* small sample-to-sample correlation */
		state_ptr->td = 1;	/* signal may be data */
	else				/* signal is voice */
		state_ptr->td = 0;

	/*
	 * Adaptation speed control.
	 */
	state_ptr->dms += (fi - state_ptr->dms) >> 5;		/* FILTA */
	state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7);	/* FILTB */

	if (tr == 1)
		state_ptr->ap = 256;
	else if (y < 1536)					/* SUBTC */
		state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
	else if (state_ptr->td == 1)
		state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
	else if (abs((state_ptr->dms << 2) - state_ptr->dml) >=
	    (state_ptr->dml >> 3))
		state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
	else
		state_ptr->ap += (-state_ptr->ap) >> 4;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -