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

📄 adpcm.dsp

📁 adsp21x的数字信号处理器ADPCM音频压缩源代码
💻 DSP
📖 第 1 页 / 共 2 页
字号:
{
	The code below represents a full duplex Adaptive Differential
	Pulse Code Modulation (ADPCM) transcoder.  This program has been
	developed in accordance with ANSI specification T1.301-1987 and
	CCITT G.721 (bis).  It is fully bit-compatible with the test 
	vectors supplied by both of these organizations.

	An Application Note is available which describes the operation
	of the algorithm in detail.  A copy of this Note can be obtained
	from Analog Devices, DSP Division.

	Analog Devices		American National	Consultive Committee
	DSP Division		Standards Institute	on International
	P.O. Box 9106		1430 Broadway		Telephone and Telegraph
	Norwood, Ma 02062-9106	New York, N.Y. 10018
	(617) 461 - 3672

	Gordon A. Sterling 	
	Analog Devices
	DSP Division
	   6/28/88

		Calling Parameters
	AR = Companded PCM value (encoder)
	     ADPCM I value (decoder)

	M0=3;		L0=18;
	M1=1;		L1=6;
	M2=-1	
			L3=0;
	M4=0		L4=6;
	M5=1		L5=2
	M6=-1		L6=5

		Return Values
	AR = ADPCM I value (encoder)
	     Companded PCM value (decoder)

		Altered Registers
	AX0, AX1, AY0, AY1, AF, AR,
	MX0, MX1, MY0, MY1, MR,
	I0, I1, I3, I4, I5, I6
	SI, SR
	M3

		Cycle Count
	467 cycles for encode 
	514 cycles for decode

}

.MODULE		Adaptive_Differential_PCM;

.ENTRY		adpcm_encode, adpcm_decode;

.VAR/PM/CIRC 	b_buf[6];			{b coefficients for encode}
.VAR/PM/CIRC	a_buf[2];			{a coefficients for encode}
.VAR/PM/CIRC	b_buf_r[6];			{b coefficients for decode}
.VAR/PM/CIRC	a_buf_r[2];			{a coefficients for decode}

.VAR/DM/CIRC	b_delay_r[18];			{dq delay for decode}
.VAR/DM/CIRC	a_delay_r[6];			{sr delay for decode}
.VAR/DM/CIRC	b_delay[18];			{dq delay for encode}
.VAR/DM/CIRC	a_delay[6];			{sr delay for encode}

.VAR/DM/CIRC	mult_data[5];			{Predictor immediate data}

.VAR/DM		qn_values[10],dq_values[8];	{quantizer and dequantizer data}
.VAR/DM		f_values[12], w_values[8];	{Update coefficient data}
.VAR/DM		a_data[10];

.VAR/DM		s_e,s_r,a_ik,dq,p;
.VAR/DM		sez,sl,yu,yl_h,yl_l,y,y_2,ap,p_o,p_o_o,dms,dml,tdp,tr;
.VAR/DM		a_ik_r,dq_r,p_r;
.VAR/DM		yu_r,yl_h_r,yl_l_r,ap_r,p_o_r;
.VAR/DM 	p_o_o_r,dms_r,dml_r,tdp_r;

.VAR/DM		sp_r;				{PCM code word for synchronous adj}

.VAR/DM		hld_a_t, hld_b_t, hld_a_r, hld_b_r;

.INIT		qn_values:	7, 14, H#3F80, 
				400, 349, 300, 246, 178, 80, H#FF84;

.INIT		dq_values : 	h#F800, 4, 135, 213, 273, 323, 373, 425;

.INIT		f_values : 	-5, 0, 5120, 544, 
				0, 0, 0, 512, 512, 512, 1536, 3584;	

.INIT		w_values:	65344, 288, 656, 1024, 1792, 3168, 5680, 17952;

.INIT		mult_data : 	H#1FFF, H#4000, h#7E00, H#7FFF, H#FFFE;

.INIT		a_data :	H#1FFF, 2, 16384, 0, -7, 192, H#3000, H#D000, 
				H#D200, H#3C00;

.INIT		hld_a_t : ^a_delay;
.INIT		hld_b_t : ^b_delay;
.INIT		hld_a_r : ^a_delay_r;
.INIT		hld_b_r : ^b_delay_r;

