SB-CELP decoder (continued)
[speexdsp.git] / libspeex / cb_search.c
index 2a3e75d..dcdf72a 100644 (file)
 #include <stdio.h>
 #include "stack_alloc.h"
 #include "vq.h"
-
+#include "matrix.h"
+
+static float scal_gains4[16] = {
+   0.27713,
+   0.49282,
+   0.69570,
+   0.90786,
+   1.14235,
+   1.42798,
+   1.80756,
+   2.42801
+};
 
 /*---------------------------------------------------------------------------*\
                                                                              
@@ -83,7 +94,7 @@ int   nsf                       /* number of samples in subframe */
   bscore = 0.0;
   impulse[0] = 1.0;
 
-  /* Calculate impulse response of  A(z/g2) / ( A(z)*(z/g1) ) */
+  /* Calculate impulse response of  A(z/g1) / ( A(z)*(z/g2) ) */
   residue_zero(impulse, awk1, h, nsf, p);
   syn_filt_zero(h, ak, h, nsf, p);
   syn_filt_zero(h, awk2, h, nsf,p);
@@ -128,7 +139,6 @@ int   nsf                       /* number of samples in subframe */
 
 
 
-
 void split_cb_search(
 float target[],                        /* target vector */
 float ak[],                    /* LPCs for this subframe */
@@ -144,11 +154,12 @@ float *stack
 {
    int i,j;
    float *resp, *E, *Ee;
-   float *t, *r, *e;
+   float *t, *r, *e, *tresp;
    float *gains;
    int *ind;
-   float *shape_cb, *gain_cb;
-   int shape_cb_size, gain_cb_size, subvect_size, nb_subvect;
+   float *shape_cb;
+   int shape_cb_size, subvect_size, nb_subvect;
+   float exc_energy=0;
    split_cb_params *params;
 
    params = (split_cb_params *) par;
@@ -156,9 +167,8 @@ float *stack
    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*subvect_size);
+   tresp = PUSH(stack, shape_cb_size*nsf);
    E = PUSH(stack, shape_cb_size);
    Ee = PUSH(stack, shape_cb_size);
    t = PUSH(stack, nsf);
@@ -166,7 +176,28 @@ float *stack
    e = PUSH(stack, nsf);
    gains = PUSH(stack, nb_subvect);
    ind = (int*)PUSH(stack, nb_subvect);
-   
+
+   syn_filt_zero(target, awk1, e, nsf, p);
+   residue_zero(e, ak, e, nsf, p);
+   residue_zero(e, awk2, e, nsf, p);
+   for (i=0;i<nsf;i++)
+      exc_energy += e[i]*e[i];
+   exc_energy=sqrt(.125*exc_energy);
+
+   /* Quantize global (average) gain */
+   {
+      float q;
+      int id;
+      q=log(exc_energy+.1);
+      q=floor(.5+2*(q-2));
+      if (q<0)
+         q=0;
+      if (q>15)
+         q=15;
+      id = (int)q;
+      frame_bits_pack(bits, id, 4);
+      exc_energy=exp(.5*q+2);
+   }
 
    for (i=0;i<nsf;i++)
       t[i]=target[i];
@@ -184,6 +215,7 @@ float *stack
          Ee[i]+=shape_cb[i*subvect_size+j]*shape_cb[i*subvect_size+j];
       
    }
+
    for (i=0;i<nb_subvect;i++)
    {
       int best_index=0;
@@ -201,12 +233,37 @@ float *stack
          }
       }
       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);        
+      {
+         int s=0, best_id, j;
+         float best_dist;
+         best_gain /= .01+exc_energy;
+         if (best_gain<0)
+         {
+            best_gain=-best_gain;
+            s=1;
+         }
+         best_dist=(best_gain-scal_gains4[0])*(best_gain-scal_gains4[0]);
+         best_id=0;
+         for (j=1;j<8;j++)
+         {
+            float dist;
+            dist=(best_gain-scal_gains4[j])*(best_gain-scal_gains4[j]);
+            if (dist<best_dist)
+            {
+               best_id=j;
+               best_dist=dist;
+            }
+         }
+         best_gain=scal_gains4[best_id];
+         /*printf ("gain_quant: %f %d %f\n", best_gain, best_id, scal_gains4[best_id]);*/
+         if (s)
+            best_gain=-best_gain;
+         best_gain *= exc_energy;
+         frame_bits_pack(bits,s,1);
+         frame_bits_pack(bits,best_id,3);
+      }
       ind[i]=best_index;
-      gains[i]=best_gain*Ee[ind[i]];
+      gains[i]=best_gain;
 
       for (j=0;j<nsf;j++)
          e[j]=0;
@@ -216,63 +273,25 @@ float *stack
       syn_filt_zero(r, ak, r, nsf, p);
       syn_filt_zero(r, awk2, r, nsf,p);
       for (j=0;j<nsf;j++)
+         tresp[i*nsf+j]=r[j];
+      for (j=0;j<nsf;j++)
          t[j]-=r[j];
    }
