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

📄 ns_adpcm.dsp

📁 adsp21x的数字信号处理器ADPCM音频压缩源代码
💻 DSP
📖 第 1 页 / 共 2 页
字号:
{
	The code below represents a full duplex Adaptive Differential
	Pulse Code Modulation (ADPCM) transcoder.  Although 
	developed in accordance with ANSI specification T1.301-1987 and
	CCITT G.721 (bis), it has been modified to improve its speed.

	The modifications include the removal of the synchronous coding 
	adjustment and the tone and transition detectors.  These deletions 
	should not noticably affect speech-only coding.

	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
	   9/3/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
	437 cycles for encode 
	409 cycles for decode

}

.MODULE		Adaptive_Differential_PCM;

.ENTRY		ns_adpcm_encode, ns_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}

ns_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}

		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;

		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}

ns_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}
		
		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;
	
		CALL compress;			{Compress PCM value}
	
		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}

⌨️ 快捷键说明

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