melp_sub.c
资源名称:melpfix.rar [点击查看]
上传用户:cxx_68
上传日期:2021-02-21
资源大小:161k
文件大小:26k
源码类别:
语音压缩
开发平台:
Visual C++
- /*
- 2.4 kbps MELP Proposed Federal Standard speech coder
- Fixed-point C code, version 1.0
- Copyright (c) 1998, Texas Instruments, Inc.
- Texas Instruments has intellectual property rights on the MELP
- algorithm. The Texas Instruments contact for licensing issues for
- commercial and non-government use is William Gordon, Director,
- Government Contracts, Texas Instruments Incorporated, Semiconductor
- Group (phone 972 480 7442).
- The fixed-point version of the voice codec Mixed Excitation Linear
- Prediction (MELP) is based on specifications on the C-language software
- simulation contained in GSM 06.06 which is protected by copyright and
- is the property of the European Telecommunications Standards Institute
- (ETSI). This standard is available from the ETSI publication office
- tel. +33 (0)4 92 94 42 58. ETSI has granted a license to United States
- Department of Defense to use the C-language software simulation contained
- in GSM 06.06 for the purposes of the development of a fixed-point
- version of the voice codec Mixed Excitation Linear Prediction (MELP).
- Requests for authorization to make other use of the GSM 06.06 or
- otherwise distribute or modify them need to be addressed to the ETSI
- Secretariat fax: +33 493 65 47 16.
- */
- /*
- melp_sub.c: MELP-specific subroutines
- */
- #include <stdio.h>
- #include <math.h>
- #include "spbstd.h"
- #include "mathhalf.h"
- #include "wmops.h"
- #include "math_lib.h"
- #include "mat.h"
- #include "dsp_sub.h"
- #include "melp_sub.h"
- #include "pit.h"
- #include "constant.h"
- /*
- Name: bpvc_ana.c
- Description: Bandpass voicing analysis
- Inputs:
- speech[] - input speech signal
- fpitch[] - initial (floating point) pitch estimates
- Outputs:
- bpvc[] - bandpass voicing decisions
- pitch[] - frame pitch estimates
- Returns: void
- Copyright (c) 1995,1997 by Texas Instruments, Inc. All rights reserved.
- */
- /* Q values
- --------
- speech - Q0
- fpitch - Q7
- bpvc - Q14
- pitch - Q7
- */
- /* Filter orders */
- #define ENV_ORD 2
- #define BPF_ORD 6
- static Shortword PITCHMAX;
- static Shortword PITCHMIN;
- static Shortword PITCHMAX_Q7;
- static Shortword PITCHMIN_Q7;
- static Shortword FRAME;
- static Shortword NUM_BANDS;
- static Shortword PIT_BEG;
- static Shortword PIT_P_FR;
- static Shortword PIT_FR_BEG;
- static Shortword FIRST_CNTR;
- static Shortword BPF_BEG;
- static Shortword NUM_PITCHES;
- static Shortword LMIN;
- /* Static memory */
- static Shortword **bpfsp;
- static Shortword **bpfdelin;
- static Shortword **bpfdelout;
- static Shortword **envdel;
- static Shortword *envdel2;
- static Shortword *sigbuf;
- /* External variables */
- extern Shortword bpf_num[], bpf_den[];
- void bpvc_ana(Shortword speech[], Shortword fpitch[], Shortword bpvc[],
- Shortword pitch[])
- {
- Shortword pcorr, temp, scale;
- Shortword j,section;
- Shortword filt_index;
- /* Filter lowest band and estimate pitch */
- v_equ(&sigbuf[PIT_BEG],&bpfsp[0][0],(Shortword)(PIT_P_FR-FRAME));
- v_equ(&sigbuf[PIT_BEG+PIT_P_FR-FRAME],
- &speech[PIT_FR_BEG+PIT_P_FR-FRAME],FRAME);
- for (section=0; section<BPF_ORD/2; section++) {
- iir_2nd_s(&sigbuf[PIT_BEG+PIT_P_FR-FRAME],
- &bpf_den[section*3],&bpf_num[section*3],
- &sigbuf[PIT_BEG+PIT_P_FR-FRAME],&bpfdelin[0][section*2],
- &bpfdelout[0][section*2],FRAME);
- }
- v_equ(&bpfsp[0][0],&sigbuf[PIT_BEG+FRAME],(Shortword)(PIT_P_FR-FRAME));
- /* Scale signal for pitch correlations */
- f_pitch_scale(&sigbuf[PIT_BEG],&sigbuf[PIT_BEG],PIT_P_FR);
- *pitch = frac_pch(&sigbuf[FIRST_CNTR],&bpvc[0],fpitch[0],5,
- PITCHMIN,PITCHMAX,PITCHMIN_Q7,PITCHMAX_Q7,LMIN);
- for (j = 1; j < NUM_PITCHES; j++) {
- temp = frac_pch(&sigbuf[FIRST_CNTR],&pcorr,fpitch[j],5,
- PITCHMIN,PITCHMAX,PITCHMIN_Q7,PITCHMAX_Q7,LMIN);
- /* choose largest correlation value */
- if (pcorr > bpvc[0]) {
- *pitch = temp;
- bpvc[0] = pcorr;
- }
- }
- /* Calculate bandpass voicing for frames */
- for (j = 1; j < NUM_BANDS; j++) {
- /* Bandpass filter input speech */
- v_equ(&sigbuf[PIT_BEG],&bpfsp[j][0],(Shortword)(PIT_P_FR-FRAME));
- v_equ(&sigbuf[PIT_BEG+PIT_P_FR-FRAME],
- &speech[PIT_FR_BEG+PIT_P_FR-FRAME],FRAME);
- for (section=0; section<BPF_ORD/2; section++) {
- filt_index = j*(BPF_ORD/2)*3 + section*3;
- iir_2nd_s(&sigbuf[PIT_BEG+PIT_P_FR-FRAME],
- &bpf_den[filt_index],&bpf_num[filt_index],
- &sigbuf[PIT_BEG+PIT_P_FR-FRAME],&bpfdelin[j][section*2],
- &bpfdelout[j][section*2],FRAME);
- }
- v_equ(&bpfsp[j][0],&sigbuf[PIT_BEG+FRAME],(Shortword)(PIT_P_FR-FRAME));
- /* Scale signal for pitch correlations */
- scale = f_pitch_scale(&sigbuf[PIT_BEG],&sigbuf[PIT_BEG],PIT_P_FR);
- /* Check correlations for each frame */
- temp = frac_pch(&sigbuf[FIRST_CNTR],&bpvc[j],*pitch,0,
- PITCHMIN,PITCHMAX,PITCHMIN_Q7,PITCHMAX_Q7,LMIN);
- /* Calculate envelope of bandpass filtered input speech */
- /* update delay buffers without scaling */
- temp = shr(envdel2[j],scale);
- envdel2[j] = shr(sigbuf[PIT_BEG+FRAME-1],(Shortword)(-scale));
- v_equ_shr(&sigbuf[PIT_BEG-ENV_ORD],&envdel[j][0],scale,ENV_ORD);
- envelope(&sigbuf[PIT_BEG],temp,&sigbuf[PIT_BEG],PIT_P_FR);
- v_equ_shr(&envdel[j][0],&sigbuf[PIT_BEG+FRAME-ENV_ORD],
- (Shortword)(-scale),ENV_ORD);
- /* Scale signal for pitch correlations */
- f_pitch_scale(&sigbuf[PIT_BEG],&sigbuf[PIT_BEG],PIT_P_FR);
- /* Check correlations for each frame */
- temp = frac_pch(&sigbuf[FIRST_CNTR],&pcorr,*pitch,0,
- PITCHMIN,PITCHMAX,PITCHMIN_Q7,PITCHMAX_Q7,LMIN);
- /* reduce envelope correlation */
- pcorr = sub(pcorr,(Shortword)X01_Q14);
- if (pcorr > bpvc[j])
- bpvc[j] = pcorr;
- }
- } /* bpvc_ana */
- void bpvc_ana_init(Shortword fr, Shortword pmin, Shortword pmax,
- Shortword nbands, Shortword num_p, Shortword lmin)
- {
- /* Initialize constants */
- FRAME = fr;
- PITCHMIN = pmin;
- PITCHMAX = pmax;
- PITCHMIN_Q7 = shl(pmin,7);
- PITCHMAX_Q7 = shl(pmax,7);
- NUM_BANDS = nbands;
- NUM_PITCHES = num_p;
- LMIN = lmin;
- PIT_BEG = BPF_ORD;
- PIT_P_FR = ((2*PITCHMAX)+1);
- PIT_FR_BEG = (-PITCHMAX);
- FIRST_CNTR = (PIT_BEG+PITCHMAX);
- BPF_BEG = (PIT_BEG+PIT_P_FR-FRAME);
- /* Allocate memory */
- MEM_2ALLOC(malloc,bpfdelin,NUM_BANDS,BPF_ORD,Shortword);
- v_zap(&bpfdelin[0][0],(Shortword)(NUM_BANDS*BPF_ORD));
- MEM_2ALLOC(malloc,bpfdelout,NUM_BANDS,BPF_ORD,Shortword);
- v_zap(&bpfdelout[0][0],(Shortword)(NUM_BANDS*BPF_ORD));
- MEM_2ALLOC(malloc,bpfsp,NUM_BANDS,PIT_P_FR-FRAME,Shortword);
- v_zap(&bpfsp[0][0],(Shortword)(NUM_BANDS*(PIT_P_FR-FRAME)));
- MEM_2ALLOC(malloc,envdel,NUM_BANDS,ENV_ORD,Shortword);
- v_zap(&envdel[0][0],(Shortword)(NUM_BANDS*ENV_ORD));
- MEM_ALLOC(malloc,envdel2,NUM_BANDS,Shortword);
- v_zap(envdel2,NUM_BANDS);
- /* Allocate scratch buffer */
- MEM_ALLOC(malloc,sigbuf,PIT_BEG+PIT_P_FR,Shortword);
- }
- /*
- Name: dc_rmv.c
- Description: remove DC from input signal
- Inputs:
- sigin[] - input signal
- dcdel[] - filter delay history (size DC_ORD)
- frame - number of samples to filter
- Outputs:
- sigout[] - output signal
- dcdel[] - updated filter delay history
- Returns: void
- See_Also:
- Copyright (c) 1995,1997 by Texas Instruments, Inc. All rights reserved.
- */
- /* Filter order */
- #define DC_ORD 4
- /* DC removal filter */
- /* 4th order Chebychev Type II 60 Hz removal filter */
- /* cutoff=60 Hz, stop=-30 dB */
- /* matlab commands: [z,p,k]=cheby2(4,30,0.015,'high'); */
- /* sos=zp2sos(z,p,k); */
- /* order of sections swapped */
- /* Q13 */
- static Shortword dc_num[(DC_ORD/2)*3] = {
- 7769, -15534, 7769,
- 8007, -15999, 8007};
- /* sign of coefficients for dc_den is reversed */
- static Shortword dc_den[(DC_ORD/2)*3] = {
- -8192, 15521, -7358,
- -8192, 15986, -7836};
- void dc_rmv(Shortword sigin[],Shortword sigout[],Shortword delin[],
- Shortword delout_hi[],Shortword delout_lo[],
- Shortword frame)
- {
- Shortword section;
- /* Remove DC from input speech */
- v_equ(sigout,sigin,frame);
- for (section=0; section<DC_ORD/2; section++) {
- iir_2nd_d(sigout,&dc_den[section*3],&dc_num[section*3],sigout,
- &delin[section*2],&delout_hi[section*2],&delout_lo[section*2],
- frame);
- }
- }
- /*
- Name: gain_ana.c
- Description: analyze gain level for input signal
- Inputs:
- sigin[] - input signal
- pitch - pitch value (for pitch synchronous window)
- minlength - minimum window length
- maxlength - maximum window length
- Outputs:
- Returns: log gain in dB
- See_Also:
- Copyright (c) 1997 by Texas Instruments, Inc. All rights reserved.
- Q values
- --------
- pitch - Q7
- sigin (speech) - Q0
- */
- #define CONSTANT_SCALE 0
- #define MINGAIN 0
- #define LOG10OF2X2 1233 /* 2*log10(2) in Q11 */
- Shortword gain_ana(Shortword sigin[], Shortword pitch,
- Shortword minlength, Shortword maxlength)
- {
- Shortword length; /* Q0 */
- Shortword flength; /* Q6 */
- Shortword gain; /* Q8 */
- Shortword pitch_Q6; /* Q6 */
- Shortword scale;
- Shortword tmp_minlength;
- Shortword sigbegin;
- Shortword *temp_buf, *tmp_sig;
- Shortword S_temp1, S_temp2;
- Longword L_temp;
- /* initialize scaled pitch and minlength */
- pitch_Q6 = shr(pitch,1); /* Q7->Q6 */ data_move();
- tmp_minlength = shl(minlength,6); data_move();
- /* Find shortest pitch multiple window length (floating point) */
- flength = pitch_Q6; data_move();
- while (flength < tmp_minlength) {
- /* increment complexity for while statement */
- compare_nonzero();
- flength = add(flength,pitch_Q6); data_move();
- }
- /* Convert window length to integer and check against maximum */
- length = shr(add(flength, (Shortword)X05_Q6), 6); data_move();
- /* increment complexity for if statement */
- compare_nonzero();
- if (length > maxlength) {
- /* divide by 2 */
- length = shr(length,1); data_move();
- }
- /* Calculate RMS gain in dB */
- /*gain = 10.0*log10(0.01+(v_magsq(&sigin[-(length/2)],length)/length));*/
- /* use this adaptive scaling if more precision needed at low
- levels. Seemed like it wasn't worth the mips */
- sigbegin = negate(shr(length,1));
- /* Right shift input signal and put in temp buffer */
- MEM_ALLOC(MALLOC,temp_buf,length,Shortword);
- #if(CONSTANT_SCALE)
- scale=3;
- #else
- scale = 3;
- v_equ_shr(temp_buf,&sigin[sigbegin],scale,length);
- L_temp = L_v_magsq(temp_buf,length,0,1);
- compare_zero();
- if (L_temp) {
- S_temp1 = norm_l(L_temp);
- scale = sub(scale,shr(S_temp1,1));
- if (scale < 0)
- scale = 0;
- }
- else
- scale = 0;
- #endif
- if (scale)
- v_equ_shr(temp_buf,&sigin[sigbegin],scale,length);
- else
- v_equ(temp_buf,&sigin[sigbegin],length);
- tmp_sig = temp_buf - sigbegin;
- /* increment complexity for if statement */
- compare_zero();
- if (scale) {
- L_temp = L_v_magsq(&tmp_sig[sigbegin],length,0,0);
- S_temp1 = L_log10_fxp(L_temp,0);
- S_temp2 = L_log10_fxp(L_deposit_l(length),0);
- S_temp1 = sub(S_temp1,S_temp2);
- /* shift right to counter-act for the shift in L_mult */
- S_temp2 = extract_l(L_shr(L_mult(scale,LOG10OF2X2),1));
- S_temp1 = add(S_temp1,S_temp2);
- S_temp1 = mult(TEN_Q11,S_temp1);
- gain = shl(S_temp1,1); data_move();
- }
- else {
- L_temp = L_v_magsq(&tmp_sig[sigbegin],length,0,0);
- /* Add one to avoid log of a zero value */
- if (L_temp == 0)
- S_temp1 = N2_Q11;
- else
- S_temp1 = L_log10_fxp(L_temp,0);
- S_temp2 = L_log10_fxp(L_deposit_l(length),0);
- S_temp1 = sub(S_temp1,S_temp2);
- S_temp1 = mult(TEN_Q11,S_temp1);
- gain = shl(S_temp1,1); data_move();
- }
- /* increment complexity for if statement */
- compare_nonzero();
- if (gain < MINGAIN) {
- gain = MINGAIN; data_move();
- }
- MEM_FREE(FREE,temp_buf);
- return(gain);
- } /* gain_ana */
- /*
- Name: lin_int_bnd.c
- Description: Linear interpolation within bounds
- Inputs:
- x - input X value
- xmin - minimum X value
- xmax - maximum X value
- ymin - minimum Y value
- ymax - maximum Y value
- Returns: y - interpolated and bounded y value
- Copyright (c) 1995,1997 by Texas Instruments, Inc. All rights reserved.
- Q values:
- x,xmin,xmax - Q8
- y,ymin,ymax - Q15
- */
- Shortword lin_int_bnd(Shortword x,Shortword xmin,Shortword xmax,
- Shortword ymin,Shortword ymax)
- {
- Shortword y;
- Shortword temp1,temp2;
- if (x <= xmin)
- y = ymin;
- else if (x >= xmax)
- y = ymax;
- else {
- /* y = ymin + (x-xmin)*(ymax-ymin)/(xmax-xmin); */
- temp1 = sub(x,xmin);
- temp2 = sub(ymax,ymin);
- temp1 = mult(temp1,temp2); /* temp1 in Q8 */
- temp2 = sub(xmax,xmin);
- /* temp1 always smaller than temp2 */
- temp1 = divide_s(temp1,temp2); /* temp1 in Q15 */
- y = add(ymin,temp1);
- }
- return(y);
- }
- /*
- Name: noise_est.c
- Description: Estimate long-term noise floor
- Inputs:
- gain - input gain (in dB)
- noise_gain - current noise gain estimate
- up - maximum up stepsize
- down - maximum down stepsize
- min - minimum allowed gain
- max - maximum allowed gain
- Outputs:
- noise_gain - updated noise gain estimate
- Returns: void
- Copyright (c) 1995,1997 by Texas Instruments, Inc. All rights reserved.
- Q values:
- gain - Q8
- *noise_gain - Q8
- up - Q19
- down - Q17
- min - Q8
- max - Q8
- */
- void noise_est(Shortword gain,Shortword *noise_gain,Shortword up,
- Shortword down,Shortword min,Shortword max)
- {
- Shortword temp1,temp2;
- Longword L_noise_gain,L_temp;
- /* Update noise_gain */
- /* temp1 = add(*noise_gain,up);
- temp2 = add(*noise_gain,down); */
- L_noise_gain = L_deposit_h(*noise_gain); /* L_noise_gain in Q24 */
- L_temp = L_shl(L_deposit_l(up),5);
- L_temp = L_add(L_noise_gain,L_temp);
- temp1 = round(L_temp);
- L_temp = L_shl(L_deposit_l(down),7);
- L_temp = L_add(L_noise_gain,L_temp);
- temp2 = round(L_temp);
- compare_nonzero();
- if (gain > temp1)
- *noise_gain = temp1;
- else if (gain < temp2)
- *noise_gain = temp2;
- else
- *noise_gain = gain;
- /* Constrain total range of noise_gain */
- compare_nonzero();
- if (*noise_gain < min)
- *noise_gain = min;
- compare_nonzero();
- if (*noise_gain > max)
- *noise_gain = max;
- }
- /*
- Name: noise_sup.c
- Description: Perform noise suppression on speech gain
- Inputs: (all in dB)
- gain - input gain (in dB)
- noise_gain - current noise gain estimate (in dB)
- max_noise - maximum allowed noise gain
- max_atten - maximum allowed attenuation
- nfact - noise floor boost
- Outputs:
- gain - updated gain
- Returns: void
- Copyright (c) 1995,1997 by Texas Instruments, Inc. All rights reserved.
- Q values:
- *gain - Q8
- noise_gain - Q8
- max_noise - Q8
- max_atten - Q8
- nfact - Q8
- */
- void noise_sup(Shortword *gain,Shortword noise_gain,Shortword max_noise,
- Shortword max_atten,Shortword nfact)
- {
- Shortword gain_lev,suppress;
- Shortword temp;
- Longword L_temp;
- /* Reduce effect for louder background noise */
- if (noise_gain > max_noise)
- noise_gain = max_noise;
- /* Calculate suppression factor */
- gain_lev = sub(*gain,add(noise_gain,nfact));
- compare_nonzero();
- if (gain_lev > X0001_Q8) {
- /* suppress = -10.0*log10(1.0 - pow(10.0,-0.1*gain_lev)); */
- L_temp = L_mult((Shortword)M01_Q15,gain_lev); /* L_temp in Q24 */
- temp = extract_h(L_shl(L_temp,4)); /* temp in Q12 */
- temp = pow10_fxp(temp,14);
- temp = sub(ONE_Q14,temp);
- suppress = mult(M10_Q11,log10_fxp(temp,14)); /* log returns Q12 */
- compare_nonzero();
- if (suppress > max_atten)
- suppress = max_atten;
- }
- else
- suppress = max_atten;
- /* Apply suppression to input gain */
- *gain = sub(*gain,suppress);
- } /* noise_sup */
- /*
- Name: q_bpvc.c, q_bpvc_dec.c
- Description: Quantize/decode bandpass voicing
- Inputs:
- bpvc, bpvc_index
- bpthresh - threshold
- NUM_BANDS - number of bands
- Outputs:
- bpvc, bpvc_index
- Returns: uv_flag - flag if unvoiced
- Copyright (c) 1995,1997 by Texas Instruments, Inc. All rights reserved.
- Q values:
- *bpvc - Q14
- bpthresh - Q14
- */
- /* Compile constants */
- #define INVALID_BPVC 0001
- Shortword q_bpvc(Shortword *bpvc,Shortword *bpvc_index,Shortword bpthresh,
- Shortword NUM_BANDS)
- {
- Shortword j, uv_flag;
- uv_flag = 1; data_move();
- if (bpvc[0] > bpthresh) {
- /* Voiced: pack bandpass voicing */
- uv_flag = 0; data_move();
- *bpvc_index = 0; data_move();
- bpvc[0] = ONE_Q14; data_move();
- for (j = 1; j < NUM_BANDS; j++) {
- *bpvc_index = shl(*bpvc_index,1); /* left shift one bit */
- if (bpvc[j] > bpthresh) {
- bpvc[j] = ONE_Q14; data_move();
- *bpvc_index |= 1; logic();
- }
- else {
- bpvc[j] = 0; data_move();
- *bpvc_index |= 0; logic();
- }
- }
- /* Don't use invalid code (only top band voiced) */
- if (*bpvc_index == INVALID_BPVC) {
- bpvc[(NUM_BANDS-1)] = 0;
- *bpvc_index = 0;
- }
- }
- else {
- /* Unvoiced: force all bands unvoiced */
- *bpvc_index = 0;
- for (j = 0; j < NUM_BANDS; j++)
- bpvc[j] = 0;
- }
- return(uv_flag);
- } /* q_bpvc */
- void q_bpvc_dec(Shortword *bpvc,Shortword *bpvc_index,Shortword uv_flag,
- Shortword NUM_BANDS)
- {
- Shortword j;
- if (uv_flag) {
- /* Unvoiced: set all bpvc to 0 */
- *bpvc_index = 0;
- bpvc[0] = 0;
- }
- else {
- /* Voiced: set bpvc[0] to 1.0 */
- bpvc[0] = ONE_Q14;
- }
- if (*bpvc_index == INVALID_BPVC) {
- /* Invalid code received: set higher band voicing to zero */
- *bpvc_index = 0;
- }
- /* Decode remaining bands */
- for (j = NUM_BANDS-1; j > 0; j--) {
- compare_nonzero();
- logic();
- if ((*bpvc_index & 1) == 1)
- bpvc[j] = ONE_Q14;
- else
- bpvc[j] = 0;
- *bpvc_index = shr(*bpvc_index,1);
- }
- } /* q_bpvc_dec */
- /*
- Name: q_gain.c, q_gain_dec.c
- Description: Quantize/decode two gain terms using quasi-differential coding
- Inputs:
- gain[2],gain_index[2]
- GN_QLO,GN_QUP,GN_QLEV for second gain term
- Outputs:
- gain[2],gain_index[2]
- Returns: void
- Copyright (c) 1995,1997 by Texas Instruments, Inc. All rights reserved.
- Q values:
- *gain - Q8
- GN_QLO - Q8
- GN_QUP - Q8
- GN_QLEV_Q - Q10
- */
- /* Compile constants */
- #define GAIN_INT_DB_Q8 1280 /* (5*(1<<8)) */
- void q_gain(Shortword *gain,Shortword *gain_index,Shortword GN_QLO,
- Shortword GN_QUP,Shortword GN_QLEV,Shortword GN_QLEV_Q,
- Shortword double_flag,Shortword scale)
- {
- static Shortword prev_gain = 0;
- Shortword temp,temp2;
- /* Quantize second gain term with uniform quantizer */
- quant_u(&gain[1],&gain_index[1],GN_QLO,GN_QUP,GN_QLEV,GN_QLEV_Q,
- double_flag,scale);
- /* Check for intermediate gain interpolation */
- if (gain[0] < GN_QLO) {
- gain[0] = GN_QLO; data_move();
- }
- if (gain[0] > GN_QUP) {
- gain[0] = GN_QUP; data_move();
- }
- /* if (fabs(gain[1] - prev_gain) < GAIN_INT_DB &&
- fabs(gain[0] - 0.5*(gain[1]+prev_gain)) < 3.0) */
- temp = add(shr(gain[1],1),shr(prev_gain,1));
- if (abs_s(sub(gain[1],prev_gain)) < GAIN_INT_DB_Q8 &&
- abs_s(sub(gain[0],temp)) < THREE_Q8) {
- /* interpolate and set special code */
- /* gain[0] = 0.5*(gain[1]+prev_gain); */
- gain[0] = temp;
- gain_index[0] = 0;
- }
- else {
- /* Code intermediate gain with 7-levels */
- if (prev_gain < gain[1]) {
- temp = prev_gain; data_move();
- temp2 = gain[1]; data_move();
- }
- else {
- temp = gain[1]; data_move();
- temp2 = prev_gain; data_move();
- }
- temp = sub(temp,SIX_Q8);
- temp2 = add(temp2,SIX_Q8);
- if (temp < GN_QLO) {
- temp = GN_QLO; data_move();
- }
- if (temp2 > GN_QUP) {
- temp2 = GN_QUP; data_move();
- }
- quant_u(&gain[0],&gain_index[0],temp,temp2,6,SIX_Q12,0,3);
- /* Skip all-zero code */
- gain_index[0] = add(gain_index[0],1);
- }
- /* Update previous gain for next time */
- prev_gain = gain[1]; data_move();
- } /* q_gain */
- void q_gain_dec(Shortword *gain,Shortword *gain_index,Shortword GN_QLO,
- Shortword GN_QUP,Shortword GN_QLEV_Q,Shortword scale)
- {
- static Shortword prev_gain = 0;
- static Shortword prev_gain_err = 0;
- Shortword temp,temp2;
- /* Decode second gain term */
- quant_u_dec(gain_index[1],&gain[1],GN_QLO,GN_QUP,GN_QLEV_Q,scale);
- if (gain_index[0] == 0) {
- /* interpolation bit code for intermediate gain */
- temp = sub(gain[1],prev_gain);
- temp = abs_s(temp);
- compare_nonzero();
- if (temp > GAIN_INT_DB_Q8) {
- /* Invalid received data (bit error) */
- if (prev_gain_err == 0) {
- /* First time: don't allow gain excursion */
- gain[1] = prev_gain;
- }
- prev_gain_err = 1;
- }
- else
- prev_gain_err = 0;
- /* Use interpolated gain value */
- /* gain[0] = 0.5*(gain[1]+prev_gain); */
- gain[0] = add(shr(gain[1],1),shr(prev_gain,1));
- }
- else {
- /* Decode 7-bit quantizer for first gain term */
- prev_gain_err = 0;
- gain_index[0] = sub(gain_index[0],1);
- compare_nonzero();
- if (prev_gain < gain[1]) {
- temp = prev_gain;
- temp2 = gain[1];
- }
- else {
- temp = gain[1];
- temp2 = prev_gain;
- }
- temp = sub(temp,SIX_Q8);
- temp2 = add(temp2,SIX_Q8);
- compare_nonzero();
- if (temp < GN_QLO)
- temp = GN_QLO;
- compare_nonzero();
- if (temp2 > GN_QUP)
- temp2 = GN_QUP;
- quant_u_dec(gain_index[0],&gain[0],temp,temp2,SIX_Q12,3);
- }
- /* Update previous gain for next time */
- prev_gain = gain[1]; data_move();
- } /* q_gain_dec */
- /*
- Name: scale_adj.c
- Description: Adjust scaling of output speech signal.
- Inputs:
- speech - speech signal
- gain - desired RMS gain (log gain)
- prev_scale - previous scale factor
- length - number of samples in signal
- SCALEOVER - number of points to interpolate scale factor
- Warning: SCALEOVER is assumed to be less than length.
- Outputs:
- speech - scaled speech signal
- prev_scale - updated previous scale factor
- Returns: void
- Copyright (c) 1995,1997 by Texas Instruments, Inc. All rights reserved.
- Q values:
- *speech - Q0
- gain - Q12
- *prev_scale - Q13
- */
- void scale_adj(Shortword *speech, Shortword gain, Shortword *prev_scale,
- Shortword length, Shortword SCALEOVER,
- Shortword INV_SCALEOVER_Q18)
- {
- Shortword i;
- Shortword scale;
- Shortword shift,log_magsq,log_length;
- Shortword temp;
- Shortword *tempbuf;
- Longword L_magsq,L_length,interp1,interp2;
- Longword L_temp;
- /* Calculate desired scaling factor to match gain level */
- /* scale = gain / (sqrt(v_magsq(&speech[0],length) / length) + .01); */
- /* find normalization factor for buffer */
- MEM_ALLOC(MALLOC,tempbuf,length,Shortword);
- shift = 4;
- v_equ_shr(tempbuf,speech,shift,length);
- L_magsq = L_v_magsq(tempbuf,length,0,1);
- compare_zero();
- if (L_magsq) {
- /* normalize with 1 bit of headroom */
- temp = norm_l(L_magsq);
- temp = sub(temp,1);
- shift = sub(shift,shr(temp,1));
- }
- else
- shift = 0;
- v_equ_shr(tempbuf,speech,shift,length);
- /* exp = log(2^shift) */
- shift = shl(shift,1); /* total compensation = shift*2 */
- temp = shl(ONE_Q8,shift);
- shift = log10_fxp(temp,8); /* shift in Q12 */
- L_magsq = L_v_magsq(tempbuf,length,0,0);
- L_magsq = L_add(L_magsq,1); /* ensure L_magsq is not zero */
- log_magsq = L_log10_fxp(L_magsq,0); /* log_magsq in Q11 */
- /* L_magsq = log_magsq in Q12 */
- L_magsq = L_deposit_l(log_magsq);
- L_magsq = L_shl(L_magsq,1);
- /* compensate for normalization */
- /* L_magsq = log magnitude/2 in Q13 */
- L_temp = L_deposit_l(shift);
- L_magsq = L_add(L_magsq,L_temp);
- temp = shl(length,7);
- log_length = log10_fxp(temp,7); /* log_length in Q12 */
- /* L_length = log_length/2 in Q13 */
- L_length = L_deposit_l(log_length);
- L_temp = L_deposit_l(gain);
- L_temp = L_shl(L_temp,1); /* L_temp in Q13 */
- L_temp = L_sub(L_temp,L_magsq);
- L_temp = L_add(L_temp,L_length);
- L_temp = L_shr(L_temp,1); /* Q13 -> Q12 */
- temp = extract_l(L_temp); /* temp in Q12 */
- scale = pow10_fxp(temp,13);
- /* interpolate scale factors for first SCALEOVER points */
- for (i = 1; i < SCALEOVER; i++) {
- /* speech[i-1] *= ((scale*i + *prev_scale*(SCALEOVER-i))
- * (1.0/SCALEOVER) ); */
- temp = sub(SCALEOVER,i);
- temp = shl(temp,11);
- L_temp = L_mult(temp,INV_SCALEOVER_Q18); /* L_temp in Q30 */
- L_temp = L_shl(L_temp,1); /* L_temp in Q31 */
- temp = extract_h(L_temp); /* temp in Q15 */
- interp1 = L_mult(*prev_scale,temp); /* interp1 in Q29 */
- temp = shl(i,11);
- L_temp = L_mult(temp,INV_SCALEOVER_Q18); /* L_temp in Q30 */
- L_temp = L_shl(L_temp,1); /* L_temp in Q31 */
- temp = extract_h(L_temp); /* temp in Q15 */
- interp2 = L_mult(scale,temp); /* interp2 in Q29 */
- L_temp = L_add(interp1,interp2);
- interp1 = extract_h(L_temp); /* interp1 in Q13 */
- L_temp = L_mult(speech[i-1],(Shortword)interp1);
- L_temp = L_shl(L_temp,2);
- speech[i-1] = extract_h(L_temp);
- }
- /* Scale rest of signal */
- v_scale_shl(&speech[SCALEOVER-1],scale,(Shortword)(length-SCALEOVER+1),2);
- /* Update previous scale factor for next call */
- *prev_scale = scale; data_move();
- MEM_FREE(FREE,tempbuf);
- } /* scale_adj */