]> git.sesse.net Git - ffmpeg/blobdiff - libavcodec/ac3dec.c
Replace "signed short" typecast with "int16_t" as suggested by
[ffmpeg] / libavcodec / ac3dec.c
index 61f546fbfb2970efcd9cea10393e366e5b7834ba..6fd1e479bffc55e2db2a68def1805f4f0aef8f51 100644 (file)
 #include <string.h>
 
 #include "avcodec.h"
-#include "ac3.h"
-#include "ac3tab.h"
+#include "ac3_parser.h"
 #include "bitstream.h"
 #include "dsputil.h"
 #include "random.h"
 
-static const int nfchans_tbl[8] = { 2, 1, 2, 3, 3, 4, 4, 5 };
+/**
+ * Table of bin locations for rematrixing bands
+ * reference: Section 7.5.2 Rematrixing : Frequency Band Definitions
+ */
+static const uint8_t rematrix_band_tab[5] = { 13, 25, 37, 61, 253 };
 
-/* table for exponent to scale_factor mapping
- * scale_factor[i] = 2 ^ -(i + 15)
+/**
+ * table for exponent to scale_factor mapping
+ * scale_factors[i] = 2 ^ -i
  */
 static float scale_factors[25];
 
 /** table for grouping exponents */
-static uint8_t exp_ungroup_tbl[128][3];
+static uint8_t exp_ungroup_tab[128][3];
 
-static int16_t l3_quantizers_1[32];
-static int16_t l3_quantizers_2[32];
-static int16_t l3_quantizers_3[32];
 
-static int16_t l5_quantizers_1[128];
-static int16_t l5_quantizers_2[128];
-static int16_t l5_quantizers_3[128];
+/** tables for ungrouping mantissas */
+static float b1_mantissas[32][3];
+static float b2_mantissas[128][3];
+static float b3_mantissas[8];
+static float b4_mantissas[128][2];
+static float b5_mantissas[16];
 
-static int16_t l7_quantizers[7];
-
-static int16_t l11_quantizers_1[128];
-static int16_t l11_quantizers_2[128];
+/**
+ * Quantization table: levels for symmetric. bits for asymmetric.
+ * reference: Table 7.18 Mapping of bap to Quantizer
+ */
+static const uint8_t qntztab[16] = {
+    0, 3, 5, 7, 11, 15,
+    5, 6, 7, 8, 9, 10, 11, 12, 14, 16
+};
 
-static int16_t l15_quantizers[15];
+/** dynamic range table. converts codes to scale factors. */
+static float dynrng_tab[256];
 
-static const uint8_t qntztab[16] = { 0, 5, 7, 3, 7, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 16 };
+/** dialogue normalization table */
+static float dialnorm_tab[32];
 
-/* Adjustmens in dB gain */
+/** Adjustments in dB gain */
 #define LEVEL_MINUS_3DB         0.7071067811865476
 #define LEVEL_MINUS_4POINT5DB   0.5946035575013605
 #define LEVEL_MINUS_6DB         0.5000000000000000
-#define LEVEL_PLUS_3DB          1.4142135623730951
-#define LEVEL_PLUS_6DB          2.0000000000000000
+#define LEVEL_MINUS_9DB         0.3535533905932738
 #define LEVEL_ZERO              0.0000000000000000
+#define LEVEL_ONE               1.0000000000000000
+
+static const float gain_levels[6] = {
+    LEVEL_ZERO,
+    LEVEL_ONE,
+    LEVEL_MINUS_3DB,
+    LEVEL_MINUS_4POINT5DB,
+    LEVEL_MINUS_6DB,
+    LEVEL_MINUS_9DB
+};
+
+/**
+ * Table for center mix levels
+ * reference: Section 5.4.2.4 cmixlev
+ */
+static const uint8_t clevs[4] = { 2, 3, 4, 3 };
 
-static const float clevs[4] = { LEVEL_MINUS_3DB, LEVEL_MINUS_4POINT5DB,
-    LEVEL_MINUS_6DB, LEVEL_MINUS_4POINT5DB };
+/**
+ * Table for surround mix levels
+ * reference: Section 5.4.2.5 surmixlev
+ */
+static const uint8_t slevs[4] = { 2, 4, 0, 4 };
 
-static const float slevs[4] = { LEVEL_MINUS_3DB, LEVEL_MINUS_6DB, LEVEL_ZERO, LEVEL_MINUS_6DB };
+/**
+ * Table for default stereo downmixing coefficients
+ * reference: Section 7.8.2 Downmixing Into Two Channels
+ */
+static const uint8_t ac3_default_coeffs[8][5][2] = {
+    { { 1, 0 }, { 0, 1 },                               },
+    { { 2, 2 },                                         },
+    { { 1, 0 }, { 0, 1 },                               },
+    { { 1, 0 }, { 3, 3 }, { 0, 1 },                     },
+    { { 1, 0 }, { 0, 1 }, { 4, 4 },                     },
+    { { 1, 0 }, { 3, 3 }, { 0, 1 }, { 5, 5 },           },
+    { { 1, 0 }, { 0, 1 }, { 4, 0 }, { 0, 4 },           },
+    { { 1, 0 }, { 3, 3 }, { 0, 1 }, { 4, 0 }, { 0, 4 }, },
+};
 
-#define BLOCK_SIZE    256
+/* override ac3.h to include coupling channel */
+#undef AC3_MAX_CHANNELS
+#define AC3_MAX_CHANNELS 7
+#define CPL_CH 0
 
-/* Output and input configurations. */
-#define AC3_OUTPUT_UNMODIFIED   0x01
-#define AC3_OUTPUT_MONO         0x02
-#define AC3_OUTPUT_STEREO       0x04
-#define AC3_OUTPUT_DOLBY        0x08
-#define AC3_OUTPUT_LFEON        0x10
+#define AC3_OUTPUT_LFEON  8
 
 typedef struct {
-    uint16_t crc1;
-    uint8_t  fscod;
-
-    uint8_t  acmod;
-    uint8_t  cmixlev;
-    uint8_t  surmixlev;
-    uint8_t  dsurmod;
-
-    uint8_t  blksw;
-    uint8_t  dithflag;
-    uint8_t  cplinu;
-    uint8_t  chincpl;
-    uint8_t  phsflginu;
-    uint8_t  cplbegf;
-    uint8_t  cplendf;
-    uint8_t  cplcoe;
-    uint32_t cplbndstrc;
-    uint8_t  rematstr;
-    uint8_t  rematflg;
-    uint8_t  cplexpstr;
-    uint8_t  lfeexpstr;
-    uint8_t  chexpstr[5];
-    uint8_t  sdcycod;
-    uint8_t  fdcycod;
-    uint8_t  sgaincod;
-    uint8_t  dbpbcod;
-    uint8_t  floorcod;
-    uint8_t  csnroffst;
-    uint8_t  cplfsnroffst;
-    uint8_t  cplfgaincod;
-    uint8_t  fsnroffst[5];
-    uint8_t  fgaincod[5];
-    uint8_t  lfefsnroffst;
-    uint8_t  lfefgaincod;
-    uint8_t  cplfleak;
-    uint8_t  cplsleak;
-    uint8_t  cpldeltbae;
-    uint8_t  deltbae[5];
-    uint8_t  cpldeltnseg;
-    uint8_t  cpldeltoffst[8];
-    uint8_t  cpldeltlen[8];
-    uint8_t  cpldeltba[8];
-    uint8_t  deltnseg[5];
-    uint8_t  deltoffst[5][8];
-    uint8_t  deltlen[5][8];
-    uint8_t  deltba[5][8];
-
-    /* Derived Attributes. */
-    int      sampling_rate;
-    int      bit_rate;
-    int      frame_size;
-
-    int      nfchans;           //number of channels
-    int      lfeon;             //lfe channel in use
-
-    float    dynrng;            //dynamic range gain
-    float    dynrng2;           //dynamic range gain for 1+1 mode
-    float    chcoeffs[6];       //normalized channel coefficients
-    float    cplco[5][18];      //coupling coordinates
-    int      ncplbnd;           //number of coupling bands
-    int      ncplsubnd;         //number of coupling sub bands
-    int      cplstrtmant;       //coupling start mantissa
-    int      cplendmant;        //coupling end mantissa
-    int      endmant[5];        //channel end mantissas
+    int acmod;                              ///< audio coding mode
+    int dsurmod;                            ///< dolby surround mode
+    int blksw[AC3_MAX_CHANNELS];            ///< block switch flags
+    int dithflag[AC3_MAX_CHANNELS];         ///< dither flags
+    int dither_all;                         ///< true if all channels are dithered
+    int cplinu;                             ///< coupling in use
+    int chincpl[AC3_MAX_CHANNELS];          ///< channel in coupling
+    int phsflginu;                          ///< phase flags in use
+    int cplbndstrc[18];                     ///< coupling band structure
+    int rematstr;                           ///< rematrixing strategy
+    int nrematbnd;                          ///< number of rematrixing bands
+    int rematflg[4];                        ///< rematrixing flags
+    int expstr[AC3_MAX_CHANNELS];           ///< exponent strategies
+    int snroffst[AC3_MAX_CHANNELS];         ///< signal-to-noise ratio offsets
+    int fgain[AC3_MAX_CHANNELS];            ///< fast gain values (signal-to-mask ratio)
+    int deltbae[AC3_MAX_CHANNELS];          ///< delta bit allocation exists
+    int deltnseg[AC3_MAX_CHANNELS];         ///< number of delta segments
+    uint8_t deltoffst[AC3_MAX_CHANNELS][8]; ///< delta segment offsets
+    uint8_t deltlen[AC3_MAX_CHANNELS][8];   ///< delta segment lengths
+    uint8_t deltba[AC3_MAX_CHANNELS][8];    ///< delta values for each segment
+
+    int sampling_rate;                      ///< sample frequency, in Hz
+    int bit_rate;                           ///< stream bit rate, in bits-per-second
+    int frame_size;                         ///< current frame size, in bytes
+
+    int nchans;                             ///< number of total channels
+    int nfchans;                            ///< number of full-bandwidth channels
+    int lfeon;                              ///< lfe channel in use
+    int lfe_ch;                             ///< index of LFE channel
+    int output_mode;                        ///< output channel configuration
+    int out_channels;                       ///< number of output channels
+
+    float downmix_coeffs[AC3_MAX_CHANNELS][2];  ///< stereo downmix coefficients
+    float dialnorm[2];                      ///< dialogue normalization
+    float dynrng[2];                        ///< dynamic range
+    float cplco[AC3_MAX_CHANNELS][18];      ///< coupling coordinates
+    int   ncplbnd;                          ///< number of coupling bands
+    int   ncplsubnd;                        ///< number of coupling sub bands
+    int   startmant[AC3_MAX_CHANNELS];      ///< start frequency bin
+    int   endmant[AC3_MAX_CHANNELS];        ///< end frequency bin
     AC3BitAllocParameters bit_alloc_params; ///< bit allocation parameters
 
-    uint8_t  dcplexps[256];     //decoded coupling exponents
-    uint8_t  dexps[5][256];     //decoded fbw channel exponents
-    uint8_t  dlfeexps[256];     //decoded lfe channel exponents
-    uint8_t  cplbap[256];       //coupling bit allocation pointers
-    uint8_t  bap[5][256];       //fbw channel bit allocation pointers
-    uint8_t  lfebap[256];       //lfe channel bit allocation pointers
-
-    int      blkoutput;         //output configuration for block
+    int8_t  dexps[AC3_MAX_CHANNELS][256];   ///< decoded exponents
+    uint8_t bap[AC3_MAX_CHANNELS][256];     ///< bit allocation pointers
+    int16_t psd[AC3_MAX_CHANNELS][256];     ///< scaled exponents
+    int16_t bndpsd[AC3_MAX_CHANNELS][50];   ///< interpolated exponents
+    int16_t mask[AC3_MAX_CHANNELS][50];     ///< masking curve values
 
-    DECLARE_ALIGNED_16(float, transform_coeffs[AC3_MAX_CHANNELS][BLOCK_SIZE]);  //transform coefficients
+    DECLARE_ALIGNED_16(float, transform_coeffs[AC3_MAX_CHANNELS][256]);  ///< transform coefficients
 
     /* For IMDCT. */
-    MDCTContext imdct_512;  //for 512 sample imdct transform
-    MDCTContext imdct_256;  //for 256 sample imdct transform
-    DSPContext  dsp;        //for optimization
-
-    DECLARE_ALIGNED_16(float, output[AC3_MAX_CHANNELS][BLOCK_SIZE]);    //output after imdct transform and windowing
-    DECLARE_ALIGNED_16(float, delay[AC3_MAX_CHANNELS][BLOCK_SIZE]);     //delay - added to the next block
-    DECLARE_ALIGNED_16(float, tmp_imdct[BLOCK_SIZE]);               //temporary storage for imdct transform
-    DECLARE_ALIGNED_16(float, tmp_output[BLOCK_SIZE * 2]);          //temporary storage for output before windowing
-    DECLARE_ALIGNED_16(float, window[BLOCK_SIZE]);                  //window coefficients
+    MDCTContext imdct_512;                  ///< for 512 sample IMDCT
+    MDCTContext imdct_256;                  ///< for 256 sample IMDCT
+    DSPContext  dsp;                        ///< for optimization
+    float       add_bias;                   ///< offset for float_to_int16 conversion
+    float       mul_bias;                   ///< scaling for float_to_int16 conversion
+
+    DECLARE_ALIGNED_16(float, output[AC3_MAX_CHANNELS-1][256]);     ///< output after imdct transform and windowing
+    DECLARE_ALIGNED_16(short, int_output[AC3_MAX_CHANNELS-1][256]); ///< final 16-bit integer output
+    DECLARE_ALIGNED_16(float, delay[AC3_MAX_CHANNELS-1][256]);      ///< delay - added to the next block
+    DECLARE_ALIGNED_16(float, tmp_imdct[256]);                      ///< temporary storage for imdct transform
+    DECLARE_ALIGNED_16(float, tmp_output[512]);                     ///< temporary storage for output before windowing
+    DECLARE_ALIGNED_16(float, window[256]);                         ///< window coefficients
 
     /* Miscellaneous. */
-    GetBitContext gb;
-    AVRandomState dith_state;   //for dither generation
+    GetBitContext gb;                       ///< bitstream reader
+    AVRandomState dith_state;               ///< for dither generation
+    AVCodecContext *avctx;                  ///< parent context
 } AC3DecodeContext;
 
