More cleanup in codebook search...
authorjmvalin <jmvalin@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Thu, 14 Mar 2002 07:08:48 +0000 (07:08 +0000)
committerjmvalin <jmvalin@0101bb08-14d6-0310-b084-bc0e0c8e3800>
Thu, 14 Mar 2002 07:08:48 +0000 (07:08 +0000)
git-svn-id: http://svn.xiph.org/trunk/speex@3142 0101bb08-14d6-0310-b084-bc0e0c8e3800

libspeex/Makefile.am
libspeex/cb_search.c
libspeex/cb_search.h
libspeex/speex.c
libspeex/vq.c [new file with mode: 0644]
libspeex/vq.h [new file with mode: 0644]

index e393e00..00db952 100644 (file)
@@ -1,6 +1,6 @@
 ## Process this file with automake to produce Makefile.in. -*-Makefile-*-
 
-# $Id: Makefile.am,v 1.10 2002/03/13 18:28:09 jmvalin Exp $
+# $Id: Makefile.am,v 1.11 2002/03/14 07:08:48 jmvalin Exp $
 
 # Disable automatic dependency tracking if using other tools than gcc and gmake
 #AUTOMAKE_OPTIONS = no-dependencies
@@ -21,7 +21,8 @@ libspeex_la_SOURCES = speex.c \
        bits.c \
        modes.c \
        exc_table.c \
-       exc_gains_table.c
+       exc_gains_table.c \
+       vq.c
 
 include_HEADERS = speex.h \
        bits.h \
@@ -33,7 +34,8 @@ noinst_HEADERS = lsp.h \
        quant_lsp.h \
        cb_search.h \
        filters.h \
-       stack_alloc.h
+       stack_alloc.h \
+       vq.h
        
        
 libspeex_la_LDFLAGS = -release $(LT_RELEASE)
index 47d9641..1c52137 100644 (file)
 #include "filters.h"
 #include <math.h>
 #include <stdio.h>
+#include "stack_alloc.h"
+#include "vq.h"
 
 #define EXC_CB_SIZE 128
 #define min(a,b) ((a) < (b) ? (a) : (b))
-extern float exc_gains_table[128][5];
+extern float exc_gains_table[];
+extern float exc_table[];
 
 /*---------------------------------------------------------------------------*\
                                                                              
@@ -128,7 +131,14 @@ int   nsf                       /* number of samples in subframe */
 }
 
 
-
+split_cb_params split_cb_nb = {
+   8,               /*subvect_size*/
+   5,               /*nb_subvect*/
+   exc_table,       /*shape_cb*/
+   7,               /*shape_bits*/
+   exc_gains_table, /*gain_cb*/
+   8                /*gain_bits*/
+};
 
 
 void split_cb_search(
@@ -136,43 +146,63 @@ float target[],                   /* target vector */
 float ak[],                    /* LPCs for this subframe */
 float awk1[],                  /* Weighted LPCs for this subframe */
 float awk2[],                  /* Weighted LPCs for this subframe */
-float codebook[][8],           /* non-overlapping codebook */
-int   entries,                 /* number of entries to search */
-float *gain,                   /* gain of optimum entries */
-int   *index,                  /* index of optimum entries */
+void *par,                      /* Codebook/search parameters*/
 int   p,                        /* number of LPC coeffs */
 int   nsf,                      /* number of samples in subframe */
 float *exc,
-FrameBits *bits
+FrameBits *bits,
+float *stack
 )
 {
    int i,j;
-   float resp[EXC_CB_SIZE][8], E[EXC_CB_SIZE], Ee[EXC_CB_SIZE];
-   float t[40], r[40], e[40];
-   float gains[5];
-   int ind[5];
-   for (i=0;i<40;i++)
+   float *resp, *E, *Ee;
+   float *t, *r, *e;
+   float *gains;
+   int *ind;
+   float *shape_cb, *gain_cb;
+   int shape_cb_size, gain_cb_size, subvect_size, nb_subvect;
+   split_cb_params *params;
+
+   params = (split_cb_params *) par;
+   subvect_size = params->subvect_size;
+   nb_subvect = params->nb_subvect;
+   shape_cb_size = 1<<params->shape_bits;
+   shape_cb = params->shape_cb;
+   gain_cb_size = 1<<params->gain_bits;
+   gain_cb = params->gain_cb;
+   resp = PUSH(stack, shape_cb_size*8);
+   E = PUSH(stack, shape_cb_size);
+   Ee = PUSH(stack, shape_cb_size);
+   t = PUSH(stack, nsf);
+   r = PUSH(stack, nsf);
+   e = PUSH(stack, nsf);
+   gains = PUSH(stack, nb_subvect);
+   ind = (int*)PUSH(stack, nb_subvect);
+   
+
+   for (i=0;i<nsf;i++)
       t[i]=target[i];
-   for (i=0;i<EXC_CB_SIZE;i++)
+   for (i=0;i<shape_cb_size;i++)
    {
-      residue_zero(codebook[i], awk1, resp[i], 8, p);
-      syn_filt_zero(resp[i], ak, resp[i], 8, p);
-      syn_filt_zero(resp[i], awk2, resp[i], 8,p);
+      float *res = resp+i*subvect_size;
+      residue_zero(shape_cb+i*subvect_size, awk1, res, 8, p);
+      syn_filt_zero(res, ak, res, 8, p);
+      syn_filt_zero(res, awk2, res, 8,p);
       E[i]=0;
       for(j=0;j<8;j++)
-         E[i]+=resp[i][j]*resp[i][j];
+         E[i]+=res[j]*res[j];
       Ee[i]=0;
       for(j=0;j<8;j++)
-         Ee[i]+=codebook[i][j]*codebook[i][j];
+         Ee[i]+=shape_cb[i*subvect_size+j]*shape_cb[i*subvect_size+j];
       
    }
    for (i=0;i<5;i++)
    {
       int best_index=0;
       float g, corr, best_gain=0, score, best_score=-1;
-      for (j=0;j<EXC_CB_SIZE;j++)
+      for (j=0;j<shape_cb_size;j++)
       {
-         corr=xcorr(resp[j],t+8*i,8);
+         corr=xcorr(resp+j*subvect_size,t+8*i,8);
          score=corr*corr/(.001+E[j]);
          g = corr/(.001+E[j]);
          if (score>best_score)
@@ -182,48 +212,23 @@ FrameBits *bits
             best_gain=corr/(.001+E[j]);
          }
       }
-      frame_bits_pack(bits,best_index,7);
+      frame_bits_pack(bits,best_index,params->shape_bits);
       if (best_gain>0)
          frame_bits_pack(bits,0,1);
       else
           frame_bits_pack(bits,1,1);        
       ind[i]=best_index;
       gains[i]=best_gain*Ee[ind[i]];
-      if (0) { /* Simulating scalar quantization of the gain*/
-         float sign=1;
-         printf("before: %f\n", best_gain);
-         if (best_gain<0)
-         {
-            sign=-1;
-         }
-         best_gain = fabs(best_gain)+.1;
-         best_gain = log(best_gain);
-         if (best_gain>8)
-            best_gain=8;
-         if (best_gain<0)
-            best_gain=0;
-         /*best_gain=.125*floor(8*best_gain+.5);*/
-         best_gain=.25*floor(4*best_gain+.5);
-         best_gain=sign*exp(best_gain);
-         if (fabs(best_gain)<1.01)
-            best_gain=0;
-         printf("after: %f\n", best_gain);
-      }
 
-      printf ("search: %d %f %f %f\n", best_index, best_gain, best_gain*best_gain*E[best_index], best_score);
-      for (j=0;j<40;j++)
+      for (j=0;j<nsf;j++)
          e[j]=0;
       for (j=0;j<8;j++)
-         e[8*i+j]=best_gain*codebook[best_index][j];
-      residue_zero(e, awk1, r, 40, p);
-      syn_filt_zero(r, ak, r, 40, p);
-      syn_filt_zero(r, awk2, r, 40,p);
-      for (j=0;j<40;j++)
+         e[8*i+j]=best_gain*shape_cb[best_index*subvect_size+j];
+      residue_zero(e, awk1, r, nsf, p);
+      syn_filt_zero(r, ak, r, nsf, p);
+      syn_filt_zero(r, awk2, r, nsf,p);
+      for (j=0;j<nsf;j++)
          t[j]-=r[j];
-
-      /*FIXME: Should move that out of the loop if we are to vector-quantize the gains*/
-      /*for (j=0;j<40;j++)
-        exc[j]+=e[j];*/
    }
 
    {
@@ -254,50 +259,38 @@ FrameBits *bits
         gains[i]*=max_gain;
       frame_bits_pack(bits,max_index,3);
 
-      if (max_index>2)
-      {
-      for (i=0;i<5;i++)
-         printf ("%f ", gains[i]);
-      printf ("cbgains: \n");
-      }
       /*Vector quantize gains[i]*/
-      for (i=0;i<256;i++)
-      {
-         float dist=0;
-         for (j=0;j<5;j++)
-            dist += (exc_gains_table[i][j]-gains[j])*(exc_gains_table[i][j]-gains[j]);
-         if (i==0 || dist<min_dist)
-         {
-            min_dist=dist;
-            best_vq_index=i;
-         }
-      }
-      frame_bits_pack(bits,best_vq_index,8);
+      best_vq_index = vq_index(gains, gain_cb, nb_subvect, gain_cb_size);
+      frame_bits_pack(bits,best_vq_index,params->gain_bits);
+
       printf ("best_gains_vq_index %d %f %d\n", best_vq_index, min_dist, max_index);
-#if 1
+
+#if 1 /* If 0, the gains are not quantized */
       for (i=0;i<5;i++)
-         gains[i]= sign[i]*exc_gains_table[best_vq_index][i]/max_gain/(Ee[ind[i]]+.001);
+         gains[i]= sign[i]*gain_cb[best_vq_index*nb_subvect+i]/max_gain/(Ee[ind[i]]+.001);
 #else 
       for (i=0;i<5;i++)
          gains[i]= sign[i]*gains[i]/max_gain/(Ee[ind[i]]+.001);
 #endif  
-
-   printf ("unquant gains: ");
-   for (i=0;i<5;i++)
-      printf ("%f ", gains[i]);
-   printf ("\n");
     
       for (i=0;i<5;i++)
          for (j=0;j<8;j++)
-            exc[8*i+j]+=gains[i]*codebook[ind[i]][j];
+            exc[8*i+j]+=gains[i]*shape_cb[ind[i]*subvect_size+j];
    }
