package btools.codec; /** * Encoder/Decoder for signed integers that automatically detects the typical * range of these numbers to determine a noisy-bit count as a very simple * dictionary * * Adapted for 3-pass encoding (counters -> statistics -> encoding ) * but doesn't do anything at pass1 */ public final class NoisyDiffCoder { private int tot; private int[] freqs; private int noisybits; private StatCoderContext bc; private int pass; /** * Create a decoder and read the noisy-bit count from the gibe context */ public NoisyDiffCoder( StatCoderContext bc ) { noisybits = bc.decodeVarBits(); this.bc = bc; } /** * Create an encoder for 3-pass-encoding */ public NoisyDiffCoder() { } /** * encodes a signed int (pass3 only, stats collection in pass2) */ public void encodeSignedValue( int value ) { if ( pass == 3 ) { bc.encodeNoisyDiff( value, noisybits ); } else if ( pass == 2 ) { count( value < 0 ? -value : value ); } } /** * decodes a signed int */ public int decodeSignedValue() { return bc.decodeNoisyDiff( noisybits ); } /** * Starts a new encoding pass and (in pass3) calculates the noisy-bit count * from the stats collected in pass2 and writes that to the given context */ public void encodeDictionary( StatCoderContext bc ) { if ( ++pass == 3 ) { // how many noisy bits? for ( noisybits = 0; noisybits < 14 && tot > 0; noisybits++ ) { if ( freqs[noisybits] < ( tot >> 1 ) ) break; } bc.encodeVarBits( noisybits ); } this.bc = bc; } private void count( int value ) { if ( freqs == null ) freqs = new int[14]; int bm = 1; for ( int i = 0; i < 14; i++ ) { if ( value < bm ) break; else freqs[i]++; bm <<= 1; } tot++; } }