VirtualBox

source: vbox/trunk/src/libs/libvorbis-1.3.7/vq/bookutil.c@ 103131

Last change on this file since 103131 was 96468, checked in by vboxsync, 2 years ago

libs/libvorbis-1.3.7: Re-exporting, hopefully this time everything is there. bugref:10275

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette