(1-gamma)*st->gain[i]*st->gain[i]*st->old_ps[i]/(1+st->noise[i]+st->echo_noise[i]);
(1-gamma)*st->gain[i]*st->gain[i]*st->old_ps[i]/(1+st->noise[i]+st->echo_noise[i]+st->reverb_estimate[i]);
int speex_preprocess(SpeexPreprocessState *st, short *x, float *echo){   int i;   int is_speech=1;   float mean_post=0;   float mean_prior=0;   int N = st->ps_size;   int N3 = 2*N - st->frame_size;   int N4 = st->frame_size - N3;   float scale=.5/N;   float *ps=st->ps;   float Zframe=0, Pframe;   preprocess_analysis(st, x);   update_noise_prob(st);   st->nb_preprocess++;   /* Noise estimation always updated for the 20 first times */   if (st->nb_adapt<10)   {      update_noise(st, ps, echo);   }   /* Deal with residual echo if provided */   if (echo)      for (i=1;i<N;i++)         st->echo_noise[i] = (.7*st->echo_noise[i] + .3* echo[i]);   /* Compute a posteriori SNR */   for (i=1;i<N;i++)   {      st->post[i] = ps[i]/(1+st->noise[i]+st->echo_noise[i]) - 1;      if (st->post[i]>100)         st->post[i]=100;      /*if (st->post[i]<0)        st->post[i]=0;*/      mean_post+=st->post[i];   }   mean_post /= N;   if (mean_post<0)      mean_post=0;   /* Special case for first frame */   if (st->nb_adapt==1)      for (i=1;i<N;i++)         st->old_ps[i] = ps[i];   /* Compute a priori SNR */   {      /* A priori update rate */      float gamma;      float min_gamma=0.12;      gamma = 1.0/st->nb_preprocess;      /*Make update rate smaller when there's no speech*/#if 0      if (mean_post<3.5 && mean_prior < 1)         min_gamma *= (mean_post+.5);      else         min_gamma *= 4.;#else      min_gamma = .1*fabs(mean_prior - mean_post)*fabs(mean_prior - mean_post);      if (min_gamma>.15)         min_gamma = .15;      if (min_gamma<.02)         min_gamma = .02;#endif      /*min_gamma = .08;*/      /*if (gamma<min_gamma)*/         gamma=min_gamma;            for (i=1;i<N;i++)      {                  /* A priori SNR update */         st->prior[i] = gamma*max(0.0,st->post[i]) +         (1-gamma)*st->gain[i]*st->gain[i]*st->old_ps[i]/(1+st->noise[i]+st->echo_noise[i]);                  if (st->prior[i]>100)            st->prior[i]=100;                  mean_prior+=st->prior[i];      }   }   mean_prior /= N;#if 0   for (i=0;i<N;i++)   {      fprintf (stderr, "%f ", st->prior[i]);   }   fprintf (stderr, "\n");#endif   /*fprintf (stderr, "%f %f\n", mean_prior,mean_post);*/   if (st->nb_preprocess>=20)   {      int do_update = 0;      float noise_ener=0, sig_ener=0;      /* If SNR is low (both a priori and a posteriori), update the noise estimate*/      /*if (mean_prior<.23 && mean_post < .5)*/      if (mean_prior<.23 && mean_post < .5)         do_update = 1;      for (i=1;i<N;i++)      {         noise_ener += st->noise[i];         sig_ener += ps[i];      }      if (noise_ener > 3*sig_ener)         do_update = 1;      /*do_update = 0;*/      if (do_update)      {         st->consec_noise++;      } else {         st->consec_noise=0;      }   }   if (st->vad_enabled)      is_speech = speex_compute_vad(st, ps, mean_prior, mean_post);   if (st->consec_noise>=3)   {      update_noise(st, st->old_ps, echo);   } else {      for (i=1;i<N-1;i++)      {         if (st->update_prob[i]<.5)            st->noise[i] = .90*st->noise[i] + .1*st->ps[i];      }   }   for (i=1;i<N;i++)   {      st->zeta[i] = .7*st->zeta[i] + .3*st->prior[i];   }   {      int freq_start = (int)(300.0*2*N/st->sampling_rate);      int freq_end   = (int)(2000.0*2*N/st->sampling_rate);      for (i=freq_start;i<freq_end;i++)      {         Zframe += st->zeta[i];               }   }   Zframe /= N;   if (Zframe<ZMIN)   {      Pframe = 0;   } else {      if (Zframe > 1.5*st->Zlast)      {         Pframe = 1;         st->Zpeak = Zframe;         if (st->Zpeak > 10)            st->Zpeak = 10;         if (st->Zpeak < 1)            st->Zpeak = 1;      } else {         if (Zframe < st->Zpeak*ZMIN)         {            Pframe = 0;         } else if (Zframe > st->Zpeak*ZMAX)         {            Pframe = 1;         } else {            Pframe = log(Zframe/(st->Zpeak*ZMIN)) / log(ZMAX/ZMIN);         }      }   }   st->Zlast = Zframe;   /*fprintf (stderr, "%f\n", Pframe);*/   /* Compute gain according to the Ephraim-Malah algorithm */   for (i=1;i<N;i++)   {      float MM;      float theta;      float prior_ratio;      float p, q;      float zeta1;      float P1;      prior_ratio = st->prior[i]/(1.0001+st->prior[i]);      theta = (1+st->post[i])*prior_ratio;      if (i==1 || i==N-1)         zeta1 = st->zeta[i];      else         zeta1 = .25*st->zeta[i-1] + .5*st->zeta[i] + .25*st->zeta[i+1];      if (zeta1<ZMIN)         P1 = 0;      else if (zeta1>ZMAX)         P1 = 1;      else         P1 = LOG_MIN_MAX_1 * log(ZMIN_1*zeta1);        /*P1 = log(zeta1/ZMIN)/log(ZMAX/ZMIN);*/            /* FIXME: add global prop (P2) */      q = 1-Pframe*P1;      if (q>.95)         q=.95;      p=1/(1 + (q/(1-q))*(1+st->prior[i])*exp(-theta));      #if 0      /* log-spectral magnitude estimator */      if (theta<6)         MM = 0.74082*pow(theta+1,.61)/sqrt(.0001+theta);      else         MM=1;#else      /* Optimal estimator for loudness domain */      MM = hypergeom_gain(theta);#endif      st->gain[i] = prior_ratio * MM;      /*Put some (very arbitraty) limit on the gain*/      if (st->gain[i]>2)      {         st->gain[i]=2;      }      if (st->denoise_enabled)      {         st->gain2[i]=p*p*st->gain[i];      } else {         st->gain2[i]=1;      }   }   st->gain2[0]=st->gain[0]=0;   st->gain2[N-1]=st->gain[N-1]=0;   if (st->agc_enabled)      speex_compute_agc(st, mean_prior);#if 0   if (!is_speech)   {      for (i=0;i<N;i++)         st->gain2[i] = 0;   }#if 0 else {      for (i=0;i<N;i++)         st->gain2[i] = 1;   }#endif#endif   /* Apply computed gain */   for (i=1;i<N;i++)   {      st->frame[2*i-1] *= st->gain2[i];      st->frame[2*i] *= st->gain2[i];   }   /* Get rid of the DC and very low frequencies */   st->frame[0]=0;   st->frame[1]=0;   st->frame[2]=0;   /* Nyquist frequency is mostly useless too */   st->frame[2*N-1]=0;   /* Inverse FFT with 1/N scaling */   drft_backward(st->fft_lookup, st->frame);   for (i=0;i<2*N;i++)      st->frame[i] *= scale;   {      float max_sample=0;      for (i=0;i<2*N;i++)         if (fabs(st->frame[i])>max_sample)            max_sample = fabs(st->frame[i]);      if (max_sample>28000)      {         float damp = 28000./max_sample;         for (i=0;i<2*N;i++)            st->frame[i] *= damp;      }   }   for (i=0;i<2*N;i++)      st->frame[i] *= st->window[i];   /* Perform overlap and add */   for (i=0;i<N3;i++)      x[i] = st->outbuf[i] + st->frame[i];   for (i=0;i<N4;i++)      x[N3+i] = st->frame[N3+i];      /* Update outbuf */   for (i=0;i<N3;i++)      st->outbuf[i] = st->frame[st->frame_size+i];   /* Save old power spectrum */   for (i=1;i<N;i++)      st->old_ps[i] = ps[i];   return is_speech;}