Update CHANGES for the 1.3.7 release
[platform/upstream/libvorbis.git] / lib / res0.c
index 5b4c013..c931ade 100644 (file)
@@ -5,13 +5,12 @@
  * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
  * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.       *
  *                                                                  *
- * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009             *
- * by the Xiph.Org Foundation http://www.xiph.org/                  *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010             *
+ * by the Xiph.Org Foundation https://xiph.org/                     *
  *                                                                  *
  ********************************************************************
 
  function: residue backend 0, 1 and 2 implementation
- last mod: $Id$
 
  ********************************************************************/
 
@@ -58,6 +57,7 @@ typedef struct {
   float      training_min[8][64];
   float     tmin;
   float     tmax;
+  int       submap;
 #endif
 
 } vorbis_look_residue0;
@@ -88,7 +88,7 @@ void res0_free_look(vorbis_look_residue *i){
             codebook *statebook=look->partbooks[j][k];
 
             /* long and short into the same bucket by current convention */
-            sprintf(buffer,"res_part%d_pass%d.vqd",j,k);
+            sprintf(buffer,"res_sub%d_part%d_pass%d.vqd",look->submap,j,k);
             of=fopen(buffer,"a");
 
             for(l=0;l<statebook->entries;l++)
@@ -148,15 +148,6 @@ void res0_free_look(vorbis_look_residue *i){
   }
 }
 
