changeset 5306:abc5c130b448 libavcodec

AC-3 decoder, soc revision 32, Jul 17 09:37:32 2006 UTC by cloud9 Latest commit. There is no error in parsing and or recovering transform coefficients. Double checked with ac3dec. Getting consistent results with the bit allocation routine and transform coefficients. The code is able to parse valid ac3 bitstreams without error from start to end. I have also implemented the imdct when block switching is not enabled. However, can anybody provide an insight into how to convert float samples to int16_t ? lrint is of no help cuz it produces output -1, 0 or 1 whereas the output should be between -32768 to 32767.
author jbr
date Sat, 14 Jul 2007 15:48:28 +0000
parents 5892b4a6380b
children 1bcccd2de20d
files ac3dec.c
diffstat 1 files changed, 398 insertions(+), 292 deletions(-) [+]
line wrap: on
line diff
--- a/ac3dec.c	Sat Jul 14 15:42:15 2007 +0000
+++ b/ac3dec.c	Sat Jul 14 15:48:28 2007 +0000
@@ -25,8 +25,8 @@
 
 #define ALT_BITSTREAM_READER
 
+#include "ac3tab.h"
 #include "ac3.h"
-#include "ac3tab.h"
 #include "ac3_decoder.h"
 #include "avcodec.h"
 #include "bitstream.h"
@@ -35,8 +35,8 @@
 #include "common.h"
 
 #define MAX_CHANNELS    6
-#define MAX_BLOCK_SIZE  256
-#define MAX_BLOCKS      6
+#define BLOCK_SIZE    256
+#define AUDIO_BLOCKS    6
 
 /* Synchronization information. */
 typedef struct {
@@ -141,9 +141,6 @@
     uint8_t  cplendf;               //coupling end frequency code
     uint32_t cplbndstrc;            //coupling band structure
     uint8_t  cplcoe;                //coupling co-ordinates exists for the channel in use
-    uint8_t  mstrcplco[5];          //master coupling co-ordinate for channels in use
-    uint8_t  cplcoexp[5][18];       //coupling co-ordinate exponenets
-    uint8_t  cplcomant[5][18];      //coupling co-ordinate mantissas
     uint32_t phsflg;                //phase flag per band
     uint8_t  rematflg;              //rematrixing flag
     uint8_t  cplexpstr;             //coupling exponent strategy
@@ -183,10 +180,8 @@
     int      ncplbnd;               //derived from ncplsubnd and cplbndstrc
     int      ncplgrps;              //derived from ncplsubnd, cplexpstr
     int      nchgrps[5];            //derived from chexpstr, and cplbegf or chbwcod
-    int      nchmant[5];            //derived from cplbegf or chbwcod
     int      ncplmant;              //derived from ncplsubnd = 12 * ncplsubnd
 
-    uint8_t  cplstrtbnd;            //coupling start band for bit allocation
     uint8_t  cplstrtmant;           //coupling start mantissa
     uint8_t  cplendmant;            //coupling end mantissa
     uint8_t  endmant[5];            //channel end mantissas
@@ -198,19 +193,22 @@
     uint8_t  bap[5][256];           //fbw channels bit allocation parameters table
     uint8_t  lfebap[256];           //lfe bit allocaiton parameters table
 
-    DECLARE_ALIGNED_16(float, transform_coeffs[MAX_CHANNELS][MAX_BLOCK_SIZE]); //transform coefficients
-    DECLARE_ALIGNED_16(float, cplcoeffs[256]);        //temporary storage for coupling transform coefficients
-    DECLARE_ALIGNED_16(float, block_output[MAX_CHANNELS][MAX_BLOCK_SIZE]);
+    DECLARE_ALIGNED_16(float, transform_coeffs[MAX_CHANNELS][BLOCK_SIZE]); //transform coefficients
+    DECLARE_ALIGNED_16(float, output[MAX_CHANNELS][BLOCK_SIZE]);  //output of the block
+    DECLARE_ALIGNED_16(float, delay[MAX_CHANNELS][BLOCK_SIZE]); //delay (for overlap and add)
+    DECLARE_ALIGNED_16(float, tmp_imdct[BLOCK_SIZE]);   //temporary storage for ff_imdct_calc
+    DECLARE_ALIGNED_16(float, tmp_output[BLOCK_SIZE * 2]);  //output of ff_imdct_calc
     float    cplco[5][18];          //coupling coordinates
     float    chcoeffs[6];           //channel coefficients for downmix
 } ac3_audio_block;
 
 
 
-#define AC3_OUTPUT_UNMODIFIED   0x00
-#define AC3_OUTPUT_MONO         0x01
-#define AC3_OUTPUT_STEREO       0x02
-#define AC3_OUTPUT_DOLBY        0x03
+#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_INPUT_DUALMONO      0x00
 #define AC3_INPUT_MONO          0x01
@@ -290,9 +288,6 @@
     MDCTContext     imdct_ctx_512;
     GetBitContext   gb;
     int             output;
-    DECLARE_ALIGNED_16(float, delay[MAX_CHANNELS][MAX_BLOCK_SIZE]);
-    DECLARE_ALIGNED_16(FFTSample, tmp_imdct[MAX_BLOCK_SIZE * 2]);
-    DECLARE_ALIGNED_16(FFTSample, tmp_output[MAX_BLOCK_SIZE * 2]);
 } AC3DecodeContext;
 
 static void ac3_common_init1(void)
@@ -315,12 +310,15 @@
 static int ac3_decode_init(AVCodecContext *avctx)
 {
     AC3DecodeContext *ctx = avctx->priv_data;
+    int i;
 
     ac3_common_init1();
 
     ff_mdct_init(&ctx->imdct_ctx_256, 8, 1);
     ff_mdct_init(&ctx->imdct_ctx_512, 9, 1);
     dither_seed(&ctx->state, 0);
+    for (i = 0; i < MAX_CHANNELS; i++)
+        memset(ctx->audio_block.delay[i], 0, sizeof(ctx->audio_block.delay[i]));
 
     return 0;
 }
@@ -388,6 +386,7 @@
     bsi->cmixlev = 0;
     bsi->surmixlev = 0;
     bsi->dsurmod = 0;