.INIT		b_buf : 0,0,0,0,0,0;				{2.14}
.INIT		a_buf : 0,0;					{2.14}
.INIT		b_delay : 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;	{16.0, 16.0, 0.16}
.INIT		a_delay : 0,0,0,0,0,0;				{16.0, 16.0, 0.16}
.INIT		p : 0;						{16.0}
.INIT 		yu :0;						{7.9}
.INIT		yl_h : 0;					{7.9}
.INIT		yl_l : 0;					{0.16}
.INIT		ap : 0;						{8.8}
.INIT		p_o : 0;					{16.0}
.INIT		p_o_o : 0;					{16.0}
.INIT		dms : 0;					{7.9}
.INIT		dml : 0;					{5.11}
.INIT		tdp : 0;					{16.0}

.INIT		b_buf_r : 0,0,0,0,0,0;				{2.14}
.INIT		a_buf_r : 0,0;					{2.14}
.INIT		b_delay_r : 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0;{16.0, 16.0, 0.16}
.INIT		a_delay_r : 0,0,0,0,0,0;			{16.0, 16.0, 0.16}
.INIT		p_r : 0;					{16.0}
.INIT 		yu_r :0;					{7.9}
.INIT		yl_h_r : 0;					{7.9}
.INIT		yl_l_r : 0;					{0.16}
.INIT		ap_r : 0;					{8.8}
.INIT		p_o_r : 0;					{16.0}
.INIT		p_o_o_r : 0;					{16.0}
.INIT		dms_r : 0;					{7.9}
.INIT		dml_r : 0;					{5.11}
.INIT		tdp_r : 0;					{16.0}

adpcm_encode:	I4=^b_buf;			{Set pointer to b-coefficients}
		I5=^a_buf;			{Set pointer to a-coefficients}
		I6=^mult_data;			{Set pointer to predictor data}
		I1=DM(hld_a_t);			{Restore pointer to s_r delay}
		I0=DM(hld_b_t);			{Restore pointer to dq delay}
		
		CALL expand;			{Expand 8-bit log-PCM to12 bits}
		DM(sl)=AR;			{Store linear PCM value in sl}
		CALL predict;			{Call s_e and sez predictors}
		AX1=DM(ap);
		AY0=DM(yl_h);
		AX0=DM(yu);
		CALL lima;			{Limit ap and compute y}
		DM(y)=AR;			{Save y for later updates}
		DM(y_2)=SR1;			{Save y>>2 for log and reconst}
		AX0=DM(sl);
		AY0=DM(s_e);
		AY1=SR1, AR=AX0-AY0;		{Compute difference signal, d}
		CALL log;			{Determine I value from d}
		DM(a_ik)=AR;
		CALL reconst;			{Compute dq based ONLY on }
		DM(dq)=AR; 
		AY0=DM(s_e);
		AR=AR+AY0;			{Compute reconstructed signal}
		DM(s_r)=AR;

		DM(I1,M1)=AR, AR=ABS AR;	{Convert s_r to floating point}
		SR1=H#4000;			{Set SR1 to minimum value}
		SE=EXP AR (HI);			{Determine exponent adjust}
		AX0=SE, SR=SR OR NORM AR (HI);	{Normalize into SR}
		SR=LSHIFT SR1 BY -9 (HI);	{Delete lower bits}
		AY0=11;				{Base exponent}
		SR=LSHIFT SR1 BY 2 (HI);	{Adjust for ADSP-210x version}
		AR=AX0+AY0;			{Compute exponent}
		DM(I1,M1)=AR;			{Save exponent}
		DM(I1,M1)=SR1;			{Save mantissa}

		MR1=DM(tdp);
		SI=DM(yl_h);
		AX1=DM(dq);
		CALL trans;			{Compute new trigger }
		DM(tr)=AR;
		
		AR=PASS AR;			{Check state of trigger}
		IF EQ CALL update_filter;	{Update filter if trigger false}
	
		MR0=DM(ap);			{Load variables for updating}
		MR1=DM(y);
		MR2=DM(tdp);			{Always load MR2 after MR1!}
		MY0=DM(yl_h);
		MY1=DM(yl_l);
		AY0=DM(y);
		MX0=DM(dms);
		MX1=DM(dml);
		CALL functw;			{Update variables}
		DM(ap)=AR;			{Store updated variables}
		DM(yu)=AX1;
		DM(yl_l)=MY1;
		DM(yl_h)=MY0;
		DM(dms)=MX0;
		DM(dml)=MX1;

		AY1=DM(tr);			{Load trigger }
		AF=PASS AY1;			{Check state of trigger}
		IF NE CALL trigger_true;	{Call only if trigger true}

		AX0=DM(a_ik);			{Get I value for return}
		AY0=H#F;			{Only 4 LSBs are used}
		AR=AX0 AND AY0;			{So mask redundant sign bits}

		DM(hld_a_t)=I1;			{Save s_r delay pointer}
		DM(hld_b_t)=I0;			{Save dq delay pointer}

		RTS;				{Return to caller}