-/*********** BEGIN INIT HELPER FUNCTIONS ***********/
 /**
  * Generate a Kaiser-Bessel Derived Window.
  */
@@ -196,7 +211,7 @@ static void ac3_window_init(float *window)
    for (i = 0; i < 256; i++) {
        tmp = i * (256 - i) * alpha2;
        bessel = 1.0;
-       for (j = 100; j > 0; j--) /* defaul to 100 iterations */
+       for (j = 100; j > 0; j--) /* default to 100 iterations */
            bessel = bessel * tmp / (j * j) + 1;
        sum += bessel;
        local_window[i] = sum;
@@ -207,58 +222,15 @@ static void ac3_window_init(float *window)
        window[i] = sqrt(local_window[i] / sum);
 }
 
-/*
- * Generate quantizer tables.
+/**
+ * Symmetrical Dequantization
+ * reference: Section 7.3.3 Expansion of Mantissas for Symmetrical Quantization
+ *            Tables 7.19 to 7.23
  */
-static void generate_quantizers_table(int16_t quantizers[], int level, int length)
+static inline float
+symmetric_dequant(int code, int levels)
 {
-    int i;
-
-    for (i = 0; i < length; i++)
-        quantizers[i] = ((2 * i - level + 1) << 15) / level;
-}
-
-static void generate_quantizers_table_1(int16_t quantizers[], int level, int length1, int length2, int size)
-{
-    int i, j;
-    int16_t v;
-
-    for (i = 0; i < length1; i++) {
-        v = ((2 * i - level + 1) << 15) / level;
-        for (j = 0; j < length2; j++)
-            quantizers[i * length2 + j] = v;
-    }
-
-    for (i = length1 * length2; i < size; i++)
-        quantizers[i] = 0;
-}
-
-static void generate_quantizers_table_2(int16_t quantizers[], int level, int length1, int length2, int size)
-{
-    int i, j;
-    int16_t v;
-
-    for (i = 0; i < length1; i++) {
-        v = ((2 * (i % level) - level + 1) << 15) / level;
-        for (j = 0; j < length2; j++)
-            quantizers[i * length2 + j] = v;
-    }
-
-    for (i = length1 * length2; i < size; i++)
-        quantizers[i] = 0;
-
-}
-
-static void generate_quantizers_table_3(int16_t quantizers[], int level, int length1, int length2, int size)
-{
-    int i, j;
-
-    for (i = 0; i < length1; i++)
-        for (j = 0; j < length2; j++)
-            quantizers[i * length2 + j] = ((2 * (j % level) - level + 1) << 15) / level;
-
-    for (i = length1 * length2; i < size; i++)
-        quantizers[i] = 0;
+    return (code - (levels >> 1)) * (2.0f / levels);
 }
 
 /*
@@ -268,45 +240,72 @@ static void ac3_tables_init(void)
 {
     int i;
 
-    /* Quantizer ungrouping tables. */
-    // for level-3 quantizers
-    generate_quantizers_table_1(l3_quantizers_1, 3, 3, 9, 32);
-    generate_quantizers_table_2(l3_quantizers_2, 3, 9, 3, 32);
-    generate_quantizers_table_3(l3_quantizers_3, 3, 9, 3, 32);
-
-    //for level-5 quantizers
-    generate_quantizers_table_1(l5_quantizers_1, 5, 5, 25, 128);
-    generate_quantizers_table_2(l5_quantizers_2, 5, 25, 5, 128);
-    generate_quantizers_table_3(l5_quantizers_3, 5, 25, 5, 128);
-
-    //for level-7 quantizers
-    generate_quantizers_table(l7_quantizers, 7, 7);
+    /* generate grouped mantissa tables
+       reference: Section 7.3.5 Ungrouping of Mantissas */
+    for(i=0; i<32; i++) {
+        /* bap=1 mantissas */
+        b1_mantissas[i][0] = symmetric_dequant( i / 9     , 3);
+        b1_mantissas[i][1] = symmetric_dequant((i % 9) / 3, 3);
+        b1_mantissas[i][2] = symmetric_dequant((i % 9) % 3, 3);
+    }
+    for(i=0; i<128; i++) {
+        /* bap=2 mantissas */
+        b2_mantissas[i][0] = symmetric_dequant( i / 25     , 5);
+        b2_mantissas[i][1] = symmetric_dequant((i % 25) / 5, 5);
+        b2_mantissas[i][2] = symmetric_dequant((i % 25) % 5, 5);
+
+        /* bap=4 mantissas */
+        b4_mantissas[i][0] = symmetric_dequant(i / 11, 11);
+        b4_mantissas[i][1] = symmetric_dequant(i % 11, 11);
+    }
+    /* generate ungrouped mantissa tables
+       reference: Tables 7.21 and 7.23 */
+    for(i=0; i<7; i++) {
+        /* bap=3 mantissas */
+        b3_mantissas[i] = symmetric_dequant(i, 7);
+    }
+    for(i=0; i<15; i++) {
+        /* bap=5 mantissas */
+        b5_mantissas[i] = symmetric_dequant(i, 15);
+    }
 
-    //for level-4 quantizers
-    generate_quantizers_table_2(l11_quantizers_1, 11, 11, 11, 128);
-    generate_quantizers_table_3(l11_quantizers_2, 11, 11, 11, 128);
+    /* generate dynamic range table
+       reference: Section 7.7.1 Dynamic Range Control */
+    for(i=0; i<256; i++) {
+        int v = (i >> 5) - ((i >> 7) << 3) - 5;
+        dynrng_tab[i] = powf(2.0f, v) * ((i & 0x1F) | 0x20);
+    }
 
-    //for level-15 quantizers
-    generate_quantizers_table(l15_quantizers, 15, 15);
-    /* End Quantizer ungrouping tables. */
+    /* generate dialogue normalization table
+       references: Section 5.4.2.8 dialnorm
+                   Section 7.6 Dialogue Normalization */
+    for(i=1; i<32; i++) {
+        dialnorm_tab[i] = expf((i-31) * M_LN10 / 20.0f);
+    }
+    dialnorm_tab[0] = dialnorm_tab[31];
 
-    //generate scale factors
+    /* generate scale factors for exponents and asymmetrical dequantization
+       reference: Section 7.3.2 Expansion of Mantissas for Asymmetric Quantization */
     for (i = 0; i < 25; i++)
-        scale_factors[i] = pow(2.0, -(i + 15));
+        scale_factors[i] = pow(2.0, -i);
 
     /* generate exponent tables
        reference: Section 7.1.3 Exponent Decoding */
     for(i=0; i<128; i++) {
-        exp_ungroup_tbl[i][0] =  i / 25;
-        exp_ungroup_tbl[i][1] = (i % 25) / 5;
-        exp_ungroup_tbl[i][2] = (i % 25) % 5;
+        exp_ungroup_tab[i][0] =  i / 25;
+        exp_ungroup_tab[i][1] = (i % 25) / 5;
+        exp_ungroup_tab[i][2] = (i % 25) % 5;
     }
 }
 
 
