/*____________________________________________________________________________ FreeAmp - The Free MP3 Player MP3 Decoder originally Copyright (C) 1995-1997 Xing Technology Corp. http://www.xingtech.com Portions Copyright (C) 1998-1999 EMusic.com This program is free software; you can redistribute it and/or modify it under the terms of the GNU 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. $Id: uph.c,v 1.3 1999/10/19 07:13:09 elrod Exp $ ____________________________________________________________________________*/ /**** uph.c *************************************************** Layer 3 audio huffman decode ******************************************************************/ #include #include #include #include #include "l3.h" /*===============================================================*/ /* max bits required for any lookup - change if htable changes */ /* quad required 10 bit w/signs must have (MAXBITS+2) >= 10 */ #define MAXBITS 9 static const HUFF_ELEMENT huff_table_0[4] = {{0}, {0}, {0}, {64}}; /* dummy must not use */ #include "htable.h" /*-- 6 bit lookup (purgebits, value) --*/ static const unsigned char quad_table_a[][2] = { {6, 11}, {6, 15}, {6, 13}, {6, 14}, {6, 7}, {6, 5}, {5, 9}, {5, 9}, {5, 6}, {5, 6}, {5, 3}, {5, 3}, {5, 10}, {5, 10}, {5, 12}, {5, 12}, {4, 2}, {4, 2}, {4, 2}, {4, 2}, {4, 1}, {4, 1}, {4, 1}, {4, 1}, {4, 4}, {4, 4}, {4, 4}, {4, 4}, {4, 8}, {4, 8}, {4, 8}, {4, 8}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, {1, 0}, }; typedef struct { const HUFF_ELEMENT *table; int linbits; int ncase; } HUFF_SETUP; #define no_bits 0 #define one_shot 1 #define no_linbits 2 #define have_linbits 3 #define quad_a 4 #define quad_b 5 static const HUFF_SETUP table_look[] = { {huff_table_0, 0, no_bits}, {huff_table_1, 0, one_shot}, {huff_table_2, 0, one_shot}, {huff_table_3, 0, one_shot}, {huff_table_0, 0, no_bits}, {huff_table_5, 0, one_shot}, {huff_table_6, 0, one_shot}, {huff_table_7, 0, no_linbits}, {huff_table_8, 0, no_linbits}, {huff_table_9, 0, no_linbits}, {huff_table_10, 0, no_linbits}, {huff_table_11, 0, no_linbits}, {huff_table_12, 0, no_linbits}, {huff_table_13, 0, no_linbits}, {huff_table_0, 0, no_bits}, {huff_table_15, 0, no_linbits}, {huff_table_16, 1, have_linbits}, {huff_table_16, 2, have_linbits}, {huff_table_16, 3, have_linbits}, {huff_table_16, 4, have_linbits}, {huff_table_16, 6, have_linbits}, {huff_table_16, 8, have_linbits}, {huff_table_16, 10, have_linbits}, {huff_table_16, 13, have_linbits}, {huff_table_24, 4, have_linbits}, {huff_table_24, 5, have_linbits}, {huff_table_24, 6, have_linbits}, {huff_table_24, 7, have_linbits}, {huff_table_24, 8, have_linbits}, {huff_table_24, 9, have_linbits}, {huff_table_24, 11, have_linbits}, {huff_table_24, 13, have_linbits}, {huff_table_0, 0, quad_a}, {huff_table_0, 0, quad_b}, }; /*========================================================*/ extern BITDAT bitdat; /*------------- get n bits from bitstream -------------*/ /* unused static unsigned int bitget(int n) { unsigned int x; if (bitdat.bits < n) { */ /* refill bit buf if necessary */ /* while (bitdat.bits <= 24) { bitdat.bitbuf = (bitdat.bitbuf << 8) | *bitdat.bs_ptr++; bitdat.bits += 8; } } bitdat.bits -= n; x = bitdat.bitbuf >> bitdat.bits; bitdat.bitbuf -= x << bitdat.bits; return x; } */ /*----- get n bits - checks for n+2 avail bits (linbits+sign) -----*/ static unsigned int bitget_lb(int n) { unsigned int x; if (bitdat.bits < (n + 2)) { /* refill bit buf if necessary */ while (bitdat.bits <= 24) { bitdat.bitbuf = (bitdat.bitbuf << 8) | *bitdat.bs_ptr++; bitdat.bits += 8; } } bitdat.bits -= n; x = bitdat.bitbuf >> bitdat.bits; bitdat.bitbuf -= x << bitdat.bits; return x; } /*------------- get n bits but DO NOT remove from bitstream --*/ static unsigned int bitget2(int n) { unsigned int x; if (bitdat.bits < (MAXBITS + 2)) { /* refill bit buf if necessary */ while (bitdat.bits <= 24) { bitdat.bitbuf = (bitdat.bitbuf << 8) | *bitdat.bs_ptr++; bitdat.bits += 8; } } x = bitdat.bitbuf >> (bitdat.bits - n); return x; } /*------------- remove n bits from bitstream ---------*/ /* unused static void bitget_purge(int n) { bitdat.bits -= n; bitdat.bitbuf -= (bitdat.bitbuf >> bitdat.bits) << bitdat.bits; } */ /*------------- get 1 bit from bitstream NO CHECK -------------*/ /* unused static unsigned int bitget_1bit() { unsigned int x; bitdat.bits--; x = bitdat.bitbuf >> bitdat.bits; bitdat.bitbuf -= x << bitdat.bits; return x; } */ /*========================================================*/ /*========================================================*/ #define mac_bitget_check(n) if( bitdat.bits < (n) ) { \ while( bitdat.bits <= 24 ) { \ bitdat.bitbuf = (bitdat.bitbuf << 8) | *bitdat.bs_ptr++; \ bitdat.bits += 8; \ } \ } /*---------------------------------------------------------*/ #define mac_bitget2(n) (bitdat.bitbuf >> (bitdat.bits-n)); /*---------------------------------------------------------*/ #define mac_bitget(n) ( bitdat.bits -= n, \ code = bitdat.bitbuf >> bitdat.bits, \ bitdat.bitbuf -= code << bitdat.bits, \ code ) /*---------------------------------------------------------*/ #define mac_bitget_purge(n) bitdat.bits -= n, \ bitdat.bitbuf -= (bitdat.bitbuf >> bitdat.bits) << bitdat.bits; /*---------------------------------------------------------*/ #define mac_bitget_1bit() ( bitdat.bits--, \ code = bitdat.bitbuf >> bitdat.bits, \ bitdat.bitbuf -= code << bitdat.bits, \ code ) /*========================================================*/ /*========================================================*/ void unpack_huff(int xy[][2], int n, int ntable) { int i; const HUFF_ELEMENT *t; const HUFF_ELEMENT *t0; int linbits; int bits; int code; int x, y; if (n <= 0) return; n = n >> 1; /* huff in pairs */ /*-------------*/ t0 = table_look[ntable].table; linbits = table_look[ntable].linbits; switch (table_look[ntable].ncase) { default: /*------------------------------------------*/ case no_bits: /*- table 0, no data, x=y=0--*/ for (i = 0; i < n; i++) { xy[i][0] = 0; xy[i][1] = 0; } return; /*------------------------------------------*/ case one_shot: /*- single lookup, no escapes -*/ for (i = 0; i < n; i++) { mac_bitget_check((MAXBITS + 2)); bits = t0[0].b.signbits; code = mac_bitget2(bits); mac_bitget_purge(t0[1 + code].b.purgebits); x = t0[1 + code].b.x; y = t0[1 + code].b.y; if (x) if (mac_bitget_1bit()) x = -x; if (y) if (mac_bitget_1bit()) y = -y; xy[i][0] = x; xy[i][1] = y; if (bitdat.bs_ptr > bitdat.bs_ptr_end) break; // bad data protect } return; /*------------------------------------------*/ case no_linbits: for (i = 0; i < n; i++) { t = t0; for (;;) { mac_bitget_check((MAXBITS + 2)); bits = t[0].b.signbits; code = mac_bitget2(bits); if (t[1 + code].b.purgebits) break; t += t[1 + code].ptr; /* ptr include 1+code */ mac_bitget_purge(bits); } mac_bitget_purge(t[1 + code].b.purgebits); x = t[1 + code].b.x; y = t[1 + code].b.y; if (x) if (mac_bitget_1bit()) x = -x; if (y) if (mac_bitget_1bit()) y = -y; xy[i][0] = x; xy[i][1] = y; if (bitdat.bs_ptr > bitdat.bs_ptr_end) break; // bad data protect } return; /*------------------------------------------*/ case have_linbits: for (i = 0; i < n; i++) { t = t0; for (;;) { bits = t[0].b.signbits; code = bitget2(bits); if (t[1 + code].b.purgebits) break; t += t[1 + code].ptr; /* ptr includes 1+code */ mac_bitget_purge(bits); } mac_bitget_purge(t[1 + code].b.purgebits); x = t[1 + code].b.x; y = t[1 + code].b.y; if (x == 15) x += bitget_lb(linbits); if (x) if (mac_bitget_1bit()) x = -x; if (y == 15) y += bitget_lb(linbits); if (y) if (mac_bitget_1bit()) y = -y; xy[i][0] = x; xy[i][1] = y; if (bitdat.bs_ptr > bitdat.bs_ptr_end) break; // bad data protect } return; } /*--- end switch ---*/ } /*==========================================================*/ int unpack_huff_quad(int vwxy[][4], int n, int nbits, int ntable) { int i; int code; int x, y, v, w; int tmp; int i_non_zero, tmp_nz; tmp_nz = 15; i_non_zero = -1; n = n >> 2; /* huff in quads */ if (ntable) goto case_quad_b; /* case_quad_a: */ for (i = 0; i < n; i++) { if (nbits <= 0) break; mac_bitget_check(10); code = mac_bitget2(6); nbits -= quad_table_a[code][0]; mac_bitget_purge(quad_table_a[code][0]); tmp = quad_table_a[code][1]; if (tmp) { i_non_zero = i; tmp_nz = tmp; } v = (tmp >> 3) & 1; w = (tmp >> 2) & 1; x = (tmp >> 1) & 1; y = tmp & 1; if (v) { if (mac_bitget_1bit()) v = -v; nbits--; } if (w) { if (mac_bitget_1bit()) w = -w; nbits--; } if (x) { if (mac_bitget_1bit()) x = -x; nbits--; } if (y) { if (mac_bitget_1bit()) y = -y; nbits--; } vwxy[i][0] = v; vwxy[i][1] = w; vwxy[i][2] = x; vwxy[i][3] = y; if (bitdat.bs_ptr > bitdat.bs_ptr_end) break; // bad data protect } if (i && nbits < 0) { i--; vwxy[i][0] = 0; vwxy[i][1] = 0; vwxy[i][2] = 0; vwxy[i][3] = 0; } i_non_zero = (i_non_zero + 1) << 2; if ((tmp_nz & 3) == 0) i_non_zero -= 2; return i_non_zero; /*--------------------*/ case_quad_b: for (i = 0; i < n; i++) { if (nbits < 4) break; nbits -= 4; mac_bitget_check(8); tmp = mac_bitget(4) ^ 15; /* one's complement of bitstream */ if (tmp) { i_non_zero = i; tmp_nz = tmp; } v = (tmp >> 3) & 1; w = (tmp >> 2) & 1; x = (tmp >> 1) & 1; y = tmp & 1; if (v) { if (mac_bitget_1bit()) v = -v; nbits--; } if (w) { if (mac_bitget_1bit()) w = -w; nbits--; } if (x) { if (mac_bitget_1bit()) x = -x; nbits--; } if (y) { if (mac_bitget_1bit()) y = -y; nbits--; } vwxy[i][0] = v; vwxy[i][1] = w; vwxy[i][2] = x; vwxy[i][3] = y; if (bitdat.bs_ptr > bitdat.bs_ptr_end) break; // bad data protect } if (nbits < 0) { i--; vwxy[i][0] = 0; vwxy[i][1] = 0; vwxy[i][2] = 0; vwxy[i][3] = 0; } i_non_zero = (i_non_zero + 1) << 2; if ((tmp_nz & 3) == 0) i_non_zero -= 2; return i_non_zero; /* return non-zero sample (to nearest pair) */ } /*-----------------------------------------------------*/