+   
+   for (i=0;i<nb_subvect;i++)
+      for (j=0;j<subvect_size;j++)
+         e[subvect_size*i+j]=gains[i]*shape_cb[ind[i]*subvect_size+j];
 
-   {
-      int best_vq_index=0, max_index;
-      float max_gain=0, log_max, min_dist=0, *sign;
-
-      sign = PUSH(stack, nb_subvect);
-      for (i=0;i<nb_subvect;i++)
-      {
-         if (gains[i]<0)
-         {
-            gains[i]=-gains[i];
-            sign[i]=-1;
-         } else {
-            sign[i]=1;
-         }
-      }
-      for (i=0;i<nb_subvect;i++)
-         if (gains[i]>max_gain)
-            max_gain=gains[i];
-      log_max=log(max_gain+1);
-      max_index = (int)(floor(.5+log_max-3));
-      if (max_index>7)
-         max_index=7;
-      if (max_index<0)
-         max_index=0;
-      max_gain=1/exp(max_index+3.0);
-      for (i=0;i<nb_subvect;i++)
-        gains[i]*=max_gain;
-      frame_bits_pack(bits,max_index,3);
-
-      /*Vector quantize gains[i]*/
-      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 0, the gains are not quantized */
-      for (i=0;i<nb_subvect;i++)
-         gains[i]= sign[i]*gain_cb[best_vq_index*nb_subvect+i]/max_gain/(Ee[ind[i]]+.001);
-#else 
-      for (i=0;i<nb_subvect;i++)
-         gains[i]= sign[i]*gains[i]/max_gain/(Ee[ind[i]]+.001);
-#endif  
-    
-      for (i=0;i<nb_subvect;i++)
-         for (j=0;j<subvect_size;j++)
-            exc[subvect_size*i+j]+=gains[i]*shape_cb[ind[i]*subvect_size+j];
-
-      POP(stack);
-   }
+   for (j=0;j<nsf;j++)
+      exc[j]+=e[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++)
+      target[j]-=r[j];
 
-   /*TODO: Perform joint optimization of gains*/
    
-   for (i=0;i<nsf;i++)
-      target[i]=t[i];
+
 
    POP(stack);
    POP(stack);
@@ -284,6 +303,9 @@ float *stack
    POP(stack);
 }
 
+
+
+
 void split_cb_unquant(
 float *exc,
 void *par,                      /* non-overlapping codebook */
@@ -296,10 +318,8 @@ float *stack
    int *ind;
    float *gains;
    float *sign;
-   int max_gain_ind, vq_gain_ind;
-   float max_gain, *Ee;
-   float *shape_cb, *gain_cb;
-   int shape_cb_size, gain_cb_size, subvect_size, nb_subvect;
+   float *shape_cb, exc_energy;
+   int shape_cb_size, subvect_size, nb_subvect;
    split_cb_params *params;
 
    params = (split_cb_params *) par;
@@ -307,37 +327,32 @@ float *stack
    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;
    
    ind = (int*)PUSH(stack, nb_subvect);
    gains = PUSH(stack, nb_subvect);
    sign = PUSH(stack, nb_subvect);
-   Ee=PUSH(stack, nb_subvect);
+
+   /* Decode global (average) gain */
+   {
+      int id;
+      id = frame_bits_unpack_unsigned(bits, 4);
+      exc_energy=exp(.5*id+2);
+   }
 
    for (i=0;i<nb_subvect;i++)
    {
+      int gain_id;
       ind[i] = frame_bits_unpack_unsigned(bits, params->shape_bits);
       if (frame_bits_unpack_unsigned(bits, 1))
          sign[i]=-1;
       else
          sign[i]=1;
-      Ee[i]=.001;
-      for (j=0;j<subvect_size;j++)
-         Ee[i]+=shape_cb[ind[i]*subvect_size+j]*shape_cb[ind[i]*subvect_size+j];
+      
+      gain_id = frame_bits_unpack_unsigned(bits, 3);
+      gains[i]=scal_gains4[gain_id];
+      gains[i] *= sign[i];
+      gains[i] *= exc_energy;
    }
-   max_gain_ind = frame_bits_unpack_unsigned(bits, 3);
-   vq_gain_ind = frame_bits_unpack_unsigned(bits, params->gain_bits);
-   printf ("unquant gains ind: %d %d\n", max_gain_ind, vq_gain_ind);
-
-   max_gain=exp(max_gain_ind+3.0);
-   for (i=0;i<nb_subvect;i++)
-      gains[i] = sign[i]*gain_cb[vq_gain_ind*nb_subvect+i]*max_gain/Ee[i];
-   
-   printf ("unquant gains: ");
-   for (i=0;i<nb_subvect;i++)
-      printf ("%f ", gains[i]);
-   printf ("\n");
 
    for (i=0;i<nb_subvect;i++)
       for (j=0;j<subvect_size;j++)
@@ -346,5 +361,4 @@ float *stack
    POP(stack);
    POP(stack);
    POP(stack);
-   POP(stack);
 }