-   /*for (i=0;i<5;i++)
-      printf ("%f ", gains[i]);
-      printf ("cbgains: \n");*/
-   /*TODO: Perform joint optimization of gains and quantization with prediction*/
+
+   /*TODO: Perform joint optimization of gains*/
    
-   for (i=0;i<40;i++)
+   for (i=0;i<nsf;i++)
       target[i]=t[i];
+
+   POP(stack);
+   POP(stack);
+   POP(stack);
+   POP(stack);
+   POP(stack);
+   POP(stack);
+   POP(stack);
+   POP(stack);
 }
 
 void split_cb_unquant(
@@ -330,7 +323,7 @@ FrameBits *bits
 
    max_gain=exp(max_gain_ind+3.0);
    for (i=0;i<5;i++)
-      gains[i] = sign[i]*exc_gains_table[vq_gain_ind][i]*max_gain/Ee[i];
+      gains[i] = sign[i]*exc_gains_table[vq_gain_ind*5+i]*max_gain/Ee[i];
    
    printf ("unquant gains: ");
    for (i=0;i<5;i++)
index 696f844..de0de11 100644 (file)
@@ -36,19 +36,28 @@ int   nsf                       /* number of samples in subframe */
 );
 
 
+typedef struct split_cb_params {
+   int     subvect_size;
+   int     nb_subvect;
+   float  *shape_cb;
+   int     shape_bits;
+   float  *gain_cb;
+   int     gain_bits;
+} split_cb_params;
+
+extern split_cb_params split_cb_nb;
+
 void split_cb_search(
 float target[],                        /* target vector */
 float ak[],                    /* LPCs for this subframe */
 float awk1[],                  /* Weighted LPCs for this subframe */
 float awk2[],                  /* Weighted LPCs for this subframe */
-float codebook[][8],           /* overlapping codebook */
-int   entries,                 /* number of entries to search */
-float *gain,                   /* gain of optimum entries */
-int   *index,                  /* index of optimum entries */
+void *par,                      /* Codebook/search parameters*/
 int   p,                        /* number of LPC coeffs */
 int   nsf,                      /* number of samples in subframe */
 float *exc,
-FrameBits *bits
+FrameBits *bits,
+float *stack
 );
 
 void split_cb_unquant(
index 373607b..05a9798 100644 (file)
@@ -327,8 +327,8 @@ void encode(EncState *st, float *in, FrameBits *bits)
 #else
       /* Perform a split-codebook search */
       split_cb_search(target, st->interp_qlpc, st->bw_lpc1, st->bw_lpc2,
-                        exc_table, 64, &gain[0], &pitch, st->lpcSize,
-                        st->subframeSize, exc, bits);
+                        &split_cb_nb, st->lpcSize,
+                        st->subframeSize, exc, bits, st->stack);
 #endif
 
       /* Compute weighted noise energy, SNR */
diff --git a/libspeex/vq.c b/libspeex/vq.c
new file mode 100644 (file)
index 0000000..d26b20a
--- /dev/null
@@ -0,0 +1,42 @@
+/* Copyright (C) 2002 Jean-Marc Valin & David Rowe
+   File: vq.c
+   Vector quantization
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+   
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "vq.h"
+
+int vq_index(float *in, float *codebook, int len, int entries)
+{
+   int i,j;
+   float min_dist=0;
+   int best_index=0;
+   for (i=0;i<entries;i++)
+   {
+      float dist=0;
+      for (j=0;j<len;j++)
+      {
+         float tmp = in[j]-*codebook++;
+         dist += tmp*tmp;
+      }
+      if (i==0 || dist<min_dist)
+      {
+         min_dist=dist;
+         best_index=i;
+      }
+   }
+   return best_index;
+}
diff --git a/libspeex/vq.h b/libspeex/vq.h
new file mode 100644 (file)
index 0000000..2460bad
--- /dev/null
@@ -0,0 +1,26 @@
+/* Copyright (C) 2002 Jean-Marc Valin & David Rowe
+   File: vq.h
+   Vector quantization
+
+   This library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+   
+   This library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+   
+   You should have received a copy of the GNU Lesser General Public
+   License along with this library; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef VQ_H
+#define VQ_H
+
+int vq_index(float *in, float *codebook, int len, int entries);
+
+
+#endif