]> Joshua Wise's Git repositories - patchfork.git/blame - jorbis/src/com/jcraft/jorbis/StaticCodeBook.java
initial import from pitchfork-0.5.5
[patchfork.git] / jorbis / src / com / jcraft / jorbis / StaticCodeBook.java
CommitLineData
964dd0bc
JW
1/* JOrbis
2 * Copyright (C) 2000 ymnk, JCraft,Inc.
3 *
4 * Written by: 2000 ymnk<ymnk@jcraft.com>
5 *
6 * Many thanks to
7 * Monty <monty@xiph.org> and
8 * The XIPHOPHORUS Company http://www.xiph.org/ .
9 * JOrbis has been based on their awesome works, Vorbis codec.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Library General Public License
13 * as published by the Free Software Foundation; either version 2 of
14 * the License, or (at your option) any later version.
15
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Library General Public License for more details.
20 *
21 * You should have received a copy of the GNU Library General Public
22 * License along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 */
25
26package com.jcraft.jorbis;
27
28import com.jcraft.jogg.*;
29
30class StaticCodeBook{
31 int dim; // codebook dimensions (elements per vector)
32 int entries; // codebook entries
33 int[] lengthlist; // codeword lengths in bits
34
35 // mapping
36 int maptype; // 0=none
37 // 1=implicitly populated values from map column
38 // 2=listed arbitrary values
39
40 // The below does a linear, single monotonic sequence mapping.
41 int q_min; // packed 32 bit float; quant value 0 maps to minval
42 int q_delta; // packed 32 bit float; val 1 - val 0 == delta
43 int q_quant; // bits: 0 < quant <= 16
44 int q_sequencep; // bitflag
45
46 // additional information for log (dB) mapping; the linear mapping
47 // is assumed to actually be values in dB. encodebias is used to
48 // assign an error weight to 0 dB. We have two additional flags:
49 // zeroflag indicates if entry zero is to represent -Inf dB; negflag
50 // indicates if we're to represent negative linear values in a
51 // mirror of the positive mapping.
52
53 int[] quantlist; // map == 1: (int)(entries/dim) element column map
54 // map == 2: list of dim*entries quantized entry vals
55
56 // encode helpers
57 EncodeAuxNearestMatch nearest_tree;
58 EncodeAuxThreshMatch thresh_tree;
59
60 StaticCodeBook(){}
61 StaticCodeBook(int dim, int entries, int[] lengthlist,
62 int maptype, int q_min, int q_delta,
63 int q_quant, int q_sequencep, int[] quantlist,
64 //EncodeAuxNearestmatch nearest_tree,
65 Object nearest_tree,
66 // EncodeAuxThreshmatch thresh_tree,
67 Object thresh_tree
68 ){
69 this();
70 this.dim=dim; this.entries=entries; this.lengthlist=lengthlist;
71 this.maptype=maptype; this.q_min=q_min; this.q_delta=q_delta;
72 this.q_quant=q_quant; this.q_sequencep=q_sequencep;
73 this.quantlist=quantlist;
74 }
75
76 int pack(Buffer opb){
77 int i;
78 boolean ordered=false;
79
80 opb.write(0x564342,24);
81 opb.write(dim, 16);
82 opb.write(entries, 24);
83
84 // pack the codewords. There are two packings; length ordered and
85 // length random. Decide between the two now.
86
87 for(i=1;i<entries;i++){
88 if(lengthlist[i]<lengthlist[i-1])break;
89 }
90 if(i==entries)ordered=true;
91
92 if(ordered){
93 // length ordered. We only need to say how many codewords of
94 // each length. The actual codewords are generated
95 // deterministically
96
97 int count=0;
98 opb.write(1,1); // ordered
99 opb.write(lengthlist[0]-1,5); // 1 to 32
100
101 for(i=1;i<entries;i++){
102 int _this=lengthlist[i];
103 int _last=lengthlist[i-1];
104 if(_this>_last){
105 for(int j=_last;j<_this;j++){
106 opb.write(i-count,ilog(entries-count));
107 count=i;
108 }
109 }
110 }
111 opb.write(i-count,ilog(entries-count));
112 }
113 else{
114 // length random. Again, we don't code the codeword itself, just
115 // the length. This time, though, we have to encode each length
116 opb.write(0,1); // unordered
117
118 // algortihmic mapping has use for 'unused entries', which we tag
119 // here. The algorithmic mapping happens as usual, but the unused
120 // entry has no codeword.
121 for(i=0;i<entries;i++){
122 if(lengthlist[i]==0)break;
123 }
124
125 if(i==entries){
126 opb.write(0,1); // no unused entries
127 for(i=0;i<entries;i++){
128 opb.write(lengthlist[i]-1,5);
129 }
130 }
131 else{
132 opb.write(1,1); // we have unused entries; thus we tag
133 for(i=0;i<entries;i++){
134 if(lengthlist[i]==0){
135 opb.write(0,1);
136 }
137 else{
138 opb.write(1,1);
139 opb.write(lengthlist[i]-1,5);
140 }
141 }
142 }
143 }
144
145 // is the entry number the desired return value, or do we have a
146 // mapping? If we have a mapping, what type?
147 opb.write(maptype,4);
148 switch(maptype){
149 case 0:
150 // no mapping
151 break;
152 case 1:
153 case 2:
154 // implicitly populated value mapping
155 // explicitly populated value mapping
156 if(quantlist==null){
157 // no quantlist? error
158 return(-1);
159 }
160
161 // values that define the dequantization
162 opb.write(q_min,32);
163 opb.write(q_delta,32);
164 opb.write(q_quant-1,4);
165 opb.write(q_sequencep,1);
166
167 {
168 int quantvals=0;
169 switch(maptype){
170 case 1:
171 // a single column of (c->entries/c->dim) quantized values for
172 // building a full value list algorithmically (square lattice)
173 quantvals=maptype1_quantvals();
174 break;
175 case 2:
176 // every value (c->entries*c->dim total) specified explicitly
177 quantvals=entries*dim;
178 break;
179 }
180
181 // quantized values
182 for(i=0;i<quantvals;i++){
183 opb.write(Math.abs(quantlist[i]),q_quant);
184 }
185 }
186 break;
187 default:
188 // error case; we don't have any other map types now
189 return(-1);
190 }
191 return(0);
192 }
193/*
194*/
195
196 // unpacks a codebook from the packet buffer into the codebook struct,
197 // readies the codebook auxiliary structures for decode
198 int unpack(Buffer opb){
199 int i;
200 //memset(s,0,sizeof(static_codebook));
201
202 // make sure alignment is correct
203 if(opb.read(24)!=0x564342){
204// goto _eofout;
205 clear();
206 return(-1);
207 }
208
209 // first the basic parameters
210 dim=opb.read(16);
211 entries=opb.read(24);
212 if(entries==-1){
213// goto _eofout;
214 clear();
215 return(-1);
216 }
217
218 // codeword ordering.... length ordered or unordered?
219 switch(opb.read(1)){
220 case 0:
221 // unordered
222 lengthlist=new int[entries];
223
224 // allocated but unused entries?
225 if(opb.read(1)!=0){
226 // yes, unused entries
227
228 for(i=0;i<entries;i++){
229 if(opb.read(1)!=0){
230 int num=opb.read(5);
231 if(num==-1){
232// goto _eofout;
233 clear();
234 return(-1);
235 }
236 lengthlist[i]=num+1;
237 }
238 else{
239 lengthlist[i]=0;
240 }
241 }
242 }
243 else{
244 // all entries used; no tagging
245 for(i=0;i<entries;i++){
246 int num=opb.read(5);
247 if(num==-1){
248// goto _eofout;
249 clear();
250 return(-1);
251 }
252 lengthlist[i]=num+1;
253 }
254 }
255 break;
256 case 1:
257 // ordered
258 {
259 int length=opb.read(5)+1;
260 lengthlist=new int[entries];
261
262 for(i=0;i<entries;){
263 int num=opb.read(ilog(entries-i));
264 if(num==-1){
265// goto _eofout;
266 clear();
267 return(-1);
268 }
269 for(int j=0;j<num;j++,i++){
270 lengthlist[i]=length;
271 }
272 length++;
273 }
274 }
275 break;
276 default:
277 // EOF
278 return(-1);
279 }
280
281 // Do we have a mapping to unpack?
282 switch((maptype=opb.read(4))){
283 case 0:
284 // no mapping
285 break;
286 case 1:
287 case 2:
288 // implicitly populated value mapping
289 // explicitly populated value mapping
290 q_min=opb.read(32);
291 q_delta=opb.read(32);
292 q_quant=opb.read(4)+1;
293 q_sequencep=opb.read(1);
294
295 {
296 int quantvals=0;
297 switch(maptype){
298 case 1:
299 quantvals=maptype1_quantvals();
300 break;
301 case 2:
302 quantvals=entries*dim;
303 break;
304 }
305
306 // quantized values
307 quantlist=new int[quantvals];
308 for(i=0;i<quantvals;i++){
309 quantlist[i]=opb.read(q_quant);
310 }
311 if(quantlist[quantvals-1]==-1){
312// goto _eofout;
313 clear();
314 return(-1);
315 }
316 }
317 break;
318 default:
319// goto _eofout;
320 clear();
321 return(-1);
322 }
323 // all set
324 return(0);
325// _errout:
326// _eofout:
327// vorbis_staticbook_clear(s);
328// return(-1);
329 }
330
331 // there might be a straightforward one-line way to do the below
332 // that's portable and totally safe against roundoff, but I haven't
333 // thought of it. Therefore, we opt on the side of caution
334 private int maptype1_quantvals(){
335 int vals=(int)(Math.floor(Math.pow(entries,1./dim)));
336
337 // the above *should* be reliable, but we'll not assume that FP is
338 // ever reliable when bitstream sync is at stake; verify via integer
339 // means that vals really is the greatest value of dim for which
340 // vals^b->bim <= b->entries
341 // treat the above as an initial guess
342 while(true){
343 int acc=1;
344 int acc1=1;
345 for(int i=0;i<dim;i++){
346 acc*=vals;
347 acc1*=vals+1;
348 }
349 if(acc<=entries && acc1>entries){ return(vals); }
350 else{
351 if(acc>entries){ vals--; }
352 else{ vals++; }
353 }
354 }
355 }
356
357 void clear(){
358// if(quantlist!=null)free(b->quantlist);
359// if(lengthlist!=null)free(b->lengthlist);
360// if(nearest_tree!=null){
361// free(b->nearest_tree->ptr0);
362// free(b->nearest_tree->ptr1);
363// free(b->nearest_tree->p);
364// free(b->nearest_tree->q);
365// memset(b->nearest_tree,0,sizeof(encode_aux_nearestmatch));
366// free(b->nearest_tree);
367// }
368// if(thresh_tree!=null){
369// free(b->thresh_tree->quantthresh);
370// free(b->thresh_tree->quantmap);
371// memset(b->thresh_tree,0,sizeof(encode_aux_threshmatch));
372// free(b->thresh_tree);
373// }
374// memset(b,0,sizeof(static_codebook));
375 }
376
377 // unpack the quantized list of values for encode/decode
378 // we need to deal with two map types: in map type 1, the values are
379 // generated algorithmically (each column of the vector counts through
380 // the values in the quant vector). in map type 2, all the values came
381 // in in an explicit list. Both value lists must be unpacked
382 float[] unquantize(){
383
384 if(maptype==1 || maptype==2){
385 int quantvals;
386 float mindel=float32_unpack(q_min);
387 float delta=float32_unpack(q_delta);
388 float[] r=new float[entries*dim];
389
390 //System.err.println("q_min="+q_min+", mindel="+mindel);
391
392 // maptype 1 and 2 both use a quantized value vector, but
393 // different sizes
394 switch(maptype){
395 case 1:
396 // most of the time, entries%dimensions == 0, but we need to be
397 // well defined. We define that the possible vales at each
398 // scalar is values == entries/dim. If entries%dim != 0, we'll
399 // have 'too few' values (values*dim<entries), which means that
400 // we'll have 'left over' entries; left over entries use zeroed
401 // values (and are wasted). So don't generate codebooks like that
402 quantvals=maptype1_quantvals();
403 for(int j=0;j<entries;j++){
404 float last=0.f;
405 int indexdiv=1;
406 for(int k=0;k<dim;k++){
407 int index=(j/indexdiv)%quantvals;
408 float val=quantlist[index];
409 val=Math.abs(val)*delta+mindel+last;
410 if(q_sequencep!=0)last=val;
411 r[j*dim+k]=val;
412 indexdiv*=quantvals;
413 }
414 }
415 break;
416 case 2:
417 for(int j=0;j<entries;j++){
418 float last=0.f;
419 for(int k=0;k<dim;k++){
420 float val=quantlist[j*dim+k];
421//if((j*dim+k)==0){System.err.println(" | 0 -> "+val+" | ");}
422 val=Math.abs(val)*delta+mindel+last;
423 if(q_sequencep!=0)last=val;
424 r[j*dim+k]=val;
425//if((j*dim+k)==0){System.err.println(" $ r[0] -> "+r[0]+" | ");}
426 }
427 }
428//System.err.println("\nr[0]="+r[0]);
429 }
430 return(r);
431 }
432 return(null);
433 }
434
435 private static int ilog(int v){
436 int ret=0;
437 while(v!=0){
438 ret++;
439 v>>>=1;
440 }
441 return(ret);
442 }
443
444 // 32 bit float (not IEEE; nonnormalized mantissa +
445 // biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm
446 // Why not IEEE? It's just not that important here.
447
448 static final int VQ_FEXP=10;
449 static final int VQ_FMAN=21;
450 static final int VQ_FEXP_BIAS=768; // bias toward values smaller than 1.
451
452 // doesn't currently guard under/overflow
453 static long float32_pack(float val){
454 int sign=0;
455 int exp;
456 int mant;
457 if(val<0){
458 sign=0x80000000;
459 val= -val;
460 }
461 exp=(int)Math.floor(Math.log(val)/Math.log(2));
462 mant=(int)Math.rint(Math.pow(val,(VQ_FMAN-1)-exp));
463 exp=(exp+VQ_FEXP_BIAS)<<VQ_FMAN;
464 return(sign|exp|mant);
465 }
466
467 static float float32_unpack(int val){
468 float mant=val&0x1fffff;
469 float sign=val&0x80000000;
470 float exp =(val&0x7fe00000)>>>VQ_FMAN;
471//System.err.println("mant="+mant+", sign="+sign+", exp="+exp);
472 //if(sign!=0.0)mant= -mant;
473 if((val&0x80000000)!=0)mant= -mant;
474//System.err.println("mant="+mant);
475 return(ldexp(mant,((int)exp)-(VQ_FMAN-1)-VQ_FEXP_BIAS));
476 }
477
478 static float ldexp(float foo, int e){
479 return (float)(foo*Math.pow(2, e));
480 }
481
482/*
483 // TEST
484 // Unit tests of the dequantizer; this stuff will be OK
485 // cross-platform, I simply want to be sure that special mapping cases
486 // actually work properly; a bug could go unnoticed for a while
487
488 // cases:
489 //
490 // no mapping
491 // full, explicit mapping
492 // algorithmic mapping
493 //
494 // nonsequential
495 // sequential
496
497 static int[] full_quantlist1={0,1,2,3, 4,5,6,7, 8,3,6,1};
498 static int[] partial_quantlist1={0,7,2};
499
500 // no mapping
501 static StaticCodeBook test1=new StaticCodeBook(4,16,null,
502 0,0,0,0,0,
503 null,null,null);
504 static float[] test1_result=null;
505
506 // linear, full mapping, nonsequential
507 static StaticCodeBook test2=new StaticCodeBook(4,3,null,
508 2,-533200896,1611661312,4,0,
509 full_quantlist1, null, null);
510 static float[] test2_result={-3,-2,-1,0, 1,2,3,4, 5,0,3,-2};
511
512 // linear, full mapping, sequential
513 static StaticCodeBook test3=new StaticCodeBook(4,3,null,
514 2, -533200896,1611661312,4,1,
515 full_quantlist1,null, null);
516 static float[] test3_result={-3,-5,-6,-6, 1,3,6,10, 5,5,8,6};
517
518 // linear, algorithmic mapping, nonsequential
519 static StaticCodeBook test4=new StaticCodeBook(3,27,null,
520 1,-533200896,1611661312,4,0,
521 partial_quantlist1,null,null);
522 static float[] test4_result={-3,-3,-3, 4,-3,-3, -1,-3,-3,
523 -3, 4,-3, 4, 4,-3, -1, 4,-3,
524 -3,-1,-3, 4,-1,-3, -1,-1,-3,
525 -3,-3, 4, 4,-3, 4, -1,-3, 4,
526 -3, 4, 4, 4, 4, 4, -1, 4, 4,
527 -3,-1, 4, 4,-1, 4, -1,-1, 4,
528 -3,-3,-1, 4,-3,-1, -1,-3,-1,
529 -3, 4,-1, 4, 4,-1, -1, 4,-1,
530 -3,-1,-1, 4,-1,-1, -1,-1,-1};
531
532 // linear, algorithmic mapping, sequential
533 static StaticCodeBook test5=new StaticCodeBook(3,27,null,
534 1,-533200896,1611661312,4,1,
535 partial_quantlist1,null,null);
536 static float[] test5_result={-3,-6,-9, 4, 1,-2, -1,-4,-7,
537 -3, 1,-2, 4, 8, 5, -1, 3, 0,
538 -3,-4,-7, 4, 3, 0, -1,-2,-5,
539 -3,-6,-2, 4, 1, 5, -1,-4, 0,
540 -3, 1, 5, 4, 8,12, -1, 3, 7,
541 -3,-4, 0, 4, 3, 7, -1,-2, 2,
542 -3,-6,-7, 4, 1, 0, -1,-4,-5,
543 -3, 1, 0, 4, 8, 7, -1, 3, 2,
544 -3,-4,-5, 4, 3, 2, -1,-2,-3};
545
546 void run_test(float[] comp){
547 float[] out=unquantize();
548 if(comp!=null){
549 if(out==null){
550 System.err.println("_book_unquantize incorrectly returned NULL");
551 System.exit(1);
552 }
553 for(int i=0;i<entries*dim;i++){
554 if(Math.abs(out[i]-comp[i])>.0001){
555 System.err.println("disagreement in unquantized and reference data:\nposition "+i+": "+out[i]+" != "+comp[i]);
556 System.exit(1);
557 }
558 }
559 }
560 else{
561 if(out!=null){
562 System.err.println("_book_unquantize returned a value array:\n correct result should have been NULL");
563 System.exit(1);
564 }
565 }
566 }
567
568 public static void main(String[] arg){
569 // run the nine dequant tests, and compare to the hand-rolled results
570 System.err.print("Dequant test 1... ");
571 test1.run_test(test1_result);
572 System.err.print("OK\nDequant test 2... ");
573 test2.run_test(test2_result);
574 System.err.print("OK\nDequant test 3... ");
575 test3.run_test(test3_result);
576 System.err.print("OK\nDequant test 4... ");
577 test4.run_test(test4_result);
578 System.err.print("OK\nDequant test 5... ");
579 test5.run_test(test5_result);
580 System.err.print("OK\n\n");
581 }
582*/
583}
584
585
586
587
588
This page took 0.069822 seconds and 4 git commands to generate.