Example #1
0
void lpc_post_filter(kiss_fft_cfg fft_fwd_cfg, MODEL *model, COMP Pw[], float ak[],
                     int order, int dump, float beta, float gamma, int bass_boost)
{
    int   i;
    COMP  x[FFT_ENC];   /* input to FFTs                */
    COMP  Aw[FFT_ENC];  /* LPC analysis filter spectrum */
    COMP  Ww[FFT_ENC];  /* weighting spectrum           */
    float Rw[FFT_ENC];  /* R = WA                       */
    float e_before, e_after, gain;
    float Pfw[FFT_ENC]; /* Post filter mag spectrum     */
    float max_Rw, min_Rw;
    float coeff;
    TIMER_VAR(tstart, tfft1, taw, tfft2, tww, tr);

    TIMER_SAMPLE(tstart);

    /* Determine LPC inverse filter spectrum 1/A(exp(jw)) -----------*/

    /* we actually want the synthesis filter A(exp(jw)) but the
       inverse (analysis) filter is easier to find as it's FIR, we
       just use the inverse of 1/A to get the synthesis filter
       A(exp(jw)) */

    for(i=0; i<FFT_ENC; i++) {
	x[i].real = 0.0;
	x[i].imag = 0.0;
    }

    for(i=0; i<=order; i++)
	x[i].real = ak[i];
    kiss_fft(fft_fwd_cfg, (kiss_fft_cpx *)x, (kiss_fft_cpx *)Aw);

    TIMER_SAMPLE_AND_LOG(tfft1, tstart, "        fft1");

    for(i=0; i<FFT_ENC/2; i++) {
	Aw[i].real = 1.0/(Aw[i].real*Aw[i].real + Aw[i].imag*Aw[i].imag);
    }

    TIMER_SAMPLE_AND_LOG(taw, tfft1, "        Aw");

    /* Determine weighting filter spectrum W(exp(jw)) ---------------*/

    for(i=0; i<FFT_ENC; i++) {
	x[i].real = 0.0;
	x[i].imag = 0.0;
    }

    x[0].real = ak[0];
    coeff = gamma;
    for(i=1; i<=order; i++) {
	x[i].real = ak[i] * coeff;
        coeff *= gamma;
    }
    kiss_fft(fft_fwd_cfg, (kiss_fft_cpx *)x, (kiss_fft_cpx *)Ww);

    TIMER_SAMPLE_AND_LOG(tfft2, taw, "        fft2");

    for(i=0; i<FFT_ENC/2; i++) {
	Ww[i].real = Ww[i].real*Ww[i].real + Ww[i].imag*Ww[i].imag;
    }

    TIMER_SAMPLE_AND_LOG(tww, tfft2, "        Ww");

    /* Determined combined filter R = WA ---------------------------*/

    max_Rw = 0.0; min_Rw = 1E32;
    for(i=0; i<FFT_ENC/2; i++) {
	Rw[i] = sqrtf(Ww[i].real * Aw[i].real);
	if (Rw[i] > max_Rw)
	    max_Rw = Rw[i];
	if (Rw[i] < min_Rw)
	    min_Rw = Rw[i];

    }

    TIMER_SAMPLE_AND_LOG(tr, tww, "        R");

    #ifdef DUMP
    if (dump)
      dump_Rw(Rw);
    #endif

    /* create post filter mag spectrum and apply ------------------*/

    /* measure energy before post filtering */

    e_before = 1E-4;
    for(i=0; i<FFT_ENC/2; i++)
	e_before += Pw[i].real;

    /* apply post filter and measure energy  */

    #ifdef DUMP
    if (dump)
	dump_Pwb(Pw);
    #endif

    e_after = 1E-4;
    for(i=0; i<FFT_ENC/2; i++) {
	Pfw[i] = powf(Rw[i], beta);
	Pw[i].real *= Pfw[i] * Pfw[i];
	e_after += Pw[i].real;
    }
    gain = e_before/e_after;

    /* apply gain factor to normalise energy */

    for(i=0; i<FFT_ENC/2; i++) {
	Pw[i].real *= gain;
    }

    if (bass_boost) {
        /* add 3dB to first 1 kHz to account for LP effect of PF */

        for(i=0; i<FFT_ENC/8; i++) {
            Pw[i].real *= 1.4*1.4;
        }
    }

    TIMER_SAMPLE_AND_LOG2(tr, "        filt");
}
Example #2
0
void aks_to_M2(
  kiss_fft_cfg  fft_fwd_cfg,
  float         ak[],	     /* LPC's */
  int           order,
  MODEL        *model,	     /* sinusoidal model parameters for this frame */
  float         E,	     /* energy term */
  float        *snr,	     /* signal to noise ratio for this frame in dB */
  int           dump,        /* true to dump sample to dump file */
  int           sim_pf,      /* true to simulate a post filter */
  int           pf,          /* true to LPC post filter */
  int           bass_boost,  /* enable LPC filter 0-1khz 3dB boost */
  float         beta,
  float         gamma        /* LPC post filter parameters */
)
{
  COMP pw[FFT_ENC];	/* input to FFT for power spectrum */
  COMP Pw[FFT_ENC];	/* output power spectrum */
  int i,m;		/* loop variables */
  int am,bm;		/* limits of current band */
  float r;		/* no. rads/bin */
  float Em;		/* energy in band */
  float Am;		/* spectral amplitude sample */
  float signal, noise;
  TIMER_VAR(tstart, tfft, tpw, tpf);

  TIMER_SAMPLE(tstart);

  r = TWO_PI/(FFT_ENC);

  /* Determine DFT of A(exp(jw)) --------------------------------------------*/

  for(i=0; i<FFT_ENC; i++) {
    pw[i].real = 0.0;
    pw[i].imag = 0.0;
  }

  for(i=0; i<=order; i++)
    pw[i].real = ak[i];
  kiss_fft(fft_fwd_cfg, (kiss_fft_cpx *)pw, (kiss_fft_cpx *)Pw);

  TIMER_SAMPLE_AND_LOG(tfft, tstart, "      fft");

  /* Determine power spectrum P(w) = E/(A(exp(jw))^2 ------------------------*/

  for(i=0; i<FFT_ENC/2; i++)
    Pw[i].real = E/(Pw[i].real*Pw[i].real + Pw[i].imag*Pw[i].imag);

  TIMER_SAMPLE_AND_LOG(tpw, tfft, "      Pw");

  if (pf)
      lpc_post_filter(fft_fwd_cfg, model, Pw, ak, order, dump, beta, gamma, bass_boost);

  TIMER_SAMPLE_AND_LOG(tpf, tpw, "      LPC post filter");

  #ifdef DUMP
  if (dump)
      dump_Pw(Pw);
  #endif

  /* Determine magnitudes from P(w) ----------------------------------------*/

  /* when used just by decoder {A} might be all zeroes so init signal
     and noise to prevent log(0) errors */

  signal = 1E-30; noise = 1E-32;

  for(m=1; m<=model->L; m++) {
      am = (int)((m - 0.5)*model->Wo/r + 0.5);
      bm = (int)((m + 0.5)*model->Wo/r + 0.5);
      Em = 0.0;

      for(i=am; i<bm; i++)
          Em += Pw[i].real;
      Am = sqrtf(Em);

      signal += model->A[m]*model->A[m];
      noise  += (model->A[m] - Am)*(model->A[m] - Am);

      /* This code significantly improves perf of LPC model, in
         particular when combined with phase0.  The LPC spectrum tends
         to track just under the peaks of the spectral envelope, and
         just above nulls.  This algorithm does the reverse to
         compensate - raising the amplitudes of spectral peaks, while
         attenuating the null.  This enhances the formants, and
         supresses the energy between formants. */

      if (sim_pf) {
          if (Am > model->A[m])
              Am *= 0.7;
          if (Am < model->A[m])
              Am *= 1.4;
      }

      model->A[m] = Am;
  }
  *snr = 10.0*log10f(signal/noise);

  TIMER_SAMPLE_AND_LOG2(tpf, "      rec");
}
Example #3
0
File: nlp.c Project: kasfis/codec2
float nlp(
  void *nlp_state, 
  float  Sn[],			/* input speech vector */
  int    n,			/* frames shift (no. new samples in Sn[]) */
  int    pmin,                  /* minimum pitch value */
  int    pmax,			/* maximum pitch value */
  float *pitch,			/* estimated pitch period in samples */
  COMP   Sw[],                  /* Freq domain version of Sn[] */
  COMP   W[],                   /* Freq domain window */
  float *prev_Wo
)
{
    NLP   *nlp;
    float  notch;		    /* current notch filter output    */
    COMP   fw[PE_FFT_SIZE];	    /* DFT of squared signal (input)  */
    COMP   Fw[PE_FFT_SIZE];	    /* DFT of squared signal (output) */
    float  gmax;
    int    gmax_bin;
    int    m, i,j;
    float  best_f0;
    TIMER_VAR(start, tnotch, filter, peakpick, window, fft, magsq, shiftmem);
    
    assert(nlp_state != NULL);
    nlp = (NLP*)nlp_state;
    m = nlp->m;

    TIMER_SAMPLE(start);

    /* Square, notch filter at DC, and LP filter vector */

    for(i=m-n; i<m; i++) 	    /* square latest speech samples */
	nlp->sq[i] = Sn[i]*Sn[i];

    for(i=m-n; i<m; i++) {	/* notch filter at DC */
	notch = nlp->sq[i] - nlp->mem_x;
	notch += COEFF*nlp->mem_y;
	nlp->mem_x = nlp->sq[i];
	nlp->mem_y = notch;
	nlp->sq[i] = notch + 1.0;  /* With 0 input vectors to codec,
				      kiss_fft() would take a long
				      time to execute when running in
				      real time.  Problem was traced
				      to kiss_fft function call in
				      this function. Adding this small
				      constant fixed problem.  Not
				      exactly sure why. */
    }

    TIMER_SAMPLE_AND_LOG(tnotch, start, "      square and notch");

    for(i=m-n; i<m; i++) {	/* FIR filter vector */

	for(j=0; j<NLP_NTAP-1; j++)
	    nlp->mem_fir[j] = nlp->mem_fir[j+1];
	nlp->mem_fir[NLP_NTAP-1] = nlp->sq[i];

	nlp->sq[i] = 0.0;
	for(j=0; j<NLP_NTAP; j++)
	    nlp->sq[i] += nlp->mem_fir[j]*nlp_fir[j];
    }

    TIMER_SAMPLE_AND_LOG(filter, tnotch, "      filter");
 
    /* Decimate and DFT */

    for(i=0; i<PE_FFT_SIZE; i++) {
	fw[i].real = 0.0;
	fw[i].imag = 0.0;
    }
    for(i=0; i<m/DEC; i++) {
	fw[i].real = nlp->sq[i*DEC]*nlp->w[i];
    }
    TIMER_SAMPLE_AND_LOG(window, filter, "      window");
    #ifdef DUMP
    dump_dec(Fw);
    #endif

    kiss_fft(nlp->fft_cfg, (kiss_fft_cpx *)fw, (kiss_fft_cpx *)Fw);
    TIMER_SAMPLE_AND_LOG(fft, window, "      fft");

    for(i=0; i<PE_FFT_SIZE; i++)
	Fw[i].real = Fw[i].real*Fw[i].real + Fw[i].imag*Fw[i].imag;

    TIMER_SAMPLE_AND_LOG(magsq, fft, "      mag sq");
    #ifdef DUMP
    dump_sq(nlp->sq);
    dump_Fw(Fw);
    #endif

    /* find global peak */

    gmax = 0.0;
    gmax_bin = PE_FFT_SIZE*DEC/pmax;
    for(i=PE_FFT_SIZE*DEC/pmax; i<=PE_FFT_SIZE*DEC/pmin; i++) {
	if (Fw[i].real > gmax) {
	    gmax = Fw[i].real;
	    gmax_bin = i;
	}
    }
    
    TIMER_SAMPLE_AND_LOG(peakpick, magsq, "      peak pick");

    //#define POST_PROCESS_MBE
    #ifdef POST_PROCESS_MBE
    best_f0 = post_process_mbe(Fw, pmin, pmax, gmax, Sw, W, prev_Wo);
    #else
    best_f0 = post_process_sub_multiples(Fw, pmin, pmax, gmax, gmax_bin, prev_Wo);
    #endif

    TIMER_SAMPLE_AND_LOG(shiftmem, peakpick,  "      post process");

    /* Shift samples in buffer to make room for new samples */

    for(i=0; i<m-n; i++)
	nlp->sq[i] = nlp->sq[i+n];

    /* return pitch and F0 estimate */

    *pitch = (float)SAMPLE_RATE/best_f0;

    TIMER_SAMPLE_AND_LOG2(shiftmem,  "      shift mem");

    TIMER_SAMPLE_AND_LOG2(start,  "      nlp int");

    return(best_f0);  
}