All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.github.axet.libvorbis.Jstatic_codebook Maven / Gradle / Ivy

package com.github.axet.libvorbis;

import com.github.axet.libogg.Joggpack_buffer;

/**
This structure encapsulates huffman and VQ style encoding books; it
doesn't do anything specific to either.

valuelist/quantlist are nonNULL (and q_* significant) only if
there's entry->value mapping to be done.

If encode-side mapping must be done (and thus the entry needs to be
hunted), the auxiliary encode pointer will point to a decision
tree.  This is true of both VQ and huffman, but is mostly useful
with VQ.
*/
public final class Jstatic_codebook {
	/** codebook dimensions (elements per vector) */
	int   dim = 0;
	/** codebook entries */
	int   entries = 0;
	/** codeword lengths in bits */
	byte[] lengthlist = null;

	/** mapping
* 0 = none
* 1 = implicitly populated values from map column
* 2 = listed arbitrary values */ int maptype = 0; /* The below does a linear, single monotonic sequence mapping. */ /** packed 32 bit float; quant value 0 maps to minval */ int q_min = 0; /** packed 32 bit float; val 1 - val 0 == delta */ int q_delta = 0; /** bits: 0 < quant <= 16 */ private int q_quant = 0; /** bitflag */ private int q_sequencep = 0; /** map == 1: (int)(entries^(1/dim)) element column map
* map == 2: list of dim*entries quantized entry vals */ private int[] quantlist = null; private int allocedp = 0; // Jstatic_codebook() { } public Jstatic_codebook( final int i_dim, final int i_entries, final byte[] pi_lengthlist, final int i_maptype, final int i_q_min, final int i_q_delta, final int i_q_quant, final int i_q_sequencep, final int[] pi_quantlist, final int i_allocedp ) { dim = i_dim; entries = i_entries; lengthlist = pi_lengthlist; maptype = i_maptype; q_min = i_q_min; q_delta = i_q_delta; q_quant = i_q_quant; q_sequencep = i_q_sequencep; quantlist = pi_quantlist; allocedp = i_allocedp; } private final void clear() { dim = 0; entries = 0; lengthlist = null; maptype = 0; q_min = 0; q_delta = 0; q_quant = 0; q_sequencep = 0; quantlist = null; allocedp = 0; } // sharedbook.c /** 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 */ final int _book_maptype1_quantvals() { final int e = this.entries;// java if( e < 1 ) { return 0; } final int d = this.dim;// java int vals = (int)Math.floor( Math.pow( (double)e, 1. / d ) ); /* 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 */ if( vals < 1 ) { vals = 1; } while( true ) { int acc = 1; int acc1 = 1; int i; for( i = 0; i < d; i++ ) { if( e / vals < acc ) { break; } acc *= vals; if( Integer.MAX_VALUE / (vals + 1) < acc1 ) { acc1 = Integer.MAX_VALUE; } else { acc1 *= vals + 1; } } if( i >= d && acc <= e && acc1 > e ) { return (vals); } else { if( i < d || acc > e ) { vals--; } else { vals++; } } } } /** 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 */ final float[] _book_unquantize(final int n, final int[] sparsemap) { if( this.maptype == 1 || this.maptype == 2 ) { final float mindel = Jcodec._float32_unpack( this.q_min ); final float delta = Jcodec._float32_unpack( this.q_delta ); final int dimension = this.dim;// java final float[] r = new float[n * dimension]; int count = 0; final boolean is_qsequencep = this.q_sequencep != 0; /* maptype 1 and 2 both use a quantized value vector, but different sizes */ final int[] quant_list = this.quantlist;// java final byte[] length_list = this.lengthlist;// java switch( this.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 last ) { for( j = last; j < ithis; j++ ) { opb.oggpack_write( i - count, Jcodec.ov_ilog( entries_count - count ) ); count = i; } } } opb.oggpack_write( i - count, Jcodec.ov_ilog( entries_count - 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.oggpack_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_count; i++ ) { if( length_list[i] == 0 ) { break; } } if( i == entries_count ) { opb.oggpack_write( 0, 1 ); /* no unused entries */ for( i = 0; i < entries_count; i++ ) { opb.oggpack_write( length_list[i] - 1, 5 ); } } else { opb.oggpack_write( 1, 1 ); /* we have unused entries; thus we tag */ for( i = 0; i < entries_count; i++ ) { if( length_list[i] == 0 ) { opb.oggpack_write( 0, 1 ); } else { opb.oggpack_write( 1, 1 ); opb.oggpack_write( length_list[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.oggpack_write( this.maptype, 4 ); switch( this.maptype ) { case 0: /* no mapping */ break; case 1: case 2: /* implicitly populated value mapping */ /* explicitly populated value mapping */ if( this.quantlist == null ) { /* no quantlist? error */ return (-1); } /* values that define the dequantization */ opb.oggpack_write( this.q_min, 32 ); opb.oggpack_write( this.q_delta, 32 ); opb.oggpack_write( this.q_quant - 1, 4 ); opb.oggpack_write( this.q_sequencep, 1 ); { int quantvals; switch( this.maptype ) { case 1: /* a single column of (c->entries.->dim) quantized values for building a full value list algorithmically (square lattice) */ quantvals = _book_maptype1_quantvals(); break; case 2: /* every value (c->entries*c->dim total) specified explicitly */ quantvals = entries_count * this.dim; break; default: /* NOT_REACHABLE */ quantvals = -1; } /* quantized values */ final int[] quant_list = this.quantlist;// java for( i = 0; i < quantvals; i++ ) { int val = quant_list[i]; if( val < 0 ) { val = -val; } opb.oggpack_write( val, this.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 */ static final Jstatic_codebook vorbis_staticbook_unpack(final Joggpack_buffer opb) { final Jstatic_codebook s = new Jstatic_codebook(); s.allocedp = 1; /* make sure alignment is correct */ if( opb.oggpack_read( 24 ) != 0x564342 ) {// goto _eofout; s.vorbis_staticbook_destroy(); return (null); } /* first the basic parameters */ s.dim = opb.oggpack_read( 16 ); final int entries = opb.oggpack_read( 24 ); s.entries = entries; if( entries == -1 ) {// goto _eofout; s.vorbis_staticbook_destroy(); return (null); } if( Jcodec.ov_ilog( s.dim ) + Jcodec.ov_ilog( entries ) > 24 ) {//goto _eofout; s.vorbis_staticbook_destroy(); return (null); } /* codeword ordering.... length ordered or unordered? */ switch( opb.oggpack_read( 1 ) ) { case 0: { int unused; /* allocated but unused entries? */ unused = opb.oggpack_read( 1 ); if( (entries * (unused != 0 ? 1 : 5) + 7) >> 3 > opb.storage - opb.oggpack_bytes() ) {// goto _eofout; s.vorbis_staticbook_destroy(); return (null); } /* unordered */ final byte[] lengthlist = new byte[entries]; s.lengthlist = lengthlist; /* allocated but unused entries? */ if( unused != 0 ) { /* yes, unused entries */ for( int i = 0; i < entries; i++ ) { if( opb.oggpack_read( 1 ) != 0 ) { final int num = opb.oggpack_read( 5 ); if( num == -1 ) {// goto _eofout; s.vorbis_staticbook_destroy(); return (null); } lengthlist[i] = (byte)(num + 1); } else { lengthlist[i] = 0; } } } else { /* all entries used; no tagging */ for( int i = 0; i < entries; i++ ) { final int num = opb.oggpack_read( 5 ); if( num == -1 ) {// goto _eofout; s.vorbis_staticbook_destroy(); return (null); } lengthlist[i] = (byte)(num + 1); } } break; } case 1: /* ordered */ { int length = opb.oggpack_read( 5 ) + 1; if( length == 0 ) {// goto _eofout; s.vorbis_staticbook_destroy(); return (null); } final byte[] lengthlist = new byte[entries]; s.lengthlist = lengthlist; for( int i = 0; i < entries; ) { final int num = opb.oggpack_read( Jcodec.ov_ilog( entries - i ) ); if( num == -1 ) {// goto _eofout; s.vorbis_staticbook_destroy(); return (null); } if( length > 32 || num > entries - i || (num > 0 && (num - 1) >> (length - 1 ) > 1 ) ) { s.vorbis_staticbook_destroy(); return (null);//goto _errout; } if( length > 32 ) {// goto _errout; s.vorbis_staticbook_destroy(); return (null); } for( int j = 0; j < num; j++, i++ ) { lengthlist[i] = (byte)length; } length++; } } break; default: /* EOF */ // goto _eofout; s.vorbis_staticbook_destroy(); return (null); } /* Do we have a mapping to unpack? */ switch( (s.maptype = opb.oggpack_read( 4 )) ) { case 0: /* no mapping */ break; case 1: case 2: /* implicitly populated value mapping */ /* explicitly populated value mapping */ s.q_min = opb.oggpack_read( 32 ); s.q_delta = opb.oggpack_read( 32 ); final int q_quant = opb.oggpack_read( 4 ) + 1; s.q_quant = q_quant; s.q_sequencep = opb.oggpack_read( 1 ); if( s.q_sequencep == -1 ) {// goto _eofout; s.vorbis_staticbook_destroy(); return (null); } { int quantvals = 0; switch( s.maptype ) { case 1: quantvals = (s.dim == 0 ? 0 : s._book_maptype1_quantvals() ); break; case 2: quantvals = entries * s.dim; break; } /* quantized values */ if( ((quantvals * q_quant + 7) >> 3) > opb.storage - opb.oggpack_bytes() ) { s.vorbis_staticbook_destroy(); return (null);// goto _eofout; } final int[] quantlist = new int[quantvals]; s.quantlist = quantlist; for( int i = 0; i < quantvals; i++ ) { quantlist[i] = opb.oggpack_read( q_quant ); } if( quantvals != 0 && quantlist[quantvals - 1] == -1 ) {//goto _eofout; s.vorbis_staticbook_destroy(); return (null); } } break; default: //goto _errout; s.vorbis_staticbook_destroy(); return (null); } /* all set */ return (s); //_errout: //_eofout: // vorbis_staticbook_destroy( s ); // return (null); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy