split out the include
authorMonty <xiphmont@xiph.org>
Wed, 15 Dec 1999 08:37:22 +0000 (08:37 +0000)
committerMonty <xiphmont@xiph.org>
Wed, 15 Dec 1999 08:37:22 +0000 (08:37 +0000)
add quantization to training

svn path=/trunk/vorbis/; revision=194

vq/train.c
vq/vqgen.c
vq/vqgen.h [new file with mode: 0644]

index 446c6d5..4c0eddf 100644 (file)
@@ -14,7 +14,7 @@
  function: utility main for training codebooks
  author: Monty <xiphmont@mit.edu>
  modifications by: Monty
- last modification date: Dec 10 1999
+ last modification date: Dec 14 1999
 
  ********************************************************************/
 
@@ -75,7 +75,7 @@ static int rline(FILE *in,FILE *out,char *line,int max,int pass){
 }
 
 /* command line:
-   trainvq [vq=file | [entries=n] [dim=n]] met=n in=file,firstcol 
+   trainvq [vq=file | [entries=n] [dim=n] [quant=n]] met=n in=file,firstcol 
            [in=file,firstcol]
 */
 
@@ -87,7 +87,7 @@ void setexit(int dummy){
 
 int main(int argc,char *argv[]){
   vqgen v;
-  int entries=-1,dim=-1;
+  int entries=-1,dim=-1,quant=-1;
   FILE *out=NULL;
   int met=0;
   double (*metric)(vqgen *,double *, double *)=NULL;
@@ -131,13 +131,13 @@ int main(int argc,char *argv[]){
        double a;
            
        rline(in,out,line,160,1);
-       if(sscanf(line,"%d %d %d",&entries,&dim,&met)!=3){
+       if(sscanf(line,"%d %d %d %d",&entries,&dim,&met,&quant)!=3){
          fprintf(stderr,"Syntax error reading book file\n");
          exit(1);
        }
 
        metric=set_metric(met);
-       vqgen_init(&v,dim,entries,metric,0.);
+       vqgen_init(&v,dim,entries,metric,quant);
        init=1;
 
        /* entries, bias, points */
@@ -177,6 +177,9 @@ int main(int argc,char *argv[]){
     }
 
     /* set parameters if we're not loading a pre book */
+    if(!strncmp(*argv,"quant=",6)){
+      sscanf(*argv,"quant=%d",&quant);
+    }
     if(!strncmp(*argv,"entries=",8)){
       sscanf(*argv,"entries=%d",&entries);
     }
@@ -204,12 +207,12 @@ int main(int argc,char *argv[]){
        exit(1);
       }
       if(!init){
-       if(dim==-1 || entries==-1){
-         fprintf(stderr,"Must specify dimensionality and entries before"
+       if(dim==-1 || entries==-1 || quant==-1){
+         fprintf(stderr,"Must specify dimensionality,entries,quant before"
                  " first input file\n");
          exit(1);
        }
-       vqgen_init(&v,dim,entries,metric,0.);
+       vqgen_init(&v,dim,entries,metric,quant);
        init=1;
       }
 
@@ -248,7 +251,7 @@ int main(int argc,char *argv[]){
 
   /* save the book */
 
-  fprintf(out,"%d %d %d\n",entries,dim,met);
+  fprintf(out,"%d %d %d %d\n",entries,dim,met,quant);
 
   i=0;
   for(j=0;j<entries;j++)
index e9db712..552cf18 100644 (file)
@@ -86,11 +86,11 @@ void _vqgen_seed(vqgen *v){
 
 void vqgen_init(vqgen *v,int elements,int entries,
                double (*metric)(vqgen *,double *, double *),
-               double spread){
+               int quant){
   memset(v,0,sizeof(vqgen));
 
   v->elements=elements;
-  v->errspread=spread;
+  v->quantbits=quant;
   v->allocated=32768;
   v->pointlist=malloc(v->allocated*v->elements*sizeof(double));
 
@@ -115,54 +115,6 @@ void vqgen_addpoint(vqgen *v, double *p){
   if(v->points==v->entries)_vqgen_seed(v);
 }
 
-/* take the trained entries, look at the points that comprise the cell
-   and find midpoints (as the actual encoding process uses euclidian
-   distance rather than any more complex metric to find the closest
-   match */
-
-double *vqgen_midpoint(vqgen *v){
-  long i,j,k;
-  double *lo=malloc(v->entries*v->elements*sizeof(double));
-  double *hi=malloc(v->entries*v->elements*sizeof(double));
-
-  memset(v->assigned,0,sizeof(long)*v->entries);
-  for(i=0;i<v->points;i++){
-    double *ppt=_point(v,i);
-    double firstmetric=v->metric_func(v,_now(v,0),ppt)+v->bias[0];
-    long   firstentry=0;
-    for(j=1;j<v->entries;j++){
-      double thismetric=v->metric_func(v,_now(v,j),_point(v,i))+v->bias[j];
-      if(thismetric<firstmetric){
-       firstmetric=thismetric;
-       firstentry=j;
-      }
-    }
-    
-    j=firstentry;
-    if(v->assigned[j]++){
-      for(k=0;k<v->elements;k++){
-       if(ppt[k]<vN(lo,j)[k])vN(lo,j)[k]=ppt[k];
-       if(ppt[k]>vN(hi,j)[k])vN(hi,j)[k]=ppt[k];
-      }
-    }else{
-      for(k=0;k<v->elements;k++){
-       vN(lo,j)[k]=ppt[k];
-       vN(hi,j)[k]=ppt[k];
-      }
-    }
-  }
-
-  for(j=0;j<v->entries;j++)
-    if(v->assigned[j])
-      for(k=0;k<v->elements;k++)
-       vN(lo,j)[k]=(vN(lo,j)[k]+vN(hi,j)[k])/2.;
-    else
-      for(k=0;k<v->elements;k++)
-       vN(lo,j)[k]=_now(v,j)[k];
-  free(hi);
-  return(lo);
-}
-
 double vqgen_iterate(vqgen *v){
   long   i,j,k;
   double fdesired=(double)v->points/v->entries;
@@ -286,7 +238,8 @@ double vqgen_iterate(vqgen *v){
   for(i=0;i<v->entries;i++)
     v->bias[i]=nearbias[(i+1)*desired-1];
 
-  /* last, assign midpoints */
+  /* assign midpoints */
+
   for(j=0;j<v->entries;j++){
     asserror+=fabs(v->assigned[j]-fdesired);
     if(v->assigned[j])
@@ -298,6 +251,31 @@ double vqgen_iterate(vqgen *v){
 #endif
   }
 
+  {
+    /* midpoints must be quantized.  but we need to know the range in
+       order to do so */
+    double *min=alloca(sizeof(double)*v->elements);
+    double *max=alloca(sizeof(double)*v->elements);
+   
+    for(k=0;k<v->elements;k++)
+      min[k]=max[k]=_now(v,0)[k];
+    for(j=1;j<v->entries;j++){
+      for(k=0;k<v->elements;k++){
+       double val=_now(v,0)[k];
+       if(val<min[k])min[k]=val;
+       if(val>max[k])max[k]=val;
+      }
+    }
+    for(k=0;k<v->elements;k++){
+      double base=min[k];
+      double delta=max[k]-min[k]/((1<<v->quantbits)-1);
+      for(j=0;j<v->entries;j++){
+       double val=_now(v,j)[k];
+       _now(v,j)[k]=rint((val-base)/delta);
+      }
+    }
+  }
+
   asserror/=(v->entries*fdesired);
   fprintf(stderr,": dist %g(%g) metric error=%g \n",
          asserror,fdesired,meterror/v->points);
diff --git a/vq/vqgen.h b/vq/vqgen.h
new file mode 100644 (file)
index 0000000..6fcc54d
--- /dev/null
@@ -0,0 +1,70 @@
+/********************************************************************
+ *                                                                  *
+ * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE.  *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *
+ * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE.    *
+ * PLEASE READ THESE TERMS DISTRIBUTING.                            *
+ *                                                                  *
+ * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999             *
+ * by 1999 Monty <monty@xiph.org> and The XIPHOPHORUS Company       *
+ * http://www.xiph.org/                                             *
+ *                                                                  *
+ ********************************************************************/
+
+#ifndef _VQGEN_H_
+#define _VQGEN_H_
+
+typedef struct vqgen{
+  int it;
+
+  int    elements;
+  int    quantbits;
+
+  /* point cache */
+  double *pointlist; 
+  long   points;
+  long   allocated;
+
+  /* entries */
+  double *entrylist;
+  long   *assigned;
+  double *bias;
+  long   entries;
+
+  double (*metric_func)   (struct vqgen *v,double *a,double *b);
+} vqgen;
+
+typedef struct vqbook{
+  long elements;
+  long entries;
+  double *valuelist;
+  long   *codelist;
+  long   *lengthlist;
+
+  /* auxiliary encoding/decoding information */
+  long   *ptr0;
+  long   *ptr1;
+
+  /* auxiliary encoding information */
+  double *n;
+  double *c;
+  long   aux;
+  long   alloc;
+
+} vqbook;
+
+extern void vqgen_init(vqgen *v,int elements,int entries,
+                      double (*metric)(vqgen *,double *, double *),
+                      int quant);
+extern void vqgen_addpoint(vqgen *v, double *p);
+extern double *vqgen_midpoint(vqgen *v);
+extern double vqgen_iterate(vqgen *v);
+extern int vqenc_entry(vqbook *b,double *val);
+extern void vqgen_book(vqgen *v,vqbook *b);
+
+#endif
+
+
+
+
+