[16] | 1 | /******************************************************************** |
---|
| 2 | * * |
---|
| 3 | * THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. * |
---|
| 4 | * USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS * |
---|
| 5 | * GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE * |
---|
| 6 | * IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. * |
---|
| 7 | * * |
---|
| 8 | * THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 * |
---|
| 9 | * by the Xiph.Org Foundation http://www.xiph.org/ * |
---|
| 10 | * * |
---|
| 11 | ******************************************************************** |
---|
| 12 | |
---|
| 13 | function: utility functions for loading .vqh and .vqd files |
---|
| 14 | last mod: $Id: bookutil.c 13293 2007-07-24 00:09:47Z xiphmont $ |
---|
| 15 | |
---|
| 16 | ********************************************************************/ |
---|
| 17 | |
---|
| 18 | #include <stdlib.h> |
---|
| 19 | #include <stdio.h> |
---|
| 20 | #include <math.h> |
---|
| 21 | #include <string.h> |
---|
| 22 | #include <errno.h> |
---|
| 23 | #include "bookutil.h" |
---|
| 24 | |
---|
| 25 | /* A few little utils for reading files */ |
---|
| 26 | /* read a line. Use global, persistent buffering */ |
---|
| 27 | static char *linebuffer=NULL; |
---|
| 28 | static int lbufsize=0; |
---|
| 29 | char *get_line(FILE *in){ |
---|
| 30 | long sofar=0; |
---|
| 31 | if(feof(in))return NULL; |
---|
| 32 | |
---|
| 33 | while(1){ |
---|
| 34 | int gotline=0; |
---|
| 35 | |
---|
| 36 | while(!gotline){ |
---|
| 37 | if(sofar+1>=lbufsize){ |
---|
| 38 | if(!lbufsize){ |
---|
| 39 | lbufsize=1024; |
---|
| 40 | linebuffer=_ogg_malloc(lbufsize); |
---|
| 41 | }else{ |
---|
| 42 | lbufsize*=2; |
---|
| 43 | linebuffer=_ogg_realloc(linebuffer,lbufsize); |
---|
| 44 | } |
---|
| 45 | } |
---|
| 46 | { |
---|
| 47 | long c=fgetc(in); |
---|
| 48 | switch(c){ |
---|
| 49 | case EOF: |
---|
| 50 | if(sofar==0)return(NULL); |
---|
| 51 | /* fallthrough correct */ |
---|
| 52 | case '\n': |
---|
| 53 | linebuffer[sofar]='\0'; |
---|
| 54 | gotline=1; |
---|
| 55 | break; |
---|
| 56 | default: |
---|
| 57 | linebuffer[sofar++]=c; |
---|
| 58 | linebuffer[sofar]='\0'; |
---|
| 59 | break; |
---|
| 60 | } |
---|
| 61 | } |
---|
| 62 | } |
---|
| 63 | |
---|
| 64 | if(linebuffer[0]=='#'){ |
---|
| 65 | sofar=0; |
---|
| 66 | }else{ |
---|
| 67 | return(linebuffer); |
---|
| 68 | } |
---|
| 69 | } |
---|
| 70 | } |
---|
| 71 | |
---|
| 72 | /* read the next numerical value from the given file */ |
---|
| 73 | static char *value_line_buff=NULL; |
---|
| 74 | |
---|
| 75 | int get_line_value(FILE *in,float *value){ |
---|
| 76 | char *next; |
---|
| 77 | |
---|
| 78 | if(!value_line_buff)return(-1); |
---|
| 79 | |
---|
| 80 | *value=strtod(value_line_buff, &next); |
---|
| 81 | if(next==value_line_buff){ |
---|
| 82 | value_line_buff=NULL; |
---|
| 83 | return(-1); |
---|
| 84 | }else{ |
---|
| 85 | value_line_buff=next; |
---|
| 86 | while(*value_line_buff>44)value_line_buff++; |
---|
| 87 | if(*value_line_buff==44)value_line_buff++; |
---|
| 88 | return(0); |
---|
| 89 | } |
---|
| 90 | } |
---|
| 91 | |
---|
| 92 | int get_next_value(FILE *in,float *value){ |
---|
| 93 | while(1){ |
---|
| 94 | if(get_line_value(in,value)){ |
---|
| 95 | value_line_buff=get_line(in); |
---|
| 96 | if(!value_line_buff)return(-1); |
---|
| 97 | }else{ |
---|
| 98 | return(0); |
---|
| 99 | } |
---|
| 100 | } |
---|
| 101 | } |
---|
| 102 | |
---|
| 103 | int get_next_ivalue(FILE *in,long *ivalue){ |
---|
| 104 | float value; |
---|
| 105 | int ret=get_next_value(in,&value); |
---|
| 106 | *ivalue=value; |
---|
| 107 | return(ret); |
---|
| 108 | } |
---|
| 109 | |
---|
| 110 | static float sequence_base=0.f; |
---|
| 111 | static int v_sofar=0; |
---|
| 112 | void reset_next_value(void){ |
---|
| 113 | value_line_buff=NULL; |
---|
| 114 | sequence_base=0.f; |
---|
| 115 | v_sofar=0; |
---|
| 116 | } |
---|
| 117 | |
---|
| 118 | char *setup_line(FILE *in){ |
---|
| 119 | reset_next_value(); |
---|
| 120 | value_line_buff=get_line(in); |
---|
| 121 | return(value_line_buff); |
---|
| 122 | } |
---|
| 123 | |
---|
| 124 | |
---|
| 125 | int get_vector(codebook *b,FILE *in,int start, int n,float *a){ |
---|
| 126 | int i; |
---|
| 127 | const static_codebook *c=b->c; |
---|
| 128 | |
---|
| 129 | while(1){ |
---|
| 130 | |
---|
| 131 | if(v_sofar==n || get_line_value(in,a)){ |
---|
| 132 | reset_next_value(); |
---|
| 133 | if(get_next_value(in,a)) |
---|
| 134 | break; |
---|
| 135 | for(i=0;i<start;i++){ |
---|
| 136 | sequence_base=*a; |
---|
| 137 | get_line_value(in,a); |
---|
| 138 | } |
---|
| 139 | } |
---|
| 140 | |
---|
| 141 | for(i=1;i<c->dim;i++) |
---|
| 142 | if(get_line_value(in,a+i)) |
---|
| 143 | break; |
---|
| 144 | |
---|
| 145 | if(i==c->dim){ |
---|
| 146 | float temp=a[c->dim-1]; |
---|
| 147 | for(i=0;i<c->dim;i++)a[i]-=sequence_base; |
---|
| 148 | if(c->q_sequencep)sequence_base=temp; |
---|
| 149 | v_sofar++; |
---|
| 150 | return(0); |
---|
| 151 | } |
---|
| 152 | sequence_base=0.f; |
---|
| 153 | } |
---|
| 154 | |
---|
| 155 | return(-1); |
---|
| 156 | } |
---|
| 157 | |
---|
| 158 | /* read lines fromt he beginning until we find one containing the |
---|
| 159 | specified string */ |
---|
| 160 | char *find_seek_to(FILE *in,char *s){ |
---|
| 161 | rewind(in); |
---|
| 162 | while(1){ |
---|
| 163 | char *line=get_line(in); |
---|
| 164 | if(line){ |
---|
| 165 | if(strstr(line,s)) |
---|
| 166 | return(line); |
---|
| 167 | }else |
---|
| 168 | return(NULL); |
---|
| 169 | } |
---|
| 170 | } |
---|
| 171 | |
---|
| 172 | |
---|
| 173 | /* this reads the format as written by vqbuild/latticebuild; innocent |
---|
| 174 | (legal) tweaking of the file that would not affect its valid |
---|
| 175 | header-ness will break this routine */ |
---|
| 176 | |
---|
| 177 | codebook *codebook_load(char *filename){ |
---|
| 178 | codebook *b=_ogg_calloc(1,sizeof(codebook)); |
---|
| 179 | static_codebook *c=(static_codebook *)(b->c=_ogg_calloc(1,sizeof(static_codebook))); |
---|
| 180 | encode_aux_nearestmatch *a=NULL; |
---|
| 181 | encode_aux_threshmatch *t=NULL; |
---|
| 182 | encode_aux_pigeonhole *p=NULL; |
---|
| 183 | int quant_to_read=0; |
---|
| 184 | FILE *in=fopen(filename,"r"); |
---|
| 185 | char *line; |
---|
| 186 | long i; |
---|
| 187 | |
---|
| 188 | if(in==NULL){ |
---|
| 189 | fprintf(stderr,"Couldn't open codebook %s\n",filename); |
---|
| 190 | exit(1); |
---|
| 191 | } |
---|
| 192 | |
---|
| 193 | /* find the codebook struct */ |
---|
| 194 | find_seek_to(in,"static static_codebook "); |
---|
| 195 | |
---|
| 196 | /* get the major important values */ |
---|
| 197 | line=get_line(in); |
---|
| 198 | if(sscanf(line,"%ld, %ld,", |
---|
| 199 | &(c->dim),&(c->entries))!=2){ |
---|
| 200 | fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line); |
---|
| 201 | exit(1); |
---|
| 202 | } |
---|
| 203 | line=get_line(in); |
---|
| 204 | line=get_line(in); |
---|
| 205 | if(sscanf(line,"%d, %ld, %ld, %d, %d,", |
---|
| 206 | &(c->maptype),&(c->q_min),&(c->q_delta),&(c->q_quant), |
---|
| 207 | &(c->q_sequencep))!=5){ |
---|
| 208 | fprintf(stderr,"1: syntax in %s in line:\t %s",filename,line); |
---|
| 209 | exit(1); |
---|
| 210 | } |
---|
| 211 | |
---|
| 212 | /* find the auxiliary encode struct[s] (if any) */ |
---|
| 213 | if(find_seek_to(in,"static encode_aux_nearestmatch _vq_aux")){ |
---|
| 214 | /* how big? */ |
---|
| 215 | c->nearest_tree=a=_ogg_calloc(1,sizeof(encode_aux_nearestmatch)); |
---|
| 216 | line=get_line(in); |
---|
| 217 | line=get_line(in); |
---|
| 218 | line=get_line(in); |
---|
| 219 | line=get_line(in); |
---|
| 220 | line=get_line(in); |
---|
| 221 | if(sscanf(line,"%ld, %ld",&(a->aux),&(a->alloc))!=2){ |
---|
| 222 | fprintf(stderr,"2: syntax in %s in line:\t %s",filename,line); |
---|
| 223 | exit(1); |
---|
| 224 | } |
---|
| 225 | |
---|
| 226 | /* load ptr0 */ |
---|
| 227 | find_seek_to(in,"static long _vq_ptr0"); |
---|
| 228 | reset_next_value(); |
---|
| 229 | a->ptr0=_ogg_malloc(sizeof(long)*a->aux); |
---|
| 230 | for(i=0;i<a->aux;i++) |
---|
| 231 | if(get_next_ivalue(in,a->ptr0+i)){ |
---|
| 232 | fprintf(stderr,"out of data while reading codebook %s\n",filename); |
---|
| 233 | exit(1); |
---|
| 234 | } |
---|
| 235 | |
---|
| 236 | /* load ptr1 */ |
---|
| 237 | find_seek_to(in,"static long _vq_ptr1"); |
---|
| 238 | reset_next_value(); |
---|
| 239 | a->ptr1=_ogg_malloc(sizeof(long)*a->aux); |
---|
| 240 | for(i=0;i<a->aux;i++) |
---|
| 241 | if(get_next_ivalue(in,a->ptr1+i)){ |
---|
| 242 | fprintf(stderr,"out of data while reading codebook %s\n",filename); |
---|
| 243 | exit(1); |
---|
| 244 | } |
---|
| 245 | |
---|
| 246 | |
---|
| 247 | /* load p */ |
---|
| 248 | find_seek_to(in,"static long _vq_p_"); |
---|
| 249 | reset_next_value(); |
---|
| 250 | a->p=_ogg_malloc(sizeof(long)*a->aux); |
---|
| 251 | for(i=0;i<a->aux;i++) |
---|
| 252 | if(get_next_ivalue(in,a->p+i)){ |
---|
| 253 | fprintf(stderr,"out of data while reading codebook %s\n",filename); |
---|
| 254 | exit(1); |
---|
| 255 | } |
---|
| 256 | |
---|
| 257 | /* load q */ |
---|
| 258 | find_seek_to(in,"static long _vq_q_"); |
---|
| 259 | reset_next_value(); |
---|
| 260 | a->q=_ogg_malloc(sizeof(long)*a->aux); |
---|
| 261 | for(i=0;i<a->aux;i++) |
---|
| 262 | if(get_next_ivalue(in,a->q+i)){ |
---|
| 263 | fprintf(stderr,"out of data while reading codebook %s\n",filename); |
---|
| 264 | exit(1); |
---|
| 265 | } |
---|
| 266 | } |
---|
| 267 | |
---|
| 268 | if(find_seek_to(in,"static encode_aux_threshmatch _vq_aux")){ |
---|
| 269 | /* how big? */ |
---|
| 270 | c->thresh_tree=t=_ogg_calloc(1,sizeof(encode_aux_threshmatch)); |
---|
| 271 | line=get_line(in); |
---|
| 272 | line=get_line(in); |
---|
| 273 | line=get_line(in); |
---|
| 274 | if(sscanf(line,"%d",&(t->quantvals))!=1){ |
---|
| 275 | fprintf(stderr,"3: syntax in %s in line:\t %s",filename,line); |
---|
| 276 | exit(1); |
---|
| 277 | } |
---|
| 278 | line=get_line(in); |
---|
| 279 | if(sscanf(line,"%d",&(t->threshvals))!=1){ |
---|
| 280 | fprintf(stderr,"4: syntax in %s in line:\t %s",filename,line); |
---|
| 281 | exit(1); |
---|
| 282 | } |
---|
| 283 | /* load quantthresh */ |
---|
| 284 | find_seek_to(in,"static float _vq_quantthresh_"); |
---|
| 285 | reset_next_value(); |
---|
| 286 | t->quantthresh=_ogg_malloc(sizeof(float)*t->threshvals); |
---|
| 287 | for(i=0;i<t->threshvals-1;i++) |
---|
| 288 | if(get_next_value(in,t->quantthresh+i)){ |
---|
| 289 | fprintf(stderr,"out of data 1 while reading codebook %s\n",filename); |
---|
| 290 | exit(1); |
---|
| 291 | } |
---|
| 292 | /* load quantmap */ |
---|
| 293 | find_seek_to(in,"static long _vq_quantmap_"); |
---|
| 294 | reset_next_value(); |
---|
| 295 | t->quantmap=_ogg_malloc(sizeof(long)*t->threshvals); |
---|
| 296 | for(i=0;i<t->threshvals;i++) |
---|
| 297 | if(get_next_ivalue(in,t->quantmap+i)){ |
---|
| 298 | fprintf(stderr,"out of data 2 while reading codebook %s\n",filename); |
---|
| 299 | exit(1); |
---|
| 300 | } |
---|
| 301 | } |
---|
| 302 | |
---|
| 303 | if(find_seek_to(in,"static encode_aux_pigeonhole _vq_aux")){ |
---|
| 304 | int pigeons=1,i; |
---|
| 305 | /* how big? */ |
---|
| 306 | c->pigeon_tree=p=_ogg_calloc(1,sizeof(encode_aux_pigeonhole)); |
---|
| 307 | line=get_line(in); |
---|
| 308 | if(sscanf(line,"%f, %f, %d, %d",&(p->min),&(p->del), |
---|
| 309 | &(p->mapentries),&(p->quantvals))!=4){ |
---|
| 310 | fprintf(stderr,"5: syntax in %s in line:\t %s",filename,line); |
---|
| 311 | exit(1); |
---|
| 312 | } |
---|
| 313 | line=get_line(in); |
---|
| 314 | line=get_line(in); |
---|
| 315 | if(sscanf(line,"%ld",&(p->fittotal))!=1){ |
---|
| 316 | fprintf(stderr,"6: syntax in %s in line:\t %s",filename,line); |
---|
| 317 | exit(1); |
---|
| 318 | } |
---|
| 319 | /* load pigeonmap */ |
---|
| 320 | find_seek_to(in,"static long _vq_pigeonmap_"); |
---|
| 321 | reset_next_value(); |
---|
| 322 | p->pigeonmap=_ogg_malloc(sizeof(long)*p->mapentries); |
---|
| 323 | for(i=0;i<p->mapentries;i++) |
---|
| 324 | if(get_next_ivalue(in,p->pigeonmap+i)){ |
---|
| 325 | fprintf(stderr,"out of data (pigeonmap) while reading codebook %s\n",filename); |
---|
| 326 | exit(1); |
---|
| 327 | } |
---|
| 328 | /* load fitlist */ |
---|
| 329 | find_seek_to(in,"static long _vq_fitlist_"); |
---|
| 330 | reset_next_value(); |
---|
| 331 | p->fitlist=_ogg_malloc(sizeof(long)*p->fittotal); |
---|
| 332 | for(i=0;i<p->fittotal;i++) |
---|
| 333 | if(get_next_ivalue(in,p->fitlist+i)){ |
---|
| 334 | fprintf(stderr,"out of data (fitlist) while reading codebook %s\n",filename); |
---|
| 335 | exit(1); |
---|
| 336 | } |
---|
| 337 | /* load fitmap */ |
---|
| 338 | find_seek_to(in,"static long _vq_fitmap_"); |
---|
| 339 | reset_next_value(); |
---|
| 340 | for(i=0;i<c->dim;i++)pigeons*=p->quantvals; |
---|
| 341 | p->fitmap=_ogg_malloc(sizeof(long)*pigeons); |
---|
| 342 | for(i=0;i<pigeons;i++) |
---|
| 343 | if(get_next_ivalue(in,p->fitmap+i)){ |
---|
| 344 | fprintf(stderr,"out of data (fitmap) while reading codebook %s\n",filename); |
---|
| 345 | exit(1); |
---|
| 346 | } |
---|
| 347 | |
---|
| 348 | /* load fitlength */ |
---|
| 349 | find_seek_to(in,"static long _vq_fitlength_"); |
---|
| 350 | reset_next_value(); |
---|
| 351 | p->fitlength=_ogg_malloc(sizeof(long)*pigeons); |
---|
| 352 | for(i=0;i<pigeons;i++) |
---|
| 353 | if(get_next_ivalue(in,p->fitlength+i)){ |
---|
| 354 | fprintf(stderr,"out of data (fitlength) while reading codebook %s\n",filename); |
---|
| 355 | exit(1); |
---|
| 356 | } |
---|
| 357 | } |
---|
| 358 | |
---|
| 359 | switch(c->maptype){ |
---|
| 360 | case 0: |
---|
| 361 | quant_to_read=0; |
---|
| 362 | break; |
---|
| 363 | case 1: |
---|
| 364 | quant_to_read=_book_maptype1_quantvals(c); |
---|
| 365 | break; |
---|
| 366 | case 2: |
---|
| 367 | quant_to_read=c->entries*c->dim; |
---|
| 368 | break; |
---|
| 369 | } |
---|
| 370 | |
---|
| 371 | /* load the quantized entries */ |
---|
| 372 | find_seek_to(in,"static long _vq_quantlist_"); |
---|
| 373 | reset_next_value(); |
---|
| 374 | c->quantlist=_ogg_malloc(sizeof(long)*quant_to_read); |
---|
| 375 | for(i=0;i<quant_to_read;i++) |
---|
| 376 | if(get_next_ivalue(in,c->quantlist+i)){ |
---|
| 377 | fprintf(stderr,"out of data while reading codebook %s\n",filename); |
---|
| 378 | exit(1); |
---|
| 379 | } |
---|
| 380 | |
---|
| 381 | /* load the lengthlist */ |
---|
| 382 | find_seek_to(in,"_lengthlist"); |
---|
| 383 | reset_next_value(); |
---|
| 384 | c->lengthlist=_ogg_malloc(sizeof(long)*c->entries); |
---|
| 385 | for(i=0;i<c->entries;i++) |
---|
| 386 | if(get_next_ivalue(in,c->lengthlist+i)){ |
---|
| 387 | fprintf(stderr,"out of data while reading codebook %s\n",filename); |
---|
| 388 | exit(1); |
---|
| 389 | } |
---|
| 390 | |
---|
| 391 | /* got it all */ |
---|
| 392 | fclose(in); |
---|
| 393 | |
---|
| 394 | vorbis_book_init_encode(b,c); |
---|
| 395 | |
---|
| 396 | return(b); |
---|
| 397 | } |
---|
| 398 | |
---|
| 399 | void spinnit(char *s,int n){ |
---|
| 400 | static int p=0; |
---|
| 401 | static long lasttime=0; |
---|
| 402 | long test; |
---|
| 403 | struct timeval thistime; |
---|
| 404 | |
---|
| 405 | gettimeofday(&thistime,NULL); |
---|
| 406 | test=thistime.tv_sec*10+thistime.tv_usec/100000; |
---|
| 407 | if(lasttime!=test){ |
---|
| 408 | lasttime=test; |
---|
| 409 | |
---|
| 410 | fprintf(stderr,"%s%d ",s,n); |
---|
| 411 | |
---|
| 412 | p++;if(p>3)p=0; |
---|
| 413 | switch(p){ |
---|
| 414 | case 0: |
---|
| 415 | fprintf(stderr,"| \r"); |
---|
| 416 | break; |
---|
| 417 | case 1: |
---|
| 418 | fprintf(stderr,"/ \r"); |
---|
| 419 | break; |
---|
| 420 | case 2: |
---|
| 421 | fprintf(stderr,"- \r"); |
---|
| 422 | break; |
---|
| 423 | case 3: |
---|
| 424 | fprintf(stderr,"\\ \r"); |
---|
| 425 | break; |
---|
| 426 | } |
---|
| 427 | fflush(stderr); |
---|
| 428 | } |
---|
| 429 | } |
---|
| 430 | |
---|
| 431 | void build_tree_from_lengths(int vals, long *hist, long *lengths){ |
---|
| 432 | int i,j; |
---|
| 433 | long *membership=_ogg_malloc(vals*sizeof(long)); |
---|
| 434 | long *histsave=alloca(vals*sizeof(long)); |
---|
| 435 | memcpy(histsave,hist,vals*sizeof(long)); |
---|
| 436 | |
---|
| 437 | for(i=0;i<vals;i++)membership[i]=i; |
---|
| 438 | |
---|
| 439 | /* find codeword lengths */ |
---|
| 440 | /* much more elegant means exist. Brute force n^2, minimum thought */ |
---|
| 441 | for(i=vals;i>1;i--){ |
---|
| 442 | int first=-1,second=-1; |
---|
| 443 | long least=-1; |
---|
| 444 | |
---|
| 445 | spinnit("building... ",i); |
---|
| 446 | |
---|
| 447 | /* find the two nodes to join */ |
---|
| 448 | for(j=0;j<vals;j++) |
---|
| 449 | if(least==-1 || hist[j]<=least){ |
---|
| 450 | least=hist[j]; |
---|
| 451 | first=membership[j]; |
---|
| 452 | } |
---|
| 453 | least=-1; |
---|
| 454 | for(j=0;j<vals;j++) |
---|
| 455 | if((least==-1 || hist[j]<=least) && membership[j]!=first){ |
---|
| 456 | least=hist[j]; |
---|
| 457 | second=membership[j]; |
---|
| 458 | } |
---|
| 459 | if(first==-1 || second==-1){ |
---|
| 460 | fprintf(stderr,"huffman fault; no free branch\n"); |
---|
| 461 | exit(1); |
---|
| 462 | } |
---|
| 463 | |
---|
| 464 | /* join them */ |
---|
| 465 | least=hist[first]+hist[second]; |
---|
| 466 | for(j=0;j<vals;j++) |
---|
| 467 | if(membership[j]==first || membership[j]==second){ |
---|
| 468 | membership[j]=first; |
---|
| 469 | hist[j]=least; |
---|
| 470 | lengths[j]++; |
---|
| 471 | } |
---|
| 472 | } |
---|
| 473 | for(i=0;i<vals-1;i++) |
---|
| 474 | if(membership[i]!=membership[i+1]){ |
---|
| 475 | fprintf(stderr,"huffman fault; failed to build single tree\n"); |
---|
| 476 | exit(1); |
---|
| 477 | } |
---|
| 478 | |
---|
| 479 | /* for sanity check purposes: how many bits would it have taken to |
---|
| 480 | encode the training set? */ |
---|
| 481 | { |
---|
| 482 | long bitsum=0; |
---|
| 483 | long samples=0; |
---|
| 484 | for(i=0;i<vals;i++){ |
---|
| 485 | bitsum+=(histsave[i]-1)*lengths[i]; |
---|
| 486 | samples+=histsave[i]-1; |
---|
| 487 | } |
---|
| 488 | |
---|
| 489 | if(samples){ |
---|
| 490 | fprintf(stderr,"\rTotal samples in training set: %ld \n",samples); |
---|
| 491 | fprintf(stderr,"\rTotal bits used to represent training set: %ld\n", |
---|
| 492 | bitsum); |
---|
| 493 | } |
---|
| 494 | } |
---|
| 495 | |
---|
| 496 | free(membership); |
---|
| 497 | } |
---|
| 498 | |
---|
| 499 | /* wrap build_tree_from_lengths to allow zero entries in the histogram */ |
---|
| 500 | void build_tree_from_lengths0(int vals, long *hist, long *lengths){ |
---|
| 501 | |
---|
| 502 | /* pack the 'sparse' hit list into a dense list, then unpack |
---|
| 503 | the lengths after the build */ |
---|
| 504 | |
---|
| 505 | int upper=0,i; |
---|
| 506 | long *lengthlist=_ogg_calloc(vals,sizeof(long)); |
---|
| 507 | long *newhist=alloca(vals*sizeof(long)); |
---|
| 508 | |
---|
| 509 | for(i=0;i<vals;i++) |
---|
| 510 | if(hist[i]>0) |
---|
| 511 | newhist[upper++]=hist[i]; |
---|
| 512 | |
---|
| 513 | if(upper != vals){ |
---|
| 514 | fprintf(stderr,"\rEliminating %d unused entries; %d entries remain\n", |
---|
| 515 | vals-upper,upper); |
---|
| 516 | } |
---|
| 517 | |
---|
| 518 | build_tree_from_lengths(upper,newhist,lengthlist); |
---|
| 519 | |
---|
| 520 | upper=0; |
---|
| 521 | for(i=0;i<vals;i++) |
---|
| 522 | if(hist[i]>0) |
---|
| 523 | lengths[i]=lengthlist[upper++]; |
---|
| 524 | else |
---|
| 525 | lengths[i]=0; |
---|
| 526 | |
---|
| 527 | free(lengthlist); |
---|
| 528 | } |
---|
| 529 | |
---|
| 530 | void write_codebook(FILE *out,char *name,const static_codebook *c){ |
---|
| 531 | encode_aux_pigeonhole *p=c->pigeon_tree; |
---|
| 532 | encode_aux_threshmatch *t=c->thresh_tree; |
---|
| 533 | encode_aux_nearestmatch *n=c->nearest_tree; |
---|
| 534 | int i,j,k; |
---|
| 535 | |
---|
| 536 | /* save the book in C header form */ |
---|
| 537 | |
---|
| 538 | /* first, the static vectors, then the book structure to tie it together. */ |
---|
| 539 | /* quantlist */ |
---|
| 540 | if(c->quantlist){ |
---|
| 541 | long vals=(c->maptype==1?_book_maptype1_quantvals(c):c->entries*c->dim); |
---|
| 542 | fprintf(out,"static long _vq_quantlist_%s[] = {\n",name); |
---|
| 543 | for(j=0;j<vals;j++){ |
---|
| 544 | fprintf(out,"\t%ld,\n",c->quantlist[j]); |
---|
| 545 | } |
---|
| 546 | fprintf(out,"};\n\n"); |
---|
| 547 | } |
---|
| 548 | |
---|
| 549 | /* lengthlist */ |
---|
| 550 | fprintf(out,"static long _vq_lengthlist_%s[] = {\n",name); |
---|
| 551 | for(j=0;j<c->entries;){ |
---|
| 552 | fprintf(out,"\t"); |
---|
| 553 | for(k=0;k<16 && j<c->entries;k++,j++) |
---|
| 554 | fprintf(out,"%2ld,",c->lengthlist[j]); |
---|
| 555 | fprintf(out,"\n"); |
---|
| 556 | } |
---|
| 557 | fprintf(out,"};\n\n"); |
---|
| 558 | |
---|
| 559 | if(t){ |
---|
| 560 | /* quantthresh */ |
---|
| 561 | fprintf(out,"static float _vq_quantthresh_%s[] = {\n",name); |
---|
| 562 | for(j=0;j<t->threshvals-1;){ |
---|
| 563 | fprintf(out,"\t"); |
---|
| 564 | for(k=0;k<8 && j<t->threshvals-1;k++,j++) |
---|
| 565 | fprintf(out,"%.5g, ",t->quantthresh[j]); |
---|
| 566 | fprintf(out,"\n"); |
---|
| 567 | } |
---|
| 568 | fprintf(out,"};\n\n"); |
---|
| 569 | |
---|
| 570 | /* quantmap */ |
---|
| 571 | fprintf(out,"static long _vq_quantmap_%s[] = {\n",name); |
---|
| 572 | for(j=0;j<t->threshvals;){ |
---|
| 573 | fprintf(out,"\t"); |
---|
| 574 | for(k=0;k<8 && j<t->threshvals;k++,j++) |
---|
| 575 | fprintf(out,"%5ld,",t->quantmap[j]); |
---|
| 576 | fprintf(out,"\n"); |
---|
| 577 | } |
---|
| 578 | fprintf(out,"};\n\n"); |
---|
| 579 | |
---|
| 580 | fprintf(out,"static encode_aux_threshmatch _vq_auxt_%s = {\n",name); |
---|
| 581 | fprintf(out,"\t_vq_quantthresh_%s,\n",name); |
---|
| 582 | fprintf(out,"\t_vq_quantmap_%s,\n",name); |
---|
| 583 | fprintf(out,"\t%d,\n",t->quantvals); |
---|
| 584 | fprintf(out,"\t%d\n};\n\n",t->threshvals); |
---|
| 585 | } |
---|
| 586 | |
---|
| 587 | if(p){ |
---|
| 588 | int pigeons=1; |
---|
| 589 | for(i=0;i<c->dim;i++)pigeons*=p->quantvals; |
---|
| 590 | |
---|
| 591 | /* pigeonmap */ |
---|
| 592 | fprintf(out,"static long _vq_pigeonmap_%s[] = {\n",name); |
---|
| 593 | for(j=0;j<p->mapentries;){ |
---|
| 594 | fprintf(out,"\t"); |
---|
| 595 | for(k=0;k<8 && j<p->mapentries;k++,j++) |
---|
| 596 | fprintf(out,"%5ld, ",p->pigeonmap[j]); |
---|
| 597 | fprintf(out,"\n"); |
---|
| 598 | } |
---|
| 599 | fprintf(out,"};\n\n"); |
---|
| 600 | /* fitlist */ |
---|
| 601 | fprintf(out,"static long _vq_fitlist_%s[] = {\n",name); |
---|
| 602 | for(j=0;j<p->fittotal;){ |
---|
| 603 | fprintf(out,"\t"); |
---|
| 604 | for(k=0;k<8 && j<p->fittotal;k++,j++) |
---|
| 605 | fprintf(out,"%5ld, ",p->fitlist[j]); |
---|
| 606 | fprintf(out,"\n"); |
---|
| 607 | } |
---|
| 608 | fprintf(out,"};\n\n"); |
---|
| 609 | /* fitmap */ |
---|
| 610 | fprintf(out,"static long _vq_fitmap_%s[] = {\n",name); |
---|
| 611 | for(j=0;j<pigeons;){ |
---|
| 612 | fprintf(out,"\t"); |
---|
| 613 | for(k=0;k<8 && j<pigeons;k++,j++) |
---|
| 614 | fprintf(out,"%5ld, ",p->fitmap[j]); |
---|
| 615 | fprintf(out,"\n"); |
---|
| 616 | } |
---|
| 617 | fprintf(out,"};\n\n"); |
---|
| 618 | /* fitlength */ |
---|
| 619 | fprintf(out,"static long _vq_fitlength_%s[] = {\n",name); |
---|
| 620 | for(j=0;j<pigeons;){ |
---|
| 621 | fprintf(out,"\t"); |
---|
| 622 | for(k=0;k<8 && j<pigeons;k++,j++) |
---|
| 623 | fprintf(out,"%5ld, ",p->fitlength[j]); |
---|
| 624 | fprintf(out,"\n"); |
---|
| 625 | } |
---|
| 626 | fprintf(out,"};\n\n"); |
---|
| 627 | |
---|
| 628 | fprintf(out,"static encode_aux_pigeonhole _vq_auxp_%s = {\n",name); |
---|
| 629 | fprintf(out,"\t%g, %g, %d, %d,\n", |
---|
| 630 | p->min,p->del,p->mapentries,p->quantvals); |
---|
| 631 | |
---|
| 632 | fprintf(out,"\t_vq_pigeonmap_%s,\n",name); |
---|
| 633 | |
---|
| 634 | fprintf(out,"\t%ld,\n",p->fittotal); |
---|
| 635 | fprintf(out,"\t_vq_fitlist_%s,\n",name); |
---|
| 636 | fprintf(out,"\t_vq_fitmap_%s,\n",name); |
---|
| 637 | fprintf(out,"\t_vq_fitlength_%s\n};\n\n",name); |
---|
| 638 | } |
---|
| 639 | |
---|
| 640 | if(n){ |
---|
| 641 | |
---|
| 642 | /* ptr0 */ |
---|
| 643 | fprintf(out,"static long _vq_ptr0_%s[] = {\n",name); |
---|
| 644 | for(j=0;j<n->aux;){ |
---|
| 645 | fprintf(out,"\t"); |
---|
| 646 | for(k=0;k<8 && j<n->aux;k++,j++) |
---|
| 647 | fprintf(out,"%6ld,",n->ptr0[j]); |
---|
| 648 | fprintf(out,"\n"); |
---|
| 649 | } |
---|
| 650 | fprintf(out,"};\n\n"); |
---|
| 651 | |
---|
| 652 | /* ptr1 */ |
---|
| 653 | fprintf(out,"static long _vq_ptr1_%s[] = {\n",name); |
---|
| 654 | for(j=0;j<n->aux;){ |
---|
| 655 | fprintf(out,"\t"); |
---|
| 656 | for(k=0;k<8 && j<n->aux;k++,j++) |
---|
| 657 | fprintf(out,"%6ld,",n->ptr1[j]); |
---|
| 658 | fprintf(out,"\n"); |
---|
| 659 | } |
---|
| 660 | fprintf(out,"};\n\n"); |
---|
| 661 | |
---|
| 662 | /* p */ |
---|
| 663 | fprintf(out,"static long _vq_p_%s[] = {\n",name); |
---|
| 664 | for(j=0;j<n->aux;){ |
---|
| 665 | fprintf(out,"\t"); |
---|
| 666 | for(k=0;k<8 && j<n->aux;k++,j++) |
---|
| 667 | fprintf(out,"%6ld,",n->p[j]*c->dim); |
---|
| 668 | fprintf(out,"\n"); |
---|
| 669 | } |
---|
| 670 | fprintf(out,"};\n\n"); |
---|
| 671 | |
---|
| 672 | /* q */ |
---|
| 673 | fprintf(out,"static long _vq_q_%s[] = {\n",name); |
---|
| 674 | for(j=0;j<n->aux;){ |
---|
| 675 | fprintf(out,"\t"); |
---|
| 676 | for(k=0;k<8 && j<n->aux;k++,j++) |
---|
| 677 | fprintf(out,"%6ld,",n->q[j]*c->dim); |
---|
| 678 | fprintf(out,"\n"); |
---|
| 679 | } |
---|
| 680 | fprintf(out,"};\n\n"); |
---|
| 681 | |
---|
| 682 | fprintf(out,"static encode_aux_nearestmatch _vq_auxn_%s = {\n",name); |
---|
| 683 | fprintf(out,"\t_vq_ptr0_%s,\n",name); |
---|
| 684 | fprintf(out,"\t_vq_ptr1_%s,\n",name); |
---|
| 685 | fprintf(out,"\t_vq_p_%s,\n",name); |
---|
| 686 | fprintf(out,"\t_vq_q_%s,\n",name); |
---|
| 687 | fprintf(out,"\t%ld, %ld\n};\n\n",n->aux,n->aux); |
---|
| 688 | } |
---|
| 689 | |
---|
| 690 | /* tie it all together */ |
---|
| 691 | |
---|
| 692 | fprintf(out,"static static_codebook %s = {\n",name); |
---|
| 693 | |
---|
| 694 | fprintf(out,"\t%ld, %ld,\n",c->dim,c->entries); |
---|
| 695 | fprintf(out,"\t_vq_lengthlist_%s,\n",name); |
---|
| 696 | fprintf(out,"\t%d, %ld, %ld, %d, %d,\n", |
---|
| 697 | c->maptype,c->q_min,c->q_delta,c->q_quant,c->q_sequencep); |
---|
| 698 | if(c->quantlist) |
---|
| 699 | fprintf(out,"\t_vq_quantlist_%s,\n",name); |
---|
| 700 | else |
---|
| 701 | fprintf(out,"\tNULL,\n"); |
---|
| 702 | |
---|
| 703 | if(n) |
---|
| 704 | fprintf(out,"\t&_vq_auxn_%s,\n",name); |
---|
| 705 | else |
---|
| 706 | fprintf(out,"\tNULL,\n"); |
---|
| 707 | if(t) |
---|
| 708 | fprintf(out,"\t&_vq_auxt_%s,\n",name); |
---|
| 709 | else |
---|
| 710 | fprintf(out,"\tNULL,\n"); |
---|
| 711 | if(p) |
---|
| 712 | fprintf(out,"\t&_vq_auxp_%s,\n",name); |
---|
| 713 | else |
---|
| 714 | fprintf(out,"\tNULL,\n"); |
---|
| 715 | |
---|
| 716 | fprintf(out,"\t0\n};\n\n"); |
---|
| 717 | } |
---|