📄 ns_adpcm.dsp
字号:
{
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 + -