diff options
| author | Björn Stenberg <bjorn@haxx.se> | 2007-01-08 23:53:00 +0000 |
|---|---|---|
| committer | Björn Stenberg <bjorn@haxx.se> | 2007-01-08 23:53:00 +0000 |
| commit | 7039a05147b8bbfc829babea1c65bd436450b505 (patch) | |
| tree | 4ba555eb84ed97b72b0575034d5b0530a393713e /songdbj/com/jcraft/jorbis/StaticCodeBook.java | |
| parent | 6d4c19707ef95942e323cbdc89fbbfdbe45e7cc5 (diff) | |
| download | rockbox-7039a05147b8bbfc829babea1c65bd436450b505.zip rockbox-7039a05147b8bbfc829babea1c65bd436450b505.tar.gz rockbox-7039a05147b8bbfc829babea1c65bd436450b505.tar.bz2 rockbox-7039a05147b8bbfc829babea1c65bd436450b505.tar.xz | |
Splitting out songdbj
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@11953 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'songdbj/com/jcraft/jorbis/StaticCodeBook.java')
| -rw-r--r-- | songdbj/com/jcraft/jorbis/StaticCodeBook.java | 588 |
1 files changed, 0 insertions, 588 deletions
diff --git a/songdbj/com/jcraft/jorbis/StaticCodeBook.java b/songdbj/com/jcraft/jorbis/StaticCodeBook.java deleted file mode 100644 index 7d9d6dc..0000000 --- a/songdbj/com/jcraft/jorbis/StaticCodeBook.java +++ /dev/null @@ -1,588 +0,0 @@ -/* JOrbis - * Copyright (C) 2000 ymnk, JCraft,Inc. - * - * Written by: 2000 ymnk<ymnk@jcraft.com> - * - * Many thanks to - * Monty <monty@xiph.org> and - * The XIPHOPHORUS Company http://www.xiph.org/ . - * JOrbis has been based on their awesome works, Vorbis codec. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public License - * as published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -package com.jcraft.jorbis; - -import com.jcraft.jogg.*; - -class StaticCodeBook{ - int dim; // codebook dimensions (elements per vector) - int entries; // codebook entries - int[] lengthlist; // codeword lengths in bits - - // mapping - int maptype; // 0=none - // 1=implicitly populated values from map column - // 2=listed arbitrary values - - // The below does a linear, single monotonic sequence mapping. - int q_min; // packed 32 bit float; quant value 0 maps to minval - int q_delta; // packed 32 bit float; val 1 - val 0 == delta - int q_quant; // bits: 0 < quant <= 16 - int q_sequencep; // bitflag - - // additional information for log (dB) mapping; the linear mapping - // is assumed to actually be values in dB. encodebias is used to - // assign an error weight to 0 dB. We have two additional flags: - // zeroflag indicates if entry zero is to represent -Inf dB; negflag - // indicates if we're to represent negative linear values in a - // mirror of the positive mapping. - - int[] quantlist; // map == 1: (int)(entries/dim) element column map - // map == 2: list of dim*entries quantized entry vals - - // encode helpers - EncodeAuxNearestMatch nearest_tree; - EncodeAuxThreshMatch thresh_tree; - - StaticCodeBook(){} - StaticCodeBook(int dim, int entries, int[] lengthlist, - int maptype, int q_min, int q_delta, - int q_quant, int q_sequencep, int[] quantlist, - //EncodeAuxNearestmatch nearest_tree, - Object nearest_tree, - // EncodeAuxThreshmatch thresh_tree, - Object thresh_tree - ){ - this(); - this.dim=dim; this.entries=entries; this.lengthlist=lengthlist; - this.maptype=maptype; this.q_min=q_min; this.q_delta=q_delta; - this.q_quant=q_quant; this.q_sequencep=q_sequencep; - this.quantlist=quantlist; - } - - int pack(Buffer opb){ - int i; - boolean ordered=false; - - opb.write(0x564342,24); - opb.write(dim, 16); - opb.write(entries, 24); - - // pack the codewords. There are two packings; length ordered and - // length random. Decide between the two now. - - for(i=1;i<entries;i++){ - if(lengthlist[i]<lengthlist[i-1])break; - } - if(i==entries)ordered=true; - - if(ordered){ - // length ordered. We only need to say how many codewords of - // each length. The actual codewords are generated - // deterministically - - int count=0; - opb.write(1,1); // ordered - opb.write(lengthlist[0]-1,5); // 1 to 32 - - for(i=1;i<entries;i++){ - int _this=lengthlist[i]; - int _last=lengthlist[i-1]; - if(_this>_last){ - for(int j=_last;j<_this;j++){ - opb.write(i-count,ilog(entries-count)); - count=i; - } - } - } - opb.write(i-count,ilog(entries-count)); - } - else{ - // length random. Again, we don't code the codeword itself, just - // the length. This time, though, we have to encode each length - opb.write(0,1); // unordered - - // algortihmic mapping has use for 'unused entries', which we tag - // here. The algorithmic mapping happens as usual, but the unused - // entry has no codeword. - for(i=0;i<entries;i++){ - if(lengthlist[i]==0)break; - } - - if(i==entries){ - opb.write(0,1); // no unused entries - for(i=0;i<entries;i++){ - opb.write(lengthlist[i]-1,5); - } - } - else{ - opb.write(1,1); // we have unused entries; thus we tag - for(i=0;i<entries;i++){ - if(lengthlist[i]==0){ - opb.write(0,1); - } - else{ - opb.write(1,1); - opb.write(lengthlist[i]-1,5); - } - } - } - } - - // is the entry number the desired return value, or do we have a - // mapping? If we have a mapping, what type? - opb.write(maptype,4); - switch(maptype){ - case 0: - // no mapping - break; - case 1: - case 2: - // implicitly populated value mapping - // explicitly populated value mapping - if(quantlist==null){ - // no quantlist? error - return(-1); - } - - // values that define the dequantization - opb.write(q_min,32); - opb.write(q_delta,32); - opb.write(q_quant-1,4); - opb.write(q_sequencep,1); - - { - int quantvals=0; - switch(maptype){ - case 1: - // a single column of (c->entries/c->dim) quantized values for - // building a full value list algorithmically (square lattice) - quantvals=maptype1_quantvals(); - break; - case 2: - // every value (c->entries*c->dim total) specified explicitly - quantvals=entries*dim; - break; - } - - // quantized values - for(i=0;i<quantvals;i++){ - opb.write(Math.abs(quantlist[i]),q_quant); - } - } - break; - default: - // error case; we don't have any other map types now - return(-1); - } - return(0); - } -/* -*/ - - // unpacks a codebook from the packet buffer into the codebook struct, - // readies the codebook auxiliary structures for decode - int unpack(Buffer opb){ - int i; - //memset(s,0,sizeof(static_codebook)); - - // make sure alignment is correct - if(opb.read(24)!=0x564342){ -// goto _eofout; - clear(); - return(-1); - } - - // first the basic parameters - dim=opb.read(16); - entries=opb.read(24); - if(entries==-1){ -// goto _eofout; - clear(); - return(-1); - } - - // codeword ordering.... length ordered or unordered? - switch(opb.read(1)){ - case 0: - // unordered - lengthlist=new int[entries]; - - // allocated but unused entries? - if(opb.read(1)!=0){ - // yes, unused entries - - for(i=0;i<entries;i++){ - if(opb.read(1)!=0){ - int num=opb.read(5); - if(num==-1){ -// goto _eofout; - clear(); - return(-1); - } - lengthlist[i]=num+1; - } - else{ - lengthlist[i]=0; - } - } - } - else{ - // all entries used; no tagging - for(i=0;i<entries;i++){ - int num=opb.read(5); - if(num==-1){ -// goto _eofout; - clear(); - return(-1); - } - lengthlist[i]=num+1; - } - } - break; - case 1: - // ordered - { - int length=opb.read(5)+1; - lengthlist=new int[entries]; - - for(i=0;i<entries;){ - int num=opb.read(ilog(entries-i)); - if(num==-1){ -// goto _eofout; - clear(); - return(-1); - } - for(int j=0;j<num;j++,i++){ - lengthlist[i]=length; - } - length++; - } - } - break; - default: - // EOF - return(-1); - } - - // Do we have a mapping to unpack? - switch((maptype=opb.read(4))){ - case 0: - // no mapping - break; - case 1: - case 2: - // implicitly populated value mapping - // explicitly populated value mapping - q_min=opb.read(32); - q_delta=opb.read(32); - q_quant=opb.read(4)+1; - q_sequencep=opb.read(1); - - { - int quantvals=0; - switch(maptype){ - case 1: - quantvals=maptype1_quantvals(); - break; - case 2: - quantvals=entries*dim; - break; - } - - // quantized values - quantlist=new int[quantvals]; - for(i=0;i<quantvals;i++){ - quantlist[i]=opb.read(q_quant); - } - if(quantlist[quantvals-1]==-1){ -// goto _eofout; - clear(); - return(-1); - } - } - break; - default: -// goto _eofout; - clear(); - return(-1); - } - // all set - return(0); -// _errout: -// _eofout: -// vorbis_staticbook_clear(s); -// return(-1); - } - - // there might be a straightforward one-line way to do the below - // that's portable and totally safe against roundoff, but I haven't - // thought of it. Therefore, we opt on the side of caution - private int maptype1_quantvals(){ - int vals=(int)(Math.floor(Math.pow(entries,1./dim))); - - // the above *should* be reliable, but we'll not assume that FP is - // ever reliable when bitstream sync is at stake; verify via integer - // means that vals really is the greatest value of dim for which - // vals^b->bim <= b->entries - // treat the above as an initial guess - while(true){ - int acc=1; - int acc1=1; - for(int i=0;i<dim;i++){ - acc*=vals; - acc1*=vals+1; - } - if(acc<=entries && acc1>entries){ return(vals); } - else{ - if(acc>entries){ vals--; } - else{ vals++; } - } - } - } - - void clear(){ -// if(quantlist!=null)free(b->quantlist); -// if(lengthlist!=null)free(b->lengthlist); -// if(nearest_tree!=null){ -// free(b->nearest_tree->ptr0); -// free(b->nearest_tree->ptr1); -// free(b->nearest_tree->p); -// free(b->nearest_tree->q); -// memset(b->nearest_tree,0,sizeof(encode_aux_nearestmatch)); -// free(b->nearest_tree); -// } -// if(thresh_tree!=null){ -// free(b->thresh_tree->quantthresh); -// free(b->thresh_tree->quantmap); -// memset(b->thresh_tree,0,sizeof(encode_aux_threshmatch)); -// free(b->thresh_tree); -// } -// memset(b,0,sizeof(static_codebook)); - } - - // unpack the quantized list of values for encode/decode - // we need to deal with two map types: in map type 1, the values are - // generated algorithmically (each column of the vector counts through - // the values in the quant vector). in map type 2, all the values came - // in in an explicit list. Both value lists must be unpacked - float[] unquantize(){ - - if(maptype==1 || maptype==2){ - int quantvals; - float mindel=float32_unpack(q_min); - float delta=float32_unpack(q_delta); - float[] r=new float[entries*dim]; - - //System.err.println("q_min="+q_min+", mindel="+mindel); - - // maptype 1 and 2 both use a quantized value vector, but - // different sizes - switch(maptype){ - case 1: - // most of the time, entries%dimensions == 0, but we need to be - // well defined. We define that the possible vales at each - // scalar is values == entries/dim. If entries%dim != 0, we'll - // have 'too few' values (values*dim<entries), which means that - // we'll have 'left over' entries; left over entries use zeroed - // values (and are wasted). So don't generate codebooks like that - quantvals=maptype1_quantvals(); - for(int j=0;j<entries;j++){ - float last=0.f; - int indexdiv=1; - for(int k=0;k<dim;k++){ - int index=(j/indexdiv)%quantvals; - float val=quantlist[index]; - val=Math.abs(val)*delta+mindel+last; - if(q_sequencep!=0)last=val; - r[j*dim+k]=val; - indexdiv*=quantvals; - } - } - break; - case 2: - for(int j=0;j<entries;j++){ - float last=0.f; - for(int k=0;k<dim;k++){ - float val=quantlist[j*dim+k]; -//if((j*dim+k)==0){System.err.println(" | 0 -> "+val+" | ");} - val=Math.abs(val)*delta+mindel+last; - if(q_sequencep!=0)last=val; - r[j*dim+k]=val; -//if((j*dim+k)==0){System.err.println(" $ r[0] -> "+r[0]+" | ");} - } - } -//System.err.println("\nr[0]="+r[0]); - } - return(r); - } - return(null); - } - - private static int ilog(int v){ - int ret=0; - while(v!=0){ - ret++; - v>>>=1; - } - return(ret); - } - - // 32 bit float (not IEEE; nonnormalized mantissa + - // biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm - // Why not IEEE? It's just not that important here. - - static final int VQ_FEXP=10; - static final int VQ_FMAN=21; - static final int VQ_FEXP_BIAS=768; // bias toward values smaller than 1. - - // doesn't currently guard under/overflow - static long float32_pack(float val){ - int sign=0; - int exp; - int mant; - if(val<0){ - sign=0x80000000; - val= -val; - } - exp=(int)Math.floor(Math.log(val)/Math.log(2)); - mant=(int)Math.rint(Math.pow(val,(VQ_FMAN-1)-exp)); - exp=(exp+VQ_FEXP_BIAS)<<VQ_FMAN; - return(sign|exp|mant); - } - - static float float32_unpack(int val){ - float mant=val&0x1fffff; - float sign=val&0x80000000; - float exp =(val&0x7fe00000)>>>VQ_FMAN; -//System.err.println("mant="+mant+", sign="+sign+", exp="+exp); - //if(sign!=0.0)mant= -mant; - if((val&0x80000000)!=0)mant= -mant; -//System.err.println("mant="+mant); - return(ldexp(mant,((int)exp)-(VQ_FMAN-1)-VQ_FEXP_BIAS)); - } - - static float ldexp(float foo, int e){ - return (float)(foo*Math.pow(2, e)); - } - -/* - // TEST - // Unit tests of the dequantizer; this stuff will be OK - // cross-platform, I simply want to be sure that special mapping cases - // actually work properly; a bug could go unnoticed for a while - - // cases: - // - // no mapping - // full, explicit mapping - // algorithmic mapping - // - // nonsequential - // sequential - - static int[] full_quantlist1={0,1,2,3, 4,5,6,7, 8,3,6,1}; - static int[] partial_quantlist1={0,7,2}; - - // no mapping - static StaticCodeBook test1=new StaticCodeBook(4,16,null, - 0,0,0,0,0, - null,null,null); - static float[] test1_result=null; - - // linear, full mapping, nonsequential - static StaticCodeBook test2=new StaticCodeBook(4,3,null, - 2,-533200896,1611661312,4,0, - full_quantlist1, null, null); - static float[] test2_result={-3,-2,-1,0, 1,2,3,4, 5,0,3,-2}; - - // linear, full mapping, sequential - static StaticCodeBook test3=new StaticCodeBook(4,3,null, - 2, -533200896,1611661312,4,1, - full_quantlist1,null, null); - static float[] test3_result={-3,-5,-6,-6, 1,3,6,10, 5,5,8,6}; - - // linear, algorithmic mapping, nonsequential - static StaticCodeBook test4=new StaticCodeBook(3,27,null, - 1,-533200896,1611661312,4,0, - partial_quantlist1,null,null); - static float[] test4_result={-3,-3,-3, 4,-3,-3, -1,-3,-3, - -3, 4,-3, 4, 4,-3, -1, 4,-3, - -3,-1,-3, 4,-1,-3, -1,-1,-3, - -3,-3, 4, 4,-3, 4, -1,-3, 4, - -3, 4, 4, 4, 4, 4, -1, 4, 4, - -3,-1, 4, 4,-1, 4, -1,-1, 4, - -3,-3,-1, 4,-3,-1, -1,-3,-1, - -3, 4,-1, 4, 4,-1, -1, 4,-1, - -3,-1,-1, 4,-1,-1, -1,-1,-1}; - - // linear, algorithmic mapping, sequential - static StaticCodeBook test5=new StaticCodeBook(3,27,null, - 1,-533200896,1611661312,4,1, - partial_quantlist1,null,null); - static float[] test5_result={-3,-6,-9, 4, 1,-2, -1,-4,-7, - -3, 1,-2, 4, 8, 5, -1, 3, 0, - -3,-4,-7, 4, 3, 0, -1,-2,-5, - -3,-6,-2, 4, 1, 5, -1,-4, 0, - -3, 1, 5, 4, 8,12, -1, 3, 7, - -3,-4, 0, 4, 3, 7, -1,-2, 2, - -3,-6,-7, 4, 1, 0, -1,-4,-5, - -3, 1, 0, 4, 8, 7, -1, 3, 2, - -3,-4,-5, 4, 3, 2, -1,-2,-3}; - - void run_test(float[] comp){ - float[] out=unquantize(); - if(comp!=null){ - if(out==null){ - System.err.println("_book_unquantize incorrectly returned NULL"); - System.exit(1); - } - for(int i=0;i<entries*dim;i++){ - if(Math.abs(out[i]-comp[i])>.0001){ - System.err.println("disagreement in unquantized and reference data:\nposition "+i+": "+out[i]+" != "+comp[i]); - System.exit(1); - } - } - } - else{ - if(out!=null){ - System.err.println("_book_unquantize returned a value array:\n correct result should have been NULL"); - System.exit(1); - } - } - } - - public static void main(String[] arg){ - // run the nine dequant tests, and compare to the hand-rolled results - System.err.print("Dequant test 1... "); - test1.run_test(test1_result); - System.err.print("OK\nDequant test 2... "); - test2.run_test(test2_result); - System.err.print("OK\nDequant test 3... "); - test3.run_test(test3_result); - System.err.print("OK\nDequant test 4... "); - test4.run_test(test4_result); - System.err.print("OK\nDequant test 5... "); - test5.run_test(test5_result); - System.err.print("OK\n\n"); - } -*/ -} - - - - - |