/* * Copyright (C) 2011 in-somnia * * This file is part of JAAD. * * JAAD is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 3 of the * License, or (at your option) any later version. * * JAAD 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 Lesser General * Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. * If not, see <http://www.gnu.org/licenses/>. */ package net.sourceforge.jaad.aac.huffman; import net.sourceforge.jaad.aac.AACException; import net.sourceforge.jaad.aac.syntax.BitStream; //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(BitStream 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(BitStream 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(BitStream 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(BitStream in) throws AACException { final int offset = findOffset(in, HCB_SF); return HCB_SF[offset][2]; } public static void decodeSpectralData(BitStream in, int cb, int[] data, int off) throws AACException { int[][] HCB; try { HCB = CODEBOOKS[cb-1]; } catch(ArrayIndexOutOfBoundsException ex) { System.out.println("codebook: "+cb); ex.printStackTrace(); throw ex; } //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); } }