diff liba52/parse.c @ 18720:4bad7f00556e

sync with liba52 0.7.4, patch by Emanuele Giaquinta >emanuele.giaquinta ! gmail * com< part 1: functional changes
author rathann
date Thu, 15 Jun 2006 22:58:06 +0000
parents 07f1e7669772
children 722ac20fac5f
line wrap: on
line diff
--- a/liba52/parse.c	Thu Jun 15 08:43:41 2006 +0000
+++ b/liba52/parse.c	Thu Jun 15 22:58:06 2006 +0000
@@ -1,6 +1,6 @@
 /*
  * parse.c
- * Copyright (C) 2000-2001 Michel Lespinasse <walken@zoy.org>
+ * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org>
  * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
  *
  * This file is part of a52dec, a free ATSC A-52 stream decoder.
@@ -28,6 +28,7 @@
 #include "config.h"
 
 #include <stdlib.h>
+#include <stdio.h>
 #include <string.h>
 #include <inttypes.h>
 
@@ -53,37 +54,52 @@
 
 static uint8_t halfrate[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3};
 
-sample_t * a52_init (uint32_t mm_accel)
+a52_state_t * a52_init (uint32_t mm_accel)
 {
-    sample_t * samples;
+    a52_state_t * state;
     int i;
 
-    samples = memalign (16, 256 * 12 * sizeof (sample_t));
+    state = malloc (sizeof (a52_state_t));
+    if (state == NULL)
+	return NULL;
+
+    state->samples = memalign (16, 256 * 12 * sizeof (sample_t));
 #if defined(__MINGW32__) && defined(HAVE_SSE) 
     for(i=0;i<10;i++){
-      if((int)samples%16){
+      if((int)state->samples%16){
         sample_t* samplestmp=malloc(256 * 12 * sizeof (sample_t));   
-        free(samples);
-        samples = samplestmp;    
+        free(state->samples);
+        state->samples = samplestmp;    
       }
       else break;
     }
 #endif
-    if(((int)samples%16) && (mm_accel&MM_ACCEL_X86_SSE)){
+    if(((int)state->samples%16) && (mm_accel&MM_ACCEL_X86_SSE)){
       mm_accel &=~MM_ACCEL_X86_SSE;
-      printf("liba52: unable to get 16 byte aligned memory disabling usage of SSE instructions\n");
+      fprintf(stderr, "liba52: unable to get 16 byte aligned memory disabling usage of SSE instructions\n");
     }   
     
-    if (samples == NULL)
+    if (state->samples == NULL) {
+	free (state);
 	return NULL;    
+    }
+
+    for (i = 0; i < 256 * 12; i++)
+	state->samples[i] = 0;
+
+    state->downmixed = 1;
+
+    state->lfsr_state = 1;
     
-    imdct_init (mm_accel);
+    a52_imdct_init (mm_accel);
     downmix_accel_init(mm_accel);
     
-    for (i = 0; i < 256 * 12; i++)
-	samples[i] = 0;
+    return state;
+}
 
-    return samples;
+sample_t * a52_samples (a52_state_t * state)
+{
+    return state->samples;
 }
 
 int a52_syncinfo (uint8_t * buf, int * flags,
@@ -117,7 +133,7 @@
     *bit_rate = (bitrate * 1000) >> half;
 
     switch (buf[4] & 0xc0) {
-    case 0:	/* 48 KHz */
+    case 0:
 	*sample_rate = 48000 >> half;
 	return 4 * bitrate;
     case 0x40:
@@ -143,21 +159,21 @@
     state->halfrate = halfrate[buf[5] >> 3];
     state->acmod = acmod = buf[6] >> 5;
 
-    bitstream_set_ptr (buf + 6);
-    bitstream_skip (3);	/* skip acmod we already parsed */
+    a52_bitstream_set_ptr (state, buf + 6);
+    bitstream_skip (state, 3);	/* skip acmod we already parsed */
 
-    if ((acmod == 2) && (bitstream_get (2) == 2))	/* dsurmod */
+    if ((acmod == 2) && (bitstream_get (state, 2) == 2))	/* dsurmod */
 	acmod = A52_DOLBY;
 
     if ((acmod & 1) && (acmod != 1))
-	state->clev = clev[bitstream_get (2)];	/* cmixlev */
+	state->clev = clev[bitstream_get (state, 2)];	/* cmixlev */
 
     if (acmod & 4)
-	state->slev = slev[bitstream_get (2)];	/* surmixlev */
+	state->slev = slev[bitstream_get (state, 2)];	/* surmixlev */
 
