[xiph-commits] r12151 - trunk/speex/libspeex

jm at svn.xiph.org jm at svn.xiph.org
Tue Nov 28 06:56:32 PST 2006


Author: jm
Date: 2006-11-28 06:56:27 -0800 (Tue, 28 Nov 2006)
New Revision: 12151

Modified:
   trunk/speex/libspeex/filters.c
   trunk/speex/libspeex/filters.h
   trunk/speex/libspeex/sb_celp.c
   trunk/speex/libspeex/sb_celp.h
Log:
Replaced fir_mem_up by qmf_synth which doesn't require intermediate
results. Saved 2.5 kB in the wideband encoder and the same in the decoder.


Modified: trunk/speex/libspeex/filters.c
===================================================================
--- trunk/speex/libspeex/filters.c	2006-11-28 14:22:55 UTC (rev 12150)
+++ trunk/speex/libspeex/filters.c	2006-11-28 14:56:27 UTC (rev 12151)
@@ -650,31 +650,119 @@
          a1 = a[j+1];
          x1 = xx[N-2+j-i];
 
-         y0 = ADD32(y0,SHR32(MULT16_16(a0, x1),2));
-         y1 = ADD32(y1,SHR32(MULT16_16(a1, x1),2));
-         y2 = ADD32(y2,SHR32(MULT16_16(a0, x0),2));
-         y3 = ADD32(y3,SHR32(MULT16_16(a1, x0),2));
+         y0 = ADD32(y0,MULT16_16(a0, x1));
+         y1 = ADD32(y1,MULT16_16(a1, x1));
+         y2 = ADD32(y2,MULT16_16(a0, x0));
+         y3 = ADD32(y3,MULT16_16(a1, x0));
 
          a0 = a[j+2];
          a1 = a[j+3];
          x0 = xx[N+j-i];
 
-         y0 = ADD32(y0,SHR32(MULT16_16(a0, x0),2));
-         y1 = ADD32(y1,SHR32(MULT16_16(a1, x0),2));
-         y2 = ADD32(y2,SHR32(MULT16_16(a0, x1),2));
-         y3 = ADD32(y3,SHR32(MULT16_16(a1, x1),2));
+         y0 = ADD32(y0,MULT16_16(a0, x0));
+         y1 = ADD32(y1,MULT16_16(a1, x0));
+         y2 = ADD32(y2,MULT16_16(a0, x1));
+         y3 = ADD32(y3,MULT16_16(a1, x1));
       }
-      y[i] = y0;
-      y[i+1] = y1;
-      y[i+2] = y2;
-      y[i+3] = y3;
+      y[i] = SHR32(y0,1);
+      y[i+1] = SHR32(y1,1);
+      y[i+2] = SHR32(y2,1);
+      y[i+3] = SHR32(y3,1);
    }
 
    for (i = 0; i < M - 1; i += 2)
       mem[i+1] = xx[i];
 }
 
+void qmf_synth(const spx_sig_t *x1, const spx_sig_t *x2, const spx_word16_t *a, spx_word16_t *y, int N, int M, spx_word32_t *mem1, spx_word32_t *mem2, char *stack)
+   /* assumptions:
+      all odd x[i] are zero -- well, actually they are left out of the array now
+      N and M are multiples of 4 */
+{
+   int i, j;
+   VARDECL(spx_word16_t *xx1);
+   VARDECL(spx_word16_t *xx2);
+   
+   ALLOC(xx1, M+N-1, spx_word16_t);
+   ALLOC(xx2, M+N-1, spx_word16_t);
+
+   for (i = 0; i < N/2; i++)
+      xx1[2*i] = PSHR32(x1[N/2-1-i],SIG_SHIFT);
+   for (i = 0; i < M - 1; i += 2)
+      xx1[N+i] = mem1[i+1];
+   for (i = 0; i < N/2; i++)
+      xx2[2*i] = PSHR32(x2[N/2-1-i],SIG_SHIFT);
+   for (i = 0; i < M - 1; i += 2)
+      xx2[N+i] = mem2[i+1];
+
+   for (i = 0; i < N; i += 4) {
+      spx_sig_t y0, y1, y2, y3;
+      spx_word16_t x10, x20;
+
+      y0 = y1 = y2 = y3 = 0;
+      x10 = xx1[N-4-i];
+      x20 = xx2[N-4-i];
+
+      for (j = 0; j < M; j += 4) {
+         spx_word16_t x11, x21;
+         spx_word16_t a0, a1;
+
+         a0 = a[j];
+         a1 = a[j+1];
+         x11 = xx1[N-2+j-i];
+         x21 = xx2[N-2+j-i];
+
 #ifdef FIXED_POINT
+         /* We multiply twice by the same coef to avoid overflows */
+         y0 = MAC16_16(MAC16_16(y0, a0, x11), NEG16(a0), x21);
+         y1 = MAC16_16(MAC16_16(y1, a1, x11), a1, x21);
+         y2 = MAC16_16(MAC16_16(y2, a0, x10), NEG16(a0), x20);
+         y3 = MAC16_16(MAC16_16(y3, a1, x10), a1, x20);
+#else
+         y0 = ADD32(y0,MULT16_16(a0, x11-x21));
+         y1 = ADD32(y1,MULT16_16(a1, x11+x21));
+         y2 = ADD32(y2,MULT16_16(a0, x10-x20));
+         y3 = ADD32(y3,MULT16_16(a1, x10+x20));
+#endif
+         a0 = a[j+2];
+         a1 = a[j+3];
+         x10 = xx1[N+j-i];
+         x20 = xx2[N+j-i];
+
+#ifdef FIXED_POINT
+         /* We multiply twice by the same coef to avoid overflows */
+         y0 = MAC16_16(MAC16_16(y0, a0, x10), NEG16(a0), x20);
+         y1 = MAC16_16(MAC16_16(y1, a1, x10), a1, x20);
+         y2 = MAC16_16(MAC16_16(y2, a0, x11), NEG16(a0), x21);
+         y3 = MAC16_16(MAC16_16(y3, a1, x11), a1, x21);
+#else
+         y0 = ADD32(y0,MULT16_16(a0, x10-x20));
+         y1 = ADD32(y1,MULT16_16(a1, x10+x20));
+         y2 = ADD32(y2,MULT16_16(a0, x11-x21));
+         y3 = ADD32(y3,MULT16_16(a1, x11+x21));
+#endif
+      }
+#ifdef FIXED_POINT
+      y[i] = EXTRACT16(SATURATE32(PSHR32(y0,15),32767));
+      y[i+1] = EXTRACT16(SATURATE32(PSHR32(y1,15),32767));
+      y[i+2] = EXTRACT16(SATURATE32(PSHR32(y2,15),32767));
+      y[i+3] = EXTRACT16(SATURATE32(PSHR32(y3,15),32767));
+#else
+      /* Normalize up explicitly if we're in float */
+      y[i] = 2.*y0;
+      y[i+1] = 2.*y1;
+      y[i+2] = 2.*y2;
+      y[i+3] = 2.*y3;
+#endif
+   }
+
+   for (i = 0; i < M - 1; i += 2)
+      mem1[i+1] = xx1[i];
+   for (i = 0; i < M - 1; i += 2)
+      mem2[i+1] = xx2[i];
+}
+
+#ifdef FIXED_POINT
 #if 0
 const spx_word16_t shift_filt[3][7] = {{-33,    1043,   -4551,   19959,   19959,   -4551,    1043},
                                  {-98,    1133,   -4425,   29179,    8895,   -2328,     444},

Modified: trunk/speex/libspeex/filters.h
===================================================================
--- trunk/speex/libspeex/filters.h	2006-11-28 14:22:55 UTC (rev 12150)
+++ trunk/speex/libspeex/filters.h	2006-11-28 14:56:27 UTC (rev 12151)
@@ -60,8 +60,8 @@
 
 void qmf_decomp(const spx_word16_t *xx, const spx_word16_t *aa, spx_sig_t *, spx_sig_t *y2, int N, int M, spx_word16_t *mem, char *stack);
 void fir_mem_up(const spx_sig_t *x, const spx_word16_t *a, spx_sig_t *y, int N, int M, spx_word32_t *mem, char *stack);
+void qmf_synth(const spx_sig_t *x1, const spx_sig_t *x2, const spx_word16_t *a, spx_word16_t *y, int N, int M, spx_word32_t *mem1, spx_word32_t *mem2, char *stack);
 
-
 void filter_mem2(const spx_sig_t *x, const spx_coef_t *num, const spx_coef_t *den, spx_sig_t *y, int N, int ord, spx_mem_t *mem);
 void fir_mem2(const spx_sig_t *x, const spx_coef_t *num, spx_sig_t *y, int N, int ord, spx_mem_t *mem);
 void iir_mem2(const spx_sig_t *x, const spx_coef_t *den, spx_sig_t *y, int N, int ord, spx_mem_t *mem);

Modified: trunk/speex/libspeex/sb_celp.c
===================================================================
--- trunk/speex/libspeex/sb_celp.c	2006-11-28 14:22:55 UTC (rev 12150)
+++ trunk/speex/libspeex/sb_celp.c	2006-11-28 14:56:27 UTC (rev 12151)
@@ -203,25 +203,6 @@
 
 extern const spx_word16_t lpc_window[];
 
-static void mix_and_saturate(spx_word32_t *x0, spx_word32_t *x1, spx_word16_t *out, int len)
-{
-   int i;
-   for (i=0;i<len;i++)
-   {
-      spx_word32_t tmp;
-#ifdef FIXED_POINT
-      tmp=PSHR32(SUB32(x0[i],x1[i]),SIG_SHIFT-1);
-#else
-      tmp=2*(x0[i]-x1[i]);
-#endif
-      if (tmp>32767)
-         out[i] = 32767;
-      else if (tmp<-32767)
-         out[i] = -32767;
-      else
-         out[i] = EXTRACT16(tmp);
-   }
-}
 
 void *sb_encoder_init(const SpeexMode *m)
 {
@@ -269,8 +250,6 @@
    st->x0d=(spx_sig_t*)speex_alloc((st->frame_size)*sizeof(spx_sig_t));
    st->x1d=(spx_sig_t*)speex_alloc((st->frame_size)*sizeof(spx_sig_t));
    st->high=(spx_sig_t*)speex_alloc((st->full_frame_size)*sizeof(spx_sig_t));
-   st->y0=(spx_sig_t*)speex_alloc((st->full_frame_size)*sizeof(spx_sig_t));
-   st->y1=(spx_sig_t*)speex_alloc((st->full_frame_size)*sizeof(spx_sig_t));
 
    st->h0_mem=(spx_word16_t*)speex_alloc((QMF_ORDER)*sizeof(spx_word16_t));
    st->h1_mem=(spx_word16_t*)speex_alloc((QMF_ORDER)*sizeof(spx_word16_t));
@@ -338,8 +317,6 @@
    speex_free(st->x0d);
    speex_free(st->x1d);
    speex_free(st->high);
-   speex_free(st->y0);
-   speex_free(st->y1);
 
    speex_free(st->h0_mem);
    speex_free(st->h1_mem);
@@ -569,11 +546,7 @@
 
 #ifdef RESYNTH
       /* Reconstruct the original */
-      fir_mem_up(st->x0d, h0, st->y0, st->full_frame_size, QMF_ORDER, st->g0_mem, stack);
-      fir_mem_up(st->high, h1, st->y1, st->full_frame_size, QMF_ORDER, st->g1_mem, stack);
-
-      for (i=0;i<st->full_frame_size;i++)
-         in[i]=SHR(st->y0[i]-st->y1[i], SIG_SHIFT-1);
+      qmf_synth(st->x0d, st->high, h0, in, st->full_frame_size, QMF_ORDER, st->g0_mem, st->g1_mem, stack);
 #endif
 
       if (dtx)
@@ -815,11 +788,7 @@
 
 #ifdef RESYNTH
    /* Reconstruct the original */
-   fir_mem_up(st->x0d, h0, st->y0, st->full_frame_size, QMF_ORDER, st->g0_mem, stack);
-   fir_mem_up(st->high, h1, st->y1, st->full_frame_size, QMF_ORDER, st->g1_mem, stack);
-
-   for (i=0;i<st->full_frame_size;i++)
-      in[i]=SHR(st->y0[i]-st->y1[i], SIG_SHIFT-1);
+   qmf_synth(st->x0d, st->high, h0, in, st->full_frame_size, QMF_ORDER, st->g0_mem, st->g1_mem, stack);
 #endif
    for (i=0;i<st->lpcSize;i++)
       st->old_lsp[i] = st->lsp[i];
@@ -876,8 +845,6 @@
    st->x0d = (spx_sig_t*)speex_alloc((st->frame_size)*sizeof(spx_sig_t));
    st->x1d = (spx_sig_t*)speex_alloc((st->frame_size)*sizeof(spx_sig_t));
    st->high = (spx_sig_t*)speex_alloc((st->full_frame_size)*sizeof(spx_sig_t));
-   st->y0 = (spx_sig_t*)speex_alloc((st->full_frame_size)*sizeof(spx_sig_t));
-   st->y1 = (spx_sig_t*)speex_alloc((st->full_frame_size)*sizeof(spx_sig_t));
 
    st->g0_mem = (spx_word32_t*)speex_alloc((QMF_ORDER)*sizeof(spx_word32_t));
    st->g1_mem = (spx_word32_t*)speex_alloc((QMF_ORDER)*sizeof(spx_word32_t));
@@ -919,8 +886,6 @@
    speex_free(st->x0d);
    speex_free(st->x1d);
    speex_free(st->high);
-   speex_free(st->y0);
-   speex_free(st->y1);
    speex_free(st->g0_mem);
    speex_free(st->g1_mem);
    speex_free(st->exc);
@@ -969,11 +934,7 @@
    
    
    /* Reconstruct the original */
-   fir_mem_up(st->x0d, h0, st->y0, st->full_frame_size, QMF_ORDER, st->g0_mem, stack);
-   fir_mem_up(st->high, h1, st->y1, st->full_frame_size, QMF_ORDER, st->g1_mem, stack);
-
-   mix_and_saturate(st->y0, st->y1, out, st->full_frame_size);
-
+   qmf_synth(st->x0d, st->high, h0, out, st->full_frame_size, QMF_ORDER, st->g0_mem, st->g1_mem, stack);
    if (dtx)
    {
       st->submodeID=saved_modeid;
@@ -1067,11 +1028,8 @@
       /* Final signal synthesis from excitation */
       iir_mem2(st->exc, st->interp_qlpc, st->high, st->frame_size, st->lpcSize, st->mem_sp);
 
-      fir_mem_up(st->x0d, h0, st->y0, st->full_frame_size, QMF_ORDER, st->g0_mem, stack);
-      fir_mem_up(st->high, h1, st->y1, st->full_frame_size, QMF_ORDER, st->g1_mem, stack);
+      qmf_synth(st->x0d, st->high, h0, out, st->full_frame_size, QMF_ORDER, st->g0_mem, st->g1_mem, stack);
 
-      mix_and_saturate(st->y0, st->y1, out, st->full_frame_size);
-
       return 0;
 
    }
@@ -1236,11 +1194,7 @@
 
    }
 
-   fir_mem_up(st->x0d, h0, st->y0, st->full_frame_size, QMF_ORDER, st->g0_mem, stack);
-   fir_mem_up(st->high, h1, st->y1, st->full_frame_size, QMF_ORDER, st->g1_mem, stack);
-
-   mix_and_saturate(st->y0, st->y1, out, st->full_frame_size);
-
+   qmf_synth(st->x0d, st->high, h0, out, st->full_frame_size, QMF_ORDER, st->g0_mem, st->g1_mem, stack);
    for (i=0;i<st->lpcSize;i++)
       st->old_qlsp[i] = st->qlsp[i];
 

Modified: trunk/speex/libspeex/sb_celp.h
===================================================================
--- trunk/speex/libspeex/sb_celp.h	2006-11-28 14:22:55 UTC (rev 12150)
+++ trunk/speex/libspeex/sb_celp.h	2006-11-28 14:56:27 UTC (rev 12151)
@@ -60,7 +60,6 @@
    char  *stack;                  /**< Temporary allocation stack */
    spx_sig_t *x0d, *x1d;          /**< QMF filter signals*/
    spx_sig_t *high;               /**< High-band signal (buffer) */
-   spx_sig_t *y0, *y1;            /**< QMF synthesis signals */
    spx_word16_t *h0_mem, *h1_mem;
    spx_word32_t *g0_mem, *g1_mem; /**< QMF memories */
 
@@ -127,7 +126,6 @@
    char  *stack;
    spx_sig_t *x0d, *x1d;
    spx_sig_t *high;
-   spx_sig_t *y0, *y1;
    spx_word32_t *g0_mem, *g1_mem;
 
    spx_sig_t *exc;



More information about the commits mailing list