adpcm_decode:	I1=DM(hld_a_r);			{Restore s_r delay pointer}
		I0=DM(hld_b_r);			{Restore dq delay pointer}
		I4=^b_buf_r;			{Set pointer to b-coefficients}
		I5=^a_buf_r;			{Set pointer to a-coefficients}
		I6=^mult_data;			{Set pointer to predictor data}
		
		SR=LSHIFT AR BY 12 (HI);	{Get sign of ADPCM I value here}
		SR=ASHIFT SR1 BY -12 (HI);	{Sign extend ADPCM value to 16}
		DM(a_ik_r)=SR1;			{Save I value}
		CALL predict;			{Call s_e and sez predictor}
		AX1=DM(ap_r);
		AY0=DM(yl_h_r);
		AX0=DM(yu_r);
		CALL lima;			{Limit ap and compute y}
		DM(y)=AR;
		DM(y_2)=SR1;
		AY1=DM(y_2);
		AR=DM(a_ik_r);
		CALL reconst;			{Compute dq from received I}
		DM(dq_r)=AR; 
		AY0=DM(s_e);
		AR=AR+AY0;			{Compute reconstructed signal}
		DM(s_r)=AR;
	
		DM(I1,M1)=AR, AR=ABS AR;	{Make s_r floating point}
		SR1=H#4000;			{Set SR1 to minimum value}
		SE=EXP AR (HI);			{Determine exponent adjust}
		AX0=SE, SR=SR OR NORM AR (HI);	{Normalize value}
		SR=LSHIFT SR1 BY -9 (HI);	{Remove LSBs per spec}
		AY0=11;				{Base exponent}
		SR=LSHIFT SR1 BY 2 (HI);	{Adjust for ADSP-210x version}
		AR=AX0+AY0;			{Compute exponent}
		DM(I1,M1)=AR;			{Store exponent}
		DM(I1,M1)=SR1;			{Store mantissa}
		
		MR1=DM(tdp_r);
		SI=DM(yl_h_r);
		AX1=DM(dq_r);
		CALL trans;			{Compute new trigger}
		DM(tr)=AR;
		
		AR=PASS AR;			{Check state of trigger}
		IF EQ CALL update_filter_r;	{Update filter if trigger false}
	
		AY0=DM(y);			{Load uariables for updating}
		MY1=DM(yl_l_r);
		MY0=DM(yl_h_r);
		MR0=DM(ap_r);
		MR1=DM(y);
		MR2=DM(tdp_r);			{Always load MR2 after MR1!}
		MX0=DM(dms_r);
		MX1=DM(dml_r);
		CALL functw;			{Update variables}
		DM(yu_r)=AX1;			{Stored updated variables}
		DM(yl_l_r)=MY1;
		DM(yl_h_r)=MY0;
		DM(ap_r)=AR;
		DM(dms_r)=MX0;
		DM(dml_r)=MX1;
	
		AY1=DM(tr);			{Load current trigger}
		AF=PASS AY1;			{Check state of trigger}
		IF NE CALL trigger_true_r;	{Call only if trigger true}
		
		CALL compress;			{Compress PCM value}
		DM(sp_r)=AR;			{Save original value for sync}
		CALL expand;			{Expand for sync coding adj}
		AY0=DM(s_e);
		AR=AR-AY0;			{Compute dx for sync coding}
		AY1=DM(y_2);
		CALL log;			{Compute new dqx value}
		CALL sync;			{Adjust PCM value by +1,-1, 0}
	
		DM(hld_a_r)=I1;			{Save s_r delay pointer}
		DM(hld_b_r)=I0;			{Save dq delay pointer}
	
		RTS;