-    state->lfeon = bitstream_get (1);
+    state->lfeon = bitstream_get (state, 1);
 
-    state->output = downmix_init (acmod, *flags, level,
+    state->output = a52_downmix_init (acmod, *flags, level,
 				  state->clev, state->slev);
     if (state->output < 0)
 	return 1;
@@ -169,31 +185,34 @@
     state->bias = bias;
     state->dynrnge = 1;
     state->dynrngcall = NULL;
+    state->cplba.deltbae = DELTA_BIT_NONE;
+    state->ba[0].deltbae = state->ba[1].deltbae = state->ba[2].deltbae =
+	state->ba[3].deltbae = state->ba[4].deltbae = DELTA_BIT_NONE;
 
     chaninfo = !acmod;
     do {
-	bitstream_skip (5);	/* dialnorm */
-	if (bitstream_get (1))	/* compre */
-	    bitstream_skip (8);	/* compr */
-	if (bitstream_get (1))	/* langcode */
-	    bitstream_skip (8);	/* langcod */
-	if (bitstream_get (1))	/* audprodie */
-	    bitstream_skip (7);	/* mixlevel + roomtyp */
+	bitstream_skip (state, 5);	/* dialnorm */
+	if (bitstream_get (state, 1))	/* compre */
+	    bitstream_skip (state, 8);	/* compr */
+	if (bitstream_get (state, 1))	/* langcode */
+	    bitstream_skip (state, 8);	/* langcod */
+	if (bitstream_get (state, 1))	/* audprodie */
+	    bitstream_skip (state, 7);	/* mixlevel + roomtyp */
     } while (chaninfo--);
 
-    bitstream_skip (2);		/* copyrightb + origbs */
+    bitstream_skip (state, 2);		/* copyrightb + origbs */
 
-    if (bitstream_get (1))	/* timecod1e */
-	bitstream_skip (14);	/* timecod1 */
-    if (bitstream_get (1))	/* timecod2e */
-	bitstream_skip (14);	/* timecod2 */
+    if (bitstream_get (state, 1))	/* timecod1e */
+	bitstream_skip (state, 14);	/* timecod1 */
+    if (bitstream_get (state, 1))	/* timecod2e */
+	bitstream_skip (state, 14);	/* timecod2 */
 
-    if (bitstream_get (1)) {	/* addbsie */
+    if (bitstream_get (state, 1)) {	/* addbsie */
 	int addbsil;
 
-	addbsil = bitstream_get (6);
+	addbsil = bitstream_get (state, 6);
 	do {
-	    bitstream_skip (8);	/* addbsi */
+	    bitstream_skip (state, 8);	/* addbsi */
 	} while (addbsil--);
     }
 
@@ -211,13 +230,13 @@
     }
 }
 
