www.pudn.com > AVS_M_ver10.rar > dec_ace.c


/* 
*********************************************************************** 
* COPYRIGHT AND WARRANTY INFORMATION 
* 
* Copyright 2007  Audio Video Coding Standard, Part Ⅹ 
* 
* This software module was developed by AVS Audio sub-group 
* 
* DISCLAIMER OF WARRANTY 
* 
* These software programs are available to the users without any 
* license fee or royalty on an "as is" basis. The AVS disclaims 
* any and all warranties, whether express, implied, or statutory, 
* including any implied warranties of merchantability or of fitness 
* for a particular purpose. In no event shall the contributors or  
* the AVS be liable for any incidental, punitive, or consequential 
* damages of any kind whatsoever arising from the use of this program. 
* 
* This disclaimer of warranty extends to the user of this program 
* and user's customers, employees, agents, transferees, successors, 
* and assigns. 
* 
* The AVS does not represent or warrant that the program furnished 
* hereunder are free of infringement of any third-party patents. 
* Commercial implementations of AVS, including shareware, may be 
* subject to royalty fees to patent holders. Information regarding 
* the AVS patent policy is available from the AVS Web site at 
* http://www.avs.org.cn 
* 
* THIS IS NOT A GRANT OF PATENT RIGHTS - SEE THE AVS PATENT POLICY. 
************************************************************************ 
*/ 
 
