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-2007 * |
---|
9 | * by the Xiph.Org Foundation http://www.xiph.org/ * |
---|
10 | * * |
---|
11 | ******************************************************************** |
---|
12 | |
---|
13 | function: basic shared codebook operations |
---|
14 | last mod: $Id: sharedbook.c 13293 2007-07-24 00:09:47Z xiphmont $ |
---|
15 | |
---|
16 | ********************************************************************/ |
---|
17 | |
---|
18 | #include <stdlib.h> |
---|
19 | #include <math.h> |
---|
20 | #include <string.h> |
---|
21 | #include <ogg/ogg.h> |
---|
22 | #include "os.h" |
---|
23 | #include "misc.h" |
---|
24 | #include "vorbis/codec.h" |
---|
25 | #include "codebook.h" |
---|
26 | #include "scales.h" |
---|
27 | |
---|
28 | /**** pack/unpack helpers ******************************************/ |
---|
29 | int _ilog(unsigned int v){ |
---|
30 | int ret=0; |
---|
31 | while(v){ |
---|
32 | ret++; |
---|
33 | v>>=1; |
---|
34 | } |
---|
35 | return(ret); |
---|
36 | } |
---|
37 | |
---|
38 | /* 32 bit float (not IEEE; nonnormalized mantissa + |
---|
39 | biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm |
---|
40 | Why not IEEE? It's just not that important here. */ |
---|
41 | |
---|
42 | #define VQ_FEXP 10 |
---|
43 | #define VQ_FMAN 21 |
---|
44 | #define VQ_FEXP_BIAS 768 /* bias toward values smaller than 1. */ |
---|
45 | |
---|
46 | /* doesn't currently guard under/overflow */ |
---|
47 | long _float32_pack(float val){ |
---|
48 | int sign=0; |
---|
49 | long exp; |
---|
50 | long mant; |
---|
51 | if(val<0){ |
---|
52 | sign=0x80000000; |
---|
53 | val= -val; |
---|
54 | } |
---|
55 | exp= floor(log(val)/log(2.f)); |
---|
56 | mant=rint(ldexp(val,(VQ_FMAN-1)-exp)); |
---|
57 | exp=(exp+VQ_FEXP_BIAS)<<VQ_FMAN; |
---|
58 | |
---|
59 | return(sign|exp|mant); |
---|
60 | } |
---|
61 | |
---|
62 | float _float32_unpack(long val){ |
---|
63 | double mant=val&0x1fffff; |
---|
64 | int sign=val&0x80000000; |
---|
65 | long exp =(val&0x7fe00000L)>>VQ_FMAN; |
---|
66 | if(sign)mant= -mant; |
---|
67 | return(ldexp(mant,exp-(VQ_FMAN-1)-VQ_FEXP_BIAS)); |
---|
68 | } |
---|
69 | |
---|
70 | /* given a list of word lengths, generate a list of codewords. Works |
---|
71 | for length ordered or unordered, always assigns the lowest valued |
---|
72 | codewords first. Extended to handle unused entries (length 0) */ |
---|
73 | ogg_uint32_t *_make_words(long *l,long n,long sparsecount){ |
---|
74 | long i,j,count=0; |
---|
75 | ogg_uint32_t marker[33]; |
---|
76 | ogg_uint32_t *r=_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r)); |
---|
77 | memset(marker,0,sizeof(marker)); |
---|
78 | |
---|
79 | for(i=0;i<n;i++){ |
---|
80 | long length=l[i]; |
---|
81 | if(length>0){ |
---|
82 | ogg_uint32_t entry=marker[length]; |
---|
83 | |
---|
84 | /* when we claim a node for an entry, we also claim the nodes |
---|
85 | below it (pruning off the imagined tree that may have dangled |
---|
86 | from it) as well as blocking the use of any nodes directly |
---|
87 | above for leaves */ |
---|
88 | |
---|
89 | /* update ourself */ |
---|
90 | if(length<32 && (entry>>length)){ |
---|
91 | /* error condition; the lengths must specify an overpopulated tree */ |
---|
92 | _ogg_free(r); |
---|
93 | return(NULL); |
---|
94 | } |
---|
95 | r[count++]=entry; |
---|
96 | |
---|
97 | /* Look to see if the next shorter marker points to the node |
---|
98 | above. if so, update it and repeat. */ |
---|
99 | { |
---|
100 | for(j=length;j>0;j--){ |
---|
101 | |
---|
102 | if(marker[j]&1){ |
---|
103 | /* have to jump branches */ |
---|
104 | if(j==1) |
---|
105 | marker[1]++; |
---|
106 | else |
---|
107 | marker[j]=marker[j-1]<<1; |
---|
108 | break; /* invariant says next upper marker would already |
---|
109 | have been moved if it was on the same path */ |
---|
110 | } |
---|
111 | marker[j]++; |
---|
112 | } |
---|
113 | } |
---|
114 | |
---|
115 | /* prune the tree; the implicit invariant says all the longer |
---|
116 | markers were dangling from our just-taken node. Dangle them |
---|
117 | from our *new* node. */ |
---|
118 | for(j=length+1;j<33;j++) |
---|
119 | if((marker[j]>>1) == entry){ |
---|
120 | entry=marker[j]; |
---|
121 | marker[j]=marker[j-1]<<1; |
---|
122 | }else |
---|
123 | break; |
---|
124 | }else |
---|
125 | if(sparsecount==0)count++; |
---|
126 | } |
---|
127 | |
---|
128 | /* bitreverse the words because our bitwise packer/unpacker is LSb |
---|
129 | endian */ |
---|
130 | for(i=0,count=0;i<n;i++){ |
---|
131 | ogg_uint32_t temp=0; |
---|
132 | for(j=0;j<l[i];j++){ |
---|
133 | temp<<=1; |
---|
134 | temp|=(r[count]>>j)&1; |
---|
135 | } |
---|
136 | |
---|
137 | if(sparsecount){ |
---|
138 | if(l[i]) |
---|
139 | r[count++]=temp; |
---|
140 | }else |
---|
141 | r[count++]=temp; |
---|
142 | } |
---|
143 | |
---|
144 | return(r); |
---|
145 | } |
---|
146 | |
---|
147 | /* there might be a straightforward one-line way to do the below |
---|
148 | that's portable and totally safe against roundoff, but I haven't |
---|
149 | thought of it. Therefore, we opt on the side of caution */ |
---|
150 | long _book_maptype1_quantvals(const static_codebook *b){ |
---|
151 | long vals=floor(pow((float)b->entries,1.f/b->dim)); |
---|
152 | |
---|
153 | /* the above *should* be reliable, but we'll not assume that FP is |
---|
154 | ever reliable when bitstream sync is at stake; verify via integer |
---|
155 | means that vals really is the greatest value of dim for which |
---|
156 | vals^b->bim <= b->entries */ |
---|
157 | /* treat the above as an initial guess */ |
---|
158 | while(1){ |
---|
159 | long acc=1; |
---|
160 | long acc1=1; |
---|
161 | int i; |
---|
162 | for(i=0;i<b->dim;i++){ |
---|
163 | acc*=vals; |
---|
164 | acc1*=vals+1; |
---|
165 | } |
---|
166 | if(acc<=b->entries && acc1>b->entries){ |
---|
167 | return(vals); |
---|
168 | }else{ |
---|
169 | if(acc>b->entries){ |
---|
170 | vals--; |
---|
171 | }else{ |
---|
172 | vals++; |
---|
173 | } |
---|
174 | } |
---|
175 | } |
---|
176 | } |
---|
177 | |
---|
178 | /* unpack the quantized list of values for encode/decode ***********/ |
---|
179 | /* we need to deal with two map types: in map type 1, the values are |
---|
180 | generated algorithmically (each column of the vector counts through |
---|
181 | the values in the quant vector). in map type 2, all the values came |
---|
182 | in in an explicit list. Both value lists must be unpacked */ |
---|
183 | float *_book_unquantize(const static_codebook *b,int n,int *sparsemap){ |
---|
184 | long j,k,count=0; |
---|
185 | if(b->maptype==1 || b->maptype==2){ |
---|
186 | int quantvals; |
---|
187 | float mindel=_float32_unpack(b->q_min); |
---|
188 | float delta=_float32_unpack(b->q_delta); |
---|
189 | float *r=_ogg_calloc(n*b->dim,sizeof(*r)); |
---|
190 | |
---|
191 | /* maptype 1 and 2 both use a quantized value vector, but |
---|
192 | different sizes */ |
---|
193 | switch(b->maptype){ |
---|
194 | case 1: |
---|
195 | /* most of the time, entries%dimensions == 0, but we need to be |
---|
196 | well defined. We define that the possible vales at each |
---|
197 | scalar is values == entries/dim. If entries%dim != 0, we'll |
---|
198 | have 'too few' values (values*dim<entries), which means that |
---|
199 | we'll have 'left over' entries; left over entries use zeroed |
---|
200 | values (and are wasted). So don't generate codebooks like |
---|
201 | that */ |
---|
202 | quantvals=_book_maptype1_quantvals(b); |
---|
203 | for(j=0;j<b->entries;j++){ |
---|
204 | if((sparsemap && b->lengthlist[j]) || !sparsemap){ |
---|
205 | float last=0.f; |
---|
206 | int indexdiv=1; |
---|
207 | for(k=0;k<b->dim;k++){ |
---|
208 | int index= (j/indexdiv)%quantvals; |
---|
209 | float val=b->quantlist[index]; |
---|
210 | val=fabs(val)*delta+mindel+last; |
---|
211 | if(b->q_sequencep)last=val; |
---|
212 | if(sparsemap) |
---|
213 | r[sparsemap[count]*b->dim+k]=val; |
---|
214 | else |
---|
215 | r[count*b->dim+k]=val; |
---|
216 | indexdiv*=quantvals; |
---|
217 | } |
---|
218 | count++; |
---|
219 | } |
---|
220 | |
---|
221 | } |
---|
222 | break; |
---|
223 | case 2: |
---|
224 | for(j=0;j<b->entries;j++){ |
---|
225 | if((sparsemap && b->lengthlist[j]) || !sparsemap){ |
---|
226 | float last=0.f; |
---|
227 | |
---|
228 | for(k=0;k<b->dim;k++){ |
---|
229 | float val=b->quantlist[j*b->dim+k]; |
---|
230 | val=fabs(val)*delta+mindel+last; |
---|
231 | if(b->q_sequencep)last=val; |
---|
232 | if(sparsemap) |
---|
233 | r[sparsemap[count]*b->dim+k]=val; |
---|
234 | else |
---|
235 | r[count*b->dim+k]=val; |
---|
236 | } |
---|
237 | count++; |
---|
238 | } |
---|
239 | } |
---|
240 | break; |
---|
241 | } |
---|
242 | |
---|
243 | return(r); |
---|
244 | } |
---|
245 | return(NULL); |
---|
246 | } |
---|
247 | |
---|
248 | void vorbis_staticbook_clear(static_codebook *b){ |
---|
249 | if(b->allocedp){ |
---|
250 | if(b->quantlist)_ogg_free(b->quantlist); |
---|
251 | if(b->lengthlist)_ogg_free(b->lengthlist); |
---|
252 | if(b->nearest_tree){ |
---|
253 | _ogg_free(b->nearest_tree->ptr0); |
---|
254 | _ogg_free(b->nearest_tree->ptr1); |
---|
255 | _ogg_free(b->nearest_tree->p); |
---|
256 | _ogg_free(b->nearest_tree->q); |
---|
257 | memset(b->nearest_tree,0,sizeof(*b->nearest_tree)); |
---|
258 | _ogg_free(b->nearest_tree); |
---|
259 | } |
---|
260 | if(b->thresh_tree){ |
---|
261 | _ogg_free(b->thresh_tree->quantthresh); |
---|
262 | _ogg_free(b->thresh_tree->quantmap); |
---|
263 | memset(b->thresh_tree,0,sizeof(*b->thresh_tree)); |
---|
264 | _ogg_free(b->thresh_tree); |
---|
265 | } |
---|
266 | |
---|
267 | memset(b,0,sizeof(*b)); |
---|
268 | } |
---|
269 | } |
---|
270 | |
---|
271 | void vorbis_staticbook_destroy(static_codebook *b){ |
---|
272 | if(b->allocedp){ |
---|
273 | vorbis_staticbook_clear(b); |
---|
274 | _ogg_free(b); |
---|
275 | } |
---|
276 | } |
---|
277 | |
---|
278 | void vorbis_book_clear(codebook *b){ |
---|
279 | /* static book is not cleared; we're likely called on the lookup and |
---|
280 | the static codebook belongs to the info struct */ |
---|
281 | if(b->valuelist)_ogg_free(b->valuelist); |
---|
282 | if(b->codelist)_ogg_free(b->codelist); |
---|
283 | |
---|
284 | if(b->dec_index)_ogg_free(b->dec_index); |
---|
285 | if(b->dec_codelengths)_ogg_free(b->dec_codelengths); |
---|
286 | if(b->dec_firsttable)_ogg_free(b->dec_firsttable); |
---|
287 | |
---|
288 | memset(b,0,sizeof(*b)); |
---|
289 | } |
---|
290 | |
---|
291 | int vorbis_book_init_encode(codebook *c,const static_codebook *s){ |
---|
292 | |
---|
293 | memset(c,0,sizeof(*c)); |
---|
294 | c->c=s; |
---|
295 | c->entries=s->entries; |
---|
296 | c->used_entries=s->entries; |
---|
297 | c->dim=s->dim; |
---|
298 | c->codelist=_make_words(s->lengthlist,s->entries,0); |
---|
299 | c->valuelist=_book_unquantize(s,s->entries,NULL); |
---|
300 | |
---|
301 | return(0); |
---|
302 | } |
---|
303 | |
---|
304 | static ogg_uint32_t bitreverse(ogg_uint32_t x){ |
---|
305 | x= ((x>>16)&0x0000ffffUL) | ((x<<16)&0xffff0000UL); |
---|
306 | x= ((x>> 8)&0x00ff00ffUL) | ((x<< 8)&0xff00ff00UL); |
---|
307 | x= ((x>> 4)&0x0f0f0f0fUL) | ((x<< 4)&0xf0f0f0f0UL); |
---|
308 | x= ((x>> 2)&0x33333333UL) | ((x<< 2)&0xccccccccUL); |
---|
309 | return((x>> 1)&0x55555555UL) | ((x<< 1)&0xaaaaaaaaUL); |
---|
310 | } |
---|
311 | |
---|
312 | static int sort32a(const void *a,const void *b){ |
---|
313 | return ( **(ogg_uint32_t **)a>**(ogg_uint32_t **)b)- |
---|
314 | ( **(ogg_uint32_t **)a<**(ogg_uint32_t **)b); |
---|
315 | } |
---|
316 | |
---|
317 | /* decode codebook arrangement is more heavily optimized than encode */ |
---|
318 | int vorbis_book_init_decode(codebook *c,const static_codebook *s){ |
---|
319 | int i,j,n=0,tabn; |
---|
320 | int *sortindex; |
---|
321 | memset(c,0,sizeof(*c)); |
---|
322 | |
---|
323 | /* count actually used entries */ |
---|
324 | for(i=0;i<s->entries;i++) |
---|
325 | if(s->lengthlist[i]>0) |
---|
326 | n++; |
---|
327 | |
---|
328 | c->entries=s->entries; |
---|
329 | c->used_entries=n; |
---|
330 | c->dim=s->dim; |
---|
331 | |
---|
332 | if(n>0){ |
---|
333 | |
---|
334 | /* two different remappings go on here. |
---|
335 | |
---|
336 | First, we collapse the likely sparse codebook down only to |
---|
337 | actually represented values/words. This collapsing needs to be |
---|
338 | indexed as map-valueless books are used to encode original entry |
---|
339 | positions as integers. |
---|
340 | |
---|
341 | Second, we reorder all vectors, including the entry index above, |
---|
342 | by sorted bitreversed codeword to allow treeless decode. */ |
---|
343 | |
---|
344 | /* perform sort */ |
---|
345 | ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries); |
---|
346 | ogg_uint32_t **codep=alloca(sizeof(*codep)*n); |
---|
347 | |
---|
348 | if(codes==NULL)goto err_out; |
---|
349 | |
---|
350 | for(i=0;i<n;i++){ |
---|
351 | codes[i]=bitreverse(codes[i]); |
---|
352 | codep[i]=codes+i; |
---|
353 | } |
---|
354 | |
---|
355 | qsort(codep,n,sizeof(*codep),sort32a); |
---|
356 | |
---|
357 | sortindex=alloca(n*sizeof(*sortindex)); |
---|
358 | c->codelist=_ogg_malloc(n*sizeof(*c->codelist)); |
---|
359 | /* the index is a reverse index */ |
---|
360 | for(i=0;i<n;i++){ |
---|
361 | int position=codep[i]-codes; |
---|
362 | sortindex[position]=i; |
---|
363 | } |
---|
364 | |
---|
365 | for(i=0;i<n;i++) |
---|
366 | c->codelist[sortindex[i]]=codes[i]; |
---|
367 | _ogg_free(codes); |
---|
368 | |
---|
369 | |
---|
370 | c->valuelist=_book_unquantize(s,n,sortindex); |
---|
371 | c->dec_index=_ogg_malloc(n*sizeof(*c->dec_index)); |
---|
372 | |
---|
373 | for(n=0,i=0;i<s->entries;i++) |
---|
374 | if(s->lengthlist[i]>0) |
---|
375 | c->dec_index[sortindex[n++]]=i; |
---|
376 | |
---|
377 | c->dec_codelengths=_ogg_malloc(n*sizeof(*c->dec_codelengths)); |
---|
378 | for(n=0,i=0;i<s->entries;i++) |
---|
379 | if(s->lengthlist[i]>0) |
---|
380 | c->dec_codelengths[sortindex[n++]]=s->lengthlist[i]; |
---|
381 | |
---|
382 | c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */ |
---|
383 | if(c->dec_firsttablen<5)c->dec_firsttablen=5; |
---|
384 | if(c->dec_firsttablen>8)c->dec_firsttablen=8; |
---|
385 | |
---|
386 | tabn=1<<c->dec_firsttablen; |
---|
387 | c->dec_firsttable=_ogg_calloc(tabn,sizeof(*c->dec_firsttable)); |
---|
388 | c->dec_maxlength=0; |
---|
389 | |
---|
390 | for(i=0;i<n;i++){ |
---|
391 | if(c->dec_maxlength<c->dec_codelengths[i]) |
---|
392 | c->dec_maxlength=c->dec_codelengths[i]; |
---|
393 | if(c->dec_codelengths[i]<=c->dec_firsttablen){ |
---|
394 | ogg_uint32_t orig=bitreverse(c->codelist[i]); |
---|
395 | for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++) |
---|
396 | c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1; |
---|
397 | } |
---|
398 | } |
---|
399 | |
---|
400 | /* now fill in 'unused' entries in the firsttable with hi/lo search |
---|
401 | hints for the non-direct-hits */ |
---|
402 | { |
---|
403 | ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen); |
---|
404 | long lo=0,hi=0; |
---|
405 | |
---|
406 | for(i=0;i<tabn;i++){ |
---|
407 | ogg_uint32_t word=i<<(32-c->dec_firsttablen); |
---|
408 | if(c->dec_firsttable[bitreverse(word)]==0){ |
---|
409 | while((lo+1)<n && c->codelist[lo+1]<=word)lo++; |
---|
410 | while( hi<n && word>=(c->codelist[hi]&mask))hi++; |
---|
411 | |
---|
412 | /* we only actually have 15 bits per hint to play with here. |
---|
413 | In order to overflow gracefully (nothing breaks, efficiency |
---|
414 | just drops), encode as the difference from the extremes. */ |
---|
415 | { |
---|
416 | unsigned long loval=lo; |
---|
417 | unsigned long hival=n-hi; |
---|
418 | |
---|
419 | if(loval>0x7fff)loval=0x7fff; |
---|
420 | if(hival>0x7fff)hival=0x7fff; |
---|
421 | c->dec_firsttable[bitreverse(word)]= |
---|
422 | 0x80000000UL | (loval<<15) | hival; |
---|
423 | } |
---|
424 | } |
---|
425 | } |
---|
426 | } |
---|
427 | } |
---|
428 | |
---|
429 | return(0); |
---|
430 | err_out: |
---|
431 | vorbis_book_clear(c); |
---|
432 | return(-1); |
---|
433 | } |
---|
434 | |
---|
435 | static float _dist(int el,float *ref, float *b,int step){ |
---|
436 | int i; |
---|
437 | float acc=0.f; |
---|
438 | for(i=0;i<el;i++){ |
---|
439 | float val=(ref[i]-b[i*step]); |
---|
440 | acc+=val*val; |
---|
441 | } |
---|
442 | return(acc); |
---|
443 | } |
---|
444 | |
---|
445 | int _best(codebook *book, float *a, int step){ |
---|
446 | encode_aux_threshmatch *tt=book->c->thresh_tree; |
---|
447 | |
---|
448 | #if 0 |
---|
449 | encode_aux_nearestmatch *nt=book->c->nearest_tree; |
---|
450 | encode_aux_pigeonhole *pt=book->c->pigeon_tree; |
---|
451 | #endif |
---|
452 | int dim=book->dim; |
---|
453 | int k,o; |
---|
454 | /*int savebest=-1; |
---|
455 | float saverr;*/ |
---|
456 | |
---|
457 | /* do we have a threshhold encode hint? */ |
---|
458 | if(tt){ |
---|
459 | int index=0,i; |
---|
460 | /* find the quant val of each scalar */ |
---|
461 | for(k=0,o=step*(dim-1);k<dim;k++,o-=step){ |
---|
462 | |
---|
463 | i=tt->threshvals>>1; |
---|
464 | if(a[o]<tt->quantthresh[i]){ |
---|
465 | |
---|
466 | for(;i>0;i--) |
---|
467 | if(a[o]>=tt->quantthresh[i-1]) |
---|
468 | break; |
---|
469 | |
---|
470 | }else{ |
---|
471 | |
---|
472 | for(i++;i<tt->threshvals-1;i++) |
---|
473 | if(a[o]<tt->quantthresh[i])break; |
---|
474 | |
---|
475 | } |
---|
476 | |
---|
477 | index=(index*tt->quantvals)+tt->quantmap[i]; |
---|
478 | } |
---|
479 | /* regular lattices are easy :-) */ |
---|
480 | if(book->c->lengthlist[index]>0) /* is this unused? If so, we'll |
---|
481 | use a decision tree after all |
---|
482 | and fall through*/ |
---|
483 | return(index); |
---|
484 | } |
---|
485 | |
---|
486 | #if 0 |
---|
487 | /* do we have a pigeonhole encode hint? */ |
---|
488 | if(pt){ |
---|
489 | const static_codebook *c=book->c; |
---|
490 | int i,besti=-1; |
---|
491 | float best=0.f; |
---|
492 | int entry=0; |
---|
493 | |
---|
494 | /* dealing with sequentialness is a pain in the ass */ |
---|
495 | if(c->q_sequencep){ |
---|
496 | int pv; |
---|
497 | long mul=1; |
---|
498 | float qlast=0; |
---|
499 | for(k=0,o=0;k<dim;k++,o+=step){ |
---|
500 | pv=(int)((a[o]-qlast-pt->min)/pt->del); |
---|
501 | if(pv<0 || pv>=pt->mapentries)break; |
---|
502 | entry+=pt->pigeonmap[pv]*mul; |
---|
503 | mul*=pt->quantvals; |
---|
504 | qlast+=pv*pt->del+pt->min; |
---|
505 | } |
---|
506 | }else{ |
---|
507 | for(k=0,o=step*(dim-1);k<dim;k++,o-=step){ |
---|
508 | int pv=(int)((a[o]-pt->min)/pt->del); |
---|
509 | if(pv<0 || pv>=pt->mapentries)break; |
---|
510 | entry=entry*pt->quantvals+pt->pigeonmap[pv]; |
---|
511 | } |
---|
512 | } |
---|
513 | |
---|
514 | /* must be within the pigeonholable range; if we quant outside (or |
---|
515 | in an entry that we define no list for), brute force it */ |
---|
516 | if(k==dim && pt->fitlength[entry]){ |
---|
517 | /* search the abbreviated list */ |
---|
518 | long *list=pt->fitlist+pt->fitmap[entry]; |
---|
519 | for(i=0;i<pt->fitlength[entry];i++){ |
---|
520 | float this=_dist(dim,book->valuelist+list[i]*dim,a,step); |
---|
521 | if(besti==-1 || this<best){ |
---|
522 | best=this; |
---|
523 | besti=list[i]; |
---|
524 | } |
---|
525 | } |
---|
526 | |
---|
527 | return(besti); |
---|
528 | } |
---|
529 | } |
---|
530 | |
---|
531 | if(nt){ |
---|
532 | /* optimized using the decision tree */ |
---|
533 | while(1){ |
---|
534 | float c=0.f; |
---|
535 | float *p=book->valuelist+nt->p[ptr]; |
---|
536 | float *q=book->valuelist+nt->q[ptr]; |
---|
537 | |
---|
538 | for(k=0,o=0;k<dim;k++,o+=step) |
---|
539 | c+=(p[k]-q[k])*(a[o]-(p[k]+q[k])*.5); |
---|
540 | |
---|
541 | if(c>0.f) /* in A */ |
---|
542 | ptr= -nt->ptr0[ptr]; |
---|
543 | else /* in B */ |
---|
544 | ptr= -nt->ptr1[ptr]; |
---|
545 | if(ptr<=0)break; |
---|
546 | } |
---|
547 | return(-ptr); |
---|
548 | } |
---|
549 | #endif |
---|
550 | |
---|
551 | /* brute force it! */ |
---|
552 | { |
---|
553 | const static_codebook *c=book->c; |
---|
554 | int i,besti=-1; |
---|
555 | float best=0.f; |
---|
556 | float *e=book->valuelist; |
---|
557 | for(i=0;i<book->entries;i++){ |
---|
558 | if(c->lengthlist[i]>0){ |
---|
559 | float this=_dist(dim,e,a,step); |
---|
560 | if(besti==-1 || this<best){ |
---|
561 | best=this; |
---|
562 | besti=i; |
---|
563 | } |
---|
564 | } |
---|
565 | e+=dim; |
---|
566 | } |
---|
567 | |
---|
568 | /*if(savebest!=-1 && savebest!=besti){ |
---|
569 | fprintf(stderr,"brute force/pigeonhole disagreement:\n" |
---|
570 | "original:"); |
---|
571 | for(i=0;i<dim*step;i+=step)fprintf(stderr,"%g,",a[i]); |
---|
572 | fprintf(stderr,"\n" |
---|
573 | "pigeonhole (entry %d, err %g):",savebest,saverr); |
---|
574 | for(i=0;i<dim;i++)fprintf(stderr,"%g,", |
---|
575 | (book->valuelist+savebest*dim)[i]); |
---|
576 | fprintf(stderr,"\n" |
---|
577 | "bruteforce (entry %d, err %g):",besti,best); |
---|
578 | for(i=0;i<dim;i++)fprintf(stderr,"%g,", |
---|
579 | (book->valuelist+besti*dim)[i]); |
---|
580 | fprintf(stderr,"\n"); |
---|
581 | }*/ |
---|
582 | return(besti); |
---|
583 | } |
---|
584 | } |
---|
585 | |
---|
586 | long vorbis_book_codeword(codebook *book,int entry){ |
---|
587 | if(book->c) /* only use with encode; decode optimizations are |
---|
588 | allowed to break this */ |
---|
589 | return book->codelist[entry]; |
---|
590 | return -1; |
---|
591 | } |
---|
592 | |
---|
593 | long vorbis_book_codelen(codebook *book,int entry){ |
---|
594 | if(book->c) /* only use with encode; decode optimizations are |
---|
595 | allowed to break this */ |
---|
596 | return book->c->lengthlist[entry]; |
---|
597 | return -1; |
---|
598 | } |
---|
599 | |
---|
600 | #ifdef _V_SELFTEST |
---|
601 | |
---|
602 | /* Unit tests of the dequantizer; this stuff will be OK |
---|
603 | cross-platform, I simply want to be sure that special mapping cases |
---|
604 | actually work properly; a bug could go unnoticed for a while */ |
---|
605 | |
---|
606 | #include <stdio.h> |
---|
607 | |
---|
608 | /* cases: |
---|
609 | |
---|
610 | no mapping |
---|
611 | full, explicit mapping |
---|
612 | algorithmic mapping |
---|
613 | |
---|
614 | nonsequential |
---|
615 | sequential |
---|
616 | */ |
---|
617 | |
---|
618 | static long full_quantlist1[]={0,1,2,3, 4,5,6,7, 8,3,6,1}; |
---|
619 | static long partial_quantlist1[]={0,7,2}; |
---|
620 | |
---|
621 | /* no mapping */ |
---|
622 | static_codebook test1={ |
---|
623 | 4,16, |
---|
624 | NULL, |
---|
625 | 0, |
---|
626 | 0,0,0,0, |
---|
627 | NULL, |
---|
628 | NULL,NULL |
---|
629 | }; |
---|
630 | static float *test1_result=NULL; |
---|
631 | |
---|
632 | /* linear, full mapping, nonsequential */ |
---|
633 | static_codebook test2={ |
---|
634 | 4,3, |
---|
635 | NULL, |
---|
636 | 2, |
---|
637 | -533200896,1611661312,4,0, |
---|
638 | full_quantlist1, |
---|
639 | NULL,NULL |
---|
640 | }; |
---|
641 | static float test2_result[]={-3,-2,-1,0, 1,2,3,4, 5,0,3,-2}; |
---|
642 | |
---|
643 | /* linear, full mapping, sequential */ |
---|
644 | static_codebook test3={ |
---|
645 | 4,3, |
---|
646 | NULL, |
---|
647 | 2, |
---|
648 | -533200896,1611661312,4,1, |
---|
649 | full_quantlist1, |
---|
650 | NULL,NULL |
---|
651 | }; |
---|
652 | static float test3_result[]={-3,-5,-6,-6, 1,3,6,10, 5,5,8,6}; |
---|
653 | |
---|
654 | /* linear, algorithmic mapping, nonsequential */ |
---|
655 | static_codebook test4={ |
---|
656 | 3,27, |
---|
657 | NULL, |
---|
658 | 1, |
---|
659 | -533200896,1611661312,4,0, |
---|
660 | partial_quantlist1, |
---|
661 | NULL,NULL |
---|
662 | }; |
---|
663 | static float test4_result[]={-3,-3,-3, 4,-3,-3, -1,-3,-3, |
---|
664 | -3, 4,-3, 4, 4,-3, -1, 4,-3, |
---|
665 | -3,-1,-3, 4,-1,-3, -1,-1,-3, |
---|
666 | -3,-3, 4, 4,-3, 4, -1,-3, 4, |
---|
667 | -3, 4, 4, 4, 4, 4, -1, 4, 4, |
---|
668 | -3,-1, 4, 4,-1, 4, -1,-1, 4, |
---|
669 | -3,-3,-1, 4,-3,-1, -1,-3,-1, |
---|
670 | -3, 4,-1, 4, 4,-1, -1, 4,-1, |
---|
671 | -3,-1,-1, 4,-1,-1, -1,-1,-1}; |
---|
672 | |
---|
673 | /* linear, algorithmic mapping, sequential */ |
---|
674 | static_codebook test5={ |
---|
675 | 3,27, |
---|
676 | NULL, |
---|
677 | 1, |
---|
678 | -533200896,1611661312,4,1, |
---|
679 | partial_quantlist1, |
---|
680 | NULL,NULL |
---|
681 | }; |
---|
682 | static float test5_result[]={-3,-6,-9, 4, 1,-2, -1,-4,-7, |
---|
683 | -3, 1,-2, 4, 8, 5, -1, 3, 0, |
---|
684 | -3,-4,-7, 4, 3, 0, -1,-2,-5, |
---|
685 | -3,-6,-2, 4, 1, 5, -1,-4, 0, |
---|
686 | -3, 1, 5, 4, 8,12, -1, 3, 7, |
---|
687 | -3,-4, 0, 4, 3, 7, -1,-2, 2, |
---|
688 | -3,-6,-7, 4, 1, 0, -1,-4,-5, |
---|
689 | -3, 1, 0, 4, 8, 7, -1, 3, 2, |
---|
690 | -3,-4,-5, 4, 3, 2, -1,-2,-3}; |
---|
691 | |
---|
692 | void run_test(static_codebook *b,float *comp){ |
---|
693 | float *out=_book_unquantize(b,b->entries,NULL); |
---|
694 | int i; |
---|
695 | |
---|
696 | if(comp){ |
---|
697 | if(!out){ |
---|
698 | fprintf(stderr,"_book_unquantize incorrectly returned NULL\n"); |
---|
699 | exit(1); |
---|
700 | } |
---|
701 | |
---|
702 | for(i=0;i<b->entries*b->dim;i++) |
---|
703 | if(fabs(out[i]-comp[i])>.0001){ |
---|
704 | fprintf(stderr,"disagreement in unquantized and reference data:\n" |
---|
705 | "position %d, %g != %g\n",i,out[i],comp[i]); |
---|
706 | exit(1); |
---|
707 | } |
---|
708 | |
---|
709 | }else{ |
---|
710 | if(out){ |
---|
711 | fprintf(stderr,"_book_unquantize returned a value array: \n" |
---|
712 | " correct result should have been NULL\n"); |
---|
713 | exit(1); |
---|
714 | } |
---|
715 | } |
---|
716 | } |
---|
717 | |
---|
718 | int main(){ |
---|
719 | /* run the nine dequant tests, and compare to the hand-rolled results */ |
---|
720 | fprintf(stderr,"Dequant test 1... "); |
---|
721 | run_test(&test1,test1_result); |
---|
722 | fprintf(stderr,"OK\nDequant test 2... "); |
---|
723 | run_test(&test2,test2_result); |
---|
724 | fprintf(stderr,"OK\nDequant test 3... "); |
---|
725 | run_test(&test3,test3_result); |
---|
726 | fprintf(stderr,"OK\nDequant test 4... "); |
---|
727 | run_test(&test4,test4_result); |
---|
728 | fprintf(stderr,"OK\nDequant test 5... "); |
---|
729 | run_test(&test5,test5_result); |
---|
730 | fprintf(stderr,"OK\n\n"); |
---|
731 | |
---|
732 | return(0); |
---|
733 | } |
---|
734 | |
---|
735 | #endif |
---|