/********************************************************************
* *
- * 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. *
+ * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
+ * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
+ * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
+ * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
* *
- * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-2000 *
- * by Monty <monty@xiph.org> and The XIPHOPHORUS Company *
- * http://www.xiph.org/ *
+ * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
+ * by the Xiph.Org Foundation http://www.xiph.org/ *
* *
********************************************************************
function: utility main for building codebooks from lattice descriptions
- last mod: $Id: latticebuild.c,v 1.3 2000/07/12 09:36:18 xiphmont Exp $
********************************************************************/
#include <math.h>
#include <string.h>
#include <errno.h>
-#include "vorbis/codebook.h"
-#include "../lib/sharedbook.h"
#include "bookutil.h"
-/* The purpose of this util is actually just to count hits and finish
- packaging the description into a static codebook.
+/* The purpose of this util is just to finish packaging the
+ description into a static codebook. It used to count hits for a
+ histogram, but I've divorced that out to add some flexibility (it
+ currently generates an equal probability codebook)
command line:
- vqlattice description.vql datafile.vqd
+ latticebuild description.vql
- the lattice description file contains five lines:
+ the lattice description file contains two lines:
<n> <dim> <multiplicitavep> <sequentialp>
<value_0> <value_1> <value_2> ... <value_n-1>
- <m>
- <thresh_0> <thresh_1> <thresh_2> ... <thresh_m-2>
- <map_0> <map_1> <map_2> ... <map_m-1>
+
+ a threshmap (or pigeonmap) struct is generated by latticehint;
+ there are fun tricks one can do with the threshmap and cascades,
+ but the utils don't know them...
- vqlattice sends residual data (for the next stage) to stdout, and
- produces description.vqh */
+ entropy encoding is done by feeding an entry list collected from a
+ training set and feeding it to latticetune along with the book.
+
+ latticebuild produces a codebook on stdout */
static int ilog(unsigned int v){
int ret=0;
int main(int argc,char *argv[]){
codebook b;
static_codebook c;
- encode_aux_threshmatch t;
double *quantlist;
long *hits;
- int entries=-1,dim=-1,quantvals=-1,addmul=-1,threshvals=-1,sequencep=0;
- FILE *out=NULL;
+ int entries=-1,dim=-1,quantvals=-1,addmul=-1,sequencep=0;
FILE *in=NULL;
char *line,*name;
- long j,k;
+ long i,j;
memset(&b,0,sizeof(b));
memset(&c,0,sizeof(c));
- memset(&t,0,sizeof(t));
if(argv[1]==NULL){
fprintf(stderr,"Need a lattice description file on the command line.\n");
{
char *ptr;
- char *filename=calloc(strlen(argv[1])+4,1);
+ char *filename=_ogg_calloc(strlen(argv[1])+4,1);
strcpy(filename,argv[1]);
in=fopen(filename,"r");
if(ptr){
*ptr='\0';
name=strdup(filename);
- sprintf(ptr,".vqh");
}else{
name=strdup(filename);
- strcat(filename,".vqh");
}
- out=fopen(filename,"w");
- if(out==NULL){
- fprintf(stderr,"Unable to open %s for writing\n",filename);
- exit(1);
- }
}
/* read the description */
line=get_line(in);
if(sscanf(line,"%d %d %d %d",&quantvals,&dim,&addmul,&sequencep)!=4){
if(sscanf(line,"%d %d %d",&quantvals,&dim,&addmul)!=3){
- fprintf(stderr,"Syntax error reading book file (line 1)\n");
+ fprintf(stderr,"Syntax error reading description file (line 1)\n");
exit(1);
}
}
entries=pow(quantvals,dim);
- c.thresh_tree=&t;
c.dim=dim;
c.entries=entries;
- c.lengthlist=malloc(entries*sizeof(long));
+ c.lengthlist=_ogg_malloc(entries*sizeof(long));
c.maptype=1;
c.q_sequencep=sequencep;
- c.quantlist=calloc(quantvals,sizeof(long));
+ c.quantlist=_ogg_calloc(quantvals,sizeof(long));
- quantlist=malloc(sizeof(long)*c.dim*c.entries);
- hits=malloc(c.entries*sizeof(long));
+ quantlist=_ogg_malloc(sizeof(double)*c.dim*c.entries);
+ hits=_ogg_malloc(c.entries*sizeof(long));
for(j=0;j<entries;j++)hits[j]=1;
for(j=0;j<entries;j++)c.lengthlist[j]=1;
reset_next_value();
- setup_line(in);
- for(j=0;j<quantvals;j++){
- if(get_line_value(in,quantlist+j)==-1){
- fprintf(stderr,"Ran out of data on line 2 of description file\n");
- exit(1);
- }
- }
-
line=setup_line(in);
- if(sscanf(line,"%d",&threshvals)!=1){
- fprintf(stderr,"Syntax error reading book file (line 3)\n");
- exit(1);
- }
-
- t.quantthresh=calloc(threshvals-1,sizeof(double));
- t.quantmap=calloc(threshvals,sizeof(int));
- t.threshvals=threshvals;
- t.quantvals=quantvals;
-
- setup_line(in);
- for(j=0;j<threshvals-1;j++){
- if(get_line_value(in,t.quantthresh+j)==-1){
- fprintf(stderr,"Ran out of data on line 4 of description file\n");
- exit(1);
- }
- }
-
- setup_line(in);
- for(j=0;j<threshvals;j++){
- if(get_next_ivalue(in,t.quantmap+j)==-1){
- fprintf(stderr,"Ran out of data on line 5 of description file\n");
+ for(j=0;j<quantvals;j++){
+ char *temp;
+ if(!line || sscanf(line,"%lf",quantlist+j)!=1){
+ fprintf(stderr,"Ran out of data on line 2 of description file\n");
exit(1);
}
+ temp=strchr(line,',');
+ if(!temp)temp=strchr(line,' ');
+ if(temp)temp++;
+ line=temp;
}
/* gen a real quant list from the more easily human-grokked input */
int fac=1;
for(j=1;j<quantvals;j++)if(quantlist[j]<min)min=quantlist[j];
for(j=0;j<quantvals;j++)
- if(min!=quantlist[j] && (mindel==-1 || quantlist[j]-min<mindel))
- mindel=quantlist[j]-min;
+ for(i=j+1;i<quantvals;i++)
+ if(mindel==-1 || fabs(quantlist[j]-quantlist[i])<mindel)
+ mindel=fabs(quantlist[j]-quantlist[i]);
- fprintf(stderr,"min=%g mindel=%g\n",min,mindel);
j=0;
while(j<quantvals){
for(j=0;j<quantvals;j++){
- double test=(quantlist[j]-min)/(mindel/fac);
- if( fabs(rint(test)-test)>.000001) break;
+ double test=fac*(quantlist[j]-min)/mindel;
+ if( fabs(rint(test)-test)>.00001f) break;
}
+ if(fac>100)break;
if(j<quantvals)fac++;
}
mindel/=fac;
+ fprintf(stderr,"min=%g mindel=%g\n",min,mindel);
c.q_min=_float32_pack(min);
c.q_delta=_float32_pack(mindel);
if(ilog(c.quantlist[j])>c.q_quant)c.q_quant=ilog(c.quantlist[j]);
}
}
-
- vorbis_book_init_encode(&b,&c);
- fclose(in);
-
- /* at this point, we have enough to do best entry matching. We
- don't have counts yet, but that's OK; match, write residual data,
- and track hits. The build word lengths when we're done */
-
- /* we have to do our own de-interleave */
- if(argv[2]==NULL){
- fprintf(stderr,"Need a data file on the command line.\n");
- exit(1);
- }
- in=fopen(argv[2],"r");
- if(!in){
- fprintf(stderr,"Could not open input file %s\n",argv[2]);
- exit(1);
- }
-
- {
- int cols=0;
- long lines=0;
- double *vec;
- int interleaved;
- line=setup_line(in);
- /* count cols before we start reading */
- {
- char *temp=line;
- while(*temp==' ')temp++;
- for(cols=0;*temp;cols++){
- while(*temp>32)temp++;
- while(*temp==' ')temp++;
- }
- }
- vec=alloca(cols*sizeof(double));
- interleaved=cols/dim;
-
- while(line){
- lines++;
-
- if(!(lines&0xff))spinnit("lines so far...",lines);
-
- /* don't need to deinterleave; besterror does that for us */
- for(j=0;j<cols;j++)
- if(get_line_value(in,vec+j)){
- fprintf(stderr,"Too few columns on line %ld in data file\n",lines);
- exit(1);
- }
-
- /* process */
- for(j=0;j<interleaved;j++)
- hits[vorbis_book_besterror(&b,vec+j,interleaved,addmul)]++;
-
- /* write */
- for(j=0;j<cols;j++)
- fprintf(stdout,"%g, ",vec[j]);
- fprintf(stdout,"\n");
-
- line=setup_line(in);
- }
- }
- fclose(in);
- /* build the codeword lengths */
+ /* build the [default] codeword lengths */
memset(c.lengthlist,0,sizeof(long)*entries);
+ for(i=0;i<entries;i++)hits[i]=1;
build_tree_from_lengths(entries,hits,c.lengthlist);
/* save the book in C header form */
- fprintf(out,
- "/********************************************************************\n"
- " * *\n"
- " * THIS FILE IS PART OF THE Ogg Vorbis SOFTWARE CODEC SOURCE CODE. *\n"
- " * USE, DISTRIBUTION AND REPRODUCTION OF THIS SOURCE IS GOVERNED BY *\n"
- " * THE GNU PUBLIC LICENSE 2, WHICH IS INCLUDED WITH THIS SOURCE. *\n"
- " * PLEASE READ THESE TERMS DISTRIBUTING. *\n"
- " * *\n"
- " * THE OggSQUISH SOURCE CODE IS (C) COPYRIGHT 1994-1999 *\n"
- " * by 1999 Monty <monty@xiph.org> and The XIPHOPHORUS Company *\n"
- " * http://www.xiph.org/ *\n"
- " * *\n"
- " ********************************************************************\n"
- "\n"
- " function: static codebook autogenerated by vq/latticebuild\n"
- "\n"
- " ********************************************************************/\n\n");
-
- fprintf(out,"#ifndef _V_%s_VQH_\n#define _V_%s_VQH_\n",name,name);
- fprintf(out,"#include \"vorbis/codebook.h\"\n\n");
-
- /* first, the static vectors, then the book structure to tie it together. */
- /* quantlist */
- fprintf(out,"static long _vq_quantlist_%s[] = {\n",name);
- for(j=0;j<_book_maptype1_quantvals(&c);j++){
- fprintf(out,"\t%ld,\n",c.quantlist[j]);
- }
- fprintf(out,"};\n\n");
-
- /* lengthlist */
- fprintf(out,"static long _vq_lengthlist_%s[] = {\n",name);
- for(j=0;j<c.entries;){
- fprintf(out,"\t");
- for(k=0;k<16 && j<c.entries;k++,j++)
- fprintf(out,"%2ld,",c.lengthlist[j]);
- fprintf(out,"\n");
- }
- fprintf(out,"};\n\n");
-
- /* quantthresh */
- fprintf(out,"static double _vq_quantthresh_%s[] = {\n",name);
- for(j=0;j<t.threshvals-1;){
- fprintf(out,"\t");
- for(k=0;k<8 && j<t.threshvals-1;k++,j++)
- fprintf(out,"%.5g, ",t.quantthresh[j]);
- fprintf(out,"\n");
- }
- fprintf(out,"};\n\n");
-
- /* quantmap */
- fprintf(out,"static long _vq_quantmap_%s[] = {\n",name);
- for(j=0;j<t.threshvals;){
- fprintf(out,"\t");
- for(k=0;k<8 && j<t.threshvals;k++,j++)
- fprintf(out,"%5ld,",t.quantmap[j]);
- fprintf(out,"\n");
- }
- fprintf(out,"};\n\n");
-
- /* tie it all together */
-
- fprintf(out,"static encode_aux_threshmatch _vq_aux_%s = {\n",name);
- fprintf(out,"\t_vq_quantthresh_%s,\n",name);
- fprintf(out,"\t_vq_quantmap_%s,\n",name);
- fprintf(out,"\t%d,\n",t.quantvals);
- fprintf(out,"\t%d\n};\n\n",t.threshvals);
-
- fprintf(out,"static static_codebook _vq_book_%s = {\n",name);
-
- fprintf(out,"\t%ld, %ld,\n",c.dim,c.entries);
- fprintf(out,"\t_vq_lengthlist_%s,\n",name);
- fprintf(out,"\t1, %ld, %ld, %d, %d,\n",
- c.q_min,c.q_delta,c.q_quant,c.q_sequencep);
- fprintf(out,"\t_vq_quantlist_%s,\n",name);
- fprintf(out,"\tNULL,\n");
- fprintf(out,"\t&_vq_aux_%s\n",name);
- fprintf(out,"};\n\n");
-
- fprintf(out,"\n#endif\n");
- fclose(out);
-
+ write_codebook(stdout,name,&c);
fprintf(stderr,"\r "
- "\nDone.\n");
+ "\nDone.\n");
exit(0);
}