#include  
#include  
#include  
#include  
#include "../include/amr_plus.h" 
void decoder_acelp( 
  int prm[],         /* input: parameters               */ 
  float A[],         /* input: coefficients NxAz[M+1]   */ 
  int lg,            /* input: frame length             */ 
  int codec_mode,    /* input: AMR-WB+ mode (see cnst.h)*/ 
  int bfi,           /* input: 1=bad frame              */ 
  float exc[],       /* i/o:   exc[-(PIT_MAX+L_INTERPOL)..lg] */ 
  float synth[],     /* i/o:   synth[-M..lg]            */ 
  int T_out[],       /* out:   LTP lag for high band    */  
  float p_out[],     /* out:   LTP gain for high band   */  
  int *pT,           /* out:   pitch for all subframe   */ 
  float *pgainT,     /* out:   pitch gain for all subfr */ 
  int pit_adj,       /* input: pitch adjust */ 
  float stab_fac,    /* input: stability of isf         */ 
  Decoder_State_Plus *st) /* i/o :  coder memory state       */ 
{ 
  int i, i_subfr, select; 
  int T0, T0_frac, index, pit_flag, T0_min, T0_max; 
  float tmp, gain_pit, gain_code, voice_fac, ener, mean_ener_code, ener_wsyn; 
  float code[L_SUBFR], buf[M+L_OVLP]; 
  float fac, exc2[L_SUBFR]; 
  float *p_A, Ap1[1+M],Ap2[1+M],Ap3[1+TILT_ORDER],Ap[1+M]; 
  short code3GPP[L_SUBFR], prm3GPP[10]; 
  int PIT_MIN;				/* Minimum pitch lag with resolution 1/4      */ 
  int PIT_FR2;				/* Minimum pitch lag with resolution 1/2      */ 
  int PIT_FR1;				/* Minimum pitch lag with resolution 1        */ 
  int PIT_MAX;				/* Maximum pitch lag                          */ 
  if(pit_adj ==0) { 
    PIT_MIN = PIT_MIN_12k8; 
    PIT_FR2 = PIT_FR2_12k8;			 
    PIT_FR1 = PIT_FR1_12k8;			 
    PIT_MAX = PIT_MAX_12k8;			 
  } 
  else { 
    i = (((pit_adj*PIT_MIN_12k8)+(FSCALE_DENOM/2))/FSCALE_DENOM)-PIT_MIN_12k8; 
    PIT_MIN = PIT_MIN_12k8 + i; 
    PIT_FR2 = PIT_FR2_12k8 - i; 
    PIT_FR1 = PIT_FR1_12k8; 
    PIT_MAX = PIT_MAX_12k8 + (6*i); 
  } 
 /*------------------------------------------------------------------------* 
  * - decode mean_ener_code for gain decoder (d_gain2.c)                   * 
  *------------------------------------------------------------------------*/ 
  index = *prm++; 
  /* decode mean energy with 2 bits : 18, 30, 42 or 54 dB */ 
  if (!bfi) { 
    mean_ener_code = (((float)index) * 12.0f) + 18.0f; 
  } 
 /*------------------------------------------------------------------------* 
  *          Loop for every subframe in the analysis frame                 * 
  *------------------------------------------------------------------------* 
  *  To find the pitch and innovation parameters. The subframe size is     * 
  *  L_SUBFR and the loop is repeated L_ACELP/L_SUBFR times.               * 
  *     - compute impulse response of weighted synthesis filter (h1[])     * 
  *     - compute the target signal for pitch search                       * 
  *     - find the closed-loop pitch parameters                            * 
  *     - encode the pitch dealy                                           * 
  *     - update the impulse response h1[] by including fixed-gain pitch   * 
  *     - find target vector for codebook search                           * 
  *     - correlation between target vector and impulse response           * 
  *     - codebook search                                                  * 
  *     - encode codebook address                                          * 
  *     - VQ of pitch and codebook gains                                   * 
  *     - find synthesis speech                                            * 
  *     - update states of weighting filter                                * 
  *------------------------------------------------------------------------*/ 
  ener_wsyn = 0.01f; 
  p_A = A; 
  for (i_subfr = 0; i_subfr < lg; i_subfr += L_SUBFR) 
  { 
    pit_flag = i_subfr; 
    if (i_subfr == (2*L_SUBFR)) { 
      pit_flag = 0; 
    } 
    index = *prm++; 
    /*-------------------------------------------------* 
     * - Decode pitch lag                              * 
     *-------------------------------------------------*/ 
 
	if (bfi)                     /* 如果发生帧错误 */ 
    { 
		switch(st->bfi_count%4)/* 将连续坏帧数对4取模 */ 
		{ 
		case 1:/* 模1 */ 
			T0 = st->old_T0 + 1;/* 将上帧的基音延迟加1作为当前帧的基音延迟 */ 
			break; 
		case 2:/* 模2 */ 
			T0 = st->old_T0 - 2;/* 将上帧的基音延迟减2作为当前帧的基音延迟 */ 
			break; 
		case 3:/* 模3 */ 
			T0 = st->old_T0 - 1;/* 将上帧的基音延迟减1作为当前帧的基音延迟 */ 
			break; 
		case 0:/* 模0 */ 
			T0 = st->old_T0 + 2;/* 将上帧的基音延迟加2作为当前帧的基音延迟 */ 
			break;	 
		} 
		if (T0 > PIT_MAX)/* 如果基音延迟大于上限 */ 
		{ 
			T0 = PIT_MAX;/* 将基音延迟设为上限 */ 
		} 
		if (T0 < PIT_MIN)/* 如果基音延迟小于下限 */ 
		{ 
			T0 = PIT_MIN;/* 将基音延迟设为下限 */ 
		} 
		 
		T0_frac = 0;/* 基音延迟分数部分置0 */ 
    } 
 
    else 
    { 
      if (pit_flag == 0) 
      { 
        if (index < (PIT_FR2-PIT_MIN)*4) 
        { 
          T0 = PIT_MIN + (index/4); 
          T0_frac = index - (T0 - PIT_MIN)*4; 
        } 
        else if (index < ( (PIT_FR2-PIT_MIN)*4 + (PIT_FR1-PIT_FR2)*2) )   
        { 
          index -=  (PIT_FR2-PIT_MIN)*4; 
          T0 = PIT_FR2 + (index/2); 
          T0_frac = index - (T0 - PIT_FR2)*2; 
          T0_frac *= 2; 
        } 
        else { 
          T0 = index + PIT_FR1 - ((PIT_FR2-PIT_MIN)*4) - ((PIT_FR1-PIT_FR2)*2); 
          T0_frac = 0; 
        } 
        /* find T0_min and T0_max for subframe 2 or 4 */ 
        T0_min = T0 - 8; 
        if (T0_min < PIT_MIN) { 
          T0_min = PIT_MIN; 
        } 
        T0_max = T0_min + 15; 
        if (T0_max > PIT_MAX) 
        { 
          T0_max = PIT_MAX; 
          T0_min = T0_max - 15; 
        } 
      } 
      else      /* if subframe 2 or 4 */ 
      { 
        T0 = T0_min + index/4; 
        T0_frac = index - (T0 - T0_min)*4; 
      } 
    } 
    /*-------------------------------------------------* 
     * - Find the pitch gain, the interpolation filter * 
     *   and the adaptive codebook vector.             * 
     *-------------------------------------------------*/ 
    pred_lt4(&exc[i_subfr], T0, T0_frac, L_SUBFR+1); 
    select = *prm++; 
    if (bfi) { 
      select = 1; 
    } 
    if (select == 0) 
    { 
	  /* ADAPTIVE_EXCITATION_SEARCH */ 
      /* find pitch excitation with lp filter */ 
      for (i=0; iseed_ace)); 
      }   
    } 
   /*-------------------------------------------------------* 
    * - Add the fixed-gain pitch contribution to code[].    * 
    *-------------------------------------------------------*/ 
    tmp = 0.0; 
