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
********************************************************************/
}
/* 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]
*/
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;
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 */
}
/* 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);
}
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;
}
/* 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++)
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));
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;
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])
#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);
--- /dev/null
+/********************************************************************
+ * *
+ * 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
+
+
+
+
+