/*
* 11/19/04 1.0 moved to LGPL.
* 16/11/99 Renamed class, added javadoc, and changed table
* name from String to 3 chars. mdm@techie.com
* 02/15/99 Java Conversion by E.B, javalayer@javazoom.net
*
* 04/19/97 : Adapted from the ISO MPEG Audio Subgroup Software Simulation
* Group's public c source for its MPEG audio decoder. Miscellaneous
* changes by Jeff Tsay (ctsay@pasteur.eecs.berkeley.edu).
*-----------------------------------------------------------------------
* Copyright (c) 1991 MPEG/audio software simulation group, All Rights Reserved
* MPEG/audio coding/decoding software, work in progress
* NOT for public distribution until verified and approved by the
* MPEG/audio committee. For further information, please contact
* Davis Pan, 508-493-2241, e-mail: pan@3d.enet.dec.com
*
* VERSION 4.1
* changes made since last update:
* date programmers comment
* 27.2.92 F.O.Witte (ITT Intermetall)
* 8/24/93 M. Iwadare Changed for 1 pass decoding.
* 7/14/94 J. Koller useless 'typedef' before huffcodetab removed
*-----------------------------------------------------------------------
* 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 org.geogebra.desktop.sound.mp3transform;
final class Huffman {
private static final int MX_OFF = 250;
private static final int HUFFMAN_COUNT = 34;
public static final Huffman[] HUFFMAN;
private final char tableName0;
private final char tableName1;
private final int xlen; // max. x-index+
private final int ylen; // max. y-index+
private final int linbits; // number of linbits
private final int[] val0; // decoder tree
private final int[] val1; // decoder tree
private final int treeLen; // length of decoder tree
private Huffman(String name, int xlen, int ylen, int linbits, int[][] val,
int treeLen) {
tableName0 = name.charAt(0);
tableName1 = name.charAt(1);
this.xlen = xlen;
this.ylen = ylen;
this.linbits = linbits;
val0 = new int[val.length];
val1 = new int[val.length];
for (int i = 0; i < val.length; i++) {
val0[i] = val[i][0];
val1[i] = val[i][1];
}
this.treeLen = treeLen;
}
/**
* Do the huffman-decoding. For counta, countb - the 4 bit value is returned
* in y, discard x.
*/
public int decode(Layer3Decoder decoder, BitReservoir br) {
// array of all huffcodtable headers
// 0..31 Huffman code table 0..31
// 32,33 count1-tables
// table 0 needs no bits
if (treeLen == 0) {
decoder.x = decoder.y = 0;
return 0;
}
int level = 1 << ((4 * 8) - 1);
int point = 0;
int error = 1;
// Lookup in Huffman table
do {
if (val0[point] == 0) {
// end of tree
decoder.x = val1[point] >>> 4;
decoder.y = val1[point] & 0xf;
error = 0;
break;
}
if (br.getOneBit() != 0) {
while (val1[point] >= MX_OFF) {
point += val1[point];
}
point += val1[point];
} else {
while (val0[point] >= MX_OFF) {
point += val0[point];
}
point += val0[point];
}
level >>>= 1;
} while (level != 0);
// Process sign encodings for quadruples tables
if (tableName0 == '3' && (tableName1 == '2' || tableName1 == '3')) {
decoder.v = (decoder.y >> 3) & 1;
decoder.w = (decoder.y >> 2) & 1;
decoder.x = (decoder.y >> 1) & 1;
decoder.y = decoder.y & 1;
// v, w, x and y are reversed in the bitstream
// switch them around to make test bistream work.
if (decoder.v != 0) {
if (br.getOneBit() != 0) {
decoder.v = -decoder.v;
}
}
if (decoder.w != 0) {
if (br.getOneBit() != 0) {
decoder.w = -decoder.w;
}
}
if (decoder.x != 0) {
if (br.getOneBit() != 0) {
decoder.x = -decoder.x;
}
}
if (decoder.y != 0) {
if (br.getOneBit() != 0) {
decoder.y = -decoder.y;
}
}
} else {
// Process sign and escape encodings for dual tables.
// x and y are reversed in the test bitstream.
// Reverse x and y here to make test bitstream work.
if (linbits != 0) {
if ((xlen - 1) == decoder.x) {
decoder.x += br.getBits(linbits);
}
}
if (decoder.x != 0) {
if (br.getOneBit() != 0) {
decoder.x = -decoder.x;
}
}
if (linbits != 0) {
if ((ylen - 1) == decoder.y) {
decoder.y += br.getBits(linbits);
}
}
if (decoder.y != 0) {
if (br.getOneBit() != 0) {
decoder.y = -decoder.y;
}
}
}
return error;
}
static {
HUFFMAN = new Huffman[HUFFMAN_COUNT];
HUFFMAN[0] = new Huffman("0 ", 0, 0, 0, Constants.VAL_TAB_0, 0);
HUFFMAN[1] = new Huffman("1 ", 2, 2, 0, Constants.VAL_TAB_1, 7);
HUFFMAN[2] = new Huffman("2 ", 3, 3, 0, Constants.VAL_TAB_2, 17);
HUFFMAN[3] = new Huffman("3 ", 3, 3, 0, Constants.VAL_TAB_3, 17);
HUFFMAN[4] = new Huffman("4 ", 0, 0, 0, Constants.VAL_TAB_4, 0);
HUFFMAN[5] = new Huffman("5 ", 4, 4, 0, Constants.VAL_TAB_5, 31);
HUFFMAN[6] = new Huffman("6 ", 4, 4, 0, Constants.VAL_TAB_6, 31);
HUFFMAN[7] = new Huffman("7 ", 6, 6, 0, Constants.VAL_TAB_7, 71);
HUFFMAN[8] = new Huffman("8 ", 6, 6, 0, Constants.VAL_TAB_8, 71);
HUFFMAN[9] = new Huffman("9 ", 6, 6, 0, Constants.VAL_TAB_9, 71);
HUFFMAN[10] = new Huffman("10", 8, 8, 0, Constants.VAL_TAB_10, 127);
HUFFMAN[11] = new Huffman("11", 8, 8, 0, Constants.VAL_TAB_11, 127);
HUFFMAN[12] = new Huffman("12", 8, 8, 0, Constants.VAL_TAB_12, 127);
HUFFMAN[13] = new Huffman("13", 16, 16, 0, Constants.VAL_TAB_13, 511);
HUFFMAN[14] = new Huffman("14", 0, 0, 0, Constants.VAL_TAB_14, 0);
HUFFMAN[15] = new Huffman("15", 16, 16, 0, Constants.VAL_TAB_15, 511);
HUFFMAN[16] = new Huffman("16", 16, 16, 1, Constants.VAL_TAB_16, 511);
HUFFMAN[17] = new Huffman("17", 16, 16, 2, Constants.VAL_TAB_16, 511);
HUFFMAN[18] = new Huffman("18", 16, 16, 3, Constants.VAL_TAB_16, 511);
HUFFMAN[19] = new Huffman("19", 16, 16, 4, Constants.VAL_TAB_16, 511);
HUFFMAN[20] = new Huffman("20", 16, 16, 6, Constants.VAL_TAB_16, 511);
HUFFMAN[21] = new Huffman("21", 16, 16, 8, Constants.VAL_TAB_16, 511);
HUFFMAN[22] = new Huffman("22", 16, 16, 10, Constants.VAL_TAB_16, 511);
HUFFMAN[23] = new Huffman("23", 16, 16, 13, Constants.VAL_TAB_16, 511);
HUFFMAN[24] = new Huffman("24", 16, 16, 4, Constants.VAL_TAB_24, 512);
HUFFMAN[25] = new Huffman("25", 16, 16, 5, Constants.VAL_TAB_24, 512);
HUFFMAN[26] = new Huffman("26", 16, 16, 6, Constants.VAL_TAB_24, 512);
HUFFMAN[27] = new Huffman("27", 16, 16, 7, Constants.VAL_TAB_24, 512);
HUFFMAN[28] = new Huffman("28", 16, 16, 8, Constants.VAL_TAB_24, 512);
HUFFMAN[29] = new Huffman("29", 16, 16, 9, Constants.VAL_TAB_24, 512);
HUFFMAN[30] = new Huffman("30", 16, 16, 11, Constants.VAL_TAB_24, 512);
HUFFMAN[31] = new Huffman("31", 16, 16, 13, Constants.VAL_TAB_24, 512);
HUFFMAN[32] = new Huffman("32", 1, 16, 0, Constants.VAL_TAB_32, 31);
HUFFMAN[33] = new Huffman("33", 1, 16, 0, Constants.VAL_TAB_33, 31);
}
}