+/**
+ * AVCodec initialization
+ */
 static int ac3_decode_init(AVCodecContext *avctx)
 {
     AC3DecodeContext *ctx = avctx->priv_data;
+    ctx->avctx = avctx;
 
     ac3_common_init();
     ac3_tables_init();
@@ -316,94 +315,74 @@ static int ac3_decode_init(AVCodecContext *avctx)
     dsputil_init(&ctx->dsp, avctx);
     av_init_random(0, &ctx->dith_state);
 
-    return 0;
-}
-/*********** END INIT FUNCTIONS ***********/
-
-/* Parse the 'sync_info' from the ac3 bitstream.
- * This function extracts the sync_info from ac3 bitstream.
- * GetBitContext within AC3DecodeContext must point to
- * start of the synchronized ac3 bitstream.
- *
- * @param ctx  AC3DecodeContext
- * @return Returns framesize, returns 0 if fscod, frmsizecod or bsid is not valid
- */
-static int ac3_parse_sync_info(AC3DecodeContext *ctx)
-{
-    GetBitContext *gb = &ctx->gb;
-    int frmsizecod, bsid;
-
-    skip_bits(gb, 16); //skip the sync_word, sync_info->sync_word = get_bits(gb, 16);
-    ctx->crc1 = get_bits(gb, 16);
-    ctx->fscod = get_bits(gb, 2);
-    if (ctx->fscod == 0x03)
-        return 0;
-    frmsizecod = get_bits(gb, 6);
-    if (frmsizecod >= 38)
-        return 0;
-    ctx->sampling_rate = ff_ac3_freqs[ctx->fscod];
-    ctx->bit_rate = ff_ac3_bitratetab[frmsizecod >> 1];
-
-    /* we include it here in order to determine validity of ac3 frame */
-    bsid = get_bits(gb, 5);
-    if (bsid > 0x08)
-        return 0;
-    skip_bits(gb, 3); //skip the bsmod, bsi->bsmod = get_bits(gb, 3);
-
-    switch (ctx->fscod) {
-        case 0x00:
-            ctx->frame_size = 4 * ctx->bit_rate;
-            return ctx->frame_size;
-        case 0x01:
-            ctx->frame_size = 2 * (320 * ctx->bit_rate / 147 + (frmsizecod & 1));
-            return ctx->frame_size;
-        case 0x02:
-            ctx->frame_size =  6 * ctx->bit_rate;
-            return ctx->frame_size;
+    /* set bias values for float to int16 conversion */
+    if(ctx->dsp.float_to_int16 == ff_float_to_int16_c) {
+        ctx->add_bias = 385.0f;
+        ctx->mul_bias = 1.0f;
+    } else {
+        ctx->add_bias = 0.0f;
+        ctx->mul_bias = 32767.0f;
     }
 
-    /* never reached */
     return 0;
 }
 
-/* Parse bsi from ac3 bitstream.
- * This function extracts the bitstream information (bsi) from ac3 bitstream.
- *
- * @param ctx AC3DecodeContext after processed by ac3_parse_sync_info
+/**
+ * Parse the 'sync info' and 'bit stream info' from the AC-3 bitstream.
+ * GetBitContext within AC3DecodeContext must point to
+ * start of the synchronized ac3 bitstream.
  */
-static void ac3_parse_bsi(AC3DecodeContext *ctx)
+static int ac3_parse_header(AC3DecodeContext *ctx)
 {
+    AC3HeaderInfo hdr;
     GetBitContext *gb = &ctx->gb;
-    int i;
-
-    ctx->cmixlev = 0;
-    ctx->surmixlev = 0;
-    ctx->dsurmod = 0;
-    ctx->nfchans = 0;
-    ctx->cpldeltbae = DBA_NONE;
-    ctx->cpldeltnseg = 0;
-    for (i = 0; i < 5; i++) {
-        ctx->deltbae[i] = DBA_NONE;
-        ctx->deltnseg[i] = 0;
+    float cmixlev, surmixlev;
+    int err, i;
+
+    err = ff_ac3_parse_header(gb->buffer, &hdr);
+    if(err)
+        return err;
+
+    /* get decoding parameters from header info */
+    ctx->bit_alloc_params.fscod       = hdr.fscod;
+    ctx->acmod                        = hdr.acmod;
+    cmixlev                           = gain_levels[clevs[hdr.cmixlev]];
+    surmixlev                         = gain_levels[slevs[hdr.surmixlev]];
+    ctx->dsurmod                      = hdr.dsurmod;
+    ctx->lfeon                        = hdr.lfeon;
+    ctx->bit_alloc_params.halfratecod = hdr.halfratecod;
+    ctx->sampling_rate                = hdr.sample_rate;
+    ctx->bit_rate                     = hdr.bit_rate;
+    ctx->nchans                       = hdr.channels;
+    ctx->nfchans                      = ctx->nchans - ctx->lfeon;
+    ctx->lfe_ch                       = ctx->nfchans + 1;
+    ctx->frame_size                   = hdr.frame_size;
+
+    /* set default output to all source channels */
+    ctx->out_channels = ctx->nchans;
+    ctx->output_mode = ctx->acmod;
+    if(ctx->lfeon)
+        ctx->output_mode |= AC3_OUTPUT_LFEON;
+
+    /* skip over portion of header which has already been read */
+    skip_bits(gb, 16); // skip the sync_word
+    skip_bits(gb, 16); // skip crc1
+    skip_bits(gb, 8);  // skip fscod and frmsizecod
+    skip_bits(gb, 11); // skip bsid, bsmod, and acmod
+    if(ctx->acmod == AC3_ACMOD_STEREO) {
+        skip_bits(gb, 2); // skip dsurmod
+    } else {
+        if((ctx->acmod & 1) && ctx->acmod != AC3_ACMOD_MONO)
+            skip_bits(gb, 2); // skip cmixlev
+        if(ctx->acmod & 4)
+            skip_bits(gb, 2); // skip surmixlev
     }
-    ctx->dynrng = 1.0;
-    ctx->dynrng2 = 1.0;
-
-    ctx->acmod = get_bits(gb, 3);
-    ctx->nfchans = nfchans_tbl[ctx->acmod];
-
-    if (ctx->acmod & 0x01 && ctx->acmod != 0x01)
-        ctx->cmixlev = get_bits(gb, 2);
-    if (ctx->acmod & 0x04)
-        ctx->surmixlev = get_bits(gb, 2);
-    if (ctx->acmod == 0x02)
-        ctx->dsurmod = get_bits(gb, 2);
-
-    ctx->lfeon = get_bits1(gb);
+    skip_bits1(gb); // skip lfeon
 
+    /* read the rest of the bsi. read twice for dual mono mode. */
     i = !(ctx->acmod);
     do {
-        skip_bits(gb, 5); //skip dialog normalization
+        ctx->dialnorm[i] = dialnorm_tab[get_bits(gb, 5)]; // dialogue normalization
         if (get_bits1(gb))
             skip_bits(gb, 8); //skip compression
         if (get_bits1(gb))
@@ -414,32 +393,48 @@ static void ac3_parse_bsi(AC3DecodeContext *ctx)
 
     skip_bits(gb, 2); //skip copyright bit and original bitstream bit
 
+    /* skip the timecodes (or extra bitstream information for Alternate Syntax)
+       TODO: read & use the xbsi1 downmix levels */
     if (get_bits1(gb))
-        skip_bits(gb, 14); //skip timecode1
+        skip_bits(gb, 14); //skip timecode1 / xbsi1
     if (get_bits1(gb))
-        skip_bits(gb, 14); //skip timecode2
+        skip_bits(gb, 14); //skip timecode2 / xbsi2
 
+    /* skip additional bitstream info */
     if (get_bits1(gb)) {
-        i = get_bits(gb, 6); //additional bsi length
+        i = get_bits(gb, 6);
         do {
             skip_bits(gb, 8);
         } while(i--);
     }
+
+    /* set stereo downmixing coefficients
+       reference: Section 7.8.2 Downmixing Into Two Channels */
+    for(i=0; i<ctx->nfchans; i++) {
+        ctx->downmix_coeffs[i][0] = gain_levels[ac3_default_coeffs[ctx->acmod][i][0]];
+        ctx->downmix_coeffs[i][1] = gain_levels[ac3_default_coeffs[ctx->acmod][i][1]];
+    }
+    if(ctx->acmod > 1 && ctx->acmod & 1) {
+        ctx->downmix_coeffs[1][0] = ctx->downmix_coeffs[1][1] = cmixlev;
+    }
+    if(ctx->acmod == AC3_ACMOD_2F1R || ctx->acmod == AC3_ACMOD_3F1R) {
+        int nf = ctx->acmod - 2;
+        ctx->downmix_coeffs[nf][0] = ctx->downmix_coeffs[nf][1] = surmixlev * LEVEL_MINUS_3DB;
+    }
+    if(ctx->acmod == AC3_ACMOD_2F2R || ctx->acmod == AC3_ACMOD_3F2R) {
+        int nf = ctx->acmod - 4;
+        ctx->downmix_coeffs[nf][0] = ctx->downmix_coeffs[nf+1][1] = surmixlev;
+    }
+
+    return 0;
 }
 
 /**
- * Decodes the grouped exponents.
- * This function decodes the coded exponents according to exponent strategy
- * and stores them in the decoded exponents buffer.
- *
- * @param[in]  gb      GetBitContext which points to start of coded exponents
- * @param[in]  expstr  Exponent coding strategy
- * @param[in]  ngrps   Number of grouped exponents
- * @param[in]  absexp  Absolute exponent or DC exponent
- * @param[out] dexps   Decoded exponents are stored in dexps
+ * Decode the grouped exponents according to exponent strategy.
+ * reference: Section 7.1.3 Exponent Decoding
  */
 static void decode_exponents(GetBitContext *gb, int expstr, int ngrps,
-                             uint8_t absexp, uint8_t *dexps)
+                             uint8_t absexp, int8_t *dexps)
 {
     int i, j, grp, grpsize;
     int dexp[256];
@@ -449,9 +444,9 @@ static void decode_exponents(GetBitContext *gb, int expstr, int ngrps,
     grpsize = expstr + (expstr == EXP_D45);
     for(grp=0,i=0; grp<ngrps; grp++) {
         expacc = get_bits(gb, 7);
-        dexp[i++] = exp_ungroup_tbl[expacc][0];
-        dexp[i++] = exp_ungroup_tbl[expacc][1];
-        dexp[i++] = exp_ungroup_tbl[expacc][2];
+        dexp[i++] = exp_ungroup_tab[expacc][0];
+        dexp[i++] = exp_ungroup_tab[expacc][1];
+        dexp[i++] = exp_ungroup_tab[expacc][2];
     }
 
     /* convert to absolute exps and expand groups */
@@ -464,818 +459,226 @@ static void decode_exponents(GetBitContext *gb, int expstr, int ngrps,
     }
 }
 
-/* Performs bit allocation.
- * This function performs bit allocation for the requested chanenl.
+/**
+ * Generate transform coefficients for each coupled channel in the coupling
+ * range using the coupling coefficients and coupling coordinates.
+ * reference: Section 7.4.3 Coupling Coordinate Format
  */
-static void do_bit_allocation(AC3DecodeContext *ctx, int chnl)
+static void uncouple_channels(AC3DecodeContext *ctx)
 {
-    int fgain, snroffset;
-
-    if (chnl == 5) {
-        fgain = ff_fgaintab[ctx->cplfgaincod];
-        snroffset = (((ctx->csnroffst - 15) << 4) + ctx->cplfsnroffst) << 2;
-        ac3_parametric_bit_allocation(&ctx->bit_alloc_params, ctx->cplbap,
-                                      ctx->dcplexps, ctx->cplstrtmant,
-                                      ctx->cplendmant, snroffset, fgain, 0,
-                                      ctx->cpldeltbae, ctx->cpldeltnseg,
-                                      ctx->cpldeltoffst, ctx->cpldeltlen,
-                                      ctx->cpldeltba);
-    }
-    else if (chnl == 6) {
-        fgain = ff_fgaintab[ctx->lfefgaincod];
-        snroffset = (((ctx->csnroffst - 15) << 4) + ctx->lfefsnroffst) << 2;
-        ac3_parametric_bit_allocation(&ctx->bit_alloc_params, ctx->lfebap,
-                                      ctx->dlfeexps, 0, 7, snroffset, fgain, 1,
-                                      DBA_NONE, 0, NULL, NULL, NULL);
-    }
-    else {
-        fgain = ff_fgaintab[ctx->fgaincod[chnl]];
-        snroffset = (((ctx->csnroffst - 15) << 4) + ctx->fsnroffst[chnl]) << 2;
-        ac3_parametric_bit_allocation(&ctx->bit_alloc_params, ctx->bap[chnl],
-                                      ctx->dexps[chnl], 0, ctx->endmant[chnl],
-                                      snroffset, fgain, 0, ctx->deltbae[chnl],
-                                      ctx->deltnseg[chnl], ctx->deltoffst[chnl],
-                                      ctx->deltlen[chnl], ctx->deltba[chnl]);
+    int i, j, ch, bnd, subbnd;
+
+    subbnd = -1;
+    i = ctx->startmant[CPL_CH];
+    for(bnd=0; bnd<ctx->ncplbnd; bnd++) {
+        do {
+            subbnd++;
+            for(j=0; j<12; j++) {
+                for(ch=1; ch<=ctx->nfchans; ch++) {
+                    if(ctx->chincpl[ch])
+                        ctx->transform_coeffs[ch][i] = ctx->transform_coeffs[CPL_CH][i] * ctx->cplco[ch][bnd] * 8.0f;
+                }
+                i++;
+            }
+        } while(ctx->cplbndstrc[subbnd]);
     }
 }
 
-typedef struct { /* grouped mantissas for 3-level 5-leve and 11-level quantization */
-    int16_t l3_quantizers[3];
-    int16_t l5_quantizers[3];
-    int16_t l11_quantizers[2];
-    int l3ptr;
-    int l5ptr;
-    int l11ptr;
+/**
+ * Grouped mantissas for 3-level 5-level and 11-level quantization
+ */
+typedef struct {
+    float b1_mant[3];
+    float b2_mant[3];
+    float b4_mant[2];
+    int b1ptr;
+    int b2ptr;
+    int b4ptr;
 } mant_groups;
 
-/* Get the transform coefficients for coupling channel and uncouple channels.
- * The coupling transform coefficients starts at the the cplstrtmant, which is
- * equal to endmant[ch] for fbw channels. Hence we can uncouple channels before
- * getting transform coefficients for the channel.
+/**
+ * Get the transform coefficients for a particular channel
+ * reference: Section 7.3 Quantization and Decoding of Mantissas
  */
-static int get_transform_coeffs_cpling(AC3DecodeContext *ctx, mant_groups *m)
-{
-    GetBitContext *gb = &ctx->gb;
-    int ch, start, end, cplbndstrc, bnd, gcode, tbap;
-    float cplcos[5], cplcoeff;
-    uint8_t *exps = ctx->dcplexps;
-    uint8_t *bap = ctx->cplbap;
-
-    cplbndstrc = ctx->cplbndstrc;
-    start = ctx->cplstrtmant;
-    bnd = 0;
-
-    while (start < ctx->cplendmant) {
-        end = start + 12;
-        while (cplbndstrc & 1) {
-            end += 12;
-            cplbndstrc >>= 1;
-        }
-        cplbndstrc >>= 1;
-        for (ch = 0; ch < ctx->nfchans; ch++)
-            cplcos[ch] = ctx->chcoeffs[ch] * ctx->cplco[ch][bnd];
-        bnd++;
-
-        while (start < end) {
-            tbap = bap[start];
-            switch(tbap) {
-                case 0:
-                    for (ch = 0; ch < ctx->nfchans; ch++)
-                        if (((ctx->chincpl) >> ch) & 1) {
-                            if ((ctx->dithflag >> ch) & 1) {
-                                cplcoeff = (av_random(&ctx->dith_state) & 0xFFFF) * scale_factors[exps[start]];
-                                ctx->transform_coeffs[ch + 1][start] = cplcoeff * cplcos[ch] * LEVEL_MINUS_3DB;
-                            } else
-                                ctx->transform_coeffs[ch + 1][start] = 0;
-                        }
-                    start++;
-                    continue;
-                case 1:
-                    if (m->l3ptr > 2) {
-                        gcode = get_bits(gb, 5);
-                        m->l3_quantizers[0] = l3_quantizers_1[gcode];
-                        m->l3_quantizers[1] = l3_quantizers_2[gcode];
-                        m->l3_quantizers[2] = l3_quantizers_3[gcode];
-                        m->l3ptr = 0;
-                    }
-                    cplcoeff = m->l3_quantizers[m->l3ptr++] * scale_factors[exps[start]];
-                    break;
-
-                case 2:
-                    if (m->l5ptr > 2) {
-                        gcode = get_bits(gb, 7);
-                        m->l5_quantizers[0] = l5_quantizers_1[gcode];
-                        m->l5_quantizers[1] = l5_quantizers_2[gcode];
-                        m->l5_quantizers[2] = l5_quantizers_3[gcode];
-                        m->l5ptr = 0;
-                    }
-                    cplcoeff = m->l5_quantizers[m->l5ptr++] * scale_factors[exps[start]];
-                    break;
-
-                case 3:
-                    cplcoeff = l7_quantizers[get_bits(gb, 3)] * scale_factors[exps[start]];
-                    break;
-
-                case 4:
-                    if (m->l11ptr > 1) {
-                        gcode = get_bits(gb, 7);
-                        m->l11_quantizers[0] = l11_quantizers_1[gcode];
-                        m->l11_quantizers[1] = l11_quantizers_2[gcode];
-                        m->l11ptr = 0;
-                    }
-                    cplcoeff = m->l11_quantizers[m->l11ptr++] * scale_factors[exps[start]];
-                    break;
-
-                case 5:
-                    cplcoeff = l15_quantizers[get_bits(gb, 4)] * scale_factors[exps[start]];
-                    break;
-
-                default:
-                    cplcoeff = (get_sbits(gb, qntztab[tbap]) << (16 - qntztab[tbap])) * scale_factors[exps[start]];
-            }
-            for (ch = 0; ch < ctx->nfchans; ch++)
-                if ((ctx->chincpl >> ch) & 1)
-                    ctx->transform_coeffs[ch + 1][start] = cplcoeff * cplcos[ch];
-            start++;
-        }
-    }
-
-    return 0;
-}
-
-/* Get the transform coefficients for particular channel */
 static int get_transform_coeffs_ch(AC3DecodeContext *ctx, int ch_index, mant_groups *m)
 {
     GetBitContext *gb = &ctx->gb;
-    int i, gcode, tbap, dithflag, end;
+    int i, gcode, tbap, start, end;
     uint8_t *exps;
     uint8_t *bap;
     float *coeffs;
-    float factors[25];
-
-    for (i = 0; i < 25; i++)
-        factors[i] = scale_factors[i] * ctx->chcoeffs[ch_index];
-
-    if (ch_index != -1) { /* fbw channels */
-        dithflag = (ctx->dithflag >> ch_index) & 1;
-        exps = ctx->dexps[ch_index];
-        bap = ctx->bap[ch_index];
-        coeffs = ctx->transform_coeffs[ch_index + 1];
-        end = ctx->endmant[ch_index];
-    } else if (ch_index == -1) {
-        dithflag = 0;
-        exps = ctx->dlfeexps;
-        bap = ctx->lfebap;
-        coeffs = ctx->transform_coeffs[0];
-        end = 7;
-    }
 
+    exps = ctx->dexps[ch_index];
+    bap = ctx->bap[ch_index];
+    coeffs = ctx->transform_coeffs[ch_index];
+    start = ctx->startmant[ch_index];
+    end = ctx->endmant[ch_index];
 
-    for (i = 0; i < end; i++) {
+    for (i = start; i < end; i++) {
         tbap = bap[i];
         switch (tbap) {
             case 0:
-                if (!dithflag) {
-                    coeffs[i] = 0;
-                    continue;
-                }
-                else {
-                    coeffs[i] = (av_random(&ctx->dith_state) & 0xFFFF) * factors[exps[i]];
-                    coeffs[i] *= LEVEL_MINUS_3DB;
-                    continue;
-                }
+                coeffs[i] = ((av_random(&ctx->dith_state) & 0xFFFF) / 65535.0f) - 0.5f;
+                break;
 
             case 1:
-                if (m->l3ptr > 2) {
+                if(m->b1ptr > 2) {
                     gcode = get_bits(gb, 5);
-                    m->l3_quantizers[0] = l3_quantizers_1[gcode];
-                    m->l3_quantizers[1] = l3_quantizers_2[gcode];
-                    m->l3_quantizers[2] = l3_quantizers_3[gcode];
-                    m->l3ptr = 0;
+                    m->b1_mant[0] = b1_mantissas[gcode][0];
+                    m->b1_mant[1] = b1_mantissas[gcode][1];
+                    m->b1_mant[2] = b1_mantissas[gcode][2];
+                    m->b1ptr = 0;
                 }
-                coeffs[i] = m->l3_quantizers[m->l3ptr++] * factors[exps[i]];
-                continue;
+                coeffs[i] = m->b1_mant[m->b1ptr++];
+                break;
 
             case 2:
-                if (m->l5ptr > 2) {
+                if(m->b2ptr > 2) {
                     gcode = get_bits(gb, 7);
-                    m->l5_quantizers[0] = l5_quantizers_1[gcode];
-                    m->l5_quantizers[1] = l5_quantizers_2[gcode];
-                    m->l5_quantizers[2] = l5_quantizers_3[gcode];
-                    m->l5ptr = 0;
+                    m->b2_mant[0] = b2_mantissas[gcode][0];
+                    m->b2_mant[1] = b2_mantissas[gcode][1];
+                    m->b2_mant[2] = b2_mantissas[gcode][2];
+                    m->b2ptr = 0;
                 }
-                coeffs[i] = m->l5_quantizers[m->l5ptr++] * factors[exps[i]];
-                continue;
+                coeffs[i] = m->b2_mant[m->b2ptr++];
+                break;
 
             case 3:
-                coeffs[i] = l7_quantizers[get_bits(gb, 3)] * factors[exps[i]];
-                continue;
+                coeffs[i] = b3_mantissas[get_bits(gb, 3)];
+                break;
 
             case 4:
-                if (m->l11ptr > 1) {
+                if(m->b4ptr > 1) {
                     gcode = get_bits(gb, 7);
-                    m->l11_quantizers[0] = l11_quantizers_1[gcode];
-                    m->l11_quantizers[1] = l11_quantizers_2[gcode];
-                    m->l11ptr = 0;
+                    m->b4_mant[0] = b4_mantissas[gcode][0];
+                    m->b4_mant[1] = b4_mantissas[gcode][1];
+                    m->b4ptr = 0;
                 }
-                coeffs[i] = m->l11_quantizers[m->l11ptr++] * factors[exps[i]];
-                continue;
+                coeffs[i] = m->b4_mant[m->b4ptr++];
+                break;
 
             case 5:
-                coeffs[i] = l15_quantizers[get_bits(gb, 4)] * factors[exps[i]];
-                continue;
+                coeffs[i] = b5_mantissas[get_bits(gb, 4)];
+                break;
 
             default:
-                coeffs[i] = (get_sbits(gb, qntztab[tbap]) << (16 - qntztab[tbap])) * factors[exps[i]];
-                continue;
+                /* asymmetric dequantization */
+                coeffs[i] = get_sbits(gb, qntztab[tbap]) * scale_factors[qntztab[tbap]-1];
+                break;
         }
+        coeffs[i] *= scale_factors[exps[i]];
     }
 
     return 0;
 }
 
-/* Get the transform coefficients.
- * This function extracts the tranform coefficients form the ac3 bitstream.
- * This function is called after bit allocation is performed.
+/**
+ * Remove random dithering from coefficients with zero-bit mantissas
+ * reference: Section 7.3.4 Dither for Zero Bit Mantissas (bap=0)
+ */
+static void remove_dithering(AC3DecodeContext *ctx) {
+    int ch, i;
+    int end=0;
+    float *coeffs;
+    uint8_t *bap;
+
+    for(ch=1; ch<=ctx->nfchans; ch++) {
+        if(!ctx->dithflag[ch]) {
+            coeffs = ctx->transform_coeffs[ch];
+            bap = ctx->bap[ch];
+            if(ctx->chincpl[ch])
+                end = ctx->startmant[CPL_CH];
+            else
+                end = ctx->endmant[ch];
+            for(i=0; i<end; i++) {
+                if(bap[i] == 0)
+                    coeffs[i] = 0.0f;
+            }
+            if(ctx->chincpl[ch]) {
+                bap = ctx->bap[CPL_CH];
+                for(; i<ctx->endmant[CPL_CH]; i++) {
+                    if(bap[i] == 0)
+                        coeffs[i] = 0.0f;
+                }
+            }
+        }
+    }
+}
+
+/**
+ * Get the transform coefficients.
  */
 static int get_transform_coeffs(AC3DecodeContext * ctx)
 {
-    int i, end;
+    int ch, end;
     int got_cplchan = 0;
     mant_groups m;
 
-    m.l3ptr = m.l5ptr = m.l11ptr = 3;
+    m.b1ptr = m.b2ptr = m.b4ptr = 3;
 
-    for (i = 0; i < ctx->nfchans; i++) {
-        /* transform coefficients for individual channel */
-        if (get_transform_coeffs_ch(ctx, i, &m))
+    for (ch = 1; ch <= ctx->nchans; ch++) {
+        /* transform coefficients for full-bandwidth channel */
+        if (get_transform_coeffs_ch(ctx, ch, &m))
             return -1;
-        /* tranform coefficients for coupling channels */
-        if ((ctx->chincpl >> i) & 1)  {
+        /* tranform coefficients for coupling channel come right after the
+           coefficients for the first coupled channel*/
+        if (ctx->chincpl[ch])  {
             if (!got_cplchan) {
-                if (get_transform_coeffs_cpling(ctx, &m)) {
-                    av_log(NULL, AV_LOG_ERROR, "error in decoupling channels\n");
+                if (get_transform_coeffs_ch(ctx, CPL_CH, &m)) {
+                    av_log(ctx->avctx, AV_LOG_ERROR, "error in decoupling channels\n");
                     return -1;
                 }
+                uncouple_channels(ctx);
                 got_cplchan = 1;
             }
-            end = ctx->cplendmant;
-        } else
-            end = ctx->endmant[i];
+            end = ctx->endmant[CPL_CH];
+        } else {
+            end = ctx->endmant[ch];
+        }
         do
-            ctx->transform_coeffs[i + 1][end] = 0;
+            ctx->transform_coeffs[ch][end] = 0;
         while(++end < 256);
     }
-    if (ctx->lfeon) {
-        if (get_transform_coeffs_ch(ctx, -1, &m))
-                return -1;
-        for (i = 7; i < 256; i++) {
-            ctx->transform_coeffs[0][i] = 0;
-        }
-    }
 
-    return 0;
-}
+    /* if any channel doesn't use dithering, zero appropriate coefficients */
+    if(!ctx->dither_all)
+        remove_dithering(ctx);
 
-/* Rematrixing routines. */
-static void do_rematrixing1(AC3DecodeContext *ctx, int start, int end)
-{
-    float tmp0, tmp1;
-
-    while (start < end) {
-        tmp0 = ctx->transform_coeffs[1][start];
-        tmp1 = ctx->transform_coeffs[2][start];
-        ctx->transform_coeffs[1][start] = tmp0 + tmp1;
-        ctx->transform_coeffs[2][start] = tmp0 - tmp1;
-        start++;
-    }
+    return 0;
 }
 
+/**
+ * Stereo rematrixing.
+ * reference: Section 7.5.4 Rematrixing : Decoding Technique
+ */
 static void do_rematrixing(AC3DecodeContext *ctx)
 {
-    int bnd1 = 13, bnd2 = 25, bnd3 = 37, bnd4 = 61;
+    int bnd, i;
     int end, bndend;
+    float tmp0, tmp1;
 
-    end = FFMIN(ctx->endmant[0], ctx->endmant[1]);
-
-    if (ctx->rematflg & 1)
-        do_rematrixing1(ctx, bnd1, bnd2);
-
-    if (ctx->rematflg & 2)
-        do_rematrixing1(ctx, bnd2, bnd3);
-
-    bndend = bnd4;
-    if (bndend > end) {
-        bndend = end;
-        if (ctx->rematflg & 4)
-            do_rematrixing1(ctx, bnd3, bndend);
-    } else {
-        if (ctx->rematflg & 4)
-            do_rematrixing1(ctx, bnd3, bnd4);
-        if (ctx->rematflg & 8)
-            do_rematrixing1(ctx, bnd4, end);
-    }
-}
-
-/* This function sets the normalized channel coefficients.
- * Transform coefficients are multipllied by the channel
- * coefficients to get normalized transform coefficients.
- */
-static void get_downmix_coeffs(AC3DecodeContext *ctx)
-{
-    int from = ctx->acmod;
-    int to = ctx->blkoutput;
-    float clev = clevs[ctx->cmixlev];
-    float slev = slevs[ctx->surmixlev];
-    float nf = 1.0; //normalization factor for downmix coeffs
-    int i;
-
-    if (!ctx->acmod) {
-        ctx->chcoeffs[0] = 2 * ctx->dynrng;
-        ctx->chcoeffs[1] = 2 * ctx->dynrng2;
-    } else {
-        for (i = 0; i < ctx->nfchans; i++)
-            ctx->chcoeffs[i] = 2 * ctx->dynrng;
-    }
-
-    if (to == AC3_OUTPUT_UNMODIFIED)
-        return;
-
-    switch (from) {
-        case AC3_ACMOD_DUALMONO:
-            switch (to) {
-                case AC3_OUTPUT_MONO:
-                case AC3_OUTPUT_STEREO: /* We Assume that sum of both mono channels is requested */
-                    nf = 0.5;
-                    ctx->chcoeffs[0] *= nf;
-                    ctx->chcoeffs[1] *= nf;
-                    break;
-            }
-            break;
-        case AC3_ACMOD_MONO:
-            switch (to) {
-                case AC3_OUTPUT_STEREO:
-                    nf = LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[0] *= nf;
-                    break;
-            }
-            break;
-        case AC3_ACMOD_STEREO:
-            switch (to) {
-                case AC3_OUTPUT_MONO:
-                    nf = LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[0] *= nf;
-                    ctx->chcoeffs[1] *= nf;
-                    break;
-            }
-            break;
-        case AC3_ACMOD_3F:
-            switch (to) {
-                case AC3_OUTPUT_MONO:
-                    nf = LEVEL_MINUS_3DB / (1.0 + clev);
-                    ctx->chcoeffs[0] *= (nf * LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[2] *= (nf * LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[1] *= ((nf * clev * LEVEL_MINUS_3DB) / 2.0);
-                    break;
-                case AC3_OUTPUT_STEREO:
-                    nf = 1.0 / (1.0 + clev);
-                    ctx->chcoeffs[0] *= nf;
-                    ctx->chcoeffs[2] *= nf;
-                    ctx->chcoeffs[1] *= (nf * clev);
-                    break;
-            }
-            break;
-        case AC3_ACMOD_2F1R:
-            switch (to) {
-                case AC3_OUTPUT_MONO:
-                    nf = 2.0 * LEVEL_MINUS_3DB / (2.0 + slev);
-                    ctx->chcoeffs[0] *= (nf * LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[1] *= (nf * LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[2] *= (nf * slev * LEVEL_MINUS_3DB);
-                    break;
-                case AC3_OUTPUT_STEREO:
-                    nf = 1.0 / (1.0 + (slev * LEVEL_MINUS_3DB));
-                    ctx->chcoeffs[0] *= nf;
-                    ctx->chcoeffs[1] *= nf;
-                    ctx->chcoeffs[2] *= (nf * slev * LEVEL_MINUS_3DB);
-                    break;
-                case AC3_OUTPUT_DOLBY:
-                    nf = 1.0 / (1.0 + LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[0] *= nf;
-                    ctx->chcoeffs[1] *= nf;
-                    ctx->chcoeffs[2] *= (nf * LEVEL_MINUS_3DB);
-                    break;
-            }
-            break;
-        case AC3_ACMOD_3F1R:
-            switch (to) {
-                case AC3_OUTPUT_MONO:
-                    nf = LEVEL_MINUS_3DB / (1.0 + clev + (slev / 2.0));
-                    ctx->chcoeffs[0] *= (nf * LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[2] *= (nf * LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[1] *= (nf * clev * LEVEL_PLUS_3DB);
-                    ctx->chcoeffs[3] *= (nf * slev * LEVEL_MINUS_3DB);
-                    break;
-                case AC3_OUTPUT_STEREO:
-                    nf = 1.0 / (1.0 + clev + (slev * LEVEL_MINUS_3DB));
-                    ctx->chcoeffs[0] *= nf;
-                    ctx->chcoeffs[2] *= nf;
-                    ctx->chcoeffs[1] *= (nf * clev);
-                    ctx->chcoeffs[3] *= (nf * slev * LEVEL_MINUS_3DB);
-                    break;
-                case AC3_OUTPUT_DOLBY:
-                    nf = 1.0 / (1.0 + (2.0 * LEVEL_MINUS_3DB));
-                    ctx->chcoeffs[0] *= nf;
-                    ctx->chcoeffs[1] *= nf;
-                    ctx->chcoeffs[1] *= (nf * LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[3] *= (nf * LEVEL_MINUS_3DB);
-                    break;
-            }
-            break;
-        case AC3_ACMOD_2F2R:
-            switch (to) {
-                case AC3_OUTPUT_MONO:
-                    nf = LEVEL_MINUS_3DB / (1.0 + slev);
-                    ctx->chcoeffs[0] *= (nf * LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[1] *= (nf * LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[2] *= (nf * slev * LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[3] *= (nf * slev * LEVEL_MINUS_3DB);
-                    break;
-                case AC3_OUTPUT_STEREO:
-                    nf = 1.0 / (1.0 + slev);
-                    ctx->chcoeffs[0] *= nf;
-                    ctx->chcoeffs[1] *= nf;
-                    ctx->chcoeffs[2] *= (nf * slev);
-                    ctx->chcoeffs[3] *= (nf * slev);
-                    break;
-                case AC3_OUTPUT_DOLBY:
-                    nf = 1.0 / (1.0 + (2.0 * LEVEL_MINUS_3DB));
-                    ctx->chcoeffs[0] *= nf;
-                    ctx->chcoeffs[1] *= nf;
-                    ctx->chcoeffs[2] *= (nf * LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[3] *= (nf * LEVEL_MINUS_3DB);
-                    break;
-            }
-            break;
-        case AC3_ACMOD_3F2R:
-            switch (to) {
-                case AC3_OUTPUT_MONO:
-                    nf = LEVEL_MINUS_3DB / (1.0 + clev + slev);
-                    ctx->chcoeffs[0] *= (nf * LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[2] *= (nf * LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[1] *= (nf * clev * LEVEL_PLUS_3DB);
-                    ctx->chcoeffs[3] *= (nf * slev * LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[4] *= (nf * slev * LEVEL_MINUS_3DB);
-                    break;
-                case AC3_OUTPUT_STEREO:
-                    nf = 1.0 / (1.0 + clev + slev);
-                    ctx->chcoeffs[0] *= nf;
-                    ctx->chcoeffs[2] *= nf;
-                    ctx->chcoeffs[1] *= (nf * clev);
-                    ctx->chcoeffs[3] *= (nf * slev);
-                    ctx->chcoeffs[4] *= (nf * slev);
-                    break;
-                case AC3_OUTPUT_DOLBY:
-                    nf = 1.0 / (1.0 + (3.0 * LEVEL_MINUS_3DB));
-                    ctx->chcoeffs[0] *= nf;
-                    ctx->chcoeffs[1] *= nf;
-                    ctx->chcoeffs[1] *= (nf * LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[3] *= (nf * LEVEL_MINUS_3DB);
-                    ctx->chcoeffs[4] *= (nf * LEVEL_MINUS_3DB);
-                    break;
-            }
-            break;
-    }
-}
-
-/*********** BEGIN DOWNMIX FUNCTIONS ***********/
-static inline void mix_dualmono_to_mono(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++)
-        output[1][i] += output[2][i];
-    memset(output[2], 0, sizeof(output[2]));
-}
-
-static inline void mix_dualmono_to_stereo(AC3DecodeContext *ctx)
-{
-    int i;
-    float tmp;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++) {
-        tmp = output[1][i] + output[2][i];
-        output[1][i] = output[2][i] = tmp;
-    }
-}
-
-static inline void upmix_mono_to_stereo(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++)
-        output[2][i] = output[1][i];
-}
-
-static inline void mix_stereo_to_mono(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++)
-        output[1][i] += output[2][i];
-    memset(output[2], 0, sizeof(output[2]));
-}
-
-static inline void mix_3f_to_mono(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++)
-        output[1][i] += (output[2][i] + output[3][i]);
-    memset(output[2], 0, sizeof(output[2]));
-    memset(output[3], 0, sizeof(output[3]));
-}
-
-static inline void mix_3f_to_stereo(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++) {
-        output[1][i] += output[2][i];
-        output[2][i] += output[3][i];
-    }
-    memset(output[3], 0, sizeof(output[3]));
-}
-
-static inline void mix_2f_1r_to_mono(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++)
-        output[1][i] += (output[2][i] + output[3][i]);
-    memset(output[2], 0, sizeof(output[2]));
-    memset(output[3], 0, sizeof(output[3]));
-
-}
-
-static inline void mix_2f_1r_to_stereo(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++) {
-        output[1][i] += output[2][i];
-        output[2][i] += output[3][i];
-    }
-    memset(output[3], 0, sizeof(output[3]));
-}
-
-static inline void mix_2f_1r_to_dolby(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++) {
-        output[1][i] -= output[3][i];
-        output[2][i] += output[3][i];
-    }
-    memset(output[3], 0, sizeof(output[3]));
-}
-
-static inline void mix_3f_1r_to_mono(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++)
-        output[1][i] = (output[2][i] + output[3][i] + output[4][i]);
-    memset(output[2], 0, sizeof(output[2]));
-    memset(output[3], 0, sizeof(output[3]));
-    memset(output[4], 0, sizeof(output[4]));
-}
-
-static inline void mix_3f_1r_to_stereo(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++) {
-        output[1][i] += (output[2][i] + output[4][i]);
-        output[2][i] += (output[3][i] + output[4][i]);
-    }
-    memset(output[3], 0, sizeof(output[3]));
-    memset(output[4], 0, sizeof(output[4]));
-}
-
-static inline void mix_3f_1r_to_dolby(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++) {
-        output[1][i] += (output[2][i] - output[4][i]);
-        output[2][i] += (output[3][i] + output[4][i]);
-    }
-    memset(output[3], 0, sizeof(output[3]));
-    memset(output[4], 0, sizeof(output[4]));
-}
-
-static inline void mix_2f_2r_to_mono(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++)
-        output[1][i] = (output[2][i] + output[3][i] + output[4][i]);
-    memset(output[2], 0, sizeof(output[2]));
-    memset(output[3], 0, sizeof(output[3]));
-    memset(output[4], 0, sizeof(output[4]));
-}
-
-static inline void mix_2f_2r_to_stereo(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++) {
-        output[1][i] += output[3][i];
-        output[2][i] += output[4][i];
-    }
-    memset(output[3], 0, sizeof(output[3]));
-    memset(output[4], 0, sizeof(output[4]));
-}
-
-static inline void mix_2f_2r_to_dolby(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++) {
-        output[1][i] -= output[3][i];
-        output[2][i] += output[4][i];
-    }
-    memset(output[3], 0, sizeof(output[3]));
-    memset(output[4], 0, sizeof(output[4]));
-}
-
-static inline void mix_3f_2r_to_mono(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++)
-        output[1][i] += (output[2][i] + output[3][i] + output[4][i] + output[5][i]);
-    memset(output[2], 0, sizeof(output[2]));
-    memset(output[3], 0, sizeof(output[3]));
-    memset(output[4], 0, sizeof(output[4]));
-    memset(output[5], 0, sizeof(output[5]));
-}
-
-static inline void mix_3f_2r_to_stereo(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++) {
-        output[1][i] += (output[2][i] + output[4][i]);
-        output[2][i] += (output[3][i] + output[5][i]);
-    }
-    memset(output[3], 0, sizeof(output[3]));
-    memset(output[4], 0, sizeof(output[4]));
-    memset(output[5], 0, sizeof(output[5]));
-}
-
-static inline void mix_3f_2r_to_dolby(AC3DecodeContext *ctx)
-{
-    int i;
-    float (*output)[BLOCK_SIZE] = ctx->output;
-
-    for (i = 0; i < 256; i++) {
-        output[1][i] += (output[2][i] - output[4][i] - output[5][i]);
-        output[2][i] += (output[3][i] + output[4][i] + output[5][i]);
-    }
-    memset(output[3], 0, sizeof(output[3]));
-    memset(output[4], 0, sizeof(output[4]));
-    memset(output[5], 0, sizeof(output[5]));
-}
-/*********** END DOWNMIX FUNCTIONS ***********/
+    end = FFMIN(ctx->endmant[1], ctx->endmant[2]);
 
-/* Downmix the output.
- * This function downmixes the output when the number of input
- * channels is not equal to the number of output channels requested.
- */
-static void do_downmix(AC3DecodeContext *ctx)
-{
-    int from = ctx->acmod;
-    int to = ctx->blkoutput;
-
-    if (to == AC3_OUTPUT_UNMODIFIED)
-        return;
-
-    switch (from) {
-        case AC3_ACMOD_DUALMONO:
-            switch (to) {
-                case AC3_OUTPUT_MONO:
-                    mix_dualmono_to_mono(ctx);
-                    break;
-                case AC3_OUTPUT_STEREO: /* We assume that sum of both mono channels is requested */
-                    mix_dualmono_to_stereo(ctx);
-                    break;
-            }
-            break;
-        case AC3_ACMOD_MONO:
-            switch (to) {
-                case AC3_OUTPUT_STEREO:
-                    upmix_mono_to_stereo(ctx);
-                    break;
-            }
-            break;
-        case AC3_ACMOD_STEREO:
-            switch (to) {
-                case AC3_OUTPUT_MONO:
-                    mix_stereo_to_mono(ctx);
-                    break;
-            }
-            break;
-        case AC3_ACMOD_3F:
-            switch (to) {
-                case AC3_OUTPUT_MONO:
-                    mix_3f_to_mono(ctx);
-                    break;
-                case AC3_OUTPUT_STEREO:
-                    mix_3f_to_stereo(ctx);
-                    break;
-            }
-            break;
-        case AC3_ACMOD_2F1R:
-            switch (to) {
-                case AC3_OUTPUT_MONO:
-                    mix_2f_1r_to_mono(ctx);
-                    break;
-                case AC3_OUTPUT_STEREO:
-                    mix_2f_1r_to_stereo(ctx);
-                    break;
-                case AC3_OUTPUT_DOLBY:
-                    mix_2f_1r_to_dolby(ctx);
-                    break;
-            }
-            break;
-        case AC3_ACMOD_3F1R:
-            switch (to) {
-                case AC3_OUTPUT_MONO:
-                    mix_3f_1r_to_mono(ctx);
-                    break;
-                case AC3_OUTPUT_STEREO:
-                    mix_3f_1r_to_stereo(ctx);
-                    break;
-                case AC3_OUTPUT_DOLBY:
-                    mix_3f_1r_to_dolby(ctx);
-                    break;
+    for(bnd=0; bnd<ctx->nrematbnd; bnd++) {
+        if(ctx->rematflg[bnd]) {
+            bndend = FFMIN(end, rematrix_band_tab[bnd+1]);
+            for(i=rematrix_band_tab[bnd]; i<bndend; i++) {
+                tmp0 = ctx->transform_coeffs[1][i];
+                tmp1 = ctx->transform_coeffs[2][i];
+                ctx->transform_coeffs[1][i] = tmp0 + tmp1;
+                ctx->transform_coeffs[2][i] = tmp0 - tmp1;
             }
-            break;
-        case AC3_ACMOD_2F2R:
-            switch (to) {
-                case AC3_OUTPUT_MONO:
-                    mix_2f_2r_to_mono(ctx);
-                    break;
-                case AC3_OUTPUT_STEREO:
-                    mix_2f_2r_to_stereo(ctx);
-                    break;
-                case AC3_OUTPUT_DOLBY:
-                    mix_2f_2r_to_dolby(ctx);
-                    break;
-            }
-            break;
-        case AC3_ACMOD_3F2R:
-            switch (to) {
-                case AC3_OUTPUT_MONO:
-                    mix_3f_2r_to_mono(ctx);
-                    break;
-                case AC3_OUTPUT_STEREO:
-                    mix_3f_2r_to_stereo(ctx);
-                    break;
-                case AC3_OUTPUT_DOLBY:
-                    mix_3f_2r_to_dolby(ctx);
-                    break;
-            }
-            break;
+        }
     }
 }
 
-/* This function performs the imdct on 256 sample transform
- * coefficients.
+/**
+ * Perform the 256-point IMDCT
  */
 static void do_imdct_256(AC3DecodeContext *ctx, int chindex)
 {
     int i, k;
-    float x[128];
+    DECLARE_ALIGNED_16(float, x[128]);
     FFTComplex z[2][64];
     float *o_ptr = ctx->tmp_output;
 
@@ -1310,390 +713,456 @@ static void do_imdct_256(AC3DecodeContext *ctx, int chindex)
     }
 }
 
-/* IMDCT Transform. */
+/**
+ * Inverse MDCT Transform.
+ * Convert frequency domain coefficients to time-domain audio samples.
+ * reference: Section 7.9.4 Transformation Equations
+ */
 static inline void do_imdct(AC3DecodeContext *ctx)
 {
     int ch;
+    int nchans;
 
-    if (ctx->blkoutput & AC3_OUTPUT_LFEON) {
-        ctx->imdct_512.fft.imdct_calc(&ctx->imdct_512, ctx->tmp_output,
-                                      ctx->transform_coeffs[0], ctx->tmp_imdct);
-    }
-    for (ch=1; ch<=ctx->nfchans; ch++) {
-        if ((ctx->blksw >> (ch-1)) & 1)
+    /* Don't perform the IMDCT on the LFE channel unless it's used in the output */
+    nchans = ctx->nfchans;
+    if(ctx->output_mode & AC3_OUTPUT_LFEON)
+        nchans++;
+
+    for (ch=1; ch<=nchans; ch++) {
+        if (ctx->blksw[ch]) {
             do_imdct_256(ctx, ch);
-        else
+        } else {
             ctx->imdct_512.fft.imdct_calc(&ctx->imdct_512, ctx->tmp_output,
                                           ctx->transform_coeffs[ch],
                                           ctx->tmp_imdct);
-
-        ctx->dsp.vector_fmul_add_add(ctx->output[ch], ctx->tmp_output,
-                                     ctx->window, ctx->delay[ch], 384, 256, 1);
-        ctx->dsp.vector_fmul_reverse(ctx->delay[ch], ctx->tmp_output+256,
+        }
+        /* For the first half of the block, apply the window, add the delay
+           from the previous block, and send to output */
+        ctx->dsp.vector_fmul_add_add(ctx->output[ch-1], ctx->tmp_output,
+                                     ctx->window, ctx->delay[ch-1], 0, 256, 1);
+        /* For the second half of the block, apply the window and store the
+           samples to delay, to be combined with the next block */
+        ctx->dsp.vector_fmul_reverse(ctx->delay[ch-1], ctx->tmp_output+256,
                                      ctx->window, 256);
     }
 }
 
-/* Parse the audio block from ac3 bitstream.
- * This function extract the audio block from the ac3 bitstream
- * and produces the output for the block. This function must
- * be called for each of the six audio block in the ac3 bitstream.
+/**
+ * Downmix the output to mono or stereo.
  */
-static int ac3_parse_audio_block(AC3DecodeContext * ctx)
+static void ac3_downmix(float samples[AC3_MAX_CHANNELS][256], int nfchans,
+                        int output_mode, float coef[AC3_MAX_CHANNELS][2])
+{
+    int i, j;
+    float v0, v1, s0, s1;
+
+    for(i=0; i<256; i++) {
+        v0 = v1 = s0 = s1 = 0.0f;
+        for(j=0; j<nfchans; j++) {
+            v0 += samples[j][i] * coef[j][0];
+            v1 += samples[j][i] * coef[j][1];
+            s0 += coef[j][0];
+            s1 += coef[j][1];
+        }
+        v0 /= s0;
+        v1 /= s1;
+        if(output_mode == AC3_ACMOD_MONO) {
+            samples[0][i] = (v0 + v1) * LEVEL_MINUS_3DB;
+        } else if(output_mode == AC3_ACMOD_STEREO) {
+            samples[0][i] = v0;
+            samples[1][i] = v1;
+        }
+    }
+}
+
+/**
+ * Parse an audio block from AC-3 bitstream.
+ */
+static int ac3_parse_audio_block(AC3DecodeContext *ctx, int blk)
 {
     int nfchans = ctx->nfchans;
     int acmod = ctx->acmod;
-    int i, bnd, rbnd, seg, grpsize;
+    int i, bnd, seg, ch;
     GetBitContext *gb = &ctx->gb;
-    int bit_alloc_flags = 0;
-    uint8_t *dexps;
-    int mstrcplco, cplcoexp, cplcomant;
-    int dynrng, chbwcod, ngrps, cplabsexp, skipl;
-
-    ctx->blksw = 0;
-    for (i = 0; i < nfchans; i++) /*block switch flag */
-        ctx->blksw |= get_bits1(gb) << i;
-
-    ctx->dithflag = 0;
-    for (i = 0; i < nfchans; i++) /* dithering flag */
-        ctx->dithflag |= get_bits1(gb) << i;
-
-    if (get_bits1(gb)) { /* dynamic range */
-        dynrng = get_sbits(gb, 8);
-        ctx->dynrng = ((((dynrng & 0x1f) | 0x20) << 13) * scale_factors[3 - (dynrng >> 5)]);
-    }
+    uint8_t bit_alloc_stages[AC3_MAX_CHANNELS];
 
-    if (acmod == 0x00 && get_bits1(gb)) { /* dynamic range 1+1 mode */
-        dynrng = get_sbits(gb, 8);
-        ctx->dynrng2 = ((((dynrng & 0x1f) | 0x20) << 13) * scale_factors[3 - (dynrng >> 5)]);
-    }
+    memset(bit_alloc_stages, 0, AC3_MAX_CHANNELS);
 
-    get_downmix_coeffs(ctx);
+    /* block switch flags */
+    for (ch = 1; ch <= nfchans; ch++)
+        ctx->blksw[ch] = get_bits1(gb);
 
-    if (get_bits1(gb)) { /* coupling strategy */
-        ctx->cplinu = get_bits1(gb);
-        ctx->cplbndstrc = 0;
-        ctx->chincpl = 0;
-        if (ctx->cplinu) { /* coupling in use */
-            for (i = 0; i < nfchans; i++)
-                ctx->chincpl |= get_bits1(gb) << i;
-
-            if (acmod == 0x02)
-                ctx->phsflginu = get_bits1(gb); //phase flag in use
+    /* dithering flags */
+    ctx->dither_all = 1;
+    for (ch = 1; ch <= nfchans; ch++) {
+        ctx->dithflag[ch] = get_bits1(gb);
+        if(!ctx->dithflag[ch])
+            ctx->dither_all = 0;
+    }
 
-            ctx->cplbegf = get_bits(gb, 4);
-            ctx->cplendf = get_bits(gb, 4);
+    /* dynamic range */
+    i = !(ctx->acmod);
+    do {
+        if(get_bits1(gb)) {
+            ctx->dynrng[i] = dynrng_tab[get_bits(gb, 8)];
+        } else if(blk == 0) {
+            ctx->dynrng[i] = 1.0f;
+        }
+    } while(i--);
 
-            if (3 + ctx->cplendf - ctx->cplbegf < 0) {
-                av_log(NULL, AV_LOG_ERROR, "cplendf = %d < cplbegf = %d\n", ctx->cplendf, ctx->cplbegf);
+    /* coupling strategy */
+    if (get_bits1(gb)) {
+        memset(bit_alloc_stages, 3, AC3_MAX_CHANNELS);
+        ctx->cplinu = get_bits1(gb);
+        if (ctx->cplinu) {
+            /* coupling in use */
+            int cplbegf, cplendf;
+
+            /* determine which channels are coupled */
+            for (ch = 1; ch <= nfchans; ch++)
+                ctx->chincpl[ch] = get_bits1(gb);
+
+            /* phase flags in use */
+            if (acmod == AC3_ACMOD_STEREO)
+                ctx->phsflginu = get_bits1(gb);
+
+            /* coupling frequency range and band structure */
+            cplbegf = get_bits(gb, 4);
+            cplendf = get_bits(gb, 4);
+            if (3 + cplendf - cplbegf < 0) {
+                av_log(ctx->avctx, AV_LOG_ERROR, "cplendf = %d < cplbegf = %d\n", cplendf, cplbegf);
                 return -1;
             }
-
-            ctx->ncplbnd = ctx->ncplsubnd = 3 + ctx->cplendf - ctx->cplbegf;
-            ctx->cplstrtmant = ctx->cplbegf * 12 + 37;
-            ctx->cplendmant = ctx->cplendf * 12 + 73;
-            for (i = 0; i < ctx->ncplsubnd - 1; i++) /* coupling band structure */
+            ctx->ncplbnd = ctx->ncplsubnd = 3 + cplendf - cplbegf;
+            ctx->startmant[CPL_CH] = cplbegf * 12 + 37;
+            ctx->endmant[CPL_CH] = cplendf * 12 + 73;
+            for (bnd = 0; bnd < ctx->ncplsubnd - 1; bnd++) {
                 if (get_bits1(gb)) {
-                    ctx->cplbndstrc |= 1 << i;
+                    ctx->cplbndstrc[bnd] = 1;
                     ctx->ncplbnd--;
                 }
+            }
+        } else {
+            /* coupling not in use */
+            for (ch = 1; ch <= nfchans; ch++)
+                ctx->chincpl[ch] = 0;
         }
     }
 
+    /* coupling coordinates */
     if (ctx->cplinu) {
-        ctx->cplcoe = 0;
+        int cplcoe = 0;
 
-        for (i = 0; i < nfchans; i++)
-            if ((ctx->chincpl) >> i & 1)
-                if (get_bits1(gb)) { /* coupling co-ordinates */
-                    ctx->cplcoe |= 1 << i;
+        for (ch = 1; ch <= nfchans; ch++) {
+            if (ctx->chincpl[ch]) {
+                if (get_bits1(gb)) {
+                    int mstrcplco, cplcoexp, cplcomant;
+                    cplcoe = 1;
                     mstrcplco = 3 * get_bits(gb, 2);
                     for (bnd = 0; bnd < ctx->ncplbnd; bnd++) {
                         cplcoexp = get_bits(gb, 4);
                         cplcomant = get_bits(gb, 4);
                         if (cplcoexp == 15)
-                            cplcomant <<= 14;
+                            ctx->cplco[ch][bnd] = cplcomant / 16.0f;
                         else
-                            cplcomant = (cplcomant | 0x10) << 13;
-                        ctx->cplco[i][bnd] = cplcomant * scale_factors[cplcoexp + mstrcplco];
+                            ctx->cplco[ch][bnd] = (cplcomant + 16.0f) / 32.0f;
+                        ctx->cplco[ch][bnd] *= scale_factors[cplcoexp + mstrcplco];
                     }
                 }
-
-        if (acmod == 0x02 && ctx->phsflginu && (ctx->cplcoe & 1 || ctx->cplcoe & 2))
-            for (bnd = 0; bnd < ctx->ncplbnd; bnd++)
+            }
+        }
+        /* phase flags */
+        if (acmod == AC3_ACMOD_STEREO && ctx->phsflginu && cplcoe) {
+            for (bnd = 0; bnd < ctx->ncplbnd; bnd++) {
                 if (get_bits1(gb))
-                    ctx->cplco[1][bnd] = -ctx->cplco[1][bnd];
+                    ctx->cplco[2][bnd] = -ctx->cplco[2][bnd];
+            }
+        }
     }
 
-    if (acmod == 0x02) {/* rematrixing */
+    /* stereo rematrixing strategy and band structure */
+    if (acmod == AC3_ACMOD_STEREO) {
         ctx->rematstr = get_bits1(gb);
         if (ctx->rematstr) {
-            ctx->rematflg = 0;
-
-            if (!(ctx->cplinu) || ctx->cplbegf > 2)
-                for (rbnd = 0; rbnd < 4; rbnd++)
-                    ctx->rematflg |= get_bits1(gb) << rbnd;
-            if (ctx->cplbegf > 0 && ctx->cplbegf <= 2 && ctx->cplinu)
-                for (rbnd = 0; rbnd < 3; rbnd++)
-                    ctx->rematflg |= get_bits1(gb) << rbnd;
-            if (ctx->cplbegf == 0 && ctx->cplinu)
-                for (rbnd = 0; rbnd < 2; rbnd++)
-                    ctx->rematflg |= get_bits1(gb) << rbnd;
+            ctx->nrematbnd = 4;
+            if(ctx->cplinu && ctx->startmant[CPL_CH] <= 61)
+                ctx->nrematbnd -= 1 + (ctx->startmant[CPL_CH] == 37);
+            for(bnd=0; bnd<ctx->nrematbnd; bnd++)
+                ctx->rematflg[bnd] = get_bits1(gb);
         }
     }
 
-    ctx->cplexpstr = EXP_REUSE;
-    ctx->lfeexpstr = EXP_REUSE;
-    if (ctx->cplinu) /* coupling exponent strategy */
-        ctx->cplexpstr = get_bits(gb, 2);
-    for (i = 0; i < nfchans; i++)  /* channel exponent strategy */
-        ctx->chexpstr[i] = get_bits(gb, 2);
-    if (ctx->lfeon)  /* lfe exponent strategy */
-        ctx->lfeexpstr = get_bits1(gb);
-
-    for (i = 0; i < nfchans; i++) /* channel bandwidth code */
-        if (ctx->chexpstr[i] != EXP_REUSE) {
-            if ((ctx->chincpl >> i) & 1)
-                ctx->endmant[i] = ctx->cplstrtmant;
+    /* exponent strategies for each channel */
+    ctx->expstr[CPL_CH] = EXP_REUSE;
+    ctx->expstr[ctx->lfe_ch] = EXP_REUSE;
+    for (ch = !ctx->cplinu; ch <= ctx->nchans; ch++) {
+        if(ch == ctx->lfe_ch)
+            ctx->expstr[ch] = get_bits(gb, 1);
+        else
+            ctx->expstr[ch] = get_bits(gb, 2);
+        if(ctx->expstr[ch] != EXP_REUSE)
+            bit_alloc_stages[ch] = 3;
+    }
+
+    /* channel bandwidth */
+    for (ch = 1; ch <= nfchans; ch++) {
+        ctx->startmant[ch] = 0;
+        if (ctx->expstr[ch] != EXP_REUSE) {
+            int prev = ctx->endmant[ch];
+            if (ctx->chincpl[ch])
+                ctx->endmant[ch] = ctx->startmant[CPL_CH];
             else {
-                chbwcod = get_bits(gb, 6);
+                int chbwcod = get_bits(gb, 6);
                 if (chbwcod > 60) {
-                    av_log(NULL, AV_LOG_ERROR, "chbwcod = %d > 60", chbwcod);
+                    av_log(ctx->avctx, AV_LOG_ERROR, "chbwcod = %d > 60", chbwcod);
                     return -1;
                 }
-                ctx->endmant[i] = chbwcod * 3 + 73;
+                ctx->endmant[ch] = chbwcod * 3 + 73;
             }
+            if(blk > 0 && ctx->endmant[ch] != prev)
+                memset(bit_alloc_stages, 3, AC3_MAX_CHANNELS);
         }
-
-    if (ctx->cplexpstr != EXP_REUSE) {/* coupling exponents */
-        bit_alloc_flags = 64;
-        cplabsexp = get_bits(gb, 4) << 1;
-        ngrps = (ctx->cplendmant - ctx->cplstrtmant) / (3 << (ctx->cplexpstr - 1));
-        decode_exponents(gb, ctx->cplexpstr, ngrps, cplabsexp, ctx->dcplexps + ctx->cplstrtmant);
     }
-
-    for (i = 0; i < nfchans; i++) /* fbw channel exponents */
-        if (ctx->chexpstr[i] != EXP_REUSE) {
-            bit_alloc_flags |= 1 << i;
-            grpsize = 3 << (ctx->chexpstr[i] - 1);
-            ngrps = (ctx->endmant[i] + grpsize - 4) / grpsize;
-            dexps = ctx->dexps[i];
-            dexps[0] = get_bits(gb, 4);
-            decode_exponents(gb, ctx->chexpstr[i], ngrps, dexps[0], dexps + 1);
-            skip_bits(gb, 2); /* skip gainrng */
+    ctx->startmant[ctx->lfe_ch] = 0;
+    ctx->endmant[ctx->lfe_ch] = 7;
+
+    /* decode exponents for each channel */
+    for (ch = !ctx->cplinu; ch <= ctx->nchans; ch++) {
+        if (ctx->expstr[ch] != EXP_REUSE) {
+            int grpsize, ngrps;
+            grpsize = 3 << (ctx->expstr[ch] - 1);
+            if(ch == CPL_CH)
+                ngrps = (ctx->endmant[ch] - ctx->startmant[ch]) / grpsize;
+            else if(ch == ctx->lfe_ch)
+                ngrps = 2;
+            else
+                ngrps = (ctx->endmant[ch] + grpsize - 4) / grpsize;
+            ctx->dexps[ch][0] = get_bits(gb, 4) << !ch;
+            decode_exponents(gb, ctx->expstr[ch], ngrps, ctx->dexps[ch][0],
+                             &ctx->dexps[ch][ctx->startmant[ch]+!!ch]);
+            if(ch != CPL_CH && ch != ctx->lfe_ch)
+                skip_bits(gb, 2); /* skip gainrng */
         }
-
-    if (ctx->lfeexpstr != EXP_REUSE) { /* lfe exponents */
-        bit_alloc_flags |= 32;
-        ctx->dlfeexps[0] = get_bits(gb, 4);
-        decode_exponents(gb, ctx->lfeexpstr, 2, ctx->dlfeexps[0], ctx->dlfeexps + 1);
     }
 
-    if (get_bits1(gb)) { /* bit allocation information */
-        bit_alloc_flags = 127;
-        ctx->sdcycod = get_bits(gb, 2);
-        ctx->fdcycod = get_bits(gb, 2);
-        ctx->sgaincod = get_bits(gb, 2);
-        ctx->dbpbcod = get_bits(gb, 2);
-        ctx->floorcod = get_bits(gb, 3);
+    /* bit allocation information */
+    if (get_bits1(gb)) {
+        ctx->bit_alloc_params.sdecay = ff_sdecaytab[get_bits(gb, 2)] >> ctx->bit_alloc_params.halfratecod;
+        ctx->bit_alloc_params.fdecay = ff_fdecaytab[get_bits(gb, 2)] >> ctx->bit_alloc_params.halfratecod;
+        ctx->bit_alloc_params.sgain  = ff_sgaintab[get_bits(gb, 2)];
+        ctx->bit_alloc_params.dbknee = ff_dbkneetab[get_bits(gb, 2)];
+        ctx->bit_alloc_params.floor  = ff_floortab[get_bits(gb, 3)];
+        for(ch=!ctx->cplinu; ch<=ctx->nchans; ch++) {
+            bit_alloc_stages[ch] = FFMAX(bit_alloc_stages[ch], 2);
+        }
     }
 
-    if (get_bits1(gb)) { /* snroffset */
-        bit_alloc_flags = 127;
-        ctx->csnroffst = get_bits(gb, 6);
-        if (ctx->cplinu) { /* coupling fine snr offset and fast gain code */
-            ctx->cplfsnroffst = get_bits(gb, 4);
-            ctx->cplfgaincod = get_bits(gb, 3);
-        }
-        for (i = 0; i < nfchans; i++) { /* channel fine snr offset and fast gain code */
-            ctx->fsnroffst[i] = get_bits(gb, 4);
-            ctx->fgaincod[i] = get_bits(gb, 3);
-        }
-        if (ctx->lfeon) { /* lfe fine snr offset and fast gain code */
-            ctx->lfefsnroffst = get_bits(gb, 4);
-            ctx->lfefgaincod = get_bits(gb, 3);
+    /* signal-to-noise ratio offsets and fast gains (signal-to-mask ratios) */
+    if (get_bits1(gb)) {
+        int csnr;
+        csnr = (get_bits(gb, 6) - 15) << 4;
+        for (ch = !ctx->cplinu; ch <= ctx->nchans; ch++) { /* snr offset and fast gain */
+            ctx->snroffst[ch] = (csnr + get_bits(gb, 4)) << 2;
+            ctx->fgain[ch] = ff_fgaintab[get_bits(gb, 3)];
         }
+        memset(bit_alloc_stages, 3, AC3_MAX_CHANNELS);
     }
 
-    if (ctx->cplinu && get_bits1(gb)) { /* coupling leak information */
-        bit_alloc_flags |= 64;
-        ctx->cplfleak = get_bits(gb, 3);
-        ctx->cplsleak = get_bits(gb, 3);
+    /* coupling leak information */
+    if (ctx->cplinu && get_bits1(gb)) {
+        ctx->bit_alloc_params.cplfleak = get_bits(gb, 3);
+        ctx->bit_alloc_params.cplsleak = get_bits(gb, 3);
+        bit_alloc_stages[CPL_CH] = FFMAX(bit_alloc_stages[CPL_CH], 2);
     }
 
-    if (get_bits1(gb)) { /* delta bit allocation information */
-        bit_alloc_flags = 127;
-
-        if (ctx->cplinu) {
-            ctx->cpldeltbae = get_bits(gb, 2);
-            if (ctx->cpldeltbae == DBA_RESERVED) {
-                av_log(NULL, AV_LOG_ERROR, "coupling delta bit allocation strategy reserved\n");
-                return -1;
-            }
-        }
-
-        for (i = 0; i < nfchans; i++) {
-            ctx->deltbae[i] = get_bits(gb, 2);
-            if (ctx->deltbae[i] == DBA_RESERVED) {
-                av_log(NULL, AV_LOG_ERROR, "delta bit allocation strategy reserved\n");
+    /* delta bit allocation information */
+    if (get_bits1(gb)) {
+        /* delta bit allocation exists (strategy) */
+        for (ch = !ctx->cplinu; ch <= nfchans; ch++) {
+            ctx->deltbae[ch] = get_bits(gb, 2);
+            if (ctx->deltbae[ch] == DBA_RESERVED) {
+                av_log(ctx->avctx, AV_LOG_ERROR, "delta bit allocation strategy reserved\n");
                 return -1;
             }
+            bit_alloc_stages[ch] = FFMAX(bit_alloc_stages[ch], 2);
         }
-
-        if (ctx->cplinu)
-            if (ctx->cpldeltbae == DBA_NEW) { /*coupling delta offset, len and bit allocation */
-                ctx->cpldeltnseg = get_bits(gb, 3);
-                for (seg = 0; seg <= ctx->cpldeltnseg; seg++) {
-                    ctx->cpldeltoffst[seg] = get_bits(gb, 5);
-                    ctx->cpldeltlen[seg] = get_bits(gb, 4);
-                    ctx->cpldeltba[seg] = get_bits(gb, 3);
-                }
-            }
-
-        for (i = 0; i < nfchans; i++)
-            if (ctx->deltbae[i] == DBA_NEW) {/*channel delta offset, len and bit allocation */
-                ctx->deltnseg[i] = get_bits(gb, 3);
-                for (seg = 0; seg <= ctx->deltnseg[i]; seg++) {
-                    ctx->deltoffst[i][seg] = get_bits(gb, 5);
-                    ctx->deltlen[i][seg] = get_bits(gb, 4);
-                    ctx->deltba[i][seg] = get_bits(gb, 3);
+        /* channel delta offset, len and bit allocation */
+        for (ch = !ctx->cplinu; ch <= nfchans; ch++) {
+            if (ctx->deltbae[ch] == DBA_NEW) {
+                ctx->deltnseg[ch] = get_bits(gb, 3);
+                for (seg = 0; seg <= ctx->deltnseg[ch]; seg++) {
+                    ctx->deltoffst[ch][seg] = get_bits(gb, 5);
+                    ctx->deltlen[ch][seg] = get_bits(gb, 4);
+                    ctx->deltba[ch][seg] = get_bits(gb, 3);
                 }
             }
+        }
+    } else if(blk == 0) {
+        for(ch=0; ch<=ctx->nchans; ch++) {
+            ctx->deltbae[ch] = DBA_NONE;
+        }
     }
 
-    if (bit_alloc_flags) {
-        /* set bit allocation parameters */
-        ctx->bit_alloc_params.fscod = ctx->fscod;
-        ctx->bit_alloc_params.halfratecod = 0;
-        ctx->bit_alloc_params.sdecay = ff_sdecaytab[ctx->sdcycod];
-        ctx->bit_alloc_params.fdecay = ff_fdecaytab[ctx->fdcycod];
-        ctx->bit_alloc_params.sgain = ff_sgaintab[ctx->sgaincod];
-        ctx->bit_alloc_params.dbknee = ff_dbkneetab[ctx->dbpbcod];
-        ctx->bit_alloc_params.floor = ff_floortab[ctx->floorcod];
-        ctx->bit_alloc_params.cplfleak = ctx->cplfleak;
-        ctx->bit_alloc_params.cplsleak = ctx->cplsleak;
-
-        if (ctx->chincpl && (bit_alloc_flags & 64))
-            do_bit_allocation(ctx, 5);
-        for (i = 0; i < nfchans; i++)
-            if ((bit_alloc_flags >> i) & 1)
-                do_bit_allocation(ctx, i);
-        if (ctx->lfeon && (bit_alloc_flags & 32))
-            do_bit_allocation(ctx, 6);
+    /* Bit allocation */
+    for(ch=!ctx->cplinu; ch<=ctx->nchans; ch++) {
+        if(bit_alloc_stages[ch] > 2) {
+            /* Exponent mapping into PSD and PSD integration */
+            ff_ac3_bit_alloc_calc_psd(ctx->dexps[ch],
+                                      ctx->startmant[ch], ctx->endmant[ch],
+                                      ctx->psd[ch], ctx->bndpsd[ch]);
+        }
+        if(bit_alloc_stages[ch] > 1) {
+            /* Compute excitation function, Compute masking curve, and
+               Apply delta bit allocation */
+            ff_ac3_bit_alloc_calc_mask(&ctx->bit_alloc_params, ctx->bndpsd[ch],
+                                       ctx->startmant[ch], ctx->endmant[ch],
+                                       ctx->fgain[ch], (ch == ctx->lfe_ch),
+                                       ctx->deltbae[ch], ctx->deltnseg[ch],
+                                       ctx->deltoffst[ch], ctx->deltlen[ch],
+                                       ctx->deltba[ch], ctx->mask[ch]);
+        }
+        if(bit_alloc_stages[ch] > 0) {
+            /* Compute bit allocation */
+            ff_ac3_bit_alloc_calc_bap(ctx->mask[ch], ctx->psd[ch],
+                                      ctx->startmant[ch], ctx->endmant[ch],
+                                      ctx->snroffst[ch],
+                                      ctx->bit_alloc_params.floor,
+                                      ctx->bap[ch]);
+        }
     }
 
-    if (get_bits1(gb)) { /* unused dummy data */
-        skipl = get_bits(gb, 9);
+    /* unused dummy data */
+    if (get_bits1(gb)) {
+        int skipl = get_bits(gb, 9);
         while(skipl--)
             skip_bits(gb, 8);
     }
+
     /* unpack the transform coefficients
-     * * this also uncouples channels if coupling is in use.
-     */
+       this also uncouples channels if coupling is in use. */
     if (get_transform_coeffs(ctx)) {
-        av_log(NULL, AV_LOG_ERROR, "Error in routine get_transform_coeffs\n");
+        av_log(ctx->avctx, AV_LOG_ERROR, "Error in routine get_transform_coeffs\n");
         return -1;
     }
 
     /* recover coefficients if rematrixing is in use */
-    if (ctx->rematflg)
+    if(ctx->acmod == AC3_ACMOD_STEREO)
         do_rematrixing(ctx);
 
-    do_downmix(ctx);
+    /* apply scaling to coefficients (headroom, dialnorm, dynrng) */
+    for(ch=1; ch<=ctx->nchans; ch++) {
+        float gain = 2.0f * ctx->mul_bias;
+        if(ctx->acmod == AC3_ACMOD_DUALMONO) {
+            gain *= ctx->dialnorm[ch-1] * ctx->dynrng[ch-1];
+        } else {
+            gain *= ctx->dialnorm[0] * ctx->dynrng[0];
+        }
+        for(i=0; i<ctx->endmant[ch]; i++) {
+            ctx->transform_coeffs[ch][i] *= gain;
+        }
+    }
 
     do_imdct(ctx);
 
-    return 0;
-}
+    /* downmix output if needed */
+    if(ctx->nchans != ctx->out_channels && !((ctx->output_mode & AC3_OUTPUT_LFEON) &&
+            ctx->nfchans == ctx->out_channels)) {
+        ac3_downmix(ctx->output, ctx->nfchans, ctx->output_mode,
+                    ctx->downmix_coeffs);
+    }
 
-static inline int16_t convert(int32_t i)
-{
-    if (i > 0x43c07fff)
-        return 32767;
-    else if (i <= 0x43bf8000)
-        return -32768;
-    else
-        return (i - 0x43c00000);
+    /* convert float to 16-bit integer */
+    for(ch=0; ch<ctx->out_channels; ch++) {
+        for(i=0; i<256; i++) {
+            ctx->output[ch][i] += ctx->add_bias;
+        }
+        ctx->dsp.float_to_int16(ctx->int_output[ch], ctx->output[ch], 256);
+    }
+
+    return 0;
 }
 
-/* Decode ac3 frame.
- *
- * @param avctx Pointer to AVCodecContext
- * @param data Pointer to pcm smaples
- * @param data_size Set to number of pcm samples produced by decoding
- * @param buf Data to be decoded
- * @param buf_size Size of the buffer
+/**
+ * Decode a single AC-3 frame.
  */
 static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size, uint8_t *buf, int buf_size)
 {
     AC3DecodeContext *ctx = (AC3DecodeContext *)avctx->priv_data;
     int16_t *out_samples = (int16_t *)data;
-    int i, j, k, start;
-    int32_t *int_ptr[6];
-
-    for (i = 0; i < 6; i++)
-        int_ptr[i] = (int32_t *)(&ctx->output[i]);
+    int i, blk, ch, err;
 
-    //Initialize the GetBitContext with the start of valid AC3 Frame.
+    /* initialize the GetBitContext with the start of valid AC-3 Frame */
     init_get_bits(&ctx->gb, buf, buf_size * 8);
 
-    //Parse the syncinfo.
-    //If 'fscod' or 'bsid' is not valid the decoder shall mute as per the standard.
-    if (!ac3_parse_sync_info(ctx)) {
-        av_log(avctx, AV_LOG_ERROR, "\n");
-        *data_size = 0;
-        return buf_size;
+    /* parse the syncinfo */
+    err = ac3_parse_header(ctx);
+    if(err) {
+        switch(err) {
+            case AC3_PARSE_ERROR_SYNC:
+                av_log(avctx, AV_LOG_ERROR, "frame sync error\n");
+                break;
+            case AC3_PARSE_ERROR_BSID:
+                av_log(avctx, AV_LOG_ERROR, "invalid bitstream id\n");
+                break;
+            case AC3_PARSE_ERROR_SAMPLE_RATE:
+                av_log(avctx, AV_LOG_ERROR, "invalid sample rate\n");
+                break;
+            case AC3_PARSE_ERROR_FRAME_SIZE:
+                av_log(avctx, AV_LOG_ERROR, "invalid frame size\n");
+                break;
+            default:
+                av_log(avctx, AV_LOG_ERROR, "invalid header\n");
+                break;
+        }
+        return -1;
     }
 
-    //Parse the BSI.
-    //If 'bsid' is not valid decoder shall not decode the audio as per the standard.
-    ac3_parse_bsi(ctx);
-
     avctx->sample_rate = ctx->sampling_rate;
     avctx->bit_rate = ctx->bit_rate;
 
-    if (avctx->channels == 0) {
-        ctx->blkoutput |= AC3_OUTPUT_UNMODIFIED;
-        if (ctx->lfeon)
-            ctx->blkoutput |= AC3_OUTPUT_LFEON;
-        avctx->channels = ctx->nfchans + ctx->lfeon;
+    /* check that reported frame size fits in input buffer */
+    if(ctx->frame_size > buf_size) {
+        av_log(avctx, AV_LOG_ERROR, "incomplete frame\n");
+        return -1;
     }
-    else if (avctx->channels == 1)
-        ctx->blkoutput |= AC3_OUTPUT_MONO;
-    else if (avctx->channels == 2) {
-        if (ctx->dsurmod == 0x02)
-            ctx->blkoutput |= AC3_OUTPUT_DOLBY;
-        else
-            ctx->blkoutput |= AC3_OUTPUT_STEREO;
+
+    /* channel config */
+    ctx->out_channels = ctx->nchans;
+    if (avctx->channels == 0) {
+        avctx->channels = ctx->out_channels;
+    } else if(ctx->out_channels < avctx->channels) {
+        av_log(avctx, AV_LOG_ERROR, "Cannot upmix AC3 from %d to %d channels.\n",
+               ctx->out_channels, avctx->channels);
+        return -1;
     }
-    else {
-        if (avctx->channels < (ctx->nfchans + ctx->lfeon))
-            av_log(avctx, AV_LOG_INFO, "ac3_decoder: AC3 Source Channels Are Less Then Specified %d: Output to %d Channels\n",avctx->channels, ctx->nfchans + ctx->lfeon);
-        ctx->blkoutput |= AC3_OUTPUT_UNMODIFIED;
-        if (ctx->lfeon)
-            ctx->blkoutput |= AC3_OUTPUT_LFEON;
-        avctx->channels = ctx->nfchans + ctx->lfeon;
+    if(avctx->channels == 2) {
+        ctx->output_mode = AC3_ACMOD_STEREO;
+    } else if(avctx->channels == 1) {
+        ctx->output_mode = AC3_ACMOD_MONO;
+    } else if(avctx->channels != ctx->out_channels) {
+        av_log(avctx, AV_LOG_ERROR, "Cannot downmix AC3 from %d to %d channels.\n",
+               ctx->out_channels, avctx->channels);
+        return -1;
     }
+    ctx->out_channels = avctx->channels;
 
-    //av_log(avctx, AV_LOG_INFO, "channels = %d \t bit rate = %d \t sampling rate = %d \n", avctx->channels, avctx->bit_rate * 1000, avctx->sample_rate);
-
-    //Parse the Audio Blocks.
-    for (i = 0; i < NB_BLOCKS; i++) {
-        if (ac3_parse_audio_block(ctx)) {
+    /* parse the audio blocks */
+    for (blk = 0; blk < NB_BLOCKS; blk++) {
+        if (ac3_parse_audio_block(ctx, blk)) {
             av_log(avctx, AV_LOG_ERROR, "error parsing the audio block\n");
             *data_size = 0;
             return ctx->frame_size;
         }
-        start = (ctx->blkoutput & AC3_OUTPUT_LFEON) ? 0 : 1;
-        for (k = 0; k < BLOCK_SIZE; k++)
-            for (j = start; j <= avctx->channels; j++)
-                *(out_samples++) = convert(int_ptr[j][k]);
+        for (i = 0; i < 256; i++)
+            for (ch = 0; ch < ctx->out_channels; ch++)
+                *(out_samples++) = ctx->int_output[ch][i];
     }
-    *data_size = NB_BLOCKS * BLOCK_SIZE * avctx->channels * sizeof (int16_t);
+    *data_size = NB_BLOCKS * 256 * avctx->channels * sizeof (int16_t);
     return ctx->frame_size;
 }
 
-/* Uninitialize ac3 decoder.
+/**
+ * Uninitialize the AC-3 decoder.
  */
 static int ac3_decode_end(AVCodecContext *avctx)
 {
@@ -1713,4 +1182,3 @@ AVCodec ac3_decoder = {
     .close = ac3_decode_end,
     .decode = ac3_decode_frame,
 };
-