annotate src/libvorbis-1.3.3/vq/bookutil.c @ 22:b07fe9e906dc

Portaudio: add missed file
author Chris Cannam
date Tue, 26 Mar 2013 12:14:11 +0000
parents 05aa0afa9217
children
rev   line source
Chris@1 1 /********************************************************************
Chris@1 2 * *
Chris@1 3 * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
Chris@1 4 * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
Chris@1 5 * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
Chris@1 6 * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
Chris@1 7 * *
Chris@1 8 * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010 *
Chris@1 9 * by the Xiph.Org Foundation http://www.xiph.org/ *
Chris@1 10 * *
Chris@1 11 ********************************************************************
Chris@1 12
Chris@1 13 function: utility functions for loading .vqh and .vqd files
Chris@1 14 last mod: $Id: bookutil.c 16959 2010-03-10 16:03:11Z xiphmont $
Chris@1 15
Chris@1 16 ********************************************************************/
Chris@1 17
Chris@1 18 #include <stdlib.h>
Chris@1 19 #include <stdio.h>
Chris@1 20 #include <math.h>
Chris@1 21 #include <string.h>
Chris@1 22 #include <errno.h>
Chris@1 23 #include "bookutil.h"
Chris@1 24
Chris@1 25 int _best(codebook *book, float *a, int step){
Chris@1 26
Chris@1 27 int dim=book->dim;
Chris@1 28 int i,j,o;
Chris@1 29 int minval=book->minval;
Chris@1 30 int del=book->delta;
Chris@1 31 int qv=book->quantvals;
Chris@1 32 int ze=(qv>>1);
Chris@1 33 int index=0;
Chris@1 34 /* assumes integer/centered encoder codebook maptype 1 no more than dim 8 */
Chris@1 35
Chris@1 36 if(del!=1){
Chris@1 37 for(i=0,o=step*(dim-1);i<dim;i++,o-=step){
Chris@1 38 int v = ((int)rint(a[o])-minval+(del>>1))/del;
Chris@1 39 int m = (v<ze ? ((ze-v)<<1)-1 : ((v-ze)<<1));
Chris@1 40 index = index*qv+ (m<0?0:(m>=qv?qv-1:m));
Chris@1 41 }
Chris@1 42 }else{
Chris@1 43 for(i=0,o=step*(dim-1);i<dim;i++,o-=step){
Chris@1 44 int v = (int)rint(a[o])-minval;
Chris@1 45 int m = (v<ze ? ((ze-v)<<1)-1 : ((v-ze)<<1));
Chris@1 46 index = index*qv+ (m<0?0:(m>=qv?qv-1:m));
Chris@1 47 }
Chris@1 48 }
Chris@1 49
Chris@1 50 if(book->c->lengthlist[index]<=0){
Chris@1 51 const static_codebook *c=book->c;
Chris@1 52 int best=-1;
Chris@1 53 /* assumes integer/centered encoder codebook maptype 1 no more than dim 8 */
Chris@1 54 int e[8]={0,0,0,0,0,0,0,0};
Chris@1 55 int maxval = book->minval + book->delta*(book->quantvals-1);
Chris@1 56 for(i=0;i<book->entries;i++){
Chris@1 57 if(c->lengthlist[i]>0){
Chris@1 58 float this=0;
Chris@1 59 for(j=0;j<dim;j++){
Chris@1 60 float val=(e[j]-a[j*step]);
Chris@1 61 this+=val*val;
Chris@1 62 }
Chris@1 63 if(best==-1 || this<best){
Chris@1 64 best=this;
Chris@1 65 index=i;
Chris@1 66 }
Chris@1 67 }
Chris@1 68 /* assumes the value patterning created by the tools in vq/ */
Chris@1 69 j=0;
Chris@1 70 while(e[j]>=maxval)
Chris@1 71 e[j++]=0;
Chris@1 72 if(e[j]>=0)
Chris@1 73 e[j]+=book->delta;
Chris@1 74 e[j]= -e[j];
Chris@1 75 }
Chris@1 76 }
Chris@1 77
Chris@1 78 return index;
Chris@1 79 }
Chris@1 80
Chris@1 81 /* A few little utils for reading files */
Chris@1 82 /* read a line. Use global, persistent buffering */
Chris@1 83 static char *linebuffer=NULL;
Chris@1 84 static int lbufsize=0;
Chris@1 85 char *get_line(FILE *in){
Chris@1 86 long sofar=0;
Chris@1 87 if(feof(in))return NULL;
Chris@1 88
Chris@1 89 while(1){
Chris@1 90 int gotline=0;
Chris@1 91
Chris@1 92 while(!gotline){
Chris@1 93 if(sofar+1>=lbufsize){
Chris@1 94 if(!lbufsize){
Chris@1 95 lbufsize=1024;
Chris@1 96 linebuffer=_ogg_malloc(lbufsize);
Chris@1 97 }else{
Chris@1 98 lbufsize*=2;
Chris@1 99 linebuffer=_ogg_realloc(linebuffer,lbufsize);
Chris@1 100 }
Chris@1 101 }
Chris@1 102 {
Chris@1 103 long c=fgetc(in);
Chris@1 104 switch(c){
Chris@1 105 case EOF:
Chris@1 106 if(sofar==0)return(NULL);
Chris@1 107 /* fallthrough correct */
Chris@1 108 case '\n':
Chris@1 109 linebuffer[sofar]='\0';
Chris@1 110 gotline=1;
Chris@1 111 break;
Chris@1 112 default:
Chris@1 113 linebuffer[sofar++]=c;
Chris@1 114 linebuffer[sofar]='\0';
Chris@1 115 break;
Chris@1 116 }
Chris@1 117 }
Chris@1 118 }
Chris@1 119
Chris@1 120 if(linebuffer[0]=='#'){
Chris@1 121 sofar=0;
Chris@1 122 }else{
Chris@1 123 return(linebuffer);
Chris@1 124 }
Chris@1 125 }
Chris@1 126 }
Chris@1 127
Chris@1 128 /* read the next numerical value from the given file */
Chris@1 129 static char *value_line_buff=NULL;
Chris@1 130
Chris@1 131 int get_line_value(FILE *in,float *value){
Chris@1 132 char *next;
Chris@1 133
Chris@1 134 if(!value_line_buff)return(-1);
Chris@1 135
Chris@1 136 *value=strtod(value_line_buff, &next);
Chris@1 137 if(next==value_line_buff){
Chris@1 138 value_line_buff=NULL;
Chris@1 139 return(-1);
Chris@1 140 }else{
Chris@1 141 value_line_buff=next;
Chris@1 142 while(*value_line_buff>44)value_line_buff++;
Chris@1 143 if(*value_line_buff==44)value_line_buff++;
Chris@1 144 return(0);
Chris@1 145 }
Chris@1 146 }
Chris@1 147
Chris@1 148 int get_next_value(FILE *in,float *value){
Chris@1 149 while(1){
Chris@1 150 if(get_line_value(in,value)){
Chris@1 151 value_line_buff=get_line(in);
Chris@1 152 if(!value_line_buff)return(-1);
Chris@1 153 }else{
Chris@1 154 return(0);
Chris@1 155 }
Chris@1 156 }
Chris@1 157 }
Chris@1 158
Chris@1 159 int get_next_ivalue(FILE *in,long *ivalue){
Chris@1 160 float value;
Chris@1 161 int ret=get_next_value(in,&value);
Chris@1 162 *ivalue=value;
Chris@1 163 return(ret);
Chris@1 164 }
Chris@1 165
Chris@1 166 static float sequence_base=0.f;
Chris@1 167 static int v_sofar=0;
Chris@1 168 void reset_next_value(void){
Chris@1 169 value_line_buff=NULL;
Chris@1 170 sequence_base=0.f;
Chris@1 171 v_sofar=0;
Chris@1 172 }
Chris@1 173
Chris@1 174 char *setup_line(FILE *in){
Chris@1 175 reset_next_value();
Chris@1 176 value_line_buff=get_line(in);
Chris@1 177 return(value_line_buff);
Chris@1 178 }
Chris@1 179
Chris@1 180
Chris@1 181 int get_vector(codebook *b,FILE *in,int start, int n,float *a){
Chris@1 182 int i;
Chris@1 183 const static_codebook *c=b->c;
Chris@1 184
Chris@1 185 while(1){
Chris@1 186
Chris@1 187 if(v_sofar==n || get_line_value(in,a)){
Chris@1 188 reset_next_value();
Chris@1 189 if(get_next_value(in,a))
Chris@1 190 break;
Chris@1 191 for(i=0;i<start;i++){
Chris@1 192 sequence_base=*a;
Chris@1 193 get_line_value(in,a);
Chris@1 194 }
Chris@1 195 }
Chris@1 196
Chris@1 197 for(i=1;i<c->dim;i++)
Chris@1 198 if(get_line_value(in,a+i))
Chris@1 199 break;
Chris@1 200
Chris@1 201 if(i==c->dim){
Chris@1 202 float temp=a[c->dim-1];
Chris@1 203 for(i=0;i<c->dim;i++)a[i]-=sequence_base;
Chris@1 204 if(c->q_sequencep)sequence_base=temp;
Chris@1 205 v_sofar++;
Chris@1 206 return(0);
Chris@1 207 }
Chris@1 208 sequence_base=0.f;
Chris@1 209 }
Chris@1 210
Chris@1 211 return(-1);
Chris@1 212 }
Chris@1 213
Chris@1 214 /* read lines fromt he beginning until we find one containing the
Chris@1 215 specified string */
Chris@1 216 char *find_seek_to(FILE *in,char *s){
Chris@1 217 rewind(in);
Chris@1 218 while(1){
Chris@1 219 char *line=get_line(in);
Chris@1 220 if(line){
Chris@1 221 if(strstr(line,s))
Chris@1 222 return(line);
Chris@1 223 }else
Chris@1 224 return(NULL);
Chris@1 225 }
Chris@1 226 }
Chris@1 227
Chris@1 228
Chris@1 229 /* this reads the format as written by vqbuild/latticebuild; innocent
Chris@1 230 (legal) tweaking of the file that would not affect its valid
Chris@1 231 header-ness will break this routine */
Chris@1 232
Chris@1 233 codebook *codebook_load(char *filename){
Chris@1 234 codebook *b=_ogg_calloc(1,sizeof(codebook));
Chris@1 235 static_codebook *c=(static_codebook *)(b->c=_ogg_calloc(1,sizeof(static_codebook)));
Chris@1 236 int quant_to_read=0;
Chris@1 237 FILE *in=fopen(filename,"r");
Chris@1 238 char *line;
Chris@1 239 long i;
Chris@1 240
Chris@1 241 if(in==NULL){
Chris@1 242 fprintf(stderr,"Couldn't open codebook %s\n",filename);
Chris@1 243 exit(1);
Chris@1 244 }
Chris@1 245
Chris@1 246 /* find the codebook struct */
Chris@1 247 find_seek_to(in,"static const static_codebook ");
Chris@1 248
Chris@1 249 /* get the major important values */
Chris@1 250 line=get_line(in);
Chris@1 251 if(sscanf(line,"%ld, %ld,",
Chris@1 252 &(c->dim),&(c->entries))!=2){
Chris@1 253 fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line);
Chris@1 254 exit(1);
Chris@1 255 }
Chris@1 256 line=get_line(in);
Chris@1 257 line=get_line(in);
Chris@1 258 if(sscanf(line,"%d, %ld, %ld, %d, %d,",
Chris@1 259 &(c->maptype),&(c->q_min),&(c->q_delta),&(c->q_quant),
Chris@1 260 &(c->q_sequencep))!=5){
Chris@1 261 fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line);
Chris@1 262 exit(1);
Chris@1 263 }
Chris@1 264
Chris@1 265 switch(c->maptype){
Chris@1 266 case 0:
Chris@1 267 quant_to_read=0;
Chris@1 268 break;
Chris@1 269 case 1:
Chris@1 270 quant_to_read=_book_maptype1_quantvals(c);
Chris@1 271 break;
Chris@1 272 case 2:
Chris@1 273 quant_to_read=c->entries*c->dim;
Chris@1 274 break;
Chris@1 275 }
Chris@1 276
Chris@1 277 /* load the quantized entries */
Chris@1 278 find_seek_to(in,"static const long _vq_quantlist_");
Chris@1 279 reset_next_value();
Chris@1 280 c->quantlist=_ogg_malloc(sizeof(long)*quant_to_read);
Chris@1 281 for(i=0;i<quant_to_read;i++)
Chris@1 282 if(get_next_ivalue(in,c->quantlist+i)){
Chris@1 283 fprintf(stderr,"out of data while reading codebook %s\n",filename);
Chris@1 284 exit(1);
Chris@1 285 }
Chris@1 286
Chris@1 287 /* load the lengthlist */
Chris@1 288 find_seek_to(in,"_lengthlist");
Chris@1 289 reset_next_value();
Chris@1 290 c->lengthlist=_ogg_malloc(sizeof(long)*c->entries);
Chris@1 291 for(i=0;i<c->entries;i++)
Chris@1 292 if(get_next_ivalue(in,c->lengthlist+i)){
Chris@1 293 fprintf(stderr,"out of data while reading codebook %s\n",filename);
Chris@1 294 exit(1);
Chris@1 295 }
Chris@1 296
Chris@1 297 /* got it all */
Chris@1 298 fclose(in);
Chris@1 299
Chris@1 300 vorbis_book_init_encode(b,c);
Chris@1 301 b->valuelist=_book_unquantize(c,c->entries,NULL);
Chris@1 302
Chris@1 303 return(b);
Chris@1 304 }
Chris@1 305
Chris@1 306 void spinnit(char *s,int n){
Chris@1 307 static int p=0;
Chris@1 308 static long lasttime=0;
Chris@1 309 long test;
Chris@1 310 struct timeval thistime;
Chris@1 311
Chris@1 312 gettimeofday(&thistime,NULL);
Chris@1 313 test=thistime.tv_sec*10+thistime.tv_usec/100000;
Chris@1 314 if(lasttime!=test){
Chris@1 315 lasttime=test;
Chris@1 316
Chris@1 317 fprintf(stderr,"%s%d ",s,n);
Chris@1 318
Chris@1 319 p++;if(p>3)p=0;
Chris@1 320 switch(p){
Chris@1 321 case 0:
Chris@1 322 fprintf(stderr,"| \r");
Chris@1 323 break;
Chris@1 324 case 1:
Chris@1 325 fprintf(stderr,"/ \r");
Chris@1 326 break;
Chris@1 327 case 2:
Chris@1 328 fprintf(stderr,"- \r");
Chris@1 329 break;
Chris@1 330 case 3:
Chris@1 331 fprintf(stderr,"\\ \r");
Chris@1 332 break;
Chris@1 333 }
Chris@1 334 fflush(stderr);
Chris@1 335 }
Chris@1 336 }
Chris@1 337
Chris@1 338 void build_tree_from_lengths(int vals, long *hist, long *lengths){
Chris@1 339 int i,j;
Chris@1 340 long *membership=_ogg_malloc(vals*sizeof(long));
Chris@1 341 long *histsave=alloca(vals*sizeof(long));
Chris@1 342 memcpy(histsave,hist,vals*sizeof(long));
Chris@1 343
Chris@1 344 for(i=0;i<vals;i++)membership[i]=i;
Chris@1 345
Chris@1 346 /* find codeword lengths */
Chris@1 347 /* much more elegant means exist. Brute force n^2, minimum thought */
Chris@1 348 for(i=vals;i>1;i--){
Chris@1 349 int first=-1,second=-1;
Chris@1 350 long least=-1;
Chris@1 351
Chris@1 352 spinnit("building... ",i);
Chris@1 353
Chris@1 354 /* find the two nodes to join */
Chris@1 355 for(j=0;j<vals;j++)
Chris@1 356 if(least==-1 || hist[j]<=least){
Chris@1 357 least=hist[j];
Chris@1 358 first=membership[j];
Chris@1 359 }
Chris@1 360 least=-1;
Chris@1 361 for(j=0;j<vals;j++)
Chris@1 362 if((least==-1 || hist[j]<=least) && membership[j]!=first){
Chris@1 363 least=hist[j];
Chris@1 364 second=membership[j];
Chris@1 365 }
Chris@1 366 if(first==-1 || second==-1){
Chris@1 367 fprintf(stderr,"huffman fault; no free branch\n");
Chris@1 368 exit(1);
Chris@1 369 }
Chris@1 370
Chris@1 371 /* join them */
Chris@1 372 least=hist[first]+hist[second];
Chris@1 373 for(j=0;j<vals;j++)
Chris@1 374 if(membership[j]==first || membership[j]==second){
Chris@1 375 membership[j]=first;
Chris@1 376 hist[j]=least;
Chris@1 377 lengths[j]++;
Chris@1 378 }
Chris@1 379 }
Chris@1 380 for(i=0;i<vals-1;i++)
Chris@1 381 if(membership[i]!=membership[i+1]){
Chris@1 382 fprintf(stderr,"huffman fault; failed to build single tree\n");
Chris@1 383 exit(1);
Chris@1 384 }
Chris@1 385
Chris@1 386 /* for sanity check purposes: how many bits would it have taken to
Chris@1 387 encode the training set? */
Chris@1 388 {
Chris@1 389 long bitsum=0;
Chris@1 390 long samples=0;
Chris@1 391 for(i=0;i<vals;i++){
Chris@1 392 bitsum+=(histsave[i]-1)*lengths[i];
Chris@1 393 samples+=histsave[i]-1;
Chris@1 394 }
Chris@1 395
Chris@1 396 if(samples){
Chris@1 397 fprintf(stderr,"\rTotal samples in training set: %ld \n",samples);
Chris@1 398 fprintf(stderr,"\rTotal bits used to represent training set: %ld\n",
Chris@1 399 bitsum);
Chris@1 400 }
Chris@1 401 }
Chris@1 402
Chris@1 403 free(membership);
Chris@1 404 }
Chris@1 405
Chris@1 406 /* wrap build_tree_from_lengths to allow zero entries in the histogram */
Chris@1 407 void build_tree_from_lengths0(int vals, long *hist, long *lengths){
Chris@1 408
Chris@1 409 /* pack the 'sparse' hit list into a dense list, then unpack
Chris@1 410 the lengths after the build */
Chris@1 411
Chris@1 412 int upper=0,i;
Chris@1 413 long *lengthlist=_ogg_calloc(vals,sizeof(long));
Chris@1 414 long *newhist=alloca(vals*sizeof(long));
Chris@1 415
Chris@1 416 for(i=0;i<vals;i++)
Chris@1 417 if(hist[i]>0)
Chris@1 418 newhist[upper++]=hist[i];
Chris@1 419
Chris@1 420 if(upper != vals){
Chris@1 421 fprintf(stderr,"\rEliminating %d unused entries; %d entries remain\n",
Chris@1 422 vals-upper,upper);
Chris@1 423 }
Chris@1 424
Chris@1 425 build_tree_from_lengths(upper,newhist,lengthlist);
Chris@1 426
Chris@1 427 upper=0;
Chris@1 428 for(i=0;i<vals;i++)
Chris@1 429 if(hist[i]>0)
Chris@1 430 lengths[i]=lengthlist[upper++];
Chris@1 431 else
Chris@1 432 lengths[i]=0;
Chris@1 433
Chris@1 434 free(lengthlist);
Chris@1 435 }
Chris@1 436
Chris@1 437 void write_codebook(FILE *out,char *name,const static_codebook *c){
Chris@1 438 int i,j,k;
Chris@1 439
Chris@1 440 /* save the book in C header form */
Chris@1 441
Chris@1 442 /* first, the static vectors, then the book structure to tie it together. */
Chris@1 443 /* quantlist */
Chris@1 444 if(c->quantlist){
Chris@1 445 long vals=(c->maptype==1?_book_maptype1_quantvals(c):c->entries*c->dim);
Chris@1 446 fprintf(out,"static const long _vq_quantlist_%s[] = {\n",name);
Chris@1 447 for(j=0;j<vals;j++){
Chris@1 448 fprintf(out,"\t%ld,\n",c->quantlist[j]);
Chris@1 449 }
Chris@1 450 fprintf(out,"};\n\n");
Chris@1 451 }
Chris@1 452
Chris@1 453 /* lengthlist */
Chris@1 454 fprintf(out,"static const long _vq_lengthlist_%s[] = {\n",name);
Chris@1 455 for(j=0;j<c->entries;){
Chris@1 456 fprintf(out,"\t");
Chris@1 457 for(k=0;k<16 && j<c->entries;k++,j++)
Chris@1 458 fprintf(out,"%2ld,",c->lengthlist[j]);
Chris@1 459 fprintf(out,"\n");
Chris@1 460 }
Chris@1 461 fprintf(out,"};\n\n");
Chris@1 462
Chris@1 463 /* tie it all together */
Chris@1 464
Chris@1 465 fprintf(out,"static const static_codebook %s = {\n",name);
Chris@1 466
Chris@1 467 fprintf(out,"\t%ld, %ld,\n",c->dim,c->entries);
Chris@1 468 fprintf(out,"\t(long *)_vq_lengthlist_%s,\n",name);
Chris@1 469 fprintf(out,"\t%d, %ld, %ld, %d, %d,\n",
Chris@1 470 c->maptype,c->q_min,c->q_delta,c->q_quant,c->q_sequencep);
Chris@1 471 if(c->quantlist)
Chris@1 472 fprintf(out,"\t(long *)_vq_quantlist_%s,\n",name);
Chris@1 473 else
Chris@1 474 fprintf(out,"\tNULL,\n");
Chris@1 475
Chris@1 476 fprintf(out,"\t0\n};\n\n");
Chris@1 477 }