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 codebook pack/unpack/code/decode operations |
---|
14 | last mod: $Id: codebook.c 13293 2007-07-24 00:09:47Z xiphmont $ |
---|
15 | |
---|
16 | ********************************************************************/ |
---|
17 | |
---|
18 | #include <stdlib.h> |
---|
19 | #include <string.h> |
---|
20 | #include <math.h> |
---|
21 | #include <ogg/ogg.h> |
---|
22 | #include "vorbis/codec.h" |
---|
23 | #include "codebook.h" |
---|
24 | #include "scales.h" |
---|
25 | #include "misc.h" |
---|
26 | #include "os.h" |
---|
27 | |
---|
28 | /* packs the given codebook into the bitstream **************************/ |
---|
29 | |
---|
30 | int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *opb){ |
---|
31 | long i,j; |
---|
32 | int ordered=0; |
---|
33 | |
---|
34 | /* first the basic parameters */ |
---|
35 | oggpack_write(opb,0x564342,24); |
---|
36 | oggpack_write(opb,c->dim,16); |
---|
37 | oggpack_write(opb,c->entries,24); |
---|
38 | |
---|
39 | /* pack the codewords. There are two packings; length ordered and |
---|
40 | length random. Decide between the two now. */ |
---|
41 | |
---|
42 | for(i=1;i<c->entries;i++) |
---|
43 | if(c->lengthlist[i-1]==0 || c->lengthlist[i]<c->lengthlist[i-1])break; |
---|
44 | if(i==c->entries)ordered=1; |
---|
45 | |
---|
46 | if(ordered){ |
---|
47 | /* length ordered. We only need to say how many codewords of |
---|
48 | each length. The actual codewords are generated |
---|
49 | deterministically */ |
---|
50 | |
---|
51 | long count=0; |
---|
52 | oggpack_write(opb,1,1); /* ordered */ |
---|
53 | oggpack_write(opb,c->lengthlist[0]-1,5); /* 1 to 32 */ |
---|
54 | |
---|
55 | for(i=1;i<c->entries;i++){ |
---|
56 | long this=c->lengthlist[i]; |
---|
57 | long last=c->lengthlist[i-1]; |
---|
58 | if(this>last){ |
---|
59 | for(j=last;j<this;j++){ |
---|
60 | oggpack_write(opb,i-count,_ilog(c->entries-count)); |
---|
61 | count=i; |
---|
62 | } |
---|
63 | } |
---|
64 | } |
---|
65 | oggpack_write(opb,i-count,_ilog(c->entries-count)); |
---|
66 | |
---|
67 | }else{ |
---|
68 | /* length random. Again, we don't code the codeword itself, just |
---|
69 | the length. This time, though, we have to encode each length */ |
---|
70 | oggpack_write(opb,0,1); /* unordered */ |
---|
71 | |
---|
72 | /* algortihmic mapping has use for 'unused entries', which we tag |
---|
73 | here. The algorithmic mapping happens as usual, but the unused |
---|
74 | entry has no codeword. */ |
---|
75 | for(i=0;i<c->entries;i++) |
---|
76 | if(c->lengthlist[i]==0)break; |
---|
77 | |
---|
78 | if(i==c->entries){ |
---|
79 | oggpack_write(opb,0,1); /* no unused entries */ |
---|
80 | for(i=0;i<c->entries;i++) |
---|
81 | oggpack_write(opb,c->lengthlist[i]-1,5); |
---|
82 | }else{ |
---|
83 | oggpack_write(opb,1,1); /* we have unused entries; thus we tag */ |
---|
84 | for(i=0;i<c->entries;i++){ |
---|
85 | if(c->lengthlist[i]==0){ |
---|
86 | oggpack_write(opb,0,1); |
---|
87 | }else{ |
---|
88 | oggpack_write(opb,1,1); |
---|
89 | oggpack_write(opb,c->lengthlist[i]-1,5); |
---|
90 | } |
---|
91 | } |
---|
92 | } |
---|
93 | } |
---|
94 | |
---|
95 | /* is the entry number the desired return value, or do we have a |
---|
96 | mapping? If we have a mapping, what type? */ |
---|
97 | oggpack_write(opb,c->maptype,4); |
---|
98 | switch(c->maptype){ |
---|
99 | case 0: |
---|
100 | /* no mapping */ |
---|
101 | break; |
---|
102 | case 1:case 2: |
---|
103 | /* implicitly populated value mapping */ |
---|
104 | /* explicitly populated value mapping */ |
---|
105 | |
---|
106 | if(!c->quantlist){ |
---|
107 | /* no quantlist? error */ |
---|
108 | return(-1); |
---|
109 | } |
---|
110 | |
---|
111 | /* values that define the dequantization */ |
---|
112 | oggpack_write(opb,c->q_min,32); |
---|
113 | oggpack_write(opb,c->q_delta,32); |
---|
114 | oggpack_write(opb,c->q_quant-1,4); |
---|
115 | oggpack_write(opb,c->q_sequencep,1); |
---|
116 | |
---|
117 | { |
---|
118 | int quantvals; |
---|
119 | switch(c->maptype){ |
---|
120 | case 1: |
---|
121 | /* a single column of (c->entries/c->dim) quantized values for |
---|
122 | building a full value list algorithmically (square lattice) */ |
---|
123 | quantvals=_book_maptype1_quantvals(c); |
---|
124 | break; |
---|
125 | case 2: |
---|
126 | /* every value (c->entries*c->dim total) specified explicitly */ |
---|
127 | quantvals=c->entries*c->dim; |
---|
128 | break; |
---|
129 | default: /* NOT_REACHABLE */ |
---|
130 | quantvals=-1; |
---|
131 | } |
---|
132 | |
---|
133 | /* quantized values */ |
---|
134 | for(i=0;i<quantvals;i++) |
---|
135 | oggpack_write(opb,labs(c->quantlist[i]),c->q_quant); |
---|
136 | |
---|
137 | } |
---|
138 | break; |
---|
139 | default: |
---|
140 | /* error case; we don't have any other map types now */ |
---|
141 | return(-1); |
---|
142 | } |
---|
143 | |
---|
144 | return(0); |
---|
145 | } |
---|
146 | |
---|
147 | /* unpacks a codebook from the packet buffer into the codebook struct, |
---|
148 | readies the codebook auxiliary structures for decode *************/ |
---|
149 | int vorbis_staticbook_unpack(oggpack_buffer *opb,static_codebook *s){ |
---|
150 | long i,j; |
---|
151 | memset(s,0,sizeof(*s)); |
---|
152 | s->allocedp=1; |
---|
153 | |
---|
154 | /* make sure alignment is correct */ |
---|
155 | if(oggpack_read(opb,24)!=0x564342)goto _eofout; |
---|
156 | |
---|
157 | /* first the basic parameters */ |
---|
158 | s->dim=oggpack_read(opb,16); |
---|
159 | s->entries=oggpack_read(opb,24); |
---|
160 | if(s->entries==-1)goto _eofout; |
---|
161 | |
---|
162 | /* codeword ordering.... length ordered or unordered? */ |
---|
163 | switch((int)oggpack_read(opb,1)){ |
---|
164 | case 0: |
---|
165 | /* unordered */ |
---|
166 | s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries); |
---|
167 | |
---|
168 | /* allocated but unused entries? */ |
---|
169 | if(oggpack_read(opb,1)){ |
---|
170 | /* yes, unused entries */ |
---|
171 | |
---|
172 | for(i=0;i<s->entries;i++){ |
---|
173 | if(oggpack_read(opb,1)){ |
---|
174 | long num=oggpack_read(opb,5); |
---|
175 | if(num==-1)goto _eofout; |
---|
176 | s->lengthlist[i]=num+1; |
---|
177 | }else |
---|
178 | s->lengthlist[i]=0; |
---|
179 | } |
---|
180 | }else{ |
---|
181 | /* all entries used; no tagging */ |
---|
182 | for(i=0;i<s->entries;i++){ |
---|
183 | long num=oggpack_read(opb,5); |
---|
184 | if(num==-1)goto _eofout; |
---|
185 | s->lengthlist[i]=num+1; |
---|
186 | } |
---|
187 | } |
---|
188 | |
---|
189 | break; |
---|
190 | case 1: |
---|
191 | /* ordered */ |
---|
192 | { |
---|
193 | long length=oggpack_read(opb,5)+1; |
---|
194 | s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries); |
---|
195 | |
---|
196 | for(i=0;i<s->entries;){ |
---|
197 | long num=oggpack_read(opb,_ilog(s->entries-i)); |
---|
198 | if(num==-1)goto _eofout; |
---|
199 | for(j=0;j<num && i<s->entries;j++,i++) |
---|
200 | s->lengthlist[i]=length; |
---|
201 | length++; |
---|
202 | } |
---|
203 | } |
---|
204 | break; |
---|
205 | default: |
---|
206 | /* EOF */ |
---|
207 | return(-1); |
---|
208 | } |
---|
209 | |
---|
210 | /* Do we have a mapping to unpack? */ |
---|
211 | switch((s->maptype=oggpack_read(opb,4))){ |
---|
212 | case 0: |
---|
213 | /* no mapping */ |
---|
214 | break; |
---|
215 | case 1: case 2: |
---|
216 | /* implicitly populated value mapping */ |
---|
217 | /* explicitly populated value mapping */ |
---|
218 | |
---|
219 | s->q_min=oggpack_read(opb,32); |
---|
220 | s->q_delta=oggpack_read(opb,32); |
---|
221 | s->q_quant=oggpack_read(opb,4)+1; |
---|
222 | s->q_sequencep=oggpack_read(opb,1); |
---|
223 | |
---|
224 | { |
---|
225 | int quantvals=0; |
---|
226 | switch(s->maptype){ |
---|
227 | case 1: |
---|
228 | quantvals=_book_maptype1_quantvals(s); |
---|
229 | break; |
---|
230 | case 2: |
---|
231 | quantvals=s->entries*s->dim; |
---|
232 | break; |
---|
233 | } |
---|
234 | |
---|
235 | /* quantized values */ |
---|
236 | s->quantlist=_ogg_malloc(sizeof(*s->quantlist)*quantvals); |
---|
237 | for(i=0;i<quantvals;i++) |
---|
238 | s->quantlist[i]=oggpack_read(opb,s->q_quant); |
---|
239 | |
---|
240 | if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout; |
---|
241 | } |
---|
242 | break; |
---|
243 | default: |
---|
244 | goto _errout; |
---|
245 | } |
---|
246 | |
---|
247 | /* all set */ |
---|
248 | return(0); |
---|
249 | |
---|
250 | _errout: |
---|
251 | _eofout: |
---|
252 | vorbis_staticbook_clear(s); |
---|
253 | return(-1); |
---|
254 | } |
---|
255 | |
---|
256 | /* returns the number of bits ************************************************/ |
---|
257 | int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b){ |
---|
258 | if(a<0 || a>=book->c->entries)return(0); |
---|
259 | oggpack_write(b,book->codelist[a],book->c->lengthlist[a]); |
---|
260 | return(book->c->lengthlist[a]); |
---|
261 | } |
---|
262 | |
---|
263 | /* One the encode side, our vector writers are each designed for a |
---|
264 | specific purpose, and the encoder is not flexible without modification: |
---|
265 | |
---|
266 | The LSP vector coder uses a single stage nearest-match with no |
---|
267 | interleave, so no step and no error return. This is specced by floor0 |
---|
268 | and doesn't change. |
---|
269 | |
---|
270 | Residue0 encoding interleaves, uses multiple stages, and each stage |
---|
271 | peels of a specific amount of resolution from a lattice (thus we want |
---|
272 | to match by threshold, not nearest match). Residue doesn't *have* to |
---|
273 | be encoded that way, but to change it, one will need to add more |
---|
274 | infrastructure on the encode side (decode side is specced and simpler) */ |
---|
275 | |
---|
276 | /* floor0 LSP (single stage, non interleaved, nearest match) */ |
---|
277 | /* returns entry number and *modifies a* to the quantization value *****/ |
---|
278 | int vorbis_book_errorv(codebook *book,float *a){ |
---|
279 | int dim=book->dim,k; |
---|
280 | int best=_best(book,a,1); |
---|
281 | for(k=0;k<dim;k++) |
---|
282 | a[k]=(book->valuelist+best*dim)[k]; |
---|
283 | return(best); |
---|
284 | } |
---|
285 | |
---|
286 | /* returns the number of bits and *modifies a* to the quantization value *****/ |
---|
287 | int vorbis_book_encodev(codebook *book,int best,float *a,oggpack_buffer *b){ |
---|
288 | int k,dim=book->dim; |
---|
289 | for(k=0;k<dim;k++) |
---|
290 | a[k]=(book->valuelist+best*dim)[k]; |
---|
291 | return(vorbis_book_encode(book,best,b)); |
---|
292 | } |
---|
293 | |
---|
294 | /* the 'eliminate the decode tree' optimization actually requires the |
---|
295 | codewords to be MSb first, not LSb. This is an annoying inelegancy |
---|
296 | (and one of the first places where carefully thought out design |
---|
297 | turned out to be wrong; Vorbis II and future Ogg codecs should go |
---|
298 | to an MSb bitpacker), but not actually the huge hit it appears to |
---|
299 | be. The first-stage decode table catches most words so that |
---|
300 | bitreverse is not in the main execution path. */ |
---|
301 | |
---|
302 | static ogg_uint32_t bitreverse(ogg_uint32_t x){ |
---|
303 | x= ((x>>16)&0x0000ffff) | ((x<<16)&0xffff0000); |
---|
304 | x= ((x>> 8)&0x00ff00ff) | ((x<< 8)&0xff00ff00); |
---|
305 | x= ((x>> 4)&0x0f0f0f0f) | ((x<< 4)&0xf0f0f0f0); |
---|
306 | x= ((x>> 2)&0x33333333) | ((x<< 2)&0xcccccccc); |
---|
307 | return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa); |
---|
308 | } |
---|
309 | |
---|
310 | STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){ |
---|
311 | int read=book->dec_maxlength; |
---|
312 | long lo,hi; |
---|
313 | long lok = oggpack_look(b,book->dec_firsttablen); |
---|
314 | |
---|
315 | if (lok >= 0) { |
---|
316 | long entry = book->dec_firsttable[lok]; |
---|
317 | if(entry&0x80000000UL){ |
---|
318 | lo=(entry>>15)&0x7fff; |
---|
319 | hi=book->used_entries-(entry&0x7fff); |
---|
320 | }else{ |
---|
321 | oggpack_adv(b, book->dec_codelengths[entry-1]); |
---|
322 | return(entry-1); |
---|
323 | } |
---|
324 | }else{ |
---|
325 | lo=0; |
---|
326 | hi=book->used_entries; |
---|
327 | } |
---|
328 | |
---|
329 | lok = oggpack_look(b, read); |
---|
330 | |
---|
331 | while(lok<0 && read>1) |
---|
332 | lok = oggpack_look(b, --read); |
---|
333 | if(lok<0)return -1; |
---|
334 | |
---|
335 | /* bisect search for the codeword in the ordered list */ |
---|
336 | { |
---|
337 | ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok); |
---|
338 | |
---|
339 | while(hi-lo>1){ |
---|
340 | long p=(hi-lo)>>1; |
---|
341 | long test=book->codelist[lo+p]>testword; |
---|
342 | lo+=p&(test-1); |
---|
343 | hi-=p&(-test); |
---|
344 | } |
---|
345 | |
---|
346 | if(book->dec_codelengths[lo]<=read){ |
---|
347 | oggpack_adv(b, book->dec_codelengths[lo]); |
---|
348 | return(lo); |
---|
349 | } |
---|
350 | } |
---|
351 | |
---|
352 | oggpack_adv(b, read); |
---|
353 | |
---|
354 | return(-1); |
---|
355 | } |
---|
356 | |
---|
357 | /* Decode side is specced and easier, because we don't need to find |
---|
358 | matches using different criteria; we simply read and map. There are |
---|
359 | two things we need to do 'depending': |
---|
360 | |
---|
361 | We may need to support interleave. We don't really, but it's |
---|
362 | convenient to do it here rather than rebuild the vector later. |
---|
363 | |
---|
364 | Cascades may be additive or multiplicitive; this is not inherent in |
---|
365 | the codebook, but set in the code using the codebook. Like |
---|
366 | interleaving, it's easiest to do it here. |
---|
367 | addmul==0 -> declarative (set the value) |
---|
368 | addmul==1 -> additive |
---|
369 | addmul==2 -> multiplicitive */ |
---|
370 | |
---|
371 | /* returns the [original, not compacted] entry number or -1 on eof *********/ |
---|
372 | long vorbis_book_decode(codebook *book, oggpack_buffer *b){ |
---|
373 | if(book->used_entries>0){ |
---|
374 | long packed_entry=decode_packed_entry_number(book,b); |
---|
375 | if(packed_entry>=0) |
---|
376 | return(book->dec_index[packed_entry]); |
---|
377 | } |
---|
378 | |
---|
379 | /* if there's no dec_index, the codebook unpacking isn't collapsed */ |
---|
380 | return(-1); |
---|
381 | } |
---|
382 | |
---|
383 | /* returns 0 on OK or -1 on eof *************************************/ |
---|
384 | long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){ |
---|
385 | if(book->used_entries>0){ |
---|
386 | int step=n/book->dim; |
---|
387 | long *entry = alloca(sizeof(*entry)*step); |
---|
388 | float **t = alloca(sizeof(*t)*step); |
---|
389 | int i,j,o; |
---|
390 | |
---|
391 | for (i = 0; i < step; i++) { |
---|
392 | entry[i]=decode_packed_entry_number(book,b); |
---|
393 | if(entry[i]==-1)return(-1); |
---|
394 | t[i] = book->valuelist+entry[i]*book->dim; |
---|
395 | } |
---|
396 | for(i=0,o=0;i<book->dim;i++,o+=step) |
---|
397 | for (j=0;j<step;j++) |
---|
398 | a[o+j]+=t[j][i]; |
---|
399 | } |
---|
400 | return(0); |
---|
401 | } |
---|
402 | |
---|
403 | long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){ |
---|
404 | if(book->used_entries>0){ |
---|
405 | int i,j,entry; |
---|
406 | float *t; |
---|
407 | |
---|
408 | if(book->dim>8){ |
---|
409 | for(i=0;i<n;){ |
---|
410 | entry = decode_packed_entry_number(book,b); |
---|
411 | if(entry==-1)return(-1); |
---|
412 | t = book->valuelist+entry*book->dim; |
---|
413 | for (j=0;j<book->dim;) |
---|
414 | a[i++]+=t[j++]; |
---|
415 | } |
---|
416 | }else{ |
---|
417 | for(i=0;i<n;){ |
---|
418 | entry = decode_packed_entry_number(book,b); |
---|
419 | if(entry==-1)return(-1); |
---|
420 | t = book->valuelist+entry*book->dim; |
---|
421 | j=0; |
---|
422 | switch((int)book->dim){ |
---|
423 | case 8: |
---|
424 | a[i++]+=t[j++]; |
---|
425 | case 7: |
---|
426 | a[i++]+=t[j++]; |
---|
427 | case 6: |
---|
428 | a[i++]+=t[j++]; |
---|
429 | case 5: |
---|
430 | a[i++]+=t[j++]; |
---|
431 | case 4: |
---|
432 | a[i++]+=t[j++]; |
---|
433 | case 3: |
---|
434 | a[i++]+=t[j++]; |
---|
435 | case 2: |
---|
436 | a[i++]+=t[j++]; |
---|
437 | case 1: |
---|
438 | a[i++]+=t[j++]; |
---|
439 | case 0: |
---|
440 | break; |
---|
441 | } |
---|
442 | } |
---|
443 | } |
---|
444 | } |
---|
445 | return(0); |
---|
446 | } |
---|
447 | |
---|
448 | long vorbis_book_decodev_set(codebook *book,float *a,oggpack_buffer *b,int n){ |
---|
449 | if(book->used_entries>0){ |
---|
450 | int i,j,entry; |
---|
451 | float *t; |
---|
452 | |
---|
453 | for(i=0;i<n;){ |
---|
454 | entry = decode_packed_entry_number(book,b); |
---|
455 | if(entry==-1)return(-1); |
---|
456 | t = book->valuelist+entry*book->dim; |
---|
457 | for (j=0;j<book->dim;) |
---|
458 | a[i++]=t[j++]; |
---|
459 | } |
---|
460 | }else{ |
---|
461 | int i,j; |
---|
462 | |
---|
463 | for(i=0;i<n;){ |
---|
464 | for (j=0;j<book->dim;) |
---|
465 | a[i++]=0.f; |
---|
466 | } |
---|
467 | } |
---|
468 | return(0); |
---|
469 | } |
---|
470 | |
---|
471 | long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch, |
---|
472 | oggpack_buffer *b,int n){ |
---|
473 | |
---|
474 | long i,j,entry; |
---|
475 | int chptr=0; |
---|
476 | if(book->used_entries>0){ |
---|
477 | for(i=offset/ch;i<(offset+n)/ch;){ |
---|
478 | entry = decode_packed_entry_number(book,b); |
---|
479 | if(entry==-1)return(-1); |
---|
480 | { |
---|
481 | const float *t = book->valuelist+entry*book->dim; |
---|
482 | for (j=0;j<book->dim;j++){ |
---|
483 | a[chptr++][i]+=t[j]; |
---|
484 | if(chptr==ch){ |
---|
485 | chptr=0; |
---|
486 | i++; |
---|
487 | } |
---|
488 | } |
---|
489 | } |
---|
490 | } |
---|
491 | } |
---|
492 | return(0); |
---|
493 | } |
---|
494 | |
---|
495 | #ifdef _V_SELFTEST |
---|
496 | /* Simple enough; pack a few candidate codebooks, unpack them. Code a |
---|
497 | number of vectors through (keeping track of the quantized values), |
---|
498 | and decode using the unpacked book. quantized version of in should |
---|
499 | exactly equal out */ |
---|
500 | |
---|
501 | #include <stdio.h> |
---|
502 | |
---|
503 | #include "vorbis/book/lsp20_0.vqh" |
---|
504 | #include "vorbis/book/res0a_13.vqh" |
---|
505 | #define TESTSIZE 40 |
---|
506 | |
---|
507 | float test1[TESTSIZE]={ |
---|
508 | 0.105939f, |
---|
509 | 0.215373f, |
---|
510 | 0.429117f, |
---|
511 | 0.587974f, |
---|
512 | |
---|
513 | 0.181173f, |
---|
514 | 0.296583f, |
---|
515 | 0.515707f, |
---|
516 | 0.715261f, |
---|
517 | |
---|
518 | 0.162327f, |
---|
519 | 0.263834f, |
---|
520 | 0.342876f, |
---|
521 | 0.406025f, |
---|
522 | |
---|
523 | 0.103571f, |
---|
524 | 0.223561f, |
---|
525 | 0.368513f, |
---|
526 | 0.540313f, |
---|
527 | |
---|
528 | 0.136672f, |
---|
529 | 0.395882f, |
---|
530 | 0.587183f, |
---|
531 | 0.652476f, |
---|
532 | |
---|
533 | 0.114338f, |
---|
534 | 0.417300f, |
---|
535 | 0.525486f, |
---|
536 | 0.698679f, |
---|
537 | |
---|
538 | 0.147492f, |
---|
539 | 0.324481f, |
---|
540 | 0.643089f, |
---|
541 | 0.757582f, |
---|
542 | |
---|
543 | 0.139556f, |
---|
544 | 0.215795f, |
---|
545 | 0.324559f, |
---|
546 | 0.399387f, |
---|
547 | |
---|
548 | 0.120236f, |
---|
549 | 0.267420f, |
---|
550 | 0.446940f, |
---|
551 | 0.608760f, |
---|
552 | |
---|
553 | 0.115587f, |
---|
554 | 0.287234f, |
---|
555 | 0.571081f, |
---|
556 | 0.708603f, |
---|
557 | }; |
---|
558 | |
---|
559 | float test3[TESTSIZE]={ |
---|
560 | 0,1,-2,3,4,-5,6,7,8,9, |
---|
561 | 8,-2,7,-1,4,6,8,3,1,-9, |
---|
562 | 10,11,12,13,14,15,26,17,18,19, |
---|
563 | 30,-25,-30,-1,-5,-32,4,3,-2,0}; |
---|
564 | |
---|
565 | static_codebook *testlist[]={&_vq_book_lsp20_0, |
---|
566 | &_vq_book_res0a_13,NULL}; |
---|
567 | float *testvec[]={test1,test3}; |
---|
568 | |
---|
569 | int main(){ |
---|
570 | oggpack_buffer write; |
---|
571 | oggpack_buffer read; |
---|
572 | long ptr=0,i; |
---|
573 | oggpack_writeinit(&write); |
---|
574 | |
---|
575 | fprintf(stderr,"Testing codebook abstraction...:\n"); |
---|
576 | |
---|
577 | while(testlist[ptr]){ |
---|
578 | codebook c; |
---|
579 | static_codebook s; |
---|
580 | float *qv=alloca(sizeof(*qv)*TESTSIZE); |
---|
581 | float *iv=alloca(sizeof(*iv)*TESTSIZE); |
---|
582 | memcpy(qv,testvec[ptr],sizeof(*qv)*TESTSIZE); |
---|
583 | memset(iv,0,sizeof(*iv)*TESTSIZE); |
---|
584 | |
---|
585 | fprintf(stderr,"\tpacking/coding %ld... ",ptr); |
---|
586 | |
---|
587 | /* pack the codebook, write the testvector */ |
---|
588 | oggpack_reset(&write); |
---|
589 | vorbis_book_init_encode(&c,testlist[ptr]); /* get it into memory |
---|
590 | we can write */ |
---|
591 | vorbis_staticbook_pack(testlist[ptr],&write); |
---|
592 | fprintf(stderr,"Codebook size %ld bytes... ",oggpack_bytes(&write)); |
---|
593 | for(i=0;i<TESTSIZE;i+=c.dim){ |
---|
594 | int best=_best(&c,qv+i,1); |
---|
595 | vorbis_book_encodev(&c,best,qv+i,&write); |
---|
596 | } |
---|
597 | vorbis_book_clear(&c); |
---|
598 | |
---|
599 | fprintf(stderr,"OK.\n"); |
---|
600 | fprintf(stderr,"\tunpacking/decoding %ld... ",ptr); |
---|
601 | |
---|
602 | /* transfer the write data to a read buffer and unpack/read */ |
---|
603 | oggpack_readinit(&read,oggpack_get_buffer(&write),oggpack_bytes(&write)); |
---|
604 | if(vorbis_staticbook_unpack(&read,&s)){ |
---|
605 | fprintf(stderr,"Error unpacking codebook.\n"); |
---|
606 | exit(1); |
---|
607 | } |
---|
608 | if(vorbis_book_init_decode(&c,&s)){ |
---|
609 | fprintf(stderr,"Error initializing codebook.\n"); |
---|
610 | exit(1); |
---|
611 | } |
---|
612 | |
---|
613 | for(i=0;i<TESTSIZE;i+=c.dim) |
---|
614 | if(vorbis_book_decodev_set(&c,iv+i,&read,c.dim)==-1){ |
---|
615 | fprintf(stderr,"Error reading codebook test data (EOP).\n"); |
---|
616 | exit(1); |
---|
617 | } |
---|
618 | for(i=0;i<TESTSIZE;i++) |
---|
619 | if(fabs(qv[i]-iv[i])>.000001){ |
---|
620 | fprintf(stderr,"read (%g) != written (%g) at position (%ld)\n", |
---|
621 | iv[i],qv[i],i); |
---|
622 | exit(1); |
---|
623 | } |
---|
624 | |
---|
625 | fprintf(stderr,"OK\n"); |
---|
626 | ptr++; |
---|
627 | } |
---|
628 | |
---|
629 | /* The above is the trivial stuff; now try unquantizing a log scale codebook */ |
---|
630 | |
---|
631 | exit(0); |
---|
632 | } |
---|
633 | |
---|
634 | #endif |
---|