-static int ilog(unsigned int v){
-  int ret=0;
-  while(v){
-    ret++;
-    v>>=1;
-  }
-  return(ret);
-}
-
 static int icount(unsigned int v){
   int ret=0;
   while(v){
@@ -182,7 +173,7 @@ void res0_pack(vorbis_info_residue *vr,oggpack_buffer *opb){
      bitmask of one indicates this partition class has bits to write
      this pass */
   for(j=0;j<info->partitions;j++){
-    if(ilog(info->secondstages[j])>3){
+    if(ov_ilog(info->secondstages[j])>3){
       /* yes, this is a minor hack due to not thinking ahead */
       oggpack_write(opb,info->secondstages[j],3);
       oggpack_write(opb,1,1);
@@ -246,6 +237,7 @@ vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){
     int entries = ci->book_param[info->groupbook]->entries;
     int dim = ci->book_param[info->groupbook]->dim;
     int partvals = 1;
+    if (dim<1) goto errout;
     while(dim>0){
       partvals *= info->partitions;
       if(partvals > entries) goto errout;
@@ -279,7 +271,7 @@ vorbis_look_residue *res0_look(vorbis_dsp_state *vd,
   look->partbooks=_ogg_calloc(look->parts,sizeof(*look->partbooks));
 
   for(j=0;j<look->parts;j++){
-    int stages=ilog(info->secondstages[j]);
+    int stages=ov_ilog(info->secondstages[j]);
     if(stages){
       if(stages>maxstage)maxstage=stages;
       look->partbooks[j]=_ogg_calloc(stages,sizeof(*look->partbooks[j]));
@@ -321,66 +313,77 @@ vorbis_look_residue *res0_look(vorbis_dsp_state *vd,
 }
 
 /* break an abstraction and copy some code for performance purposes */
-static int local_book_besterror(codebook *book,float *a){
-  int dim=book->dim,i,k,o;
-  int best=0;
-  encode_aux_threshmatch *tt=book->c->thresh_tree;
-
-  /* find the quant val of each scalar */
-  for(k=0,o=dim;k<dim;++k){
-    float val=a[--o];
-    i=tt->threshvals>>1;
-
-    if(val<tt->quantthresh[i]){
-      if(val<tt->quantthresh[i-1]){
-        for(--i;i>0;--i)
-          if(val>=tt->quantthresh[i-1])
-            break;
-      }
-    }else{
-
-      for(++i;i<tt->threshvals-1;++i)
-        if(val<tt->quantthresh[i])break;
-
+static int local_book_besterror(codebook *book,int *a){
+  int dim=book->dim;
+  int i,j,o;
+  int minval=book->minval;
+  int del=book->delta;
+  int qv=book->quantvals;
+  int ze=(qv>>1);
+  int index=0;
+  /* assumes integer/centered encoder codebook maptype 1 no more than dim 8 */
+  int p[8]={0,0,0,0,0,0,0,0};
+
+  if(del!=1){
+    for(i=0,o=dim;i<dim;i++){
+      int v = (a[--o]-minval+(del>>1))/del;
+      int m = (v<ze ? ((ze-v)<<1)-1 : ((v-ze)<<1));
+      index = index*qv+ (m<0?0:(m>=qv?qv-1:m));
+      p[o]=v*del+minval;
+    }
+  }else{
+    for(i=0,o=dim;i<dim;i++){
+      int v = a[--o]-minval;
+      int m = (v<ze ? ((ze-v)<<1)-1 : ((v-ze)<<1));
+      index = index*qv+ (m<0?0:(m>=qv?qv-1:m));
+      p[o]=v*del+minval;
     }
-
-    best=(best*tt->quantvals)+tt->quantmap[i];
   }
-  /* regular lattices are easy :-) */
 
-  if(book->c->lengthlist[best]<=0){
+  if(book->c->lengthlist[index]<=0){
     const static_codebook *c=book->c;
-    int i,j;
-    float bestf=0.f;
-    float *e=book->valuelist;
-    best=-1;
+    int best=-1;
+    /* assumes integer/centered encoder codebook maptype 1 no more than dim 8 */
+    int e[8]={0,0,0,0,0,0,0,0};
+    int maxval = book->minval + book->delta*(book->quantvals-1);
     for(i=0;i<book->entries;i++){
       if(c->lengthlist[i]>0){
-        float this=0.f;
+        int this=0;
         for(j=0;j<dim;j++){
-          float val=(e[j]-a[j]);
+          int val=(e[j]-a[j]);
           this+=val*val;
         }
-        if(best==-1 || this<bestf){
-          bestf=this;
-          best=i;
+        if(best==-1 || this<best){
+          memcpy(p,e,sizeof(p));
+          best=this;
+          index=i;
         }
       }
-      e+=dim;
+      /* assumes the value patterning created by the tools in vq/ */
+      j=0;
+      while(e[j]>=maxval)
+        e[j++]=0;
+      if(e[j]>=0)
+        e[j]+=book->delta;
+      e[j]= -e[j];
     }
   }
 
-  if(best>-1){
-    float *ptr=book->valuelist+best*dim;
+  if(index>-1){
     for(i=0;i<dim;i++)
-      *a++ -= *ptr++;
+      *a++ -= p[i];
   }
 
-  return(best);
+  return(index);
 }
 
-static int _encodepart(oggpack_buffer *opb,float *vec, int n,
+#ifdef TRAIN_RES
+static int _encodepart(oggpack_buffer *opb,int *vec, int n,
                        codebook *book,long *acc){
+#else
+static int _encodepart(oggpack_buffer *opb,int *vec, int n,
+                       codebook *book){
+#endif
   int i,bits=0;
   int dim=book->dim;
   int step=n/dim;
@@ -401,7 +404,7 @@ static int _encodepart(oggpack_buffer *opb,float *vec, int n,
 }
 
 static long **_01class(vorbis_block *vb,vorbis_look_residue *vl,
-                       float **in,int ch){
+                       int **in,int ch){
   long i,j,k;
   vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
   vorbis_info_residue0 *info=look->info;
@@ -427,17 +430,17 @@ static long **_01class(vorbis_block *vb,vorbis_look_residue *vl,
   for(i=0;i<partvals;i++){
     int offset=i*samples_per_partition+info->begin;
     for(j=0;j<ch;j++){
-      float max=0.;
-      float ent=0.;
+      int max=0;
+      int ent=0;
       for(k=0;k<samples_per_partition;k++){
-        if(fabs(in[j][offset+k])>max)max=fabs(in[j][offset+k]);
-        ent+=fabs(rint(in[j][offset+k]));
+        if(abs(in[j][offset+k])>max)max=abs(in[j][offset+k]);
+        ent+=abs(in[j][offset+k]);
       }
       ent*=scale;
 
       for(k=0;k<possible_partitions-1;k++)
         if(max<=info->classmetric1[k] &&
-           (info->classmetric2[k]<0 || (int)ent<info->classmetric2[k]))
+           (info->classmetric2[k]<0 || ent<info->classmetric2[k]))
           break;
 
       partword[j][i]=k;
@@ -467,7 +470,7 @@ static long **_01class(vorbis_block *vb,vorbis_look_residue *vl,
 /* designed for stereo or other modes where the partition size is an
    integer multiple of the number of channels encoded in the current
    submap */
-static long **_2class(vorbis_block *vb,vorbis_look_residue *vl,float **in,
+static long **_2class(vorbis_block *vb,vorbis_look_residue *vl,int **in,
                       int ch){
   long i,j,k,l;
   vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
@@ -486,17 +489,17 @@ static long **_2class(vorbis_block *vb,vorbis_look_residue *vl,float **in,
   char buffer[80];
 #endif
 
-  partword[0]=_vorbis_block_alloc(vb,n*ch/samples_per_partition*sizeof(*partword[0]));
-  memset(partword[0],0,n*ch/samples_per_partition*sizeof(*partword[0]));
+  partword[0]=_vorbis_block_alloc(vb,partvals*sizeof(*partword[0]));
+  memset(partword[0],0,partvals*sizeof(*partword[0]));
 
   for(i=0,l=info->begin/ch;i<partvals;i++){
-    float magmax=0.f;
-    float angmax=0.f;
+    int magmax=0;
+    int angmax=0;
     for(j=0;j<samples_per_partition;j+=ch){
-      if(fabs(in[0][l])>magmax)magmax=fabs(in[0][l]);
+      if(abs(in[0][l])>magmax)magmax=abs(in[0][l]);
       for(k=1;k<ch;k++)
-        if(fabs(in[k][l])>angmax)angmax=fabs(in[k][l]);
-        l++;
+        if(abs(in[k][l])>angmax)angmax=abs(in[k][l]);
+      l++;
     }
 
     for(j=0;j<possible_partitions-1;j++)
@@ -523,15 +526,26 @@ static long **_2class(vorbis_block *vb,vorbis_look_residue *vl,float **in,
 }
 
 static int _01forward(oggpack_buffer *opb,
-                      vorbis_block *vb,vorbis_look_residue *vl,
-                      float **in,int ch,
+                      vorbis_look_residue *vl,
+                      int **in,int ch,
                       long **partword,
-                      int (*encode)(oggpack_buffer *,float *,int,
-                                    codebook *,long *)){
+#ifdef TRAIN_RES
+                      int (*encode)(oggpack_buffer *,int *,int,
+                                    codebook *,long *),
+                      int submap
+#else
+                      int (*encode)(oggpack_buffer *,int *,int,
+                                    codebook *)
+#endif
+){
   long i,j,k,s;
   vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
   vorbis_info_residue0 *info=look->info;
 
+#ifdef TRAIN_RES
+  look->submap=submap;
+#endif
+
   /* move all this setup out later */
   int samples_per_partition=info->grouping;
   int possible_partitions=info->partitions;
@@ -593,13 +607,12 @@ static int _01forward(oggpack_buffer *opb,
             codebook *statebook=look->partbooks[partword[j][i]][s];
             if(statebook){
               int ret;
-              long *accumulator=NULL;
-
 #ifdef TRAIN_RES
+              long *accumulator=NULL;
               accumulator=look->training_data[s][partword[j][i]];
               {
                 int l;
-                float *samples=in[j]+offset;
+                int *samples=in[j]+offset;
                 for(l=0;l<samples_per_partition;l++){
                   if(samples[l]<look->training_min[s][partword[j][i]])
                     look->training_min[s][partword[j][i]]=samples[l];
@@ -607,10 +620,12 @@ static int _01forward(oggpack_buffer *opb,
                     look->training_max[s][partword[j][i]]=samples[l];
                 }
               }
-#endif
-
               ret=encode(opb,in[j]+offset,samples_per_partition,
                          statebook,accumulator);
+#else
+              ret=encode(opb,in[j]+offset,samples_per_partition,
+                         statebook);
+#endif
 
               look->postbits+=ret;
               resbits[partword[j][i]]+=ret;
@@ -621,19 +636,6 @@ static int _01forward(oggpack_buffer *opb,
     }
   }
 
-  /*{
-    long total=0;
-    long totalbits=0;
-    fprintf(stderr,"%d :: ",vb->mode);
-    for(k=0;k<possible_partitions;k++){
-    fprintf(stderr,"%ld/%1.2g, ",resvals[k],(float)resbits[k]/resvals[k]);
-    total+=resvals[k];
-    totalbits+=resbits[k];
-    }
-
-    fprintf(stderr,":: %ld:%1.2g\n",total,(double)totalbits/total);
-    }*/
-
   return(0);
 }
 
@@ -698,54 +700,6 @@ static int _01inverse(vorbis_block *vb,vorbis_look_residue *vl,
   return(0);
 }
 
-#if 0
-/* residue 0 and 1 are just slight variants of one another. 0 is
-   interleaved, 1 is not */
-long **res0_class(vorbis_block *vb,vorbis_look_residue *vl,
-                  float **in,int *nonzero,int ch){
-  /* we encode only the nonzero parts of a bundle */
-  int i,used=0;
-  for(i=0;i<ch;i++)
-    if(nonzero[i])
-      in[used++]=in[i];
-  if(used)
-    /*return(_01class(vb,vl,in,used,_interleaved_testhack));*/
-    return(_01class(vb,vl,in,used));
-  else
-    return(0);
-}
-
-int res0_forward(vorbis_block *vb,vorbis_look_residue *vl,
-                 float **in,float **out,int *nonzero,int ch,
-                 long **partword){
-  /* we encode only the nonzero parts of a bundle */
-  int i,j,used=0,n=vb->pcmend/2;
-  for(i=0;i<ch;i++)
-    if(nonzero[i]){
-      if(out)
-        for(j=0;j<n;j++)
-          out[i][j]+=in[i][j];
-      in[used++]=in[i];
-    }
-  if(used){
-    int ret=_01forward(vb,vl,in,used,partword,
-                      _interleaved_encodepart);
-    if(out){
-      used=0;
-      for(i=0;i<ch;i++)
-        if(nonzero[i]){
-          for(j=0;j<n;j++)
-            out[i][j]-=in[used][j];
-          used++;
-        }
-    }
-    return(ret);
-  }else{
-    return(0);
-  }
-}
-#endif
-
 int res0_inverse(vorbis_block *vb,vorbis_look_residue *vl,
                  float **in,int *nonzero,int ch){
   int i,used=0;
@@ -759,36 +713,27 @@ int res0_inverse(vorbis_block *vb,vorbis_look_residue *vl,
 }
 
 int res1_forward(oggpack_buffer *opb,vorbis_block *vb,vorbis_look_residue *vl,
-                 float **in,float **out,int *nonzero,int ch,
-                 long **partword){
-  int i,j,used=0,n=vb->pcmend/2;
+                 int **in,int *nonzero,int ch, long **partword, int submap){
+  int i,used=0;
+  (void)vb;
   for(i=0;i<ch;i++)
-    if(nonzero[i]){
-      if(out)
-        for(j=0;j<n;j++)
-          out[i][j]+=in[i][j];
+    if(nonzero[i])
       in[used++]=in[i];
-    }
 
   if(used){
-    int ret=_01forward(opb,vb,vl,in,used,partword,_encodepart);
-    if(out){
-      used=0;
-      for(i=0;i<ch;i++)
-        if(nonzero[i]){
-          for(j=0;j<n;j++)
-            out[i][j]-=in[used][j];
-          used++;
-        }
-    }
-    return(ret);
+#ifdef TRAIN_RES
+    return _01forward(opb,vl,in,used,partword,_encodepart,submap);
+#else
+    (void)submap;
+    return _01forward(opb,vl,in,used,partword,_encodepart);
+#endif
   }else{
     return(0);
   }
 }
 
 long **res1_class(vorbis_block *vb,vorbis_look_residue *vl,
-                  float **in,int *nonzero,int ch){
+                  int **in,int *nonzero,int ch){
   int i,used=0;
   for(i=0;i<ch;i++)
     if(nonzero[i])
@@ -812,7 +757,7 @@ int res1_inverse(vorbis_block *vb,vorbis_look_residue *vl,
 }
 
 long **res2_class(vorbis_block *vb,vorbis_look_residue *vl,
-                  float **in,int *nonzero,int ch){
+                  int **in,int *nonzero,int ch){
   int i,used=0;
   for(i=0;i<ch;i++)
     if(nonzero[i])used++;
@@ -827,34 +772,27 @@ long **res2_class(vorbis_block *vb,vorbis_look_residue *vl,
 
 int res2_forward(oggpack_buffer *opb,
                  vorbis_block *vb,vorbis_look_residue *vl,
-                 float **in,float **out,int *nonzero,int ch,
-                 long **partword){
+                 int **in,int *nonzero,int ch, long **partword,int submap){
   long i,j,k,n=vb->pcmend/2,used=0;
 
   /* don't duplicate the code; use a working vector hack for now and
      reshape ourselves into a single channel res1 */
   /* ugly; reallocs for each coupling pass :-( */
-  float *work=_vorbis_block_alloc(vb,ch*n*sizeof(*work));
+  int *work=_vorbis_block_alloc(vb,ch*n*sizeof(*work));
   for(i=0;i<ch;i++){
-    float *pcm=in[i];
+    int *pcm=in[i];
     if(nonzero[i])used++;
     for(j=0,k=i;j<n;j++,k+=ch)
       work[k]=pcm[j];
   }
 
   if(used){
-    int ret=_01forward(opb,vb,vl,&work,1,partword,_encodepart);
-    /* update the sofar vector */
-    if(out){
-      for(i=0;i<ch;i++){
-        float *pcm=in[i];
-        float *sofar=out[i];
-        for(j=0,k=i;j<n;j++,k+=ch)
-          sofar[j]+=pcm[j]-work[k];
-
-      }
-    }
-    return(ret);
+#ifdef TRAIN_RES
+    return _01forward(opb,vl,&work,1,partword,_encodepart,submap);
+#else
+    (void)submap;
+    return _01forward(opb,vl,&work,1,partword,_encodepart);
+#endif
   }else{
     return(0);
   }
@@ -888,7 +826,7 @@ int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl,
         if(s==0){
           /* fetch the partition word */
           int temp=vorbis_book_decode(look->phrasebook,&vb->opb);
-          if(temp==-1 || temp>info->partvals)goto eopbreak;
+          if(temp==-1 || temp>=info->partvals)goto eopbreak;
           partword[l]=look->decodemap[temp];
           if(partword[l]==NULL)goto errout;
         }