compress:	AR=DM(s_r);			{Get reconstructed signal}
		AR=ABS AR;			{Take absolute value}
		AY0=33;				{Add offset of boundries}
		AR=AR+AY0;
		AY0=8191;			{Maximum PCM value}
		AF=AR-AY0;			{Cap input}
		IF GT AR=PASS AY0;		{If in excess}
		SE=EXP AR (HI);			{Find exponent adjustmet}
		AX0=SE, SR=NORM AR (LO);	{Normalize input}
		AY0=H#4000;
		AR=SR0 XOR AY0;			{Remove first significant bit}
		SR=LSHIFT AR BY -10 (LO);	{Shift position bits}
		AR=PASS AY0;
		IF POS AR=PASS 0;		{Create sign bit}
		SR=SR OR LSHIFT AR BY -7 (LO);	{Position sign bit}
		AY0=9;
		AR=AX0+AY0;			{Compute segment}
		IF LT AR=PASS 0;
		SR=SR OR LSHIFT AR BY 4 (LO);	{Position segment bits}
		AY0=H#FF;
		AR=SR0 XOR AY0;			{Invert bits}
		RTS;

expand:		AY0=H#FF;			{Mask unwanted bits}
		AF=AR AND AY0, AX0=AY0;
		AF=AX0 XOR AF;			{Invert bits}
		AX0=H#70;
		AR=AX0 AND AF;			{Isolate segment bits}
		SR=LSHIFT AR BY -4 (LO);	{Shift to LSBs}
		SE=SR0, AR=AR XOR AF;		{Remove segment bits}
		AY0=H#FF80;
		AF=AR+AY0;
		IF LT JUMP posval;		{Detemine sign}
		AR=PASS AF;
		AR=AR+AF;			{Shift left by 1 bit}
		AY0=33;
		AR=AR+AY0;			{Add segment offset}
		SR=ASHIFT AR (LO);		{Position bits}
		AR=AY0-SR0;			{Remove segment offset}
		RTS;

posval:		AF=PASS AR;
		AR=AR+AF;			{Shift left by 1}
		AY0=33;	
		AR=AR+AY0;			{Add segment offset}
		SR=ASHIFT AR (LO);
		AR=SR0-AY0;			{Remove segment offset}
		RTS;
		
predict:	AX1=DM(I0,M2), AY1=PM(I4,M6);	{Point to dq6 and b6}
		AF=PASS 0, SI=PM(I4,M4);	{AF hold partial sum}
		AY0=DM(I6,M5);		
		MX1=3;				{This multiply will give the}
		MY1=32768;			{+48>>4 term}
		SR=ASHIFT SI BY -2 (HI);	{Downshift b6 per spec}
		CNTR=6;				{Loop once for each b}
		DO sez_cmp UNTIL CE;
		   AR=ABS SR1, SR1=DM(I6,M5);	{Get absolute value of b}
		   AR=AR AND AY0, AY0=DM(I6,M5);{Mask bits per spec}
		   SE=EXP AR (HI), MY0=DM(I0,M2);{Find exponent adjust}
		   AX0=SE, SR=SR OR NORM AR (HI);{Compute bnMANT}
		   AR=SR1 AND AY0, AY0=DM(I0,M2);{Mask bits per spec}
		   MR=AR*MY0 (SS), AX1=DM(I0,M2), AY1=PM(I4,M6);
		   AR=AX0+AY0, AY0=DM(I6,M5);	{Compute WbEXP}
		   SE=AR, MR=MR+MX1*MY1 (SU);	{Compute WbnMANT}
		   SR=LSHIFT MR1 (HI), SE=DM(I6,M5);{Compute Wbn}
		   AR=SR1 AND AY0, SI=PM(I4,M4);{Mask Wbn per spec}
		   AX0=AR, AR=AX1 XOR AY1;	{Determine sign of Wbn}
		   AR=AX0, SR=ASHIFT SI (HI);	{Downshift b(n-1) per spec}
		   IF LT AR=-AX0;		{Negate Wbn if necessary}