#ifndef PW_UPDATE 
    E_UTIL_f_preemph(code, TILT_CODE, L_SUBFR, &tmp); 
#endif 
    i = T0; 
    if (T0_frac > 2) { 
      i++; 
    } 
    E_GAIN_f_pitch_sharpening(code, i); 
   /*-------------------------------------------------* 
    * - Decode codebooks gains.                       * 
    *-------------------------------------------------*/ 
    index = *prm++; 
    st->mem_gain_code[i_subfr/L_SUBFR] =  
        d_gain2_plus(index, code, L_SUBFR, &gain_pit, &gain_code, bfi, 
                     mean_ener_code, &(st->past_gpit), &(st->past_gcode)); 
   /*----------------------------------------------------------* 
    * Update parameters for the next subframe.                 * 
    * - tilt of code: 0.0 (unvoiced) to 0.5 (voiced)           * 
    *----------------------------------------------------------*/ 
    /* energy of pitch excitation */ 
    ener = 0.0; 
    for (i=0; i 2) { 
      i++; 
    } 
    if (i > PIT_MAX) { 
      i = PIT_MAX; 
    } 
    *pT++ = i; 
    *pgainT++ = gain_pit; 
    if (pit_adj == 0) 
    { 
      E_UTIL_synthesis(p_A, &exc[i_subfr], &synth[i_subfr], L_SUBFR, &synth[i_subfr-M], 0); 
    } 
    else 
    { 
     /*------------------------------------------------------------* 
      * noise enhancer                                             * 
      * ~~~~~~~~~~~~~~                                             * 
      * - Enhance excitation on noise. (modify gain of code)       * 
      *   If signal is noisy and LPC filter is stable, move gain   * 
      *   of code 1.5 dB toward gain of code threshold.            * 
      *   This decrease by 3 dB noise energy variation.            * 
      *------------------------------------------------------------*/ 
 
	  fac = stab_fac; //ISF稳定性因子 
	  /* 固定码本增益初始化修正 */ 
	  tmp = gain_code; 
	  if (tmp < st->gc_threshold) 
	  { 
		  tmp = (float)(tmp*1.06); 
		  if (tmp > st->gc_threshold) 
		  { 
			  tmp = st->gc_threshold; 
		  } 
	  }     
	  else { 
		  tmp = (float)(tmp/1.06); 
		  if (tmp < st->gc_threshold) 
		  { 
			  tmp = st->gc_threshold; 
		  } 
	  } 
	  st->gc_threshold = tmp; 
	  /* 固定码本平滑增益的计算 */ 
	  if(fac>0.58) 
		  gain_code = (float)((0.17*tmp) + (0.83*gain_code)); 
      else 
		  gain_code = (float)((0.83*tmp) + (0.17*gain_code)); 
	  /* 固定码本增益平滑,将固定码本乘以平滑增益 */ 
	  for (i=0; imem_formant); 
	E_UTIL_tilt(code,Ap3,L_SUBFR,st->mem_tilt); 
#endif 
#ifndef PW_UPDATE 
	E_LPC_a_weight(p_A, Ap, GAMMA1, M); 
    E_UTIL_residu(Ap, &synth[i_subfr], code, L_SUBFR); 
    E_UTIL_deemph(code, TILT_FAC, L_SUBFR, &(st->mem_wsyn)); 
#endif 
 
#ifdef NEW_TVC 
#ifdef PW_UPDATE 
	if (i_subfr==192){ 
		mvr2r(Ap1, &st->wovlp[83], M+1); 
		mvr2r(Ap2, st->wovlp_ap2, M+1); 
		mvr2r(Ap3, st->wovlp_ap3, TILT_ORDER+1); 
		st->wovlp[80]= code[47]; 
		st->wovlp[81]= code[31]; 
   	} 
	if (i_subfr==128){ 
		st->wovlp[82]= code[63]; 
   	} 
#else 
	if (i_subfr==192){ 
		mvr2r(Ap, &st->wovlp[83], M+1);	 
		st->wovlp[80]= code[47]; 
		st->wovlp[81]= code[31]; 
   	} 
	if (i_subfr==128){ 
		st->wovlp[82]= code[63]; 
   	} 
#endif 
#endif		 
	 
    for (i=0; iwsyn_rms = (float)sqrt(ener_wsyn/(float)lg); 
 /*----------------------------------------------------------* 
  * find 10ms ZIR in weighted domain for next tcx frame      * 
  *----------------------------------------------------------*/ 
#ifndef NEW_TVC 
  mvr2r(&synth[lg-M], buf, M); 
  set_zero(buf+M, L_OVLP); 
  E_UTIL_synthesis(p_A, buf+M, buf+M, L_OVLP, buf, 0); 
#ifdef PW_UPDATE 
  {  float mem_temp1[M],mem_temp2[TILT_ORDER]; 
     mvr2r(st->mem_formant,mem_temp1,M); 
     mvr2r(st->mem_tilt,mem_temp2,TILT_ORDER); 
     paraChoose(p_A,&gamma1,&gamma2,&gamma3); 
     E_LPC_a_weight(p_A, Ap1, gamma1, M); 
     E_LPC_a_weight(p_A, Ap2, gamma2, M); 
     E_LPC_a_weight(p_A, Ap3, gamma3,TILT_ORDER); 
     E_UTIL_residu(Ap1, buf+M, st->wovlp, L_OVLP); 
     E_UTIL_formant(st->wovlp,Ap2,L_OVLP,mem_temp1); 
     E_UTIL_tilt(st->wovlp,Ap3,L_OVLP,mem_temp2); 
  } 
#else 
  E_LPC_a_weight(p_A, Ap, GAMMA1, M);      /* wAi of tcx is quantized */ 
  E_UTIL_residu(Ap, buf+M, st->wovlp, L_OVLP); 
  tmp = st->mem_wsyn; 
  E_UTIL_deemph(st->wovlp, TILT_FAC, L_OVLP, &tmp); 
#endif 
 
  for (i=1; i<(L_OVLP/2); i++) { 
    st->wovlp[L_OVLP-i] *= ((float)i)/((float)(L_OVLP/2)); 
  } 
#endif 
 
 #ifdef NEW_TVC 
  mvr2r(&synth[176], st->wovlp, 80); 
  set_zero(&st->wovlp[100], 28); 
  st->gw_flg=1; 
 #endif 
  
  st->ovlp_size = 0;       /* indicate ACELP frame to TCX */ 
  /* update pitch value for bfi procedure */ 
  st->old_T0_frac = T0_frac; 
  st->old_T0 = T0; 
  return; 
}