-static int parse_exponents (int expstr, int ngrps, uint8_t exponent,
-			    uint8_t * dest)
+static int parse_exponents (a52_state_t * state, int expstr, int ngrps,
+			    uint8_t exponent, uint8_t * dest)
 {
     int exps;
 
     while (ngrps--) {
-	exps = bitstream_get (7);
+	exps = bitstream_get (state, 7);
 
 	exponent += exp_1[exps];
 	if (exponent > 24)
@@ -265,18 +284,18 @@
     return 0;
 }
 
-static int parse_deltba (int8_t * deltba)
+static int parse_deltba (a52_state_t * state, int8_t * deltba)
 {
     int deltnseg, deltlen, delta, j;
 
     memset (deltba, 0, 50);
 
-    deltnseg = bitstream_get (3);
+    deltnseg = bitstream_get (state, 3);
     j = 0;
     do {
-	j += bitstream_get (5);
-	deltlen = bitstream_get (4);
-	delta = bitstream_get (3);
+	j += bitstream_get (state, 5);
+	deltlen = bitstream_get (state, 4);
+	delta = bitstream_get (state, 3);
 	delta -= (delta >= 4) ? 3 : 4;
 	if (!deltlen)
 	    continue;
@@ -293,37 +312,42 @@
 {
     int i;
 
-    if ((state->csnroffst) || (state->cplinu && state->cplba.fsnroffst) ||
-	(state->lfeon && state->lfeba.fsnroffst))
+    if ((state->csnroffst) ||
+	(state->chincpl && state->cplba.bai >> 3) ||	/* cplinu, fsnroffst */
+	(state->lfeon && state->lfeba.bai >> 3))	/* fsnroffst */
 	return 0;
     for (i = 0; i < nfchans; i++)
-	if (state->ba[i].fsnroffst)
+	if (state->ba[i].bai >> 3)			/* fsnroffst */
 	    return 0;
     return 1;
 }
 
-static inline int16_t dither_gen (void)
+static inline int16_t dither_gen (a52_state_t * state)
 {
-    static uint16_t lfsr_state = 1;
-    int16_t state;
+    int16_t nstate;
 
-    state = dither_lut[lfsr_state >> 8] ^ (lfsr_state << 8);
+    nstate = dither_lut[state->lfsr_state >> 8] ^ (state->lfsr_state << 8);
 	
-    lfsr_state = (uint16_t) state;
+    state->lfsr_state = (uint16_t) nstate;
 
-    return state;
+    return nstate;
 }
 
-static void coeff_get (sample_t * coeff, uint8_t * exp, int8_t * bap,
-		       quantizer_t * quantizer, sample_t level,
-		       int dither, int end)
+static void coeff_get (a52_state_t * state, sample_t * coeff,
+		       expbap_t * expbap, quantizer_t * quantizer,
+		       sample_t level, int dither, int end)
 {
     int i;
+    uint8_t * exp;
+    int8_t * bap;
     sample_t factor[25];
 
     for (i = 0; i <= 24; i++)
 	factor[i] = scale_factor[i] * level;
 
+    exp = expbap->exp;
+    bap = expbap->bap;
+
     for (i = 0; i < end; i++) {
 	int bapi;
 
@@ -331,7 +355,7 @@
 	switch (bapi) {
 	case 0:
 	    if (dither) {
-		coeff[i] = dither_gen() * LEVEL_3DB * factor[exp[i]];
+		coeff[i] = dither_gen (state) * LEVEL_3DB * factor[exp[i]];
 		continue;
 	    } else {
 		coeff[i] = 0;
@@ -345,7 +369,7 @@
 	    } else {
 		int code;
 
-		code = bitstream_get (5);
+		code = bitstream_get (state, 5);
 
 		quantizer->q1_ptr = 1;
 		quantizer->q1[0] = q_1_2[code];
@@ -361,7 +385,7 @@
 	    } else {
 		int code;
 
-		code = bitstream_get (7);
+		code = bitstream_get (state, 7);
 
 		quantizer->q2_ptr = 1;
 		quantizer->q2[0] = q_2_2[code];
@@ -371,7 +395,7 @@
 	    }
 
 	case 3:
-	    coeff[i] = q_3[bitstream_get (3)] * factor[exp[i]];
+	    coeff[i] = q_3[bitstream_get (state, 3)] * factor[exp[i]];
 	    continue;
 
 	case -3:
@@ -382,7 +406,7 @@
 	    } else {
 		int code;
 
-		code = bitstream_get (7);
+		code = bitstream_get (state, 7);
 
 		quantizer->q4_ptr = 0;
 		quantizer->q4 = q_4_1[code];
@@ -391,11 +415,11 @@
 	    }
 
 	case 4:
-	    coeff[i] = q_5[bitstream_get (4)] * factor[exp[i]];
+	    coeff[i] = q_5[bitstream_get (state, 4)] * factor[exp[i]];
 	    continue;
 
 	default:
-	    coeff[i] = ((bitstream_get_2 (bapi) << (16 - bapi)) *
+	    coeff[i] = ((bitstream_get_2 (state, bapi) << (16 - bapi)) *
 			  factor[exp[i]]);
 	}
     }
@@ -405,19 +429,23 @@
 				sample_t * coeff, sample_t (* samples)[256],
 				quantizer_t * quantizer, uint8_t dithflag[5])
 {
-    int sub_bnd, bnd, i, i_end, ch;
+    int cplbndstrc, bnd, i, i_end, ch;
+    uint8_t * exp;
     int8_t * bap;
-    uint8_t * exp;
     sample_t cplco[5];
 
-    bap = state->cpl_bap;
-    exp = state->cpl_exp;
-    sub_bnd = bnd = 0;
+    exp = state->cpl_expbap.exp;
+    bap = state->cpl_expbap.bap;
+    bnd = 0;
+    cplbndstrc = state->cplbndstrc;
     i = state->cplstrtmant;
     while (i < state->cplendmant) {
 	i_end = i + 12;
-	while (state->cplbndstrc[sub_bnd++])
+	while (cplbndstrc & 1) {
+	    cplbndstrc >>= 1;
 	    i_end += 12;
+	}
+	cplbndstrc >>= 1;
 	for (ch = 0; ch < nfchans; ch++)
 	    cplco[ch] = state->cplco[ch][bnd] * coeff[ch];
 	bnd++;
@@ -431,10 +459,10 @@
 	    case 0:
 		cplcoeff = LEVEL_3DB * scale_factor[exp[i]];
 		for (ch = 0; ch < nfchans; ch++)
-		    if (state->chincpl[ch]) {
+		    if ((state->chincpl >> ch) & 1) {
 			if (dithflag[ch])
 			    samples[ch][i] = (cplcoeff * cplco[ch] *
-					      dither_gen ());
+					      dither_gen (state));
 			else
 			    samples[ch][i] = 0;
 		    }
@@ -448,7 +476,7 @@
 		} else {
 		    int code;
 
-		    code = bitstream_get (5);
+		    code = bitstream_get (state, 5);
 
 		    quantizer->q1_ptr = 1;
 		    quantizer->q1[0] = q_1_2[code];
@@ -464,7 +492,7 @@
 		} else {
 		    int code;
 
-		    code = bitstream_get (7);
+		    code = bitstream_get (state, 7);
 
 		    quantizer->q2_ptr = 1;
 		    quantizer->q2[0] = q_2_2[code];
@@ -474,7 +502,7 @@
 		}
 
 	    case 3:
-		cplcoeff = q_3[bitstream_get (3)];
+		cplcoeff = q_3[bitstream_get (state, 3)];
 		break;
 
 	    case -3:
@@ -485,7 +513,7 @@
 		} else {
 		    int code;
 
-		    code = bitstream_get (7);
+		    code = bitstream_get (state, 7);
 
 		    quantizer->q4_ptr = 0;
 		    quantizer->q4 = q_4_1[code];
@@ -494,23 +522,23 @@
 		}
 
 	    case 4:
-		cplcoeff = q_5[bitstream_get (4)];
+		cplcoeff = q_5[bitstream_get (state, 4)];
 		break;
 
 	    default:
-		cplcoeff = bitstream_get_2 (bapi) << (16 - bapi);
+		cplcoeff = bitstream_get_2 (state, bapi) << (16 - bapi);
 	    }
 
 	    cplcoeff *= scale_factor[exp[i]];
 	    for (ch = 0; ch < nfchans; ch++)
-		if (state->chincpl[ch])
+		if ((state->chincpl >> ch) & 1)
 		    samples[ch][i] = cplcoeff * cplco[ch];
 	    i++;
 	}
     }
 }
 