sez_cmp:	   AF=AR+AF, AY0=DM(I6,M5);	{Add Wbn to partial sum}
		AR=PASS AF, AX1=DM(I0,M1), AY1=PM(I5,M6);{Get sezi}
		SR=ASHIFT AR BY -1 (HI);	{Downshift to produce sez}
		DM(sez)=SR1;
		SI=PM(I5,M4);			{Get a2}
		SR=ASHIFT SI (HI); 		{Downshift a2 per spec}
		AX1=DM(I1,M2), AY1=PM(I4,M5);	{Restore bn and dqn pointers}
		CNTR=2;				{Loop once for each a}
		DO s_e_cmp UNTIL CE;
		   AR=ABS SR1, SR1=DM(I6,M5);	{Get absolute value of a}
		   AR=AR AND AY0, AY0=DM(I6,M5);{Mask bits per spec}
		   SE=EXP AR (HI), MY0=DM(I1,M2);{Get exponent adjust for a}
		   AX0=SE, SR=SR OR NORM AR (HI);{Compute anMANT}
		   AR=SR1 AND AY0, AY0=DM(I1,M2);{Mask bits per spec}
		   MR=AR*MY0(SS), AX1=DM(I1,M2), AY1=PM(I5,M6);
		   AR=AX0+AY0, AY0=DM(I6,M5);	{Compute WanEXP}
		   SE=AR, MR=MR+MX1*MY1 (SU);	{Complete WanMANT computation}
		   SR=LSHIFT MR1 (HI), SE=DM(I6,M5);{Compute Wan}
		   AR=SR1 AND AY0, SI=PM(I5,M4);{Mask Wan per spec}
		   AX0=AR, AR=AX1 XOR AY1;	{Determine sign of Wan}
		   AR=AX0, SR=ASHIFT SI (HI);	{Downshift a1 per spec}
		   IF LT AR=-AX0;		{Negate Wan if necessary}
s_e_cmp:	   AF=AR+AF, AY0=DM(I6,M5);	{Add Wan to partial sum}
		AR=PASS AF, AX1=DM(I1,M1), AY1=PM(I5,M5);{Get sei}
		SR=ASHIFT AR BY -1 (HI);	{Compute se}
		DM(s_e)=SR1;
		RTS;

lima:		AY1=256;			{Maximum value for ap}
		AR=AX1, AF=AX1-AY1;		{Cap if it exceeds}
		IF GE AR=PASS AY1;
		SR=ASHIFT AR BY -2 (HI);	{>>2 to produce al}
		SR=LSHIFT SR1 BY 9 (HI);	{Adjust for ADSP-210x version}
		
mix:		MY0=SR1, AR=AX0-AY0;		{MY0=al, AR=diff}
		AR=ABS AR;			{Take absolute value of diff}
		MR=AR*MY0 (SU);			{Generate prod}
		AR=MR1+AY0;			{Add to yu}
		IF NEG AR=AY0-MR1;		{Subtract if diff < 0}
		SR=ASHIFT AR BY -2 (HI);	{Generate y>>2}
		RTS;
	
log:		I3=^qn_values;			{Point to data array}
		AR=ABS AR, AX1=DM(I3,M1);	{Take absolute of d}
		SE=EXP AR (HI), AX0=DM(I3,M1);	{Determine exponent adjust}
		AY0=SE, SR=NORM AR (HI);	{Normalize}
		AR=AX0+AY0, AY0=DM(I3,M1);	{Compute exponent}
		IF LT AR=PASS 0;		{Check for exponent -1}
		SI=AR, AR=SR1 AND AY0;		{Mask mantissa bits}
		SR=LSHIFT AR BY -7 (HI);	{Position mantissa}
		SR=SR OR LSHIFT SI BY 7 (HI);	{Position exponent}

subtb:		AR=SR1-AY1, AY0=DM(I3,M1);	{Subtract y>>2 for log}
		AX0=AR, AF=PASS AX1;		{Setup for quantizing}

quan:		AR=AX0-AY0, AY0=DM(I3,M1);	{Is dl less then upper limit?}
		IF LT AF=AF-1;

⌨️ 快捷键说明

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