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

📄 mdf.c

📁 mediastreamer2是开源的网络传输媒体流的库
💻 C
📖 第 1 页 / 共 3 页
字号:
                  st->W[chan*N*K*M + j*N*K + speak*N + i] -= SHL32(EXTEND32(st->wtmp2[i]),16+NORMALIZE_SCALEDOWN-NORMALIZE_SCALEUP-1);#else               spx_ifft(st->fft_table, &st->W[chan*N*K*M + j*N*K + speak*N], st->wtmp);               for (i=st->frame_size;i<N;i++)               {                  st->wtmp[i]=0;               }               spx_fft(st->fft_table, st->wtmp, &st->W[chan*N*K*M + j*N*K + speak*N]);#endif            }         }      }   }      /* So we can use power_spectrum_accum */    for (i=0;i<=st->frame_size;i++)      st->Rf[i] = st->Yf[i] = st->Xf[i] = 0;         Dbf = 0;   See = 0;    #ifdef TWO_PATH   /* Difference in response, this is used to estimate the variance of our residual power estimate */   for (chan = 0; chan < C; chan++)   {      spectral_mul_accum(st->X, st->W+chan*N*K*M, st->Y+chan*N, N, M*K);      spx_ifft(st->fft_table, st->Y+chan*N, st->y+chan*N);      for (i=0;i<st->frame_size;i++)         st->e[chan*N+i] = SUB16(st->e[chan*N+i+st->frame_size], st->y[chan*N+i+st->frame_size]);      Dbf += 10+mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size);      for (i=0;i<st->frame_size;i++)         st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]);      See += mdf_inner_prod(st->e+chan*N, st->e+chan*N, st->frame_size);   }#endif#ifndef TWO_PATH   Sff = See;#endif#ifdef TWO_PATH   /* Logic for updating the foreground filter */      /* For two time windows, compute the mean of the energy difference, as well as the variance */   st->Davg1 = ADD32(MULT16_32_Q15(QCONST16(.6f,15),st->Davg1), MULT16_32_Q15(QCONST16(.4f,15),SUB32(Sff,See)));   st->Davg2 = ADD32(MULT16_32_Q15(QCONST16(.85f,15),st->Davg2), MULT16_32_Q15(QCONST16(.15f,15),SUB32(Sff,See)));   st->Dvar1 = FLOAT_ADD(FLOAT_MULT(VAR1_SMOOTH, st->Dvar1), FLOAT_MUL32U(MULT16_32_Q15(QCONST16(.4f,15),Sff), MULT16_32_Q15(QCONST16(.4f,15),Dbf)));   st->Dvar2 = FLOAT_ADD(FLOAT_MULT(VAR2_SMOOTH, st->Dvar2), FLOAT_MUL32U(MULT16_32_Q15(QCONST16(.15f,15),Sff), MULT16_32_Q15(QCONST16(.15f,15),Dbf)));      /* Equivalent float code:   st->Davg1 = .6*st->Davg1 + .4*(Sff-See);   st->Davg2 = .85*st->Davg2 + .15*(Sff-See);   st->Dvar1 = .36*st->Dvar1 + .16*Sff*Dbf;   st->Dvar2 = .7225*st->Dvar2 + .0225*Sff*Dbf;   */      update_foreground = 0;   /* Check if we have a statistically significant reduction in the residual echo */   /* Note that this is *not* Gaussian, so we need to be careful about the longer tail */   if (FLOAT_GT(FLOAT_MUL32U(SUB32(Sff,See),ABS32(SUB32(Sff,See))), FLOAT_MUL32U(Sff,Dbf)))      update_foreground = 1;   else if (FLOAT_GT(FLOAT_MUL32U(st->Davg1, ABS32(st->Davg1)), FLOAT_MULT(VAR1_UPDATE,(st->Dvar1))))      update_foreground = 1;   else if (FLOAT_GT(FLOAT_MUL32U(st->Davg2, ABS32(st->Davg2)), FLOAT_MULT(VAR2_UPDATE,(st->Dvar2))))      update_foreground = 1;      /* Do we update? */   if (update_foreground)   {      st->Davg1 = st->Davg2 = 0;      st->Dvar1 = st->Dvar2 = FLOAT_ZERO;      /* Copy background filter to foreground filter */      for (i=0;i<N*M*C*K;i++)         st->foreground[i] = EXTRACT16(PSHR32(st->W[i],16));      /* Apply a smooth transition so as to not introduce blocking artifacts */      for (chan = 0; chan < C; chan++)         for (i=0;i<st->frame_size;i++)            st->e[chan*N+i+st->frame_size] = MULT16_16_Q15(st->window[i+st->frame_size],st->e[chan*N+i+st->frame_size]) + MULT16_16_Q15(st->window[i],st->y[chan*N+i+st->frame_size]);   } else {      int reset_background=0;      /* Otherwise, check if the background filter is significantly worse */      if (FLOAT_GT(FLOAT_MUL32U(NEG32(SUB32(Sff,See)),ABS32(SUB32(Sff,See))), FLOAT_MULT(VAR_BACKTRACK,FLOAT_MUL32U(Sff,Dbf))))         reset_background = 1;      if (FLOAT_GT(FLOAT_MUL32U(NEG32(st->Davg1), ABS32(st->Davg1)), FLOAT_MULT(VAR_BACKTRACK,st->Dvar1)))         reset_background = 1;      if (FLOAT_GT(FLOAT_MUL32U(NEG32(st->Davg2), ABS32(st->Davg2)), FLOAT_MULT(VAR_BACKTRACK,st->Dvar2)))         reset_background = 1;      if (reset_background)      {         /* Copy foreground filter to background filter */         for (i=0;i<N*M*C*K;i++)            st->W[i] = SHL32(EXTEND32(st->foreground[i]),16);         /* We also need to copy the output so as to get correct adaptation */         for (chan = 0; chan < C; chan++)         {                    for (i=0;i<st->frame_size;i++)               st->y[chan*N+i+st->frame_size] = st->e[chan*N+i+st->frame_size];            for (i=0;i<st->frame_size;i++)               st->e[chan*N+i] = SUB16(st->input[chan*st->frame_size+i], st->y[chan*N+i+st->frame_size]);         }                 See = Sff;         st->Davg1 = st->Davg2 = 0;         st->Dvar1 = st->Dvar2 = FLOAT_ZERO;      }   }#endif   Sey = Syy = Sdd = 0;     for (chan = 0; chan < C; chan++)   {          /* Compute error signal (for the output with de-emphasis) */       for (i=0;i<st->frame_size;i++)      {         spx_word32_t tmp_out;#ifdef TWO_PATH         tmp_out = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(st->e[chan*N+i+st->frame_size]));#else         tmp_out = SUB32(EXTEND32(st->input[chan*st->frame_size+i]), EXTEND32(st->y[chan*N+i+st->frame_size]));#endif         tmp_out = ADD32(tmp_out, EXTEND32(MULT16_16_P15(st->preemph, st->memE[chan])));      /* This is an arbitrary test for saturation in the microphone signal */         if (in[i*C+chan] <= -32000 || in[i*C+chan] >= 32000)         {         if (st->saturated == 0)            st->saturated = 1;         }         out[i*C+chan] = WORD2INT(tmp_out);         st->memE[chan] = tmp_out;      }#ifdef DUMP_ECHO_CANCEL_DATA      dump_audio(in, far_end, out, st->frame_size);#endif         /* Compute error signal (filter update version) */       for (i=0;i<st->frame_size;i++)      {         st->e[chan*N+i+st->frame_size] = st->e[chan*N+i];         st->e[chan*N+i] = 0;      }            /* Compute a bunch of correlations */      /* FIXME: bad merge */      Sey += mdf_inner_prod(st->e+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size);      Syy += mdf_inner_prod(st->y+chan*N+st->frame_size, st->y+chan*N+st->frame_size, st->frame_size);      Sdd += mdf_inner_prod(st->input+chan*st->frame_size, st->input+chan*st->frame_size, st->frame_size);            /* Convert error to frequency domain */      spx_fft(st->fft_table, st->e+chan*N, st->E+chan*N);      for (i=0;i<st->frame_size;i++)         st->y[i+chan*N] = 0;      spx_fft(st->fft_table, st->y+chan*N, st->Y+chan*N);         /* Compute power spectrum of echo (X), error (E) and filter response (Y) */      power_spectrum_accum(st->E+chan*N, st->Rf, N);      power_spectrum_accum(st->Y+chan*N, st->Yf, N);       }      /*printf ("%f %f %f %f\n", Sff, See, Syy, Sdd, st->update_cond);*/      /* Do some sanity check */   if (!(Syy>=0 && Sxx>=0 && See >= 0)#ifndef FIXED_POINT       || !(Sff < N*1e9 && Syy < N*1e9 && Sxx < N*1e9)#endif      )   {      /* Things have gone really bad */      st->screwed_up += 50;      for (i=0;i<st->frame_size*C;i++)         out[i] = 0;   } else if (SHR32(Sff, 2) > ADD32(Sdd, SHR32(MULT16_16(N, 10000),6)))   {      /* AEC seems to add lots of echo instead of removing it, let's see if it will improve */      st->screwed_up++;   } else {      /* Everything's fine */      st->screwed_up=0;   }   if (st->screwed_up>=50)   {      speex_warning("The echo canceller started acting funny and got slapped (reset). It swears it will behave now.");      speex_echo_state_reset(st);      return;   }   /* Add a small noise floor to make sure not to have problems when dividing */   See = MAX32(See, SHR32(MULT16_16(N, 100),6));        for (speak = 0; speak < K; speak++)   {      Sxx += mdf_inner_prod(st->x+speak*N+st->frame_size, st->x+speak*N+st->frame_size, st->frame_size);      power_spectrum_accum(st->X+speak*N, st->Xf, N);   }      /* Smooth far end 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]);   /* 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   }      Pyy = FLOAT_SQRT(Pyy);   Pey = FLOAT_DIVU(Pey,Pyy);   /* 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 linear regression result */   st->leak_estimate = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIVU(st->Pey, st->Pyy),14));   /* This looks like a stupid bug, but it's right (because we convert from Q14 to Q15) */   if (st->leak_estimate > 16383)      st->leak_estimate = 32767;   else      st->leak_estimate = SHL16(st->leak_estimate,1);   /*printf ("%f\n", st->leak_estimate);*/      /* Compute Residual to Error Ratio */#ifdef FIXED_POINT   tmp32 = MULT16_32_Q15(st->leak_estimate,Syy);   tmp32 = ADD32(SHR32(Sxx,13), ADD32(tmp32, SHL32(tmp32,1)));   /* Check for y in e (lower bound on RER) */   {      spx_float_t bound = PSEUDOFLOAT(Sey);      bound = FLOAT_DIVU(FLOAT_MULT(bound, bound), PSEUDOFLOAT(ADD32(1,Syy)));      if (FLOAT_GT(bound, PSEUDOFLOAT(See)))         tmp32 = See;      else if (tmp32 < FLOAT_EXTRACT32(bound))         tmp32 = FLOAT_EXTRACT32(bound);   }   if (tmp32 > SHR32(See,1))      tmp32 = SHR32(See,1);   RER = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIV32(tmp32,See),15));#else   RER = (.0001*Sxx + 3.*MULT16_32_Q15(st->leak_estimate,Syy)) / See;   /* Check for y in e (lower bound on RER) */   if (RER < Sey*Sey/(1+See*Syy))      RER = Sey*Sey/(1+See*Syy);   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 > SHL32(EXTEND32(M),15) && MULT16_32_Q15(st->leak_estimate,Syy) > MULT16_32_Q15(QCONST16(.03f,15),Syy))   {      st->adapted = 1;   }   if (st->adapted)   {      /* Normal learning rate calculation once we're past the minimal adaptation phase */      for (i=0;i<=st->frame_size;i++)      {         spx_word32_t r, e;         /* Compute frequency-domain adaptation mask */         r = MULT16_32_Q15(st->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(.7,15),r) + MULT16_32_Q15(QCONST16(.3,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(r,FLOAT_MUL32U(e,st->power[i]+10)),WEIGHT_SHIFT+16);      }   } else {      /* Temporary adaption rate if filter is not yet adapted enough */      spx_word16_t adapt_rate=0;      if (Sxx > SHR32(MULT16_16(N, 1000),6))       {         tmp32 = MULT16_32_Q15(QCONST16(.25f, 15), Sxx);#ifdef FIXED_POINT         if (tmp32 > SHR32(See,2))            tmp32 = SHR32(See,2);#else         if (tmp32 > .25*See)            tmp32 = .25*See;#endif         adapt_rate = FLOAT_EXTRACT16(FLOAT_SHL(FLOAT_DIV32(tmp32, 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);   }   /* FIXME: MC conversion required */       for (i=0;i<st->frame_size;i++)         st->last_y[i] = st->last_y[st->frame_size+i];   if (st->adapted)   {      /* If the filter is adapted, take the filtered echo */      for (i=0;i<st->frame_size;i++)         st->last_y[st->frame_size+i] = in[i]-out[i];   } else {      /* If filter isn't adapted yet, all we can do is take the far end signal directly */      /* moved earlier: for (i=0;i<N;i++)      st->last_y[i] = st->x[i];*/   }}/* Compute spectrum of estimated echo for use in an echo post-filter */void speex_echo_get_residual(SpeexEchoState *st, spx_word32_t *residual_echo, int len){   int i;   spx_word16_t leak2;   int N;      N = st->window_size;   /* 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, residual_echo, N);      #ifdef FIXED_POINT   if (st->leak_estimate > 16383)      leak2 = 32767;   else      leak2 = SHL16(st->leak_estimate, 1);#else   if (st->leak_estimate>.5)      leak2 = 1;   else      leak2 = 2*st->leak_estimate;#endif   /* Estimate residual echo */   for (i=0;i<=st->frame_size;i++)      residual_echo[i] = (spx_int32_t)MULT16_32_Q15(leak2,residual_echo[i]);   }EXPORT 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(EXTEND32(st->frame_size), 15), st->sampling_rate);#ifdef FIXED_POINT         st->beta0 = DIV32_16(SHL32(EXTEND32(st->frame_size), 16), st->sampling_rate);         st->beta_max = DIV32_16(SHL32(EXTEND32(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;      case SPEEX_ECHO_GET_IMPULSE_RESPONSE_SIZE:         /*FIXME: Implement this for multiple channels */         *((spx_int32_t *)ptr) = st->M * st->frame_size;         break;      case SPEEX_ECHO_GET_IMPULSE_RESPONSE:      {         int M = st->M, N = st->window_size, n = st->frame_size, i, j;         spx_int32_t *filt = (spx_int32_t *) ptr;         for(j=0;j<M;j++)         {            /*FIXME: Implement this for multiple channels */#ifdef FIXED_POINT            for (i=0;i<N;i++)               st->wtmp2[i] = EXTRACT16(PSHR32(st->W[j*N+i],16+NORMALIZE_SCALEDOWN));            spx_ifft(st->fft_table, st->wtmp2, st->wtmp);#else            spx_ifft(st->fft_table, &st->W[j*N], st->wtmp);#endif            for(i=0;i<n;i++)               filt[j*n+i] = PSHR32(MULT16_16(32767,st->wtmp[i]), WEIGHT_SHIFT-NORMALIZE_SCALEDOWN);         }      }         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 + -