-int a52_block (a52_state_t * state, sample_t * samples)
+int a52_block (a52_state_t * state)
 {
     static const uint8_t nfchans_tbl[] = {2, 1, 2, 3, 3, 4, 4, 5, 1, 1, 2};
     static int rematrix_band[4] = {25, 37, 61, 253};
@@ -520,21 +548,22 @@
     sample_t coeff[5];
     int chanbias;
     quantizer_t quantizer;
+    sample_t * samples;
 
     nfchans = nfchans_tbl[state->acmod];
 
     for (i = 0; i < nfchans; i++)
-	blksw[i] = bitstream_get (1);
+	blksw[i] = bitstream_get (state, 1);
 
     for (i = 0; i < nfchans; i++)
-	dithflag[i] = bitstream_get (1);
+	dithflag[i] = bitstream_get (state, 1);
 
-    chaninfo = !(state->acmod);
+    chaninfo = !state->acmod;
     do {
-	if (bitstream_get (1)) {	/* dynrnge */
+	if (bitstream_get (state, 1)) {	/* dynrnge */
 	    int dynrng;
 
-	    dynrng = bitstream_get_2 (8);
+	    dynrng = bitstream_get_2 (state, 8);
 	    if (state->dynrnge) {
 		sample_t range;
 
@@ -547,25 +576,25 @@
 	}
     } while (chaninfo--);
 
-    if (bitstream_get (1)) {	/* cplstre */
-	state->cplinu = bitstream_get (1);
-	if (state->cplinu) {
-	    static int bndtab[16] = {31, 35, 37, 39, 41, 42, 43, 44,
+    if (bitstream_get (state, 1)) {	/* cplstre */
+	state->chincpl = 0;
+	if (bitstream_get (state, 1)) {	/* cplinu */
+	    static uint8_t bndtab[16] = {31, 35, 37, 39, 41, 42, 43, 44,
 				     45, 45, 46, 46, 47, 47, 48, 48};
 	    int cplbegf;
 	    int cplendf;
 	    int ncplsubnd;
 
 	    for (i = 0; i < nfchans; i++)
-		state->chincpl[i] = bitstream_get (1);
+		state->chincpl |= bitstream_get (state, 1) << i;
 	    switch (state->acmod) {
 	    case 0: case 1:
 		return 1;
 	    case 2:
-		state->phsflginu = bitstream_get (1);
+		state->phsflginu = bitstream_get (state, 1);
 	    }
-	    cplbegf = bitstream_get (4);
-	    cplendf = bitstream_get (4);
+	    cplbegf = bitstream_get (state, 4);
+	    cplendf = bitstream_get (state, 4);
 
 	    if (cplendf + 3 - cplbegf < 0)
 		return 1;
@@ -574,28 +603,29 @@
 	    state->cplstrtmant = cplbegf * 12 + 37;
 	    state->cplendmant = cplendf * 12 + 73;
 
-	    for (i = 0; i < ncplsubnd - 1; i++) {
-		state->cplbndstrc[i] = bitstream_get (1);
-		state->ncplbnd -= state->cplbndstrc[i];
+	    state->cplbndstrc = 0;
+	    for (i = 0; i < ncplsubnd - 1; i++)
+		if (bitstream_get (state, 1)) {
+		    state->cplbndstrc |= 1 << i;
+		    state->ncplbnd--;
 	    }
-	    state->cplbndstrc[i] = 0;	/* last value is a sentinel */
 	}
     }
 
-    if (state->cplinu) {
+    if (state->chincpl) {	/* cplinu */
 	int j, cplcoe;
 
 	cplcoe = 0;
 	for (i = 0; i < nfchans; i++)
-	    if (state->chincpl[i])
-		if (bitstream_get (1)) {	/* cplcoe */
+	    if ((state->chincpl) >> i & 1)
+		if (bitstream_get (state, 1)) {	/* cplcoe */
 		    int mstrcplco, cplcoexp, cplcomant;
 
 		    cplcoe = 1;
-		    mstrcplco = 3 * bitstream_get (2);
+		    mstrcplco = 3 * bitstream_get (state, 2);
 		    for (j = 0; j < state->ncplbnd; j++) {
-			cplcoexp = bitstream_get (4);
-			cplcomant = bitstream_get (4);
+			cplcoexp = bitstream_get (state, 4);
+			cplcomant = bitstream_get (state, 4);
 			if (cplcoexp == 15)
 			    cplcomant <<= 14;
 			else
@@ -606,37 +636,38 @@
 		}
 	if ((state->acmod == 2) && state->phsflginu && cplcoe)
 	    for (j = 0; j < state->ncplbnd; j++)
-		if (bitstream_get (1))	/* phsflg */
+		if (bitstream_get (state, 1))	/* phsflg */
 		    state->cplco[1][j] = -state->cplco[1][j];
     }
 
-    if ((state->acmod == 2) && (bitstream_get (1))) {	/* rematstr */
+    if ((state->acmod == 2) && (bitstream_get (state, 1))) {	/* rematstr */
 	int end;
 
-	end = (state->cplinu) ? state->cplstrtmant : 253;
+	state->rematflg = 0;
+	end = (state->chincpl) ? state->cplstrtmant : 253;	/* cplinu */
 	i = 0;
 	do
-	    state->rematflg[i] = bitstream_get (1);
+	    state->rematflg |= bitstream_get (state, 1) << i;
 	while (rematrix_band[i++] < end);
     }
 
     cplexpstr = EXP_REUSE;
     lfeexpstr = EXP_REUSE;
-    if (state->cplinu)
-	cplexpstr = bitstream_get (2);
+    if (state->chincpl)	/* cplinu */
+	cplexpstr = bitstream_get (state, 2);
     for (i = 0; i < nfchans; i++)
-	chexpstr[i] = bitstream_get (2);
+	chexpstr[i] = bitstream_get (state, 2);
     if (state->lfeon) 
-	lfeexpstr = bitstream_get (1);
+	lfeexpstr = bitstream_get (state, 1);
 
     for (i = 0; i < nfchans; i++)
 	if (chexpstr[i] != EXP_REUSE) {
-	    if (state->cplinu && state->chincpl[i])
+	    if ((state->chincpl >> i) & 1)
 		state->endmant[i] = state->cplstrtmant;
 	    else {
 		int chbwcod;
 
-		chbwcod = bitstream_get (6);
+		chbwcod = bitstream_get (state, 6);
 		if (chbwcod > 60)
 		    return 1;
 		state->endmant[i] = chbwcod * 3 + 73;
@@ -651,9 +682,9 @@
 	do_bit_alloc = 64;
 	ncplgrps = ((state->cplendmant - state->cplstrtmant) /
 		    (3 << (cplexpstr - 1)));
-	cplabsexp = bitstream_get (4) << 1;
-	if (parse_exponents (cplexpstr, ncplgrps, cplabsexp,
-			     state->cpl_exp + state->cplstrtmant))
+	cplabsexp = bitstream_get (state, 4) << 1;
+	if (parse_exponents (state, cplexpstr, ncplgrps, cplabsexp,
+			     state->cpl_expbap.exp + state->cplstrtmant))
 	    return 1;
     }
     for (i = 0; i < nfchans; i++)
@@ -663,99 +694,94 @@
 	    do_bit_alloc |= 1 << i;
 	    grp_size = 3 << (chexpstr[i] - 1);
 	    nchgrps = (state->endmant[i] + grp_size - 4) / grp_size;
-	    state->fbw_exp[i][0] = bitstream_get (4);
-	    if (parse_exponents (chexpstr[i], nchgrps, state->fbw_exp[i][0],
-				 state->fbw_exp[i] + 1))
+	    state->fbw_expbap[i].exp[0] = bitstream_get (state, 4);
+	    if (parse_exponents (state, chexpstr[i], nchgrps,
+				 state->fbw_expbap[i].exp[0],
+				 state->fbw_expbap[i].exp + 1))
 		return 1;
-	    bitstream_skip (2);	/* gainrng */
+	    bitstream_skip (state, 2);	/* gainrng */
 	}
     if (lfeexpstr != EXP_REUSE) {
 	do_bit_alloc |= 32;
-	state->lfe_exp[0] = bitstream_get (4);
-	if (parse_exponents (lfeexpstr, 2, state->lfe_exp[0],
-			     state->lfe_exp + 1))
+	state->lfe_expbap.exp[0] = bitstream_get (state, 4);
+	if (parse_exponents (state, lfeexpstr, 2, state->lfe_expbap.exp[0],
+			     state->lfe_expbap.exp + 1))
 	    return 1;
     }
 
-    if (bitstream_get (1)) {	/* baie */
+    if (bitstream_get (state, 1)) {	/* baie */
 	do_bit_alloc = -1;
-	state->sdcycod = bitstream_get (2);
-	state->fdcycod = bitstream_get (2);
-	state->sgaincod = bitstream_get (2);
-	state->dbpbcod = bitstream_get (2);
-	state->floorcod = bitstream_get (3);
+	state->bai = bitstream_get (state, 11);
     }
-    if (bitstream_get (1)) {	/* snroffste */
+    if (bitstream_get (state, 1)) {	/* snroffste */
 	do_bit_alloc = -1;
-	state->csnroffst = bitstream_get (6);
-	if (state->cplinu) {
-	    state->cplba.fsnroffst = bitstream_get (4);
-	    state->cplba.fgaincod = bitstream_get (3);
-	}
-	for (i = 0; i < nfchans; i++) {
-	    state->ba[i].fsnroffst = bitstream_get (4);
-	    state->ba[i].fgaincod = bitstream_get (3);
-	}
-	if (state->lfeon) {
-	    state->lfeba.fsnroffst = bitstream_get (4);
-	    state->lfeba.fgaincod = bitstream_get (3);
-	}
+	state->csnroffst = bitstream_get (state, 6);
+	if (state->chincpl)	/* cplinu */
+	    state->cplba.bai = bitstream_get (state, 7);
+	for (i = 0; i < nfchans; i++)
+	    state->ba[i].bai = bitstream_get (state, 7);
+	if (state->lfeon)
+	    state->lfeba.bai = bitstream_get (state, 7);
     }
-    if ((state->cplinu) && (bitstream_get (1))) {	/* cplleake */
+    if ((state->chincpl) && (bitstream_get (state, 1))) { /* cplleake */
 	do_bit_alloc |= 64;
-	state->cplfleak = 2304 - (bitstream_get (3) << 8);
-	state->cplsleak = 2304 - (bitstream_get (3) << 8);
+	state->cplfleak = 9 - bitstream_get (state, 3);
+	state->cplsleak = 9 - bitstream_get (state, 3);
     }
 
-    if (bitstream_get (1)) {	/* deltbaie */
+    if (bitstream_get (state, 1)) {	/* deltbaie */
 	do_bit_alloc = -1;
-	if (state->cplinu)
-	    state->cplba.deltbae = bitstream_get (2);
+	if (state->chincpl)	/* cplinu */
+	    state->cplba.deltbae = bitstream_get (state, 2);
 	for (i = 0; i < nfchans; i++)
-	    state->ba[i].deltbae = bitstream_get (2);
-	if (state->cplinu && (state->cplba.deltbae == DELTA_BIT_NEW) &&
-	    parse_deltba (state->cplba.deltba))
+	    state->ba[i].deltbae = bitstream_get (state, 2);
+	if (state->chincpl &&	/* cplinu */
+	    (state->cplba.deltbae == DELTA_BIT_NEW) &&
+	    parse_deltba (state, state->cplba.deltba))
 	    return 1;
 	for (i = 0; i < nfchans; i++)
 	    if ((state->ba[i].deltbae == DELTA_BIT_NEW) &&
-		parse_deltba (state->ba[i].deltba))
+		parse_deltba (state, state->ba[i].deltba))
 		return 1;
     }
 
     if (do_bit_alloc) {
 	if (zero_snr_offsets (nfchans, state)) {
-	    memset (state->cpl_bap, 0, sizeof (state->cpl_bap));
-	    memset (state->fbw_bap, 0, sizeof (state->fbw_bap));
-	    memset (state->lfe_bap, 0, sizeof (state->lfe_bap));
+	    memset (state->cpl_expbap.bap, 0, sizeof (state->cpl_expbap.bap));
+	    for (i = 0; i < nfchans; i++)
+		memset (state->fbw_expbap[i].bap, 0,
+			sizeof (state->fbw_expbap[i].bap));
+	    memset (state->lfe_expbap.bap, 0, sizeof (state->lfe_expbap.bap));
 	} else {
-	    if (state->cplinu && (do_bit_alloc & 64))
-		bit_allocate (state, &state->cplba, state->cplstrtbnd,
+	    if (state->chincpl && (do_bit_alloc & 64))	/* cplinu */
+		a52_bit_allocate (state, &state->cplba, state->cplstrtbnd,
 			      state->cplstrtmant, state->cplendmant,
-			      state->cplfleak, state->cplsleak,
-			      state->cpl_exp, state->cpl_bap);
+				  state->cplfleak << 8, state->cplsleak << 8,
+				  &state->cpl_expbap);
 	    for (i = 0; i < nfchans; i++)
 		if (do_bit_alloc & (1 << i))
-		    bit_allocate (state, state->ba + i, 0, 0,
-				  state->endmant[i], 0, 0, state->fbw_exp[i],
-				  state->fbw_bap[i]);
+		    a52_bit_allocate (state, state->ba + i, 0, 0,
+				      state->endmant[i], 0, 0,
+				      state->fbw_expbap +i);
 	    if (state->lfeon && (do_bit_alloc & 32)) {
 		state->lfeba.deltbae = DELTA_BIT_NONE;
-		bit_allocate (state, &state->lfeba, 0, 0, 7, 0, 0,
-			      state->lfe_exp, state->lfe_bap);
+		a52_bit_allocate (state, &state->lfeba, 0, 0, 7, 0, 0,
+				  &state->lfe_expbap);
 	    }
 	}
     }
 
-    if (bitstream_get (1)) {	/* skiple */
-	i = bitstream_get (9);	/* skipl */
+    if (bitstream_get (state, 1)) {	/* skiple */
+	i = bitstream_get (state, 9);	/* skipl */
 	while (i--)
-	    bitstream_skip (8);
+	    bitstream_skip (state, 8);
     }
 
+    samples = state->samples;
     if (state->output & A52_LFE)
 	samples += 256;	/* shift for LFE channel */
 
-    chanbias = downmix_coeff (coeff, state->acmod, state->output,
+    chanbias = a52_downmix_coeff (coeff, state->acmod, state->output,
 			      state->dynrng, state->clev, state->slev);
 
     quantizer.q1_ptr = quantizer.q2_ptr = quantizer.q4_ptr = -1;
@@ -764,10 +790,10 @@
     for (i = 0; i < nfchans; i++) {
 	int j;
 
-	coeff_get (samples + 256 * i, state->fbw_exp[i], state->fbw_bap[i],
-		   &quantizer, coeff[i], dithflag[i], state->endmant[i]);
+	coeff_get (state, samples + 256 * i, state->fbw_expbap +i, &quantizer,
+		   coeff[i], dithflag[i], state->endmant[i]);
 
-	if (state->cplinu && state->chincpl[i]) {
+	if ((state->chincpl >> i) & 1) {
 	    if (!done_cpl) {
 		done_cpl = 1;
 		coeff_get_coupling (state, nfchans, coeff,
@@ -783,18 +809,21 @@
     }
 
     if (state->acmod == 2) {
-	int j, end, band;
+	int j, end, band, rematflg;
 
 	end = ((state->endmant[0] < state->endmant[1]) ?
 	       state->endmant[0] : state->endmant[1]);
 
 	i = 0;
 	j = 13;
+	rematflg = state->rematflg;
 	do {
-	    if (!state->rematflg[i]) {
+	    if (! (rematflg & 1)) {
+		rematflg >>= 1;
 		j = rematrix_band[i++];
 		continue;
 	    }
+	    rematflg >>= 1;
 	    band = rematrix_band[i++];
 	    if (band > end)
 		band = end;
@@ -811,15 +840,15 @@
 
     if (state->lfeon) {
 	if (state->output & A52_LFE) {
-	    coeff_get (samples - 256, state->lfe_exp, state->lfe_bap,
-		       &quantizer, state->dynrng, 0, 7);
+	    coeff_get (state, samples - 256, &state->lfe_expbap, &quantizer,
+		       state->dynrng, 0, 7);
 	    for (i = 7; i < 256; i++)
 		(samples-256)[i] = 0;
-	    imdct_512 (samples - 256, samples + 1536 - 256, state->bias);
+	    a52_imdct_512 (samples - 256, samples + 1536 - 256, state->bias);
 	} else {
 	    /* just skip the LFE coefficients */
-	    coeff_get (samples + 1280, state->lfe_exp, state->lfe_bap,
-		       &quantizer, 0, 0, 7);
+	    coeff_get (state, samples + 1280, &state->lfe_expbap, &quantizer,
+		       0, 0, 7);
 	}
     }
 
@@ -830,9 +859,9 @@
 		break;
 
     if (i < nfchans) {
-	if (samples[2 * 1536 - 1] == (sample_t)0x776b6e21) {
-	    samples[2 * 1536 - 1] = 0;
-	    upmix (samples + 1536, state->acmod, state->output);
+	if (state->downmixed) {
+	    state->downmixed = 0;
+	    a52_upmix (samples + 1536, state->acmod, state->output);
 	}
 
 	for (i = 0; i < nfchans; i++) {
@@ -844,10 +873,10 @@
 
 	    if (coeff[i]) {
 		if (blksw[i])
-		    imdct_256 (samples + 256 * i, samples + 1536 + 256 * i,
+		    a52_imdct_256 (samples + 256 * i, samples + 1536 + 256 * i,
 			       bias);
 		else 
-		    imdct_512 (samples + 256 * i, samples + 1536 + 256 * i,
+		    a52_imdct_512 (samples + 256 * i, samples + 1536 + 256 * i,
 			       bias);
 	    } else {
 		int j;
@@ -857,29 +886,35 @@
 	    }
 	}
 
-	downmix (samples, state->acmod, state->output, state->bias,
+	a52_downmix (samples, state->acmod, state->output, state->bias,
 		 state->clev, state->slev);
     } else {
 	nfchans = nfchans_tbl[state->output & A52_CHANNEL_MASK];
 
-	downmix (samples, state->acmod, state->output, 0,
+	a52_downmix (samples, state->acmod, state->output, 0,
 		 state->clev, state->slev);
 
-	if (samples[2 * 1536 - 1] != (sample_t)0x776b6e21) {
-	    downmix (samples + 1536, state->acmod, state->output, 0,
+	if (!state->downmixed) {
+	    state->downmixed = 1;
+	    a52_downmix (samples + 1536, state->acmod, state->output, 0,
 		     state->clev, state->slev);
-	    samples[2 * 1536 - 1] = (sample_t)0x776b6e21;
 	}
 
 	if (blksw[0])
 	    for (i = 0; i < nfchans; i++)
-		imdct_256 (samples + 256 * i, samples + 1536 + 256 * i,
+		a52_imdct_256 (samples + 256 * i, samples + 1536 + 256 * i,
 			   state->bias);
 	else 
 	    for (i = 0; i < nfchans; i++)
-		imdct_512 (samples + 256 * i, samples + 1536 + 256 * i,
+		a52_imdct_512 (samples + 256 * i, samples + 1536 + 256 * i,
 			   state->bias);
     }
 
     return 0;
 }
+
+void a52_free (a52_state_t * state)
+{
+    free (state->samples);
+    free (state);
+}