From 74f4b1bc3b627ba4c7e03498234d88cacdfbe97b Mon Sep 17 00:00:00 2001 From: Aki Date: Wed, 29 Sep 2021 22:52:49 +0200 Subject: Squashed 'vorbis/' content from commit d22c3ab5f git-subtree-dir: vorbis git-subtree-split: d22c3ab5f633460abc2532feee60ca0892134cbf --- vq/bookutil.c | 476 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 476 insertions(+) create mode 100644 vq/bookutil.c (limited to 'vq/bookutil.c') diff --git a/vq/bookutil.c b/vq/bookutil.c new file mode 100644 index 0000000..3046410 --- /dev/null +++ b/vq/bookutil.c @@ -0,0 +1,476 @@ +/******************************************************************** + * * + * 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 OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2014 * + * by the Xiph.Org Foundation http://www.xiph.org/ * + * * + ******************************************************************** + + function: utility functions for loading .vqh and .vqd files + + ********************************************************************/ + +#include +#include +#include +#include +#include +#include "bookutil.h" + +int _best(codebook *book, float *a, int step){ + + 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 */ + + if(del!=1){ + for(i=0,o=step*(dim-1);i>1))/del; + int m = (v=qv?qv-1:m)); + } + }else{ + for(i=0,o=step*(dim-1);i=qv?qv-1:m)); + } + } + + if(book->c->lengthlist[index]<=0){ + const static_codebook *c=book->c; + 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;ientries;i++){ + if(c->lengthlist[i]>0){ + float this=0; + for(j=0;j=maxval) + e[j++]=0; + if(e[j]>=0) + e[j]+=book->delta; + e[j]= -e[j]; + } + } + + return index; +} + +/* A few little utils for reading files */ +/* read a line. Use global, persistent buffering */ +static char *linebuffer=NULL; +static int lbufsize=0; +char *get_line(FILE *in){ + long sofar=0; + if(feof(in))return NULL; + + while(1){ + int gotline=0; + + while(!gotline){ + if(sofar+1>=lbufsize){ + if(!lbufsize){ + lbufsize=1024; + linebuffer=_ogg_malloc(lbufsize); + }else{ + lbufsize*=2; + linebuffer=_ogg_realloc(linebuffer,lbufsize); + } + } + { + long c=fgetc(in); + switch(c){ + case EOF: + if(sofar==0)return(NULL); + /* fallthrough correct */ + case '\n': + linebuffer[sofar]='\0'; + gotline=1; + break; + default: + linebuffer[sofar++]=c; + linebuffer[sofar]='\0'; + break; + } + } + } + + if(linebuffer[0]=='#'){ + sofar=0; + }else{ + return(linebuffer); + } + } +} + +/* read the next numerical value from the given file */ +static char *value_line_buff=NULL; + +int get_line_value(FILE *in,float *value){ + char *next; + + if(!value_line_buff)return(-1); + + *value=strtod(value_line_buff, &next); + if(next==value_line_buff){ + value_line_buff=NULL; + return(-1); + }else{ + value_line_buff=next; + while(*value_line_buff>44)value_line_buff++; + if(*value_line_buff==44)value_line_buff++; + return(0); + } +} + +int get_next_value(FILE *in,float *value){ + while(1){ + if(get_line_value(in,value)){ + value_line_buff=get_line(in); + if(!value_line_buff)return(-1); + }else{ + return(0); + } + } +} + +int get_next_ivalue(FILE *in,long *ivalue){ + float value; + int ret=get_next_value(in,&value); + *ivalue=value; + return(ret); +} + +static float sequence_base=0.f; +static int v_sofar=0; +void reset_next_value(void){ + value_line_buff=NULL; + sequence_base=0.f; + v_sofar=0; +} + +char *setup_line(FILE *in){ + reset_next_value(); + value_line_buff=get_line(in); + return(value_line_buff); +} + + +int get_vector(codebook *b,FILE *in,int start, int n,float *a){ + int i; + const static_codebook *c=b->c; + + while(1){ + + if(v_sofar==n || get_line_value(in,a)){ + reset_next_value(); + if(get_next_value(in,a)) + break; + for(i=0;idim;i++) + if(get_line_value(in,a+i)) + break; + + if(i==c->dim){ + float temp=a[c->dim-1]; + for(i=0;idim;i++)a[i]-=sequence_base; + if(c->q_sequencep)sequence_base=temp; + v_sofar++; + return(0); + } + sequence_base=0.f; + } + + return(-1); +} + +/* read lines fromt he beginning until we find one containing the + specified string */ +char *find_seek_to(FILE *in,char *s){ + rewind(in); + while(1){ + char *line=get_line(in); + if(line){ + if(strstr(line,s)) + return(line); + }else + return(NULL); + } +} + + +/* this reads the format as written by vqbuild/latticebuild; innocent + (legal) tweaking of the file that would not affect its valid + header-ness will break this routine */ + +codebook *codebook_load(char *filename){ + codebook *b=_ogg_calloc(1,sizeof(codebook)); + static_codebook *c=(static_codebook *)(b->c=_ogg_calloc(1,sizeof(static_codebook))); + int quant_to_read=0; + FILE *in=fopen(filename,"r"); + char *line; + long i; + + if(in==NULL){ + fprintf(stderr,"Couldn't open codebook %s\n",filename); + exit(1); + } + + /* find the codebook struct */ + find_seek_to(in,"static const static_codebook "); + + /* get the major important values */ + line=get_line(in); + if(sscanf(line,"%ld, %ld,", + &(c->dim),&(c->entries))!=2){ + fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line); + exit(1); + } + line=get_line(in); + line=get_line(in); + if(sscanf(line,"%d, %ld, %ld, %d, %d,", + &(c->maptype),&(c->q_min),&(c->q_delta),&(c->q_quant), + &(c->q_sequencep))!=5){ + fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line); + exit(1); + } + + switch(c->maptype){ + case 0: + quant_to_read=0; + break; + case 1: + quant_to_read=_book_maptype1_quantvals(c); + break; + case 2: + quant_to_read=c->entries*c->dim; + break; + } + + /* load the quantized entries */ + find_seek_to(in,"static const long _vq_quantlist_"); + reset_next_value(); + c->quantlist=_ogg_malloc(sizeof(long)*quant_to_read); + for(i=0;iquantlist+i)){ + fprintf(stderr,"out of data while reading codebook %s\n",filename); + exit(1); + } + + /* load the lengthlist */ + find_seek_to(in,"_lengthlist"); + reset_next_value(); + c->lengthlist=_ogg_malloc(sizeof(long)*c->entries); + for(i=0;ientries;i++) + if(get_next_ivalue(in,c->lengthlist+i)){ + fprintf(stderr,"out of data while reading codebook %s\n",filename); + exit(1); + } + + /* got it all */ + fclose(in); + + vorbis_book_init_encode(b,c); + b->valuelist=_book_unquantize(c,c->entries,NULL); + + return(b); +} + +void spinnit(char *s,int n){ + static int p=0; + static long lasttime=0; + long test; + struct timeval thistime; + + gettimeofday(&thistime,NULL); + test=thistime.tv_sec*10+thistime.tv_usec/100000; + if(lasttime!=test){ + lasttime=test; + + fprintf(stderr,"%s%d ",s,n); + + p++;if(p>3)p=0; + switch(p){ + case 0: + fprintf(stderr,"| \r"); + break; + case 1: + fprintf(stderr,"/ \r"); + break; + case 2: + fprintf(stderr,"- \r"); + break; + case 3: + fprintf(stderr,"\\ \r"); + break; + } + fflush(stderr); + } +} + +void build_tree_from_lengths(int vals, long *hist, long *lengths){ + int i,j; + long *membership=_ogg_malloc(vals*sizeof(long)); + long *histsave=alloca(vals*sizeof(long)); + memcpy(histsave,hist,vals*sizeof(long)); + + for(i=0;i1;i--){ + int first=-1,second=-1; + long least=-1; + + spinnit("building... ",i); + + /* find the two nodes to join */ + for(j=0;j0) + newhist[upper++]=hist[i]; + + if(upper != vals){ + fprintf(stderr,"\rEliminating %d unused entries; %d entries remain\n", + vals-upper,upper); + } + + build_tree_from_lengths(upper,newhist,lengthlist); + + upper=0; + for(i=0;i0) + lengths[i]=lengthlist[upper++]; + else + lengths[i]=0; + + free(lengthlist); +} + +void write_codebook(FILE *out,char *name,const static_codebook *c){ + int i,j,k; + + /* save the book in C header form */ + + /* first, the static vectors, then the book structure to tie it together. */ + /* quantlist */ + if(c->quantlist){ + long vals=(c->maptype==1?_book_maptype1_quantvals(c):c->entries*c->dim); + fprintf(out,"static const long _vq_quantlist_%s[] = {\n",name); + for(j=0;jquantlist[j]); + } + fprintf(out,"};\n\n"); + } + + /* lengthlist */ + fprintf(out,"static const char _vq_lengthlist_%s[] = {\n",name); + for(j=0;jentries;){ + fprintf(out,"\t"); + for(k=0;k<16 && jentries;k++,j++) + fprintf(out,"%2ld,",c->lengthlist[j]); + fprintf(out,"\n"); + } + fprintf(out,"};\n\n"); + + /* tie it all together */ + + fprintf(out,"static const static_codebook %s = {\n",name); + + fprintf(out,"\t%ld, %ld,\n",c->dim,c->entries); + fprintf(out,"\t(char *)_vq_lengthlist_%s,\n",name); + fprintf(out,"\t%d, %ld, %ld, %d, %d,\n", + c->maptype,c->q_min,c->q_delta,c->q_quant,c->q_sequencep); + if(c->quantlist) + fprintf(out,"\t(long *)_vq_quantlist_%s,\n",name); + else + fprintf(out,"\tNULL,\n"); + + fprintf(out,"\t0\n};\n\n"); +} -- cgit v1.1