package net.sourceforge.jaad.aac.huffman; import net.sourceforge.jaad.aac.AACException; import net.sourceforge.jaad.aac.syntax.IBitStream; /** * This class is part of JAAD ( jaadec.sourceforge.net ) that is distributed * under the Public Domain license. Code changes provided by the JCodec project * are distributed under FreeBSD license. * * @author in-somnia */ //TODO: implement decodeSpectralDataER public class Huffman implements Codebooks { private static final boolean[] UNSIGNED = {false, false, true, true, false, false, true, true, true, true, true}; private static final int QUAD_LEN = 4, PAIR_LEN = 2; private Huffman() { } private static int findOffset(IBitStream _in, int[][] table) throws AACException { int off = 0; int len = table[off][0]; int cw = _in.readBits(len); int j; while(cw!=table[off][1]) { off++; j = table[off][0]-len; len = table[off][0]; cw <<= j; cw |= _in.readBits(j); } return off; } private static void signValues(IBitStream _in, int[] data, int off, int len) throws AACException { for(int i = off; i<off+len; i++) { if(data[i]!=0) { if(_in.readBool()) data[i] = -data[i]; } } } private static int getEscape(IBitStream _in, int s) throws AACException { final boolean neg = s<0; int i = 4; while(_in.readBool()) { i++; } final int j = _in.readBits(i)|(1<<i); return (neg ? -j : j); } public static int decodeScaleFactor(IBitStream _in) throws AACException { final int offset = findOffset(_in, HCB_SF); return HCB_SF[offset][2]; } public static void decodeSpectralData(IBitStream _in, int cb, int[] data, int off) throws AACException { final int[][] HCB = CODEBOOKS[cb-1]; //find index final int offset = findOffset(_in, HCB); //copy data data[off] = HCB[offset][2]; data[off+1] = HCB[offset][3]; if(cb<5) { data[off+2] = HCB[offset][4]; data[off+3] = HCB[offset][5]; } //sign & escape if(cb<11) { if(UNSIGNED[cb-1]) signValues(_in, data, off, cb<5 ? QUAD_LEN : PAIR_LEN); } else if(cb==11||cb>15) { signValues(_in, data, off, cb<5 ? QUAD_LEN : PAIR_LEN); //virtual codebooks are always unsigned if(Math.abs(data[off])==16) data[off] = getEscape(_in, data[off]); if(Math.abs(data[off+1])==16) data[off+1] = getEscape(_in, data[off+1]); } else throw new AACException("Huffman: unknown spectral codebook: "+cb); } }