+    bsi->nfchans = 0;
     ctx->audio_block.cpldeltbae = AC3_DBASTR_NONE;
     ctx->audio_block.cpldeltnseg = 0;
     for (i = 0; i < 5; i++) {
@@ -449,8 +448,9 @@
     if (get_bits1(gb)) {
         *flags |= AC3_BSI_ADDBSIE;
         bsi->addbsil = get_bits(gb, 6);
-        for (i = 0; i < (bsi->addbsil + 1); i++)
+        do {
             skip_bits(gb, 8);
+        } while(bsi->addbsil--);
     }
 
     bsi->nfchans = nfchans_tbl[bsi->acmod];
@@ -651,19 +651,19 @@
         excite[1] = bndpsd[1] - fgain - lowcomp;
         begin = 7;
         for (bin = 2; bin < 7; bin++) {
-            if (bndend != 7 || bin != 6)
+            if (!(chnl == 6 && bin == 6))
                 lowcomp = calc_lowcomp(lowcomp, bndpsd[bin], bndpsd[bin + 1], bin);
             fastleak = bndpsd[bin] - fgain;
             slowleak = bndpsd[bin] - sgain;
             excite[bin] = fastleak - lowcomp;
-            if (bndend != 7 || bin != 6)
+            if (!(chnl == 6 && bin == 6))
                 if (bndpsd[bin] <= bndpsd[bin + 1]) {
                     begin = bin + 1;
                     break;
                 }
         }
         for (bin = begin; bin < FFMIN(bndend, 22); bin++) {
-            if (bndend != 7 || bin != 6)
+            if (!(chnl == 6 && bin == 6))
                 lowcomp = calc_lowcomp(lowcomp, bndpsd[bin], bndpsd[bin + 1], bin);
             fastleak -= fdecay;
             fastleak = FFMAX(fastleak, bndpsd[bin] - fgain);
@@ -738,7 +738,7 @@
 
     if (ab->flags & AC3_AB_SNROFFSTE) { /* check whether snroffsts are zero */
         snroffst += ab->csnroffst;
-        if (ab->flags & AC3_AB_CPLINU)
+        if (ab->flags & ab->chincpl)
             snroffst += ab->cplfsnroffst;
         for (i = 0; i < ctx->bsi.nfchans; i++)
             snroffst += ab->fsnroffst[i];
@@ -755,7 +755,7 @@
     }
 
     /* perform bit allocation */
-    if ((ab->flags & AC3_AB_CPLINU) && (flags & 64))
+    if (ab->chincpl && (flags & 64))
         do_bit_allocation1(ctx, 5);
     for (i = 0; i < ctx->bsi.nfchans; i++)
         if (flags & (1 << i))
@@ -764,34 +764,123 @@
         do_bit_allocation1(ctx, 6);
 }
 
-static inline float to_float(uint8_t exp, int16_t mantissa)
+typedef struct { /* grouped mantissas for 3-level 5-leve and 11-level quantization */
+    uint8_t gcodesl3[3];
+    uint8_t gcodesl5[3];
+    uint8_t gcodesl11[3];
+    int l3ptr;
+    int l5ptr;
+    int l11ptr;
+} mant_groups;
+
+#define TRANSFORM_COEFF(tc, m, e, f) (tc) = (m) * (f)[(e)]
+
+/* 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.
+ */
+static int get_transform_coeffs_cpling(AC3DecodeContext *ctx, mant_groups *m)
 {
-    return ((float) (mantissa * scale_factors[exp]));
-}
+    ac3_audio_block *ab = &ctx->audio_block;
+    GetBitContext *gb = &ctx->gb;
+    int sbnd, bin, ch, index, gcode;
+    float cplcos[5], cplcoeff;
+    uint8_t *exps = ab->dcplexps;
+    uint8_t *bap = ab->cplbap;
 
-typedef struct { /* grouped mantissas for 3-level 5-leve and 11-level quantization */
-    uint8_t gcodes[3];
-    uint8_t gcptr;
-} mant_group;
+    for (sbnd = ab->cplbegf; sbnd < ab->cplendf + 3; sbnd++) {
+        for (ch = 0; ch < ctx->bsi.nfchans; ch++)
+            cplcos[ch] = ab->chcoeffs[ch] * ab->cplco[ch][sbnd];
+        for (bin = 0; bin < 12; bin++) {
+            index = sbnd * 12 + bin + 37;
+            switch(bap[index]) {
+                case 0:
+                    for (ch = 0; ch < ctx->bsi.nfchans; ctx++)
+                        if (((ab->chincpl) >> ch) & 1) {
+                            if (((ab->dithflag) >> ch) & 1) {
+                                TRANSFORM_COEFF(cplcoeff, dither_int16(&ctx->state), exps[index], scale_factors);
+                                ab->transform_coeffs[ch + 1][index] = cplcoeff * cplcos[ch];
+                            } else
+                                ab->transform_coeffs[ch + 1][index] = 0;
+                        }
+                    continue;
+                case 1:
+                    if (m->l3ptr > 2) {
+                        gcode = get_bits(gb, 5);
+                        if (gcode > 26)
+                            return -1;
+                        m->gcodesl3[0] = gcode / 9;
+                        m->gcodesl3[1] = (gcode % 9) / 3;
+                        m->gcodesl3[2] = (gcode % 9) % 3;
+                        m->l3ptr = 0;
+                    }
+                    TRANSFORM_COEFF(cplcoeff, l3_q_tab[m->gcodesl3[m->l3ptr++]], exps[index], scale_factors);
+                    break;
+
+                case 2:
+                    if (m->l5ptr > 2) {
+                        gcode = get_bits(gb, 7);
+                        if (gcode > 124)
+                            return -1;
+                        m->gcodesl5[0] = gcode / 25;
+                        m->gcodesl5[1] = (gcode % 25) / 5;
+                        m->gcodesl5[2] = (gcode % 25) % 5;
+                        m->l5ptr = 0;
+                    }
+                    TRANSFORM_COEFF(cplcoeff, l5_q_tab[m->gcodesl5[m->l5ptr++]], exps[index], scale_factors);
+                    break;
+
+                case 3:
+                    gcode = get_bits(gb, 3);
+                    if (gcode > 6)
+                        return -1;
+                    TRANSFORM_COEFF(cplcoeff, l7_q_tab[gcode], exps[index], scale_factors);
+                    break;
+
+                case 4:
+                    if (m->l11ptr > 1) {
+                        gcode = get_bits(gb, 7);
+                        if (gcode > 120)
+                            return -1;
+                        m->gcodesl11[0] = gcode / 11;
+                        m->gcodesl11[1] = gcode % 11;
+                        m->l11ptr = 0;
+                    }
+                    TRANSFORM_COEFF(cplcoeff, l11_q_tab[m->gcodesl11[m->l11ptr++]], exps[index], scale_factors);
+                    break;
+
+                case 5:
+                    gcode = get_bits(gb, 4);
+                    if (gcode > 14)
+                        return -1;
+                    TRANSFORM_COEFF(cplcoeff, l15_q_tab[gcode], exps[index], scale_factors);
+                    break;
+
+                default:
+                    TRANSFORM_COEFF(cplcoeff, get_bits(gb, qntztab[bap[index]]) << (16 - qntztab[bap[index]]),
+                            exps[index], scale_factors);
+            }
+            for (ch = 0; ch < ctx->bsi.nfchans; ch++)
+                if (((ab->chincpl) >> ch) & 1)
+                    ab->transform_coeffs[ch][index] = cplcoeff * cplcos[ch];
+        }
+    }
+
+    return 0;
+}
 
 /* Get the transform coefficients for particular channel */
-static int get_transform_coeffs1(uint8_t *exps, uint8_t *bap, float chcoeff,
+static int get_transform_coeffs_ch(uint8_t *exps, uint8_t *bap, float chcoeff,
         float *coeffs, int start, int end, int dith_flag, GetBitContext *gb,
-        dither_state *state)
+        dither_state *state, mant_groups *m)
 {
-    int16_t mantissa;
     int i;
     int gcode;
-    mant_group l3_grp, l5_grp, l11_grp;
+    float factors[25];
 
-    for (i = 0; i < 3; i++)
-        l3_grp.gcodes[i] = l5_grp.gcodes[i] = l11_grp.gcodes[i] = -1;
-    l3_grp.gcptr = l5_grp.gcptr = 3;
-    l11_grp.gcptr = 2;
-
-    i = 0;
-    while (i < start)
-        coeffs[i++] = 0;
+    for (i = 0; i < 25; i++)
+        factors[i] = scale_factors[i] * chcoeff;
 
     for (i = start; i < end; i++) {
         switch (bap[i]) {
@@ -801,173 +890,112 @@
                     continue;
                 }
                 else {
-                    mantissa = dither_int16(state);
-                    coeffs[i] = to_float(exps[i], mantissa) * chcoeff;
+                    TRANSFORM_COEFF(coeffs[i], dither_int16(state), exps[i], factors);
                     continue;
                 }
 
             case 1:
-                if (l3_grp.gcptr > 2) {
+                if (m->l3ptr > 2) {
                     gcode = get_bits(gb, 5);
                     if (gcode > 26)
                         return -1;
-                    l3_grp.gcodes[0] = gcode / 9;
-                    l3_grp.gcodes[1] = (gcode % 9) / 3;
-                    l3_grp.gcodes[2] = (gcode % 9) % 3;
-                    l3_grp.gcptr = 0;
+                    m->gcodesl3[0] = gcode / 9;
+                    m->gcodesl3[1] = (gcode % 9) / 3;
+                    m->gcodesl3[2] = (gcode % 9) % 3;
+                    m->l3ptr = 0;
                 }
-                mantissa = l3_q_tab[l3_grp.gcodes[l3_grp.gcptr++]];
-                coeffs[i] = to_float(exps[i], mantissa) * chcoeff;
+                TRANSFORM_COEFF(coeffs[i], l3_q_tab[m->gcodesl3[m->l3ptr++]], exps[i], factors);
                 continue;
 
             case 2:
-                if (l5_grp.gcptr > 2) {
+                if (m->l5ptr > 2) {
                     gcode = get_bits(gb, 7);
                     if (gcode > 124)
                         return -1;
-                    l5_grp.gcodes[0] = gcode / 25;
-                    l5_grp.gcodes[1] = (gcode % 25) / 5;
-                    l5_grp.gcodes[2] = (gcode % 25) % 5;
-                    l5_grp.gcptr = 0;
+                    m->gcodesl5[0] = gcode / 25;
+                    m->gcodesl5[1] = (gcode % 25) / 5;
+                    m->gcodesl5[2] = (gcode % 25) % 5;
+                    m->l5ptr = 0;
                 }
-                mantissa = l5_q_tab[l5_grp.gcodes[l5_grp.gcptr++]];
-                coeffs[i] = to_float(exps[i], mantissa) * chcoeff;
+                TRANSFORM_COEFF(coeffs[i], l5_q_tab[m->gcodesl5[m->l5ptr++]], exps[i], factors);
                 continue;
 
             case 3:
-                mantissa = get_bits(gb, 3);
-                if (mantissa > 6)
+                gcode = get_bits(gb, 3);
+                if (gcode > 6)
                     return -1;
-                mantissa = l7_q_tab[mantissa];
-                coeffs[i] = to_float(exps[i], mantissa);
+                TRANSFORM_COEFF(coeffs[i], l7_q_tab[gcode], exps[i], factors);
                 continue;
 
             case 4:
-                if (l11_grp.gcptr > 1) {
+                if (m->l11ptr > 1) {
                     gcode = get_bits(gb, 7);
                     if (gcode > 120)
                         return -1;
-                    l11_grp.gcodes[0] = gcode / 11;
-                    l11_grp.gcodes[1] = gcode % 11;
+                    m->gcodesl11[0] = gcode / 11;
+                    m->gcodesl11[1] = gcode % 11;
+                    m->l11ptr = 0;
                 }
-                mantissa = l11_q_tab[l11_grp.gcodes[l11_grp.gcptr++]];
-                coeffs[i] = to_float(exps[i], mantissa) * chcoeff;
+                TRANSFORM_COEFF(coeffs[i], l11_q_tab[m->gcodesl11[m->l11ptr++]], exps[i], factors);
                 continue;
 
             case 5:
-                mantissa = get_bits(gb, 4);
-                if (mantissa > 14)
+                gcode = get_bits(gb, 4);
+                if (gcode > 14)
                     return -1;
-                mantissa = l15_q_tab[mantissa];
-                coeffs[i] = to_float(exps[i], mantissa) * chcoeff;
+                TRANSFORM_COEFF(coeffs[i], l15_q_tab[gcode], exps[i], factors);
                 continue;
 
             default:
-                mantissa = get_bits(gb, qntztab[bap[i]]) << (16 - qntztab[bap[i]]);
-                coeffs[i] = to_float(exps[i], mantissa) * chcoeff;
+                TRANSFORM_COEFF(coeffs[i], get_bits(gb, qntztab[bap[i]]) << (16 - qntztab[bap[i]]), exps[i], factors);
                 continue;
         }
     }
 
-    i = end;
-    while (i < 256)
-        coeffs[i++] = 0;
-
     return 0;
 }
 
-static void uncouple_channels(AC3DecodeContext * ctx)
-{
-    ac3_audio_block *ab = &ctx->audio_block;
-    int ch, sbnd, bin;
-    int index;
-    int16_t mantissa;
-
-    /* uncouple channels */
-    for (ch = 0; ch < ctx->bsi.nfchans; ch++)
-        if (ab->chincpl & (1 << ch))
-            for (sbnd = ab->cplbegf; sbnd < 3 + ab->cplendf; sbnd++)
-                for (bin = 0; bin < 12; bin++) {
-                    index = sbnd * 12 + bin + 37;
-                    ab->transform_coeffs[ch + 1][index] = ab->cplcoeffs[index] * ab->cplco[ch][sbnd] * ab->chcoeffs[ch];
-                    /* generate dither if required */
-                    if (!ab->bap[ch][index] && (ab->chincpl & (1 << ch)) && (ab->dithflag & (1 << ch))) {
-                        mantissa = dither_int16(&ctx->state);
-                        ab->transform_coeffs[ch + 1][index] = to_float(ab->dexps[ch][index], mantissa) * ab->chcoeffs[ch];
-                    }
-                }
-}
-
 static int get_transform_coeffs(AC3DecodeContext * ctx)
 {
-    int i;
+    int i, end;
     ac3_audio_block *ab = &ctx->audio_block;
     int got_cplchan = 0;
     int dithflag = 0;
+    mant_groups m;
+
+    m.l3ptr = m.l5ptr = m.l11ptr = 3;
 
     for (i = 0; i < ctx->bsi.nfchans; i++) {
         dithflag = ab->dithflag & (1 << i);
         /* transform coefficients for individual channel */
-        if (get_transform_coeffs1(ab->dexps[i], ab->bap[i], ab->chcoeffs[i], ab->transform_coeffs[i + 1],
-                    0, ab->endmant[i], dithflag, &ctx->gb, &ctx->state))
+        if (get_transform_coeffs_ch(ab->dexps[i], ab->bap[i], ab->chcoeffs[i], ab->transform_coeffs[i + 1],
+                    0, ab->endmant[i], dithflag, &ctx->gb, &ctx->state, &m))
             return -1;
         /* tranform coefficients for coupling channels */
-        if ((ab->flags & AC3_AB_CPLINU) && (ab->chincpl & (1 << i)) && !got_cplchan) {
-            if (get_transform_coeffs1(ab->dcplexps, ab->cplbap, 1.0f, ab->cplcoeffs,
-                        ab->cplstrtmant, ab->cplendmant, 0, &ctx->gb, &ctx->state))
+        if (((ab->chincpl) >> i & 1))  {
+            if (!got_cplchan) {
+                if (get_transform_coeffs_cpling(ctx, &m))
+                    return -1;
+                got_cplchan = 1;
+            }
+            end = ab->cplendmant;
+        } else
+            end = ab->endmant[i];
+        do
+            ab->transform_coeffs[i + 1][end] = 0;
+        while(++end < 256);
+    }
+    if (ctx->bsi.flags & AC3_BSI_LFEON) {
+        if (get_transform_coeffs_ch(ab->dlfeexps, ab->lfebap, 1.0f, ab->transform_coeffs[0], 0, 7, 0, &ctx->gb, &ctx->state, &m))
                 return -1;
-            got_cplchan = 1;
+        for (i = 7; i < 256; i++) {
+            ab->transform_coeffs[0][i] = 0;
         }
     }
-    if (ctx->bsi.flags & AC3_BSI_LFEON)
-        if (get_transform_coeffs1(ab->dlfeexps, ab->lfebap, 1.0f, ab->transform_coeffs[0], 0, 7, 0, &ctx->gb, &ctx->state))
-                return -1;
-
-    /* uncouple the channels from the coupling channel */
-    if (ab->flags & AC3_AB_CPLINU)
-        uncouple_channels(ctx);
 
     return 0;
 }
 
-/* generate coupling co-ordinates for each coupling subband
- * from coupling co-ordinates of each band and coupling band
- * structure information
- */
-static void generate_coupling_coordinates(AC3DecodeContext * ctx)
-{
-    ac3_audio_block *ab = &ctx->audio_block;
-    uint8_t exp, mstrcplco;
-    int16_t mant;
-    uint32_t cplbndstrc = (1 << ab->ncplsubnd) >> 1;
-    int ch, bnd, sbnd;
-    float cplco;
-
-    if (ab->cplcoe)
-        for (ch = 0; ch < ctx->bsi.nfchans; ch++)
-            if (ab->cplcoe & (1 << ch)) {
-                mstrcplco = 3 * ab->mstrcplco[ch];
-                sbnd = ab->cplbegf;
-                for (bnd = 0; bnd < ab->ncplbnd; bnd++) {
-                    exp = ab->cplcoexp[ch][bnd];
-                    if (exp == 15)
-                        mant = ab->cplcomant[ch][bnd] <<= 14;
-                    else
-                        mant = (ab->cplcomant[ch][bnd] | 0x10) << 13;
-                    cplco = to_float(exp + mstrcplco, mant);
-                    if (ctx->bsi.acmod == 0x02 && (ab->flags & AC3_AB_PHSFLGINU) && ch == 1
-                            && (ab->phsflg & (1 << bnd)))
-                        cplco = -cplco; /* invert the right channel */
-                    ab->cplco[ch][sbnd++] = cplco;
-                    while (cplbndstrc & ab->cplbndstrc) {
-                        cplbndstrc >>= 1;
-                        ab->cplco[ch][sbnd++] = cplco;
-                    }
-                    cplbndstrc >>= 1;
-                }
-            }
-}
-
 static void do_rematrixing1(AC3DecodeContext *ctx, int start, int end)
 {
     float tmp0, tmp1;
@@ -993,7 +1021,7 @@
     if (ab->rematflg & 2)
         do_rematrixing1(ctx, bnd2, bnd3);
     if (ab->rematflg & 4) {
-        if (ab->cplbegf > 0 && ab->cplbegf <= 2 && (ab->flags & AC3_AB_CPLINU))
+        if (ab->cplbegf > 0 && ab->cplbegf <= 2 && (ab->chincpl))
             do_rematrixing1(ctx, bnd3, bndend);
         else {
             do_rematrixing1(ctx, bnd3, bnd4);
@@ -1129,7 +1157,7 @@
 static inline void mix_dualmono_to_mono(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++)
         output[1][i] += output[2][i];
@@ -1140,7 +1168,7 @@
 {
     int i;
     float tmp;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++) {
         tmp = output[1][i] + output[2][i];
@@ -1151,7 +1179,7 @@
 static inline void upmix_mono_to_stereo(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++)
         output[2][i] = output[1][i];
@@ -1160,7 +1188,7 @@
 static inline void mix_stereo_to_mono(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++)
         output[1][i] += output[2][i];
@@ -1170,7 +1198,7 @@
 static inline void mix_3f_to_mono(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++)
         output[1][i] += (output[2][i] + output[3][i]);
@@ -1181,7 +1209,7 @@
 static inline void mix_3f_to_stereo(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++) {
         output[1][i] += output[2][i];
@@ -1193,7 +1221,7 @@
 static inline void mix_2f_1r_to_mono(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++)
         output[1][i] += (output[2][i] + output[3][i]);
@@ -1205,7 +1233,7 @@
 static inline void mix_2f_1r_to_stereo(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++) {
         output[1][i] += output[2][i];
@@ -1217,7 +1245,7 @@
 static inline void mix_2f_1r_to_dolby(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++) {
         output[1][i] -= output[3][i];
@@ -1229,7 +1257,7 @@
 static inline void mix_3f_1r_to_mono(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++)
         output[1][i] = (output[2][i] + output[3][i] + output[4][i]);
@@ -1241,7 +1269,7 @@
 static inline void mix_3f_1r_to_stereo(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++) {
         output[1][i] += (output[2][i] + output[4][i]);
@@ -1254,7 +1282,7 @@
 static inline void mix_3f_1r_to_dolby(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++) {
         output[1][i] += (output[2][i] - output[4][i]);
@@ -1267,7 +1295,7 @@
 static inline void mix_2f_2r_to_mono(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++)
         output[1][i] = (output[2][i] + output[3][i] + output[4][i]);
@@ -1279,7 +1307,7 @@
 static inline void mix_2f_2r_to_stereo(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++) {
         output[1][i] += output[3][i];
@@ -1292,7 +1320,7 @@
 static inline void mix_2f_2r_to_dolby(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++) {
         output[1][i] -= output[3][i];
@@ -1305,7 +1333,7 @@
 static inline void mix_3f_2r_to_mono(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++)
         output[1][i] += (output[2][i] + output[3][i] + output[4][i] + output[5][i]);
@@ -1318,7 +1346,7 @@
 static inline void mix_3f_2r_to_stereo(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++) {
         output[1][i] += (output[2][i] + output[4][i]);
@@ -1332,7 +1360,7 @@
 static inline void mix_3f_2r_to_dolby(AC3DecodeContext *ctx)
 {
     int i;
-    float (*output)[256] = ctx->audio_block.block_output;
+    float (*output)[BLOCK_SIZE] = ctx->audio_block.output;
 
     for (i = 0; i < 256; i++) {
         output[1][i] += (output[2][i] - output[4][i] - output[5][i]);
@@ -1354,7 +1382,7 @@
                 case AC3_OUTPUT_MONO:
                     mix_dualmono_to_mono(ctx);
                     break;
-                case AC3_OUTPUT_STEREO: /* We Assume that sum of both mono channels is requested */
+                case AC3_OUTPUT_STEREO: /* We assume that sum of both mono channels is requested */
                     mix_dualmono_to_stereo(ctx);
                     break;
             }
@@ -1438,6 +1466,79 @@
     }
 }
 
+static void dump_floats(const char *name, int prec, const float *tab, int n)
+{
+    int i;
+
+    av_log(NULL, AV_LOG_INFO, "%s[%d]:\n", name, n);
+    for(i=0;i<n;i++) {
+        if ((i & 7) == 0)
+            av_log(NULL, AV_LOG_INFO, "%4d: ", i);
+        av_log(NULL, AV_LOG_INFO, " %8.*f", prec, tab[i]);
+        if ((i & 7) == 7)
+            av_log(NULL, AV_LOG_INFO, "\n");
+    }
+    if ((i & 7) != 0)
+        av_log(NULL, AV_LOG_INFO, "\n");
+}
+
+static void window_and_de_interleave(float *output)
+{
+    int n2, n4, n8;
+    int k;
+
+    n2 = 512 >> 1;
+    n4 = 512 >> 2;
+    n8 = 512 >> 3;
+
+    for (k = 0; k < n8; k++) {
+        output[2 * k] *= window[2 * k];
+        output[2 * k + 1] *= window[2 * k + 1];
+        output[n4 + 2 * k] *= window[n4 + 2 * k];
+        output[n4 + 2 * k + 1] *= window[n4 + 2 * k + 1];
+        output[n2 + 2 * k] *= window[n2 - 2 * k - 1];
+        output[n2 + 2 * k + 1] *= window[n2 - 2 * k - 2];
+        output[3 * n4 + 2 * k] *= window[n4 -2 * k - 1];
+        output[3 * n4 + 2 * k + 1] *= window[n4 - 2 * k - 2];
+    }
+}
+
+static inline void overlap_and_add(float *tmp_output, float *delay, float *output)
+{
+    int n;
+
+    for (n = 0; n < BLOCK_SIZE; n++) {
+        output[n] = 2 * (tmp_output[n] + delay[n]);
+        delay[n] = tmp_output[BLOCK_SIZE + n];
+    }
+}
+
+
+static inline void do_imdct(AC3DecodeContext *ctx)
+{
+    ac3_audio_block *ab = &ctx->audio_block;
+    int i;
+
+    if (ctx->output & AC3_OUTPUT_LFEON) {
+        av_log(NULL, AV_LOG_INFO, "imdct lfe\n");
+        ff_imdct_calc(&ctx->imdct_ctx_512, ab->tmp_output, ab->transform_coeffs[0], ab->tmp_imdct);
+        window_and_de_interleave(ab->tmp_output);
+        overlap_and_add(ab->tmp_output, ab->delay[0], ab->output[0]);
+    }
+    for (i = 0; i < ctx->bsi.nfchans; i++) {
+        if (!(((ab->blksw) >> i) & 1)) {
+            av_log(NULL, AV_LOG_INFO, "imdct channel %d - block switching not enabled\n", i);
+            ff_imdct_calc(&ctx->imdct_ctx_512, ab->tmp_output, ab->transform_coeffs[i + 1], ab->tmp_imdct);
+            window_and_de_interleave(ab->tmp_output);
+            overlap_and_add(ab->tmp_output, ab->delay[i + 1], ab->output[i + 1]);
+        } else {
+            av_log(NULL, AV_LOG_INFO, "imdct channel %d skipping - block switching enabled\n", i);
+        }
+    }
+}
+
+
+
 static int ac3_parse_audio_block(AC3DecodeContext * ctx, int index)
 {
     ac3_audio_block *ab = &ctx->audio_block;
@@ -1447,8 +1548,9 @@
     GetBitContext *gb = &ctx->gb;
     uint32_t *flags = &ab->flags;
     int bit_alloc_flags = 0;
-    float drange;
+    float drange, tmpco;
     uint8_t *dexps;
+    int mstrcplco, cplcoexp, cplcomant, sbnd, cplbndstrc;
 
     *flags = 0;
     ab->blksw = 0;
@@ -1475,16 +1577,14 @@
         }
     }
     get_downmix_coeffs(ctx);
-    ab->chincpl = 0;
     if (get_bits1(gb)) { /* coupling strategy */
         *flags |= AC3_AB_CPLSTRE;
         ab->cplbndstrc = 0;
+        ab->chincpl = 0;
         if (get_bits1(gb)) { /* coupling in use */
             *flags |= AC3_AB_CPLINU;
             for (i = 0; i < nfchans; i++)
                 ab->chincpl |= get_bits1(gb) << i;
-            if (acmod == 0x00 || acmod == 0x01)
-                return -1; /* coupling needs atleast two shared channels */
             if (acmod == 0x02)
                 if (get_bits1(gb)) /* phase flag in use */
                     *flags |= AC3_AB_PHSFLGINU;
@@ -1494,7 +1594,7 @@
                 return -1;
             ab->ncplbnd = ab->ncplsubnd = 3 + ab->cplendf - ab->cplbegf;
             ab->cplstrtmant = ab->cplbegf * 12 + 37;
-            ab->cplendmant = ((ab->cplendf + 3) * 12) + 37;
+            ab->cplendmant = ab->cplendf * 12 + 73;
             for (i = 0; i < ab->ncplsubnd - 1; i++) /* coupling band structure */
                 if (get_bits1(gb)) {
                     ab->cplbndstrc |= 1 << i;
@@ -1502,43 +1602,72 @@
                 }
         }
     }
-    if (*flags & AC3_AB_CPLINU) {
+    if (ab->chincpl) {
         ab->cplcoe = 0;
         for (i = 0; i < nfchans; i++)
-            if (ab->chincpl & (1 << i))
+            if ((ab->chincpl) >> i & 1)
                 if (get_bits1(gb)) { /* coupling co-ordinates */
                     ab->cplcoe |= 1 << i;
-                    ab->mstrcplco[i] = get_bits(gb, 2);
+                    mstrcplco = 3 * get_bits(gb, 2);
+                    sbnd = ab->cplbegf;
+                    cplbndstrc = ab->cplbndstrc;
                     for (bnd = 0; bnd < ab->ncplbnd; bnd++) {
-                        ab->cplcoexp[i][bnd] = get_bits(gb, 4);
-                        ab->cplcomant[i][bnd] = get_bits(gb, 4);
+                        cplcoexp = get_bits(gb, 4);
+                        cplcomant = get_bits(gb, 4);
+                        if (cplcoexp == 15)
+                            cplcomant <<= 14;
+                        else
+                            cplcomant = (cplcomant | 0x10) << 13;
+                        tmpco = ab->cplco[i][sbnd++] = cplcomant * scale_factors[cplcoexp + mstrcplco];
+                        while (cplbndstrc & 1) {
+                            ab->cplco[i][sbnd++] = tmpco;
+                            cplbndstrc >>= 1;
+                        }
+                        cplbndstrc >>= 1;
                     }
                 }
         ab->phsflg = 0;
         if ((acmod == 0x02) && (*flags & AC3_AB_PHSFLGINU) && (ab->cplcoe & 1 || ab->cplcoe & (1 << 1))) {
+            sbnd = ab->cplbegf;
+            cplbndstrc = ab->cplbndstrc;
             for (bnd = 0; bnd < ab->ncplbnd; bnd++)
-                if (get_bits1(gb))
+                if (get_bits1(gb)) {
                     ab->phsflg |= 1 << bnd;
+                    ab->cplco[1][sbnd] = -ab->cplco[1][sbnd];
+                    sbnd++;
+                    while (cplbndstrc & 1) {
+                        ab->cplco[1][sbnd] = -ab->cplco[1][sbnd];
+                        sbnd++;
+                        cplbndstrc >>= 1;
+                    }
+                    cplbndstrc >>= 1;
+                } else {
+                    sbnd++;
+                    while (cplbndstrc & 1) {
+                        sbnd++;
+                        cplbndstrc >>= 1;
+                    }
+                    cplbndstrc >>= 1;
+                }
         }
     }
-    generate_coupling_coordinates(ctx);
     ab->rematflg = 0;
     if (acmod == 0x02) /* rematrixing */
         if (get_bits1(gb)) {
             *flags |= AC3_AB_REMATSTR;
-            if (!(*flags & AC3_AB_CPLINU) || ab->cplbegf > 2)
+            if (!(ab->chincpl) || ab->cplbegf > 2)
                 for (rbnd = 0; rbnd < 4; rbnd++)
                     ab->rematflg |= get_bits1(gb) << rbnd;
-            if (ab->cplbegf > 0 && ab->cplbegf <= 2 && (*flags & AC3_AB_CPLINU))
+            if (ab->cplbegf > 0 && ab->cplbegf <= 2 && (ab->chincpl))
                 for (rbnd = 0; rbnd < 3; rbnd++)
                     ab->rematflg |= get_bits1(gb) << rbnd;
-            if (ab->cplbegf == 0 && (*flags & AC3_AB_CPLINU))
+            if (ab->cplbegf == 0 && (ab->chincpl))
                 for (rbnd = 0; rbnd < 2; rbnd++)
                     ab->rematflg |= get_bits1(gb) << rbnd;
         }
     ab->cplexpstr = AC3_EXPSTR_REUSE;
     ab->lfeexpstr = AC3_EXPSTR_REUSE;
-    if (*flags & AC3_AB_CPLINU) /* coupling exponent strategy */
+    if (ab->chincpl) /* coupling exponent strategy */
         ab->cplexpstr = get_bits(gb, 2);
     for (i = 0; i < nfchans; i++) /* channel exponent strategy */
         ab->chexpstr[i] = get_bits(gb, 2);
@@ -1546,27 +1675,27 @@
         ab->lfeexpstr = get_bits1(gb);
     for (i = 0; i < nfchans; i++) /* channel bandwidth code */
         if (ab->chexpstr[i] != AC3_EXPSTR_REUSE) {
-            if ((ab->chincpl & (1 << i)))
+            if (((ab->chincpl) >> i) & 1)  {
                 ab->endmant[i] = ab->cplstrtmant;
+            }
             else {
                 ab->chbwcod[i] = get_bits(gb, 6);
                 if (ab->chbwcod[i] > 60) {
                     av_log(NULL, AV_LOG_ERROR, "chbwcod = %d > 60", ab->chbwcod[i]);
                     return -1;
                 }
-                ab->endmant[i] = ((ab->chbwcod[i] + 12) * 3) + 37;
+                ab->endmant[i] = ab->chbwcod[i] * 3 + 73;
             }
         }
-    if (*flags & AC3_AB_CPLINU)
-        if (ab->cplexpstr != AC3_EXPSTR_REUSE) {/* coupling exponents */
-            bit_alloc_flags |= 64;
-            ab->cplabsexp = get_bits(gb, 4) << 1;
-            ab->ncplgrps = (ab->cplendmant - ab->cplstrtmant) / (3 << (ab->cplexpstr - 1));
-            if (decode_exponents(gb, ab->cplexpstr, ab->ncplgrps, ab->cplabsexp, ab->dcplexps + ab->cplstrtmant)) {
-                    av_log(NULL, AV_LOG_ERROR, "error decoding coupling exponents\n");
-                    return -1;
-            }
+    if (ab->cplexpstr != AC3_EXPSTR_REUSE) {/* coupling exponents */
+        bit_alloc_flags |= 64;
+        ab->cplabsexp = get_bits(gb, 4) << 1;
+        ab->ncplgrps = (ab->cplendmant - ab->cplstrtmant) / (3 << (ab->cplexpstr - 1));
+        if (decode_exponents(gb, ab->cplexpstr, ab->ncplgrps, ab->cplabsexp, ab->dcplexps + ab->cplstrtmant)) {
+            av_log(NULL, AV_LOG_ERROR, "error decoding coupling exponents\n");
+            return -1;
         }
+    }
     for (i = 0; i < nfchans; i++) /* fbw channel exponents */
         if (ab->chexpstr[i] != AC3_EXPSTR_REUSE) {
             bit_alloc_flags |= 1 << i;
@@ -1580,15 +1709,14 @@
             }
             ab->gainrng[i] = get_bits(gb, 2);
         }
-    if (ctx->bsi.flags & AC3_BSI_LFEON) /* lfe exponents */
-        if (ab->lfeexpstr != AC3_EXPSTR_REUSE) {
-            bit_alloc_flags |= 32;
-            ab->dlfeexps[0] = get_bits(gb, 4);
-            if (decode_exponents(gb, ab->lfeexpstr, 2, ab->dlfeexps[0], ab->dlfeexps + 1)) {
-                av_log(NULL, AV_LOG_ERROR, "error decoding lfe exponents\n");
-                return -1;
-            }
+    if (ab->lfeexpstr != AC3_EXPSTR_REUSE) { /* lfe exponents */
+        bit_alloc_flags |= 32;
+        ab->dlfeexps[0] = get_bits(gb, 4);
+        if (decode_exponents(gb, ab->lfeexpstr, 2, ab->dlfeexps[0], ab->dlfeexps + 1)) {
+            av_log(NULL, AV_LOG_ERROR, "error decoding lfe exponents\n");
+            return -1;
         }
+    }
 
     if (get_bits1(gb)) { /* bit allocation information */
         *flags |= AC3_AB_BAIE;
@@ -1603,7 +1731,7 @@
         *flags |= AC3_AB_SNROFFSTE;
         bit_alloc_flags |= 127;
         ab->csnroffst = get_bits(gb, 6);
-        if (*flags & AC3_AB_CPLINU) { /* couling fine snr offset and fast gain code */
+        if (ab->chincpl) { /* couling fine snr offset and fast gain code */
             ab->cplfsnroffst = get_bits(gb, 4);
             ab->cplfgaincod = get_bits(gb, 3);
         }
@@ -1616,17 +1744,20 @@
             ab->lfefgaincod = get_bits(gb, 3);
         }
     }
-    if (*flags & AC3_AB_CPLINU)
+    if (ab->chincpl)
         if (get_bits1(gb)) { /* coupling leak information */
             bit_alloc_flags |= 64;
             *flags |= AC3_AB_CPLLEAKE;
             ab->cplfleak = get_bits(gb, 3);
             ab->cplsleak = get_bits(gb, 3);
         }
+    ab->cpldeltbae = AC3_DBASTR_RESERVED;
+    for (i = 0; i < nfchans; i++)
+        ab->deltbae[i] = AC3_DBASTR_RESERVED;
     if (get_bits1(gb)) { /* delta bit allocation information */
         *flags |= AC3_AB_DELTBAIE;
         bit_alloc_flags |= 127;
-        if (*flags & AC3_AB_CPLINU) {
+        if (ab->chincpl) {
             ab->cpldeltbae = get_bits(gb, 2);
             if (ab->cpldeltbae == AC3_DBASTR_RESERVED) {
                 av_log(NULL, AV_LOG_ERROR, "coupling delta bit allocation strategy reserved\n");
@@ -1640,7 +1771,7 @@
                 return -1;
             }
         }
-        if (*flags & AC3_AB_CPLINU)
+        if (ab->chincpl)
             if (ab->cpldeltbae == AC3_DBASTR_NEW) { /*coupling delta offset, len and bit allocation */
                 ab->cpldeltnseg = get_bits(gb, 3);
                 for (seg = 0; seg <= ab->cpldeltnseg; seg++) {
@@ -1661,11 +1792,10 @@
     }
 
     do_bit_allocation (ctx, bit_alloc_flags); /* perform the bit allocation */
-
     if (get_bits1(gb)) { /* unused dummy data */
         *flags |= AC3_AB_SKIPLE;
         ab->skipl = get_bits(gb, 9);
-        for (i = 0; i < ab->skipl; i++)
+        while(ab->skipl--)
             skip_bits(gb, 8);
     }
     /* unpack the transform coefficients
@@ -1675,22 +1805,50 @@
         av_log(NULL, AV_LOG_ERROR, "Error in routine get_transform_coeffs\n");
         return -1;
     }
+    /*for (i = 0; i < nfchans; i++)
+        dump_floats("channel transform coefficients", 10, ab->transform_coeffs[i + 1], BLOCK_SIZE);*/
+
     /* recover coefficients if rematrixing is in use */
     if (*flags & AC3_AB_REMATSTR)
         do_rematrixing(ctx);
 
+    do_imdct(ctx);
+    for(i = 0; i < nfchans; i++)
+        dump_floats("channel output", 10, ab->output[i + 1], BLOCK_SIZE);
+
+    do_downmix(ctx);
+
     return 0;
 }
 
+/* from FreeSWITCH Modular Media Switching Library */
+#define NORMFACT    (float)0x8000
+#define MAXSAMPLE   (float)0x7fff
+
+
+static inline int16_t convert(float f)
+{
+    short s;
+    f = f * NORMFACT;
+    if (f >= 0)
+        s = (short)(f + 0.5);
+    else
+        s = (short)(f - 0.5);
+    if ((float)s > MAXSAMPLE)
+        s = (float)MAXSAMPLE;
+    if (s < (short) -MAXSAMPLE)
+        s = (short) -MAXSAMPLE;
+
+    return s;
+}
+
 static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size, uint8_t *buf, int buf_size)
 {
     AC3DecodeContext *ctx = (AC3DecodeContext *)avctx->priv_data;
     ac3_audio_block *ab = &ctx->audio_block;
     int frame_start;
-    int i, j, k, l, value;
-    float tmp_block_first_half[128], tmp_block_second_half[128];
     int16_t *out_samples = (int16_t *)data;
-    int nfchans;
+    int i, j, k, value;
 
     //Synchronize the frame.
     frame_start = ac3_synchronize(buf, buf_size);
@@ -1708,7 +1866,7 @@
     if (!ac3_parse_sync_info(ctx)) {
         av_log(avctx, AV_LOG_ERROR, "\n");
         *data_size = 0;
-        return -1;
+        return buf_size;
     }
 
     //Check for the errors.
@@ -1719,101 +1877,49 @@
 
     //Parse the BSI.
     //If 'bsid' is not valid decoder shall not decode the audio as per the standard.
-    if (ac3_parse_bsi(ctx)) {
-        av_log(avctx, AV_LOG_ERROR, "bsid is not valid\n");
-        *data_size = 0;
-        return -1;
-    }
+    ac3_parse_bsi(ctx);
 
-    for (i = 0; i < MAX_BLOCKS; i++)
-        memset(ctx->delay[i], 0, sizeof(ctx->delay[i]));
     avctx->sample_rate = ctx->sync_info.sampling_rate;
     avctx->bit_rate = ctx->sync_info.bit_rate;
     if (avctx->channels == 0) {
-        //avctx->channels = ctx->bsi.nfchans + ((ctx->bsi.flags & AC3_BSI_LFEON) ? 1 : 0);
-        ctx->output = AC3_OUTPUT_UNMODIFIED;
-    }
-    else if ((ctx->bsi.nfchans + ((ctx->bsi.flags & AC3_BSI_LFEON) ? 1 : 0)) < avctx->channels) {
+        ctx->output |= AC3_OUTPUT_UNMODIFIED;
+        avctx->channels = ctx->bsi.nfchans;
+    } else if ((ctx->bsi.nfchans + ((ctx->bsi.flags & AC3_BSI_LFEON) ? 1 : 0)) < avctx->channels) {
         av_log(avctx, AV_LOG_INFO, "ac3_decoder: AC3 Source Channels Are Less Then Specified %d: Output to %d Channels\n",
                 avctx->channels, (ctx->bsi.nfchans + ((ctx->bsi.flags & AC3_BSI_LFEON) ? 1 : 0)));
-        //avctx->channels = ctx->bsi.nfchans + ((ctx->bsi.flags & AC3_BSI_LFEON) ? 1 : 0);
-        ctx->output = AC3_OUTPUT_UNMODIFIED;
-    }
-    else if (avctx->channels == 1) {
-        ctx->output = AC3_OUTPUT_MONO;
+        avctx->channels = ctx->bsi.nfchans;
+        ctx->output |= AC3_OUTPUT_UNMODIFIED;
+    } else if (avctx->channels == 1) {
+        ctx->output |= AC3_OUTPUT_MONO;
     } else if (avctx->channels == 2) {
         if (ctx->bsi.dsurmod == 0x02)
-            ctx->output = AC3_OUTPUT_DOLBY;
+            ctx->output |= AC3_OUTPUT_DOLBY;
         else
-            ctx->output = AC3_OUTPUT_STEREO;
+            ctx->output |= AC3_OUTPUT_STEREO;
+    }
+    if (ctx->bsi.flags & AC3_BSI_LFEON) {
+        avctx->channels++;
+        ctx->output |= AC3_OUTPUT_LFEON;
     }
 
-
-    av_log(avctx, AV_LOG_INFO, "channels = %d \t bit rate = %d \t sampling rate = %d \n", avctx->channels, avctx->sample_rate, avctx->bit_rate);
+    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.
-    *data_size = 0;
-    for (i = 0; i < 6; i++) {
+    for (i = 0; i < AUDIO_BLOCKS; i++) {
         if (ac3_parse_audio_block(ctx, i)) {
             av_log(avctx, AV_LOG_ERROR, "error parsing the audio block\n");
             *data_size = 0;
-            return -1;
-        }
-
-        av_log(NULL, AV_LOG_INFO, "doing imdct\n");
-
-        if (ctx->bsi.flags & AC3_BSI_LFEON) {
-            ff_imdct_calc(&ctx->imdct_ctx_512, ctx->tmp_output, ab->transform_coeffs[0], ctx->tmp_imdct);
-            for (l = 0; l < 256; l++)
-                ab->block_output[0][l] = ctx->tmp_output[l] * window[l] + ctx->delay[0][l] * window[255 -l];
-            memcpy(ctx->delay[0], ctx->tmp_output + 256, sizeof(ctx->delay[0]));
+            return ctx->sync_info.framesize;
         }
-
-        for (j = 0; j < ctx->bsi.nfchans; j++) {
-            if (ctx->audio_block.blksw & (1 << j)) {
-                for (k = 0; k < 128; k++) {
-                    tmp_block_first_half[k] = ab->transform_coeffs[j + 1][2 * k];
-                    tmp_block_second_half[k] = ab->transform_coeffs[j + 1][2 * k + 1];
-                }
-                ff_imdct_calc(&ctx->imdct_ctx_256, ctx->tmp_output, tmp_block_first_half, ctx->tmp_imdct);
-                for (l = 0; l < 256; l++)
-                    ab->block_output[j + 1][l] = ctx->tmp_output[l] * window[l] + ctx->delay[j + 1][l] * window[255 - l];
-                ff_imdct_calc(&ctx->imdct_ctx_256, ctx->delay[j + 1], tmp_block_second_half, ctx->tmp_imdct);
-            } else {
-                ff_imdct_calc(&ctx->imdct_ctx_512, ctx->tmp_output, ab->transform_coeffs[j + 1], ctx->tmp_imdct);
-                for (l = 0; l < 256; l++)
-                    ab->block_output[j + 1][l] = ctx->tmp_output[l] * window[l] + ctx->delay[j + 1][l] * window[255 - l];
-                memcpy(ctx->delay[j + 1], ctx->tmp_output + 256, sizeof(ctx->delay[j + 1]));
+        j = ((ctx->output & AC3_OUTPUT_LFEON) ? 0 : 1);
+        for (;j < avctx->channels; j++) {
+            for(k = 0; k < BLOCK_SIZE; k++) {
+                value = convert(ab->output[j][k]);
+                *(out_samples++) = value;
             }
         }
-        if (ctx->bsi.flags & AC3_BSI_LFEON) {
-            for (l = 0; l < 256; l++) {
-                value = lrint(ab->block_output[0][l]);
-                if (value < -32768)
-                    value = -32768;
-                else if (value > 32767)
-                    value = 32767;
-                *(out_samples++) = value;
-            }
-            *data_size += 256 * sizeof(int16_t);
-        }
-        do_downmix(ctx);
-        if (ctx->output == AC3_OUTPUT_UNMODIFIED)
-            nfchans = ctx->bsi.nfchans;
-        else
-            nfchans = avctx->channels;
-        for (k = 0; k < nfchans; k++)
-            for (l = 0; l < 256; l++) {
-                value = lrint(ab->block_output[k + 1][l]);
-                if (value < -32768)
-                    value = -32768;
-                else if (value > 32767)
-                    value = 32767;
-                *(out_samples++) = value;
-            }
-        *data_size += nfchans * 256 * sizeof (int16_t);
     }
-
+    *data_size = AUDIO_BLOCKS * BLOCK_SIZE * avctx->channels * sizeof (int16_t);
     return ctx->sync_info.framesize;
 }