Oops. Thanks to Jim Crichton for pointing out that the complexity could end up
[speexdsp.git] / libspeex / cb_search.c
index e3f3491..5c68826 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002 Jean-Marc Valin 
+/* Copyright (C) 2002-2006 Jean-Marc Valin 
    File: cb_search.c
 
    Redistribution and use in source and binary forms, with or without
@@ -70,7 +70,7 @@ static void compute_weighted_codebook(const signed char *shape_cb, const spx_wor
          for (k=0;k<=j;k++)
             resj = MAC16_16(resj,shape[k],r[j-k]);
 #ifdef FIXED_POINT
-         res16 = EXTRACT16(SHR32(resj, 11));
+         res16 = EXTRACT16(SHR32(resj, 13));
 #else
          res16 = 0.03125f*resj;
 #endif
@@ -84,10 +84,19 @@ static void compute_weighted_codebook(const signed char *shape_cb, const spx_wor
 }
 #endif
 
+#ifndef OVERRIDE_TARGET_UPDATE
+static inline void target_update(spx_word16_t *t, spx_word16_t g, spx_word16_t *r, int len)
+{
+   int n;
+   for (n=0;n<len;n++)
+      t[n] = SUB16(t[n],PSHR32(MULT16_16(g,r[n]),13));
+}
+#endif
+
 
 
 static void split_cb_search_shape_sign_N1(
-spx_sig_t target[],                    /* target vector */
+spx_word16_t target[],                 /* target vector */
 spx_coef_t ak[],                       /* LPCs for this subframe */
 spx_coef_t awk1[],                     /* Weighted LPCs for this subframe */
 spx_coef_t awk2[],                     /* Weighted LPCs for this subframe */
@@ -98,11 +107,10 @@ spx_sig_t *exc,
 spx_word16_t *r,
 SpeexBits *bits,
 char *stack,
-int   complexity,
 int   update_target
 )
 {
-   int i,j,m,n,q;
+   int i,j,m,q;
    VARDECL(spx_word16_t *resp);
 #ifdef _USE_SSE
    VARDECL(__m128 *resp2);
@@ -116,15 +124,9 @@ int   update_target
    const signed char *shape_cb;
    int shape_cb_size, subvect_size, nb_subvect;
    const split_cb_params *params;
-   int N=2;
    int best_index;
    spx_word32_t best_dist;
    int have_sign;
-   N=complexity;
-   if (N>10)
-      N=10;
-   if (N<1)
-      N=1;
    
    params = (const split_cb_params *) par;
    subvect_size = params->subvect_size;
@@ -143,9 +145,9 @@ int   update_target
    ALLOC(t, nsf, spx_word16_t);
    ALLOC(e, nsf, spx_sig_t);
    
-   /* FIXME: make that adaptive? */
+   /* FIXME: Do we still need to copy the target? */
    for (i=0;i<nsf;i++)
-      t[i]=EXTRACT16(PSHR32(target[i],6));
+      t[i]=target[i];
 
    compute_weighted_codebook(shape_cb, r, resp, resp2, E, shape_cb_size, subvect_size, stack);
 
@@ -209,13 +211,10 @@ int   update_target
          q=subvect_size-m;
 #ifdef FIXED_POINT
          g=sign*shape_cb[rind*subvect_size+m];
-         for (n=subvect_size*(i+1);n<nsf;n++,q++)
-            t[n] = SUB32(t[n],MULT16_16_Q11_32(g,r[q]));
 #else
          g=sign*0.03125*shape_cb[rind*subvect_size+m];
-         for (n=subvect_size*(i+1);n<nsf;n++,q++)
-            t[n] = SUB32(t[n],g*r[q]);
 #endif
+         target_update(t+subvect_size*(i+1), g, r+q, nsf-subvect_size*(i+1));
       }
    }
 
@@ -231,14 +230,14 @@ int   update_target
       ALLOC(r2, nsf, spx_sig_t);
       syn_percep_zero(e, ak, awk1, awk2, r2, nsf,p, stack);
       for (j=0;j<nsf;j++)
-         target[j]=SUB32(target[j],r2[j]);
+         target[j]=SUB16(target[j],EXTRACT16(PSHR32(r2[j],8)));
    }
 }
 
 
 
 void split_cb_search_shape_sign(
-spx_sig_t target[],                    /* target vector */
+spx_word16_t target[],                 /* target vector */
 spx_coef_t ak[],                       /* LPCs for this subframe */
 spx_coef_t awk1[],                     /* Weighted LPCs for this subframe */
 spx_coef_t awk2[],                     /* Weighted LPCs for this subframe */
@@ -287,12 +286,13 @@ int   update_target
    N=complexity;
    if (N>10)
       N=10;
+   /* Complexity isn't as important for the codebooks as it is for the pitch */
+   N=(2*N)/3;
    if (N<1)
       N=1;
-   
    if (N==1)
    {
-      split_cb_search_shape_sign_N1(target,ak,awk1,awk2,par,p,nsf,exc,r,bits,stack,complexity,update_target);
+      split_cb_search_shape_sign_N1(target,ak,awk1,awk2,par,p,nsf,exc,r,bits,stack,update_target);
       return;
    }
    ALLOC(ot2, N, spx_word16_t*);
@@ -339,32 +339,26 @@ int   update_target
    {
       nind[i]=itmp+2*i*nb_subvect;
       oind[i]=itmp+(2*i+1)*nb_subvect;
-      for (j=0;j<nb_subvect;j++)
-         nind[i][j]=oind[i][j]=-1;
    }
    
-   /* FIXME: make that adaptive? */
    for (i=0;i<nsf;i++)
-      t[i]=EXTRACT16(PSHR32(target[i],6));
+      t[i]=target[i];
 
    for (j=0;j<N;j++)
-      for (i=0;i<nsf;i++)
-         ot[j][i]=t[i];
-
-   /*for (i=0;i<nsf;i++)
-     printf ("%d\n", (int)t[i]);*/
+      speex_move(&ot[j][0], t, nsf*sizeof(spx_word16_t));
 
    /* Pre-compute codewords response and energy */
    compute_weighted_codebook(shape_cb, r, resp, resp2, E, shape_cb_size, subvect_size, stack);
 
    for (j=0;j<N;j++)
       odist[j]=0;
+   
    /*For all subvectors*/
    for (i=0;i<nb_subvect;i++)
    {
       /*"erase" nbest list*/
       for (j=0;j<N;j++)
-         ndist[j]=-2;
+         ndist[j]=VERY_LARGE32;
 
       /*For all n-bests of previous subvector*/
       for (j=0;j<N;j++)
@@ -391,11 +385,11 @@ int   update_target
             spx_word32_t err = ADD32(ADD32(odist[j],best_dist[k]),tener);
             
             /*update n-best list*/
-            if (err<ndist[N-1] || ndist[N-1]<-1)
+            if (err<ndist[N-1])
             {
                for (m=0;m<N;m++)
                {
-                  if (err < ndist[m] || ndist[m]<-1)
+                  if (err < ndist[m])
                   {
                      for (n=N-1;n>m;n--)
                      {
@@ -416,11 +410,10 @@ int   update_target
       }
       for (j=0;j<N;j++)
       {
-         spx_word16_t *ct = ot[best_ntarget[j]];
-         
          /*previous target (we don't care what happened before*/
          for (m=(i+1)*subvect_size;m<nsf;m++)
-            t[m]=ct[m];
+            nt[j][m]=ot[best_ntarget[j]][m];
+         
          /* New code: update the rest of the target only if it's worth it */
          for (m=0;m<subvect_size;m++)
          {
@@ -437,17 +430,12 @@ int   update_target
             q=subvect_size-m;
 #ifdef FIXED_POINT
             g=sign*shape_cb[rind*subvect_size+m];
-            for (n=subvect_size*(i+1);n<nsf;n++,q++)
-               t[n] = SUB32(t[n],MULT16_16_Q11_32(g,r[q]));
 #else
             g=sign*0.03125*shape_cb[rind*subvect_size+m];
-            for (n=subvect_size*(i+1);n<nsf;n++,q++)
-               t[n] = SUB32(t[n],g*r[q]);
 #endif
+            target_update(nt[j]+subvect_size*(i+1), g, r+q, nsf-subvect_size*(i+1));
          }
 
-         for (q=(i+1)*subvect_size;q<nsf;q++)
-            nt[j][q]=t[q];
          for (q=0;q<nb_subvect;q++)
             nind[j][q]=oind[best_ntarget[j]][q];
          nind[j][i]=best_nind[j];
@@ -509,7 +497,7 @@ int   update_target
    {
       syn_percep_zero(e, ak, awk1, awk2, r2, nsf,p, stack);
       for (j=0;j<nsf;j++)
-         target[j]=SUB32(target[j],r2[j]);
+         target[j]=SUB16(target[j],EXTRACT16(PSHR32(r2[j],8)));
    }
 }
 
@@ -519,7 +507,8 @@ spx_sig_t *exc,
 const void *par,                      /* non-overlapping codebook */
 int   nsf,                      /* number of samples in subframe */
 SpeexBits *bits,
-char *stack
+char *stack,
+spx_int32_t *seed
 )
 {
    int i,j;
@@ -572,7 +561,7 @@ char *stack
 }
 
 void noise_codebook_quant(
-spx_sig_t target[],                    /* target vector */
+spx_word16_t target[],                 /* target vector */
 spx_coef_t ak[],                       /* LPCs for this subframe */
 spx_coef_t awk1[],                     /* Weighted LPCs for this subframe */
 spx_coef_t awk2[],                     /* Weighted LPCs for this subframe */
@@ -590,13 +579,14 @@ int   update_target
    int i;
    VARDECL(spx_sig_t *tmp);
    ALLOC(tmp, nsf, spx_sig_t);
-   residue_percep_zero(target, ak, awk1, awk2, tmp, nsf, p, stack);
+   for (i=0;i<nsf;i++)
+      tmp[i]=PSHR32(EXTEND32(target[i]),SIG_SHIFT);
+   residue_percep_zero(tmp, ak, awk1, awk2, tmp, nsf, p, stack);
 
    for (i=0;i<nsf;i++)
       exc[i]+=tmp[i];
    for (i=0;i<nsf;i++)
       target[i]=0;
-
 }
 
 
@@ -605,8 +595,12 @@ spx_sig_t *exc,
 const void *par,                      /* non-overlapping codebook */
 int   nsf,                      /* number of samples in subframe */
 SpeexBits *bits,
-char *stack
+char *stack,
+spx_int32_t *seed
 )
 {
-   speex_rand_vec(1, exc, nsf);
+   int i;
+   /* FIXME: This is bad, but I don't think the function ever gets called anyway */
+   for (i=0;i<nsf;i++)
+      exc[i]=SHL32(EXTEND32(speex_rand(1, seed)),SIG_SHIFT);
 }