www.pudn.com > AVS_M_ver10.rar > dec_tcx.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" 
/* local function */ 
 
static int find_mpitch(float xri[], int lg); 
#ifdef NEW_TVC 
float ol_synth[1024+16]; 
#endif 
void decoder_tcx( 
    int prm[],         /* input:  parameters              */ 
    int nbits_AVQ[],   /* input:  nbits in parameters of AVQ */ 
    float A[],         /* input:  coefficients NxAz[M+1]  */ 
    int L_frame,       /* input:  frame length            */ 
    int bad_frame[],   /* input:  Bad frame indicator     */ 
    float exc[],       /* output: exc[-lg..lg]            */ 
    float synth[],     /* in/out: synth[-M..lg]           */ 
    Decoder_State_Plus *st) /* i/o : coder memory state        */ 
{ 
#ifdef PW_UPDATE 
  float mem_temp1[M],mem_temp2[TILT_ORDER]; 
#endif 
 
#ifdef NEW_TVC 
  int i, k, i_subfr, index, index2, lg, lext, bfi, n_pack, tmp2; 
  float tmp, gain, fac_ns,tmp1; 
  float *p_A, Ap[M+1],Ap1[M+1],Ap2[M+1],Ap3[TILT_ORDER+1]; 
  float oldsynth[16]; 
  float *xri, *xnq; 
  float window[128+128]; 
  float gband; 
  int any_loss,num_loss; 
#else   
  int i, k, i_subfr, index, lg, lext, bfi, n_pack; 
  float tmp, gain, fac_ns; 
  float *p_A, Ap[M+1],Ap1[M+1],Ap2[M+1],Ap3[TILT_ORDER+1]; 
  float *xri, *xnq; 
  float window[128+128]; 
  int any_loss,num_loss; 
#endif 
  xri = exc; 
  xnq = synth; 
  if (L_frame == (L_FRAME_PLUS/4)) { 
    n_pack = 1; 
  } else if (L_frame == (L_FRAME_PLUS/2)) { 
    n_pack = 2; 
  } else if (L_frame == (L_FRAME_PLUS)) { 
    n_pack = 4; 
  } else { 
    printf( "decoder_tcx: Invalid L_frame, exiting\n" ); 
    exit(1); 
  } 
  any_loss = 0; 
  num_loss = 0; 
  for (i=0; ipitch_tcx; 
    for (i=0; imem_formant,mem_temp1,M); 
    mvr2r(st->mem_tilt,mem_temp2,TILT_ORDER); 
    for (i_subfr=0; i_subfrmem_wsyn; 
    E_UTIL_deemph(xnq, TILT_FAC, L_frame, &tmp); 
#endif 
 
    tmp = 0.7f*st->wsyn_rms; 
    st->wsyn_rms = tmp; 
    for (i=0; i tmp) { 
        xnq[i] = tmp; 
      } else { 
        if (xnq[i] < -tmp) { 
          xnq[i] = -tmp; 
        } 
      } 
    } 
 
#ifdef PW_UPDATE 
    p_A = A; 
    for (i_subfr=0; i_subfrmem_tilt); 
      E_UTIL_deformant(&xnq[i_subfr],Ap2,L_SUBFR,st->mem_formant); 
      E_UTIL_synthesis(Ap1, &xnq[i_subfr], &synth[i_subfr], L_SUBFR, &synth[i_subfr-M], 0); 
      p_A += (M+1); 
    } 
#endif 
#ifndef PW_UPDATE 
    E_UTIL_f_preemph(xnq, TILT_FAC, L_frame, &(st->mem_wsyn)); 
    p_A = A; 
    for (i_subfr=0; i_subfrwovlp[i]=0; 
    } 
  } 
  else    
  { 
    /*----- synthesize windowed TCX target (inverse FFT of decoded 
      spectrum + noise fill-in) using available info  ------*/ 
    /* decode noise level (fac_ns) (stored in 2nd packet on TCX80) */ 
    index = *prm++; 
    if (n_pack == 4) { 
      bfi = bad_frame[1]; 
    } else { 
      bfi = bad_frame[0]; 
    } 
    if (bfi != 0) { 
      index = 0; 
    } 
    fac_ns = 0.1f*(8.0f - ((float)index)); 
    /* read index of global TCX gain : erased bits are set to 1 to 
       minimize global gain if bad_frame set erased bits to default 
       value (0 or 1 depending on parameter) */ 
    index = *prm++; 
#ifdef NEW_TVC 
    /* decode gain between two bands */ 
    index2 = *prm++; 
    gband = (float)index2 / (float)64.0; 
    /* decode parameters of multi-rate lattice VQ */ 
    AVQ_demuxdec(n_pack, prm, nbits_AVQ, xri, lg/8, bad_frame); 
    /* amplify low half band with gain gband */ 
    for (i = 0; i < lg/2; i++){ 
      xri[i+lg/2] /= gband; 
    } 
#else	 
    /* decode parameters of multi-rate lattice VQ */ 
    AVQ_demuxdec(n_pack, prm, nbits_AVQ, xri, lg/8, bad_frame); 
#endif 
    if(any_loss) { 
      adapt_low_freq_deemph_ecu(xri,lg,st); 
      reconst_spect(xri,st->old_xri,n_pack,bad_frame,lg,st->last_mode,xnq); 
      /* generate random excitation buffer */ 
      set_zero(xnq, lg); 
      rnd_ph16(&(st->seed_tcx), &xnq[lg/6], lg-(lg/6)); 
      /*----------------------------------------------* 
       * noise fill-in on unquantized subvector       * 
       * injected only from 1066Hz to 6400Hz.         * 
       *----------------------------------------------*/ 
      for(k=lg/6; kseed_tcx), &xnq[lg/6], lg-(lg/6)); 
 
      /*----------------------------------------------* 
       * noise fill-in on unquantized subvector       * 
       * injected only from 1066Hz to 6400Hz.         * 
       *----------------------------------------------*/ 
      for(k=lg/6; kold_xri,lg); 
    /* find pitch for bfi case */ 
    st->pitch_tcx = find_mpitch(xri, lg); 
    /*-----------------------------------------------------------* 
     * Compute inverse FFT for obtaining xnq[] without noise.    * 
     * Coefficients (xri[]) order are                            * 
     *    re[0], re[n/2], re[1], re[2], ... re[n/2-1], im[n/2-1] * 
     * Note that last FFT element (re[n/2]) is zeroed.           * 
     *-----------------------------------------------------------*/ 
    xri[1] = 0.0;       /* freq bin at 6400 Hz zeroed */ 
    ifft9(xri, xnq, (short)lg); 
    /*-----------------------------------------------------------* 
     * decode TCX global gain, multiply xnq[] by gain.           * 
     * windowing of xnq[] for TCX overlap.                       * 
     *-----------------------------------------------------------*/ 
    bfi = 0; /* We never have a missing gain!!! */ 
    gain = d_gain_tcx(index, xnq, lg, bfi, &(st->wsyn_rms)); 
#ifdef GAIN_CONCEAL_OLA	 
    gain_conceal_ola(&gain,xnq,st->wovlp,st->ovlp_size); 
#endif 
    for (i=0; iovlp_size==0){ 
      lext=lext/2; 
    } 
 
    cos_window(window, st->ovlp_size, lext); 
    /* adaptive windowing on overlap (beginning and end of frame) */ 
 
    for (i=0; iovlp_size; i++) { 
      xnq[i] *= window[i]; 
    } 
    if (st->ovlp_size ==0){	 
      for (i=0; iovlp_size+i]; 
      } 
    } 
    else{ 
      for (i=0; iovlp_size+i]; 
      } 
    } 
 
    //下面求解帧头的交迭信号合成语音 
    if(st->ovlp_size==0){ 
      if (lext==16) { 
        mvr2r(& st->wovlp[48], oldsynth, M); 	 
        tmp1= st->wovlp[80]; 
      } 
      else if (lext==32) { 
        mvr2r(& st->wovlp[32], oldsynth, M); 	 
        tmp1= st->wovlp[81]; 
      } 
      else { 
        mvr2r( st->wovlp, oldsynth, M); 	 
        tmp1= st->wovlp[82]; 
      } 
#ifdef PW_UPDATE 
      mvr2r(&st->wovlp[83], Ap1, M+1); 
	  mvr2r(st->wovlp_ap2, Ap2, M+1); 
	  mvr2r(st->wovlp_ap3, Ap3, TILT_ORDER+1); 
      set_zero(st->wovlp, L_OVLP); 
	  set_zero(st->wovlp_ap2, 17); 
	  set_zero(st->wovlp_ap3, 3); 
#else 
	  mvr2r(&st->wovlp[83], Ap, M+1); 
      set_zero(st->wovlp, L_OVLP); 
#endif	  	   
      tmp2=L_frame+lext; 
    } 
 
    /*-----------------------------------------------------------* 
     * TCX overlap and add.  Update memory for next overlap.     * 
     *-----------------------------------------------------------*/ 
    for (i=0; iwovlp[i]; 
    } 
    /* save overlap for next frame */ 
    if(st->ovlp_size==0){ 
      for (i=0; iwovlp[i] = xnq[i+L_frame+lext]; 
      } 
    } 
    else{ 
      for (i=0; iwovlp[i] = xnq[i+L_frame]; 
      } 
    } 
    for (i=lext; iwovlp[i] = 0.0; 
    } 
 
    /*-----------------------------------------------------------* 
     * find excitation and synthesis                             * 
     *-----------------------------------------------------------*/ 
