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

📄 mdf.c

📁 speex 1.1.12 编码 稳定版本
💻 C
📖 第 1 页 / 共 2 页
字号:
   speex_free(st->Xf);   speex_free(st->Yh);   speex_free(st->Eh);   speex_free(st->X);   speex_free(st->Y);   speex_free(st->E);   speex_free(st->W);   speex_free(st->PHI);   speex_free(st->power);   speex_free(st->power_1);   speex_free(st->window);   speex_free(st->wtmp);#ifdef FIXED_POINT   speex_free(st->wtmp2);#endif   speex_free(st);}extern int fixed_point;/** Performs echo cancellation on a frame */void speex_echo_cancel(SpeexEchoState *st, short *ref, short *echo, short *out, spx_int32_t *Yout){   int i,j;   int N,M;   spx_word32_t Syy,See;   spx_word16_t leak_estimate;   spx_word16_t ss, ss_1;   spx_float_t Pey = FLOAT_ONE, Pyy=FLOAT_ONE;   spx_float_t alpha, alpha_1;   spx_word16_t RER;   spx_word32_t tmp32;   spx_word16_t M_1;      N = st->window_size;   M = st->M;   st->cancel_count++;#ifdef FIXED_POINT   ss=DIV32_16(11469,M);   ss_1 = SUB16(32767,ss);   M_1 = DIV32_16(32767,M);#else   ss=.35/M;   ss_1 = 1-ss;   M_1 = 1.f/M;#endif   filter_dc_notch16(ref, st->notch_radius, st->d, st->frame_size, st->notch_mem);   /* Copy input data to buffer */   for (i=0;i<st->frame_size;i++)   {      spx_word16_t tmp;      st->x[i] = st->x[i+st->frame_size];      st->x[i+st->frame_size] = SUB16(echo[i], MULT16_16_P15(st->preemph, st->memX));      st->memX = echo[i];            tmp = st->d[i];      st->d[i] = st->d[i+st->frame_size];      st->d[i+st->frame_size] = SUB16(tmp, MULT16_16_P15(st->preemph, st->memD));      st->memD = tmp;   }   /* Shift memory: this could be optimized eventually*/   for (i=0;i<N*(M-1);i++)      st->X[i]=st->X[i+N];   /* Convert x (echo input) to frequency domain */   spx_fft(st->fft_table, st->x, &st->X[(M-1)*N]);      /* Compute filter response Y */   spectral_mul_accum(st->X, st->W, st->Y, N, M);      spx_ifft(st->fft_table, st->Y, st->y);#if 1   spectral_mul_accum(st->X, st->PHI, st->Y, N, M);      spx_ifft(st->fft_table, st->Y, st->e);#endif   /* Compute error signal (for the output with de-emphasis) */    for (i=0;i<st->frame_size;i++)   {      spx_word32_t tmp_out;#if 1      spx_word16_t y = MULT16_16_Q15(st->window[i+st->frame_size],st->e[i+st->frame_size]) + MULT16_16_Q15(st->window[i],st->y[i+st->frame_size]);      tmp_out = SUB32(EXTEND32(st->d[i+st->frame_size]), EXTEND32(y));#else      tmp_out = SUB32(EXTEND32(st->d[i+st->frame_size]), EXTEND32(st->y[i+st->frame_size]));#endif      /* Saturation */      if (tmp_out>32767)         tmp_out = 32767;      else if (tmp_out<-32768)         tmp_out = -32768;      tmp_out = ADD32(tmp_out, EXTEND32(MULT16_16_P15(st->preemph, st->memE)));      out[i] = tmp_out;      st->memE = tmp_out;   }   /* Compute error signal (filter update version) */    for (i=0;i<st->frame_size;i++)   {      st->e[i] = 0;      st->e[i+st->frame_size] = st->d[i+st->frame_size] - st->y[i+st->frame_size];   }   /* Compute a bunch of correlations */   See = inner_prod(st->e+st->frame_size, st->e+st->frame_size, st->frame_size);   See = ADD32(See, SHR32(10000,6));   Syy = inner_prod(st->y+st->frame_size, st->y+st->frame_size, st->frame_size);      /* Convert error to frequency domain */   spx_fft(st->fft_table, st->e, st->E);   for (i=0;i<st->frame_size;i++)      st->y[i] = 0;   spx_fft(st->fft_table, st->y, st->Y);   /* Compute power spectrum of echo (X), error (E) and filter response (Y) */   power_spectrum(st->E, st->Rf, N);   power_spectrum(st->Y, st->Yf, N);   power_spectrum(&st->X[(M-1)*N], st->Xf, N);      /* Smooth echo energy estimate over time */   for (j=0;j<=st->frame_size;j++)      st->power[j] = MULT16_32_Q15(ss_1,st->power[j]) + 1 + MULT16_32_Q15(ss,st->Xf[j]);      /* Enable this to compute the power based only on the tail (would need to compute more       efficiently to make this really useful */   if (0)   {      float scale2 = .5f/M;      for (j=0;j<=st->frame_size;j++)         st->power[j] = 0;      for (i=0;i<M;i++)      {         power_spectrum(&st->X[i*N], st->Xf, N);         for (j=0;j<=st->frame_size;j++)            st->power[j] += scale2*st->Xf[j];      }   }   /* Compute filtered spectra and (cross-)correlations */   for (j=st->frame_size;j>=0;j--)   {      spx_float_t Eh, Yh;      Eh = PSEUDOFLOAT(st->Rf[j] - st->Eh[j]);      Yh = PSEUDOFLOAT(st->Yf[j] - st->Yh[j]);      Pey = FLOAT_ADD(Pey,FLOAT_MULT(Eh,Yh));      Pyy = FLOAT_ADD(Pyy,FLOAT_MULT(Yh,Yh));#ifdef FIXED_POINT      st->Eh[j] = MAC16_32_Q15(MULT16_32_Q15(SUB16(32767,st->spec_average),st->Eh[j]), st->spec_average, st->Rf[j]);      st->Yh[j] = MAC16_32_Q15(MULT16_32_Q15(SUB16(32767,st->spec_average),st->Yh[j]), st->spec_average, st->Yf[j]);#else      st->Eh[j] = (1-st->spec_average)*st->Eh[j] + st->spec_average*st->Rf[j];      st->Yh[j] = (1-st->spec_average)*st->Yh[j] + st->spec_average*st->Yf[j];#endif   }      /* Compute correlation updatete rate */   tmp32 = MULT16_32_Q15(st->beta0,Syy);   if (tmp32 > MULT16_32_Q15(st->beta_max,See))      tmp32 = MULT16_32_Q15(st->beta_max,See);   alpha = FLOAT_DIV32(tmp32, See);   alpha_1 = FLOAT_SUB(FLOAT_ONE, alpha);   /* Update correlations (recursive average) */   st->Pey = FLOAT_ADD(FLOAT_MULT(alpha_1,st->Pey) , FLOAT_MULT(alpha,Pey));   st->Pyy = FLOAT_ADD(FLOAT_MULT(alpha_1,st->Pyy) , FLOAT_MULT(alpha,Pyy));   if (FLOAT_LT(st->Pyy, FLOAT_ONE))      st->Pyy = FLOAT_ONE;   /* We don't really hope to get better than 33 dB (MIN_LEAK-3dB) attenuation anyway */   if (FLOAT_LT(st->Pey, FLOAT_MULT(MIN_LEAK,st->Pyy)))      st->Pey = FLOAT_MULT(MIN_LEAK,st->Pyy);   if (FLOAT_GT(st->Pey, st->Pyy))      st->Pey = st->Pyy;   /* leak_estimate is the limear regression result */   leak_estimate = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIVU(st->Pey, st->Pyy),14));   if (leak_estimate > 16383)      leak_estimate = 32767;   else      leak_estimate = SHL16(leak_estimate,1);   /*printf ("%f\n", leak_estimate);*/      /* Compute Residual to Error Ratio */#ifdef FIXED_POINT   tmp32 = MULT16_32_Q15(leak_estimate,Syy);   tmp32 = ADD32(tmp32, SHL32(tmp32,1));   if (tmp32 > SHR32(See,1))      tmp32 = SHR32(See,1);   RER = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIV32(tmp32,See),15));#else   RER = 3.*MULT16_32_Q15(leak_estimate,Syy) / See;   if (RER > .5)      RER = .5;#endif   /* We consider that the filter has had minimal adaptation if the following is true*/   if (!st->adapted && st->sum_adapt > QCONST32(1,15))   {      st->adapted = 1;   }   if (st->adapted)   {      for (i=0;i<=st->frame_size;i++)      {         spx_word32_t r, e;         /* Compute frequency-domain adaptation mask */         r = MULT16_32_Q15(leak_estimate,SHL32(st->Yf[i],3));         e = SHL32(st->Rf[i],3)+1;#ifdef FIXED_POINT         if (r>SHR32(e,1))            r = SHR32(e,1);#else         if (r>.5*e)            r = .5*e;#endif         r = MULT16_32_Q15(QCONST16(.8,15),r) + MULT16_32_Q15(QCONST16(.2,15),(spx_word32_t)(MULT16_32_Q15(RER,e)));         /*st->power_1[i] = adapt_rate*r/(e*(1+st->power[i]));*/         st->power_1[i] = FLOAT_SHL(FLOAT_DIV32_FLOAT(MULT16_32_Q15(M_1,r),FLOAT_MUL32U(e,st->power[i]+10)),WEIGHT_SHIFT+16);      }   } else {      spx_word32_t Sxx;      spx_word16_t adapt_rate=0;      Sxx = inner_prod(st->x+st->frame_size, st->x+st->frame_size, st->frame_size);      /* Temporary adaption rate if filter is not adapted correctly */      tmp32 = MULT16_32_Q15(QCONST16(.15f, 15), Sxx);#ifdef FIXED_POINT      if (Sxx > SHR32(See,2))         Sxx = SHR32(See,2);#else      if (Sxx > .25*See)         Sxx = .25*See;      #endif      adapt_rate = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIV32(MULT16_32_Q15(M_1,Sxx), See),15));            for (i=0;i<=st->frame_size;i++)         st->power_1[i] = FLOAT_SHL(FLOAT_DIV32(EXTEND32(adapt_rate),ADD32(st->power[i],10)),WEIGHT_SHIFT+1);      /* How much have we adapted so far? */      st->sum_adapt = ADD32(st->sum_adapt,adapt_rate);   }   /* Compute weight gradient */   for (j=0;j<M;j++)   {      weighted_spectral_mul_conj(st->power_1, &st->X[j*N], st->E, st->PHI+N*j, N);   }   /* Gradient descent */   for (i=0;i<M*N;i++)   {      st->W[i] += st->PHI[i];      /* Old value of W in PHI */      st->PHI[i] = st->W[i] - st->PHI[i];   }      /* Update weight to prevent circular convolution (MDF / AUMDF) */   for (j=0;j<M;j++)   {      /* This is a variant of the Alternatively Updated MDF (AUMDF) */      /* Remove the "if" to make this an MDF filter */      if (j==M-1 || st->cancel_count%(M-1) == j)      {#ifdef FIXED_POINT         for (i=0;i<N;i++)            st->wtmp2[i] = PSHR32(st->W[j*N+i],NORMALIZE_SCALEDOWN+16);         spx_ifft(st->fft_table, st->wtmp2, st->wtmp);         for (i=0;i<st->frame_size;i++)         {            st->wtmp[i]=0;         }         for (i=st->frame_size;i<N;i++)         {            st->wtmp[i]=SHL(st->wtmp[i],NORMALIZE_SCALEUP);         }         spx_fft(st->fft_table, st->wtmp, st->wtmp2);         /* The "-1" in the shift is a sort of kludge that trades less efficient update speed for decrease noise */         for (i=0;i<N;i++)            st->W[j*N+i] -= SHL32(st->wtmp2[i],16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1);#else         spx_ifft(st->fft_table, &st->W[j*N], st->wtmp);         for (i=st->frame_size;i<N;i++)         {            st->wtmp[i]=0;         }         spx_fft(st->fft_table, st->wtmp, &st->W[j*N]);#endif      }   }   /* Compute spectrum of estimated echo for use in an echo post-filter (if necessary)*/   if (Yout)   {      spx_word16_t leak2;      if (st->adapted)      {         /* If the filter is adapted, take the filtered echo */         for (i=0;i<st->frame_size;i++)            st->last_y[i] = st->last_y[st->frame_size+i];         for (i=0;i<st->frame_size;i++)            st->last_y[st->frame_size+i] = ref[i]-out[i];      } else {         /* If filter isn't adapted yet, all we can do is take the echo signal directly */         for (i=0;i<N;i++)            st->last_y[i] = st->x[i];      }            /* Apply hanning window (should pre-compute it)*/      for (i=0;i<N;i++)         st->y[i] = MULT16_16_Q15(st->window[i],st->last_y[i]);            /* Compute power spectrum of the echo */      spx_fft(st->fft_table, st->y, st->Y);      power_spectrum(st->Y, st->Yps, N);      #ifdef FIXED_POINT      if (leak_estimate > 16383)         leak2 = 32767;      else         leak2 = SHL16(leak_estimate, 1);#else      if (leak_estimate>.5)         leak2 = 1;      else         leak2 = 2*leak_estimate;#endif      /* Estimate residual echo */      for (i=0;i<=st->frame_size;i++)         Yout[i] = MULT16_32_Q15(leak2,st->Yps[i]);   }}int speex_echo_ctl(SpeexEchoState *st, int request, void *ptr){   switch(request)   {            case SPEEX_ECHO_GET_FRAME_SIZE:         (*(int*)ptr) = st->frame_size;         break;      case SPEEX_ECHO_SET_SAMPLING_RATE:         st->sampling_rate = (*(int*)ptr);         st->spec_average = DIV32_16(SHL32(st->frame_size, 15), st->sampling_rate);#ifdef FIXED_POINT         st->beta0 = DIV32_16(SHL32(st->frame_size, 16), st->sampling_rate);         st->beta_max = DIV32_16(SHL32(st->frame_size, 14), st->sampling_rate);#else         st->beta0 = (2.0f*st->frame_size)/st->sampling_rate;         st->beta_max = (.5f*st->frame_size)/st->sampling_rate;#endif         if (st->sampling_rate<12000)            st->notch_radius = QCONST16(.9, 15);         else if (st->sampling_rate<24000)            st->notch_radius = QCONST16(.982, 15);         else            st->notch_radius = QCONST16(.992, 15);         break;      case SPEEX_ECHO_GET_SAMPLING_RATE:         (*(int*)ptr) = st->sampling_rate;         break;      default:         speex_warning_int("Unknown speex_echo_ctl request: ", request);         return -1;   }   return 0;}

⌨️ 快捷键说明

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