[xiph-cvs] cvs commit: speex/libspeex mdf.c speex_echo.h

Jean-Marc Valin jm at xiph.org
Mon Aug 18 20:59:27 PDT 2003



jm          03/08/18 23:59:27

  Modified:    libspeex mdf.c speex_echo.h
  Log:
  added normalization. Should be roughly equivalent to NLMS.

Revision  Changes    Path
1.2       +69 -10    speex/libspeex/mdf.c

Index: mdf.c
===================================================================
RCS file: /usr/local/cvsroot/speex/libspeex/mdf.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- mdf.c	18 Aug 2003 21:52:14 -0000	1.1
+++ mdf.c	19 Aug 2003 03:59:27 -0000	1.2
@@ -45,6 +45,7 @@
    st->window_size = 2*frame_size;
    N = st->window_size;
    M = st->M = (filter_length+N-1)/frame_size;
+   st->cancel_count=0;
 
    drft_init(&st->fft_lookup, N);
    
@@ -56,7 +57,8 @@
    st->E = (float*)speex_alloc(N*sizeof(float));
    st->W = (float*)speex_alloc(M*N*sizeof(float));
    st->PHI = (float*)speex_alloc(N*sizeof(float));
-
+   st->power = (float*)speex_alloc((frame_size+1)*sizeof(float));
+   st->power_1 = (float*)speex_alloc((frame_size+1)*sizeof(float));
    return st;
 }
 
@@ -68,13 +70,14 @@
 /** Performs echo cancellation a frame */
 void speex_echo_cancel(SpeexEchoState *st, float *ref, float *echo, float *out, float *Yout)
 {
-   int i,j;
+   int i,j,m;
    int N,M;
    float scale;
 
    N = st->window_size;
    M = st->M;
    scale = 1.0/N;
+   st->cancel_count++;
 
    for (i=0;i<st->frame_size;i++)
    {
@@ -91,6 +94,7 @@
 
    drft_forward(&st->fft_lookup, &st->X[(M-1)*N]);
 
+   /* Compute filter response Y */
    for (i=1;i<N-1;i+=2)
    {
       st->Y[i] = st->Y[i+1] = 0;
@@ -101,6 +105,11 @@
       }
    }
    st->Y[0] = st->Y[N-1] = 0;
+   for (j=0;j<M;j++)
+   {
+      st->Y[0] += st->X[j*N]*st->W[j*N];
+      st->Y[N-1] += st->X[(j+1)*N-1]*st->W[(j+1)*N-1];
+   }
 
    if (Yout)
       for (i=0;i<N;i++)
@@ -109,15 +118,12 @@
    for (i=0;i<N;i++)
       st->y[i] = st->Y[i];
    
-#if 0
-   for (i=0;i<N;i++)
-      st->y[i] = st->X[(M-1)*N+i];
-#endif
-
+   /* Filter response in time domain */
    drft_backward(&st->fft_lookup, st->y);
    for (i=0;i<N;i++)
       st->y[i] *= scale;
 
+   /* Compute error signal (echo canceller output) */
    for (i=0;i<st->frame_size;i++)
    {
       out[i] = ref[i] - st->y[i+st->frame_size];
@@ -127,6 +133,52 @@
 
    drft_forward(&st->fft_lookup, st->E);
 
+
+   /* Compute input power in each band */
+   {
+      float s;
+      float tmp, tmp2;
+
+      if (st->cancel_count<M)
+         s = 1.0/st->cancel_count;
+      else
+         s = 1.0/M;
+      
+      for (i=1,j=1;i<N-1;i+=2,j++)
+      {
+         tmp=0;
+         for (m=0;m<M;m++)
+         {
+            tmp += st->X[m*N+i]*st->X[m*N+i] + st->X[m*N+i+1]*st->X[m*N+i+1];
+         }
+         tmp *= s;
+         if (st->cancel_count<M)
+            st->power[j] = tmp;
+         else
+            st->power[j] = .8*st->power[j] + .2*tmp;
+      }
+      tmp=tmp2=0;
+      for (m=0;m<M;m++)
+      {
+         tmp += st->X[m*N]*st->X[m*N];
+         tmp2 += st->X[(m+1)*N-1]*st->X[(m+1)*N-1];
+      }
+      tmp *= s;
+      tmp2 *= s;
+      if (st->cancel_count<M)
+      {
+         st->power[0] = tmp;
+         st->power[st->frame_size] = tmp2;
+      } else {
+         st->power[0] = .8*st->power[0] + .2*tmp;
+         st->power[st->frame_size] = .8*st->power[st->frame_size] + .2*tmp2;
+      }
+      
+      for (i=0;i<=st->frame_size;i++)
+         st->power_1[i] = 1.0/(1e-10+st->power[i]);
+   }
+
+   /* Update filter weights */
    for (j=0;j<M;j++)
    {
       for (i=1;i<N-1;i+=2)
@@ -134,12 +186,19 @@
          st->PHI[i] = st->X[j*N+i]*st->E[i] + st->X[j*N+i+1]*st->E[i+1];
          st->PHI[i+1] = -st->X[j*N+i+1]*st->E[i] + st->X[j*N+i]*st->E[i+1];
       }
-      st->PHI[0] = st->PHI[N-1] = 0;
+      st->PHI[0] = st->X[j*N]*st->E[0];
+      st->PHI[N-1] = st->X[(j+1)*N-1]*st->E[N-1];
 
       /* Optionally perform some transform (normalization?) on PHI */
       
-      for (i=0;i<N;i++)
-         st->W[j*N+i] += .002*st->PHI[i];
+      for (i=1,m=1;i<N-1;i+=2,m++)
+         st->W[j*N+i] += .1*st->PHI[i]*st->power_1[m];
+      st->W[j*N] += .1*st->PHI[0]*st->power_1[0];
+      st->W[(j+1)*N-1] += .1*st->PHI[N-1]*st->power_1[st->frame_size];
+      /*
+      for (i=0,j=0;i<=N;i++,j++)
+         st->W[j*N+i] += .001*st->PHI[i];
+      */
    }
 }
 

<p><p>1.2       +4 -1      speex/libspeex/speex_echo.h

Index: speex_echo.h
===================================================================
RCS file: /usr/local/cvsroot/speex/libspeex/speex_echo.h,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- speex_echo.h	18 Aug 2003 21:52:14 -0000	1.1
+++ speex_echo.h	19 Aug 2003 03:59:27 -0000	1.2
@@ -36,6 +36,7 @@
    int frame_size;           /**< Number of samples processed each time */
    int window_size;
    int M;
+   int cancel_count;
 
    float *x;
    float *X;
@@ -44,7 +45,9 @@
    float *E;
    float *PHI;
    float *W;
-
+   float *power;
+   float *power_1;
+   
    drft_lookup fft_lookup;
 
 

<p><p>--- >8 ----
List archives:  http://www.xiph.org/archives/
Ogg project homepage: http://www.xiph.org/ogg/
To unsubscribe from this list, send a message to 'cvs-request at xiph.org'
containing only the word 'unsubscribe' in the body.  No subject is needed.
Unsubscribe messages sent to the list will be ignored/filtered.



More information about the commits mailing list