#ifdef PW_UPDATE 
	if(st->g_flg==0 && st->ovlp_size==0){ 
		p_A = A; 
		for (i_subfr=0; i_subfrmem_tilt); 
			E_UTIL_deformant(&xnq[i_subfr+lext],Ap2,L_SUBFR,st->mem_formant); 
			E_UTIL_synthesis(Ap1, &xnq[i_subfr+lext], &synth[i_subfr], L_SUBFR, &synth[i_subfr-M], 0); 
			E_UTIL_residu(p_A, &synth[i_subfr], &exc[i_subfr], L_SUBFR); 
			p_A += (M+1); 
		}		 
    } 
    else{ 
		if(st->ovlp_size==0){ 
			E_UTIL_detilt(xnq,Ap3,lext,st->mem_tilt); 
			E_UTIL_deformant(xnq,Ap2,lext,st->mem_formant); 
			E_UTIL_synthesis(Ap1, xnq, st->gw_synth, lext, oldsynth, 0); 
			mvr2r(&st->gw_synth[lext-M], ol_synth, M);    
			 
			p_A = A; 
			for (i_subfr=0; i_subfrmem_tilt); 
				E_UTIL_deformant(&xnq[i_subfr+lext],Ap2,L_SUBFR,st->mem_formant); 
				E_UTIL_synthesis(Ap1, &xnq[i_subfr+lext], &ol_synth[i_subfr+M], L_SUBFR, &ol_synth[i_subfr], 0); 
				E_UTIL_residu(p_A, &ol_synth[i_subfr+M], &exc[i_subfr], L_SUBFR); 
				p_A += (M+1); 
			}   
			mvr2r(&ol_synth[M], synth, L_frame); 
			st->mem_wsyn=tmp1;   
		}else{ 
			p_A = A; 
			for (i_subfr=0; i_subfrmem_tilt); 
				E_UTIL_deformant(&xnq[i_subfr],Ap2,L_SUBFR,st->mem_formant); 
				E_UTIL_synthesis(Ap1, &xnq[i_subfr], &synth[i_subfr], L_SUBFR, &synth[i_subfr-M], 0); 
				E_UTIL_residu(p_A, &synth[i_subfr], &exc[i_subfr], L_SUBFR); 
				p_A += (M+1); 
			}			 
		} 
    } 
    st->ovlp_size = lext;     
#endif 
#ifndef PW_UPDATE 
    if(st->g_flg==0 && st->ovlp_size==0){ 
      E_UTIL_f_preemph(&xnq[lext], TILT_FAC, L_frame, &(st->mem_wsyn)); 
      p_A = A; 
      for (i_subfr=0; i_subfrovlp_size==0){ 
        E_UTIL_f_preemph(xnq, TILT_FAC, tmp2, &tmp1); 
        E_UTIL_synthesis(Ap, xnq, st->gw_synth, lext, oldsynth, 0); 
        mvr2r(&st->gw_synth[lext-M], ol_synth, M);    
 
        p_A = A; 
        for (i_subfr=0; i_subfrmem_wsyn=tmp1;   
      }else{ 
        E_UTIL_f_preemph(xnq, TILT_FAC, L_frame, &(st->mem_wsyn)); 
        p_A = A; 
        for (i_subfr=0; i_subfrovlp_size = lext; 
#endif 
  } 
  return; 
#else 
  /*------ initialize window of TCX target : two halves of a squared 
    root of a hanning window the first part is as long as the overlap 
    length of past frame (ovlp_size) the second part is as long as 
    lext -----*/ 
  cos_window(window, st->ovlp_size, lext); 
  /* adaptive windowing on overlap (beginning and end of frame) */ 
  for (i=0; iovlp_size; i++) { 
    xnq[i] *= window[i]; 
  } 
  for (i=0; iovlp_size+i]; 
  } 
  /*-----------------------------------------------------------* 
   * TCX overlap and add.  Update memory for next overlap.     * 
   *-----------------------------------------------------------*/ 
  for (i=0; iwovlp[i]; 
  } 
  /* save overlap for next frame */ 
  for (i=0; iwovlp[i] = xnq[i+L_frame]; 
  } 
  for (i=lext; iwovlp[i] = 0.0; 
  } 
  st->ovlp_size = lext; 
  /*-----------------------------------------------------------* 
   * find excitation and synthesis                             * 
   *-----------------------------------------------------------*/ 
#ifdef PW_UPDATE 
  p_A = A; 
  for (i_subfr=0; i_subfrmem_tilt); 
    E_UTIL_deformant(&xnq[i_subfr],Ap2,L_SUBFR,st->mem_formant); 
    E_UTIL_synthesis(Ap1, &xnq[i_subfr], &synth[i_subfr], L_SUBFR, &synth[i_subfr-M], 0); 
    E_UTIL_residu(p_A, &synth[i_subfr], &exc[i_subfr], L_SUBFR); 
    p_A += (M+1); 
  } 
#endif 
#ifndef PW_UPDATE 
  E_UTIL_f_preemph(xnq, TILT_FAC, L_frame, &(st->mem_wsyn)); 
  p_A = A; 
  for (i_subfr=0; i_subfr max) { 
      max = tmp; 
      n = i; 
    } 
  } 
  pitch = (float)lg*(2.0f/(float)n); 
  /* find pitch multiple under 20ms */ 
  if (pitch >= 256.0f) { 
    n = 256; 
  } else { 
    mpitch = pitch; 
    while (mpitch < 256.0f) { 
      mpitch += pitch; 
    } 
    n = (int)floor(mpitch-pitch); 
  } 
  return(n); 
}