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

📄 melp_sub.c

📁 音频编解码 2400 bps MELP语音编解码器 定点算法
💻 C
📖 第 1 页 / 共 2 页
字号:
    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 */

⌨️ 快捷键说明

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