changeset 5311:7742d5411c9d libavcodec

AC-3 decoder, soc revision 48, Aug 16 11:27:49 2006 UTC by cloud9 I realized that the bug was not in the imdct routine but in the get_transform_coeffs. Fixed it. Code now uses the ffmpeg's imdct routines. All the mplayer's ac3 samples are decoded successfully. Also improved downmixing. Now all the downmixing coeffcients for channels are normalized such that the sum of coefficients used to construct the output for single channel never exceeds 1.0.
author jbr
date Sat, 14 Jul 2007 15:58:42 +0000
parents 9aa9197034d7
children 2c875e6274d5
files ac3dec.c
diffstat 1 files changed, 141 insertions(+), 173 deletions(-) [+]
line wrap: on
line diff
--- a/ac3dec.c	Sat Jul 14 15:57:51 2007 +0000
+++ b/ac3dec.c	Sat Jul 14 15:58:42 2007 +0000
@@ -34,6 +34,7 @@
 #include "avutil.h"
 #include "common.h"
 #include "math.h"
+#include "crc.h"
 
 #define N 512   /* constant for IMDCT Block size */
 
@@ -158,8 +159,8 @@
     DECLARE_ALIGNED_16(float, transform_coeffs[MAX_CHANNELS][BLOCK_SIZE]);
 
     /* For IMDCT. */
-    FFTContext fft_64;  //N/8 point IFFT context
-    FFTContext fft_128; //N/4 point IFFT context
+    MDCTContext imdct_512;  //N/8 point IFFT context
+    MDCTContext imdct_256;  //N/4 point IFFT context
     DECLARE_ALIGNED_16(float, output[MAX_CHANNELS][BLOCK_SIZE]);
     DECLARE_ALIGNED_16(float, delay[MAX_CHANNELS][BLOCK_SIZE]);
     DECLARE_ALIGNED_16(float, tmp_imdct[BLOCK_SIZE]);
@@ -398,8 +399,8 @@
     AC3DecodeContext *ctx = avctx->priv_data;
 
     ac3_tables_init();
-    ff_fft_init(&ctx->fft_64, 6, 1);
-    ff_fft_init(&ctx->fft_128, 7, 1);
+    ff_mdct_init(&ctx->imdct_256, 8, 1);
+    ff_mdct_init(&ctx->imdct_512, 9, 1);
     dither_seed(&ctx->dith_state, 0);
 
     return 0;
@@ -838,9 +839,9 @@
                 case 0:
                     for (ch = 0; ch < ctx->nfchans; ch++)
                         if (((ctx->chincpl) >> ch) & 1) {
-                            if (!(((ctx->dithflag) >> ch) & 1)) {
+                            if ((ctx->dithflag >> ch) & 1) {
                                 TRANSFORM_COEFF(cplcoeff, dither_int16(&ctx->dith_state), exps[start], scale_factors);
-                                ctx->transform_coeffs[ch + 1][start] = cplcoeff * cplcos[ch];
+                                ctx->transform_coeffs[ch + 1][start] = cplcoeff * cplcos[ch] * LEVEL_MINUS_3DB;
                             } else
                                 ctx->transform_coeffs[ch + 1][start] = 0;
                         }
@@ -887,7 +888,7 @@
                     break;
 
                 default:
-                    TRANSFORM_COEFF(cplcoeff, get_bits(gb, qntztab[tbap]) << (16 - qntztab[tbap]),
+                    TRANSFORM_COEFF(cplcoeff, get_sbits(gb, qntztab[tbap]) << (16 - qntztab[tbap]),
                             exps[start], scale_factors);
             }
             for (ch = 0; ch < ctx->nfchans; ch++)
@@ -932,13 +933,13 @@
         tbap = bap[i];
         switch (tbap) {
             case 0:
-                if (dithflag) {
+                if (!dithflag) {
                     coeffs[i] = 0;
                     continue;
                 }
                 else {
                     TRANSFORM_COEFF(coeffs[i], dither_int16(&ctx->dith_state), exps[i], factors);
-                    coeffs[i] *= LEVEL_PLUS_3DB;
+                    coeffs[i] *= LEVEL_MINUS_3DB;
                     continue;
                 }
 
@@ -983,7 +984,7 @@
                 continue;
 
             default:
-                TRANSFORM_COEFF(coeffs[i], get_bits(gb, qntztab[tbap]) << (16 - qntztab[tbap]), exps[i], factors);
+                TRANSFORM_COEFF(coeffs[i], get_sbits(gb, qntztab[tbap]) << (16 - qntztab[tbap]), exps[i], factors);
                 continue;
         }
     }
@@ -1075,6 +1076,7 @@
     int to = ctx->blkoutput;
     float clev = clevs[ctx->cmixlev];
     float slev = slevs[ctx->surmixlev];
+    float nf = 1.0; //normalization factor for downmix coeffs
 
     if (to == AC3_OUTPUT_UNMODIFIED)
         return;
@@ -1084,107 +1086,142 @@
             switch (to) {
                 case AC3_OUTPUT_MONO:
                 case AC3_OUTPUT_STEREO: /* We Assume that sum of both mono channels is requested */
-                    ctx->chcoeffs[0] *= LEVEL_MINUS_6DB;
-                    ctx->chcoeffs[1] *= LEVEL_MINUS_6DB;
+                    nf = 0.5;
+                    ctx->chcoeffs[0] *= nf;
+                    ctx->chcoeffs[1] *= nf;
                     break;
             }
             break;
         case AC3_INPUT_MONO:
             switch (to) {
                 case AC3_OUTPUT_STEREO:
-                    ctx->chcoeffs[0] *= LEVEL_MINUS_3DB;
+                    nf = LEVEL_MINUS_3DB;
+                    ctx->chcoeffs[0] *= nf;
                     break;
             }
             break;
         case AC3_INPUT_STEREO:
             switch (to) {
                 case AC3_OUTPUT_MONO:
-                    ctx->chcoeffs[0] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[1] *= LEVEL_MINUS_3DB;
+                    nf = LEVEL_MINUS_3DB;
+                    ctx->chcoeffs[0] *= nf;
+                    ctx->chcoeffs[1] *= nf;
                     break;
             }
             break;
         case AC3_INPUT_3F:
             switch (to) {
                 case AC3_OUTPUT_MONO:
-                    ctx->chcoeffs[0] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[2] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[1] *= (clev * LEVEL_PLUS_3DB);
+                    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:
-                    ctx->chcoeffs[1] *= clev;
+                    nf = 1.0 / (1.0 + clev);
+                    ctx->chcoeffs[0] *= nf;
+                    ctx->chcoeffs[2] *= nf;
+                    ctx->chcoeffs[1] *= (nf * clev);
                     break;
             }
             break;
         case AC3_INPUT_2F_1R:
             switch (to) {
                 case AC3_OUTPUT_MONO:
-                    ctx->chcoeffs[0] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[1] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[2] *= slev * LEVEL_MINUS_3DB;
+                    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:
-                    ctx->chcoeffs[2] *= slev * LEVEL_MINUS_3DB;
+                    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:
-                    ctx->chcoeffs[2] *= LEVEL_MINUS_3DB;
+                    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_INPUT_3F_1R:
             switch (to) {
                 case AC3_OUTPUT_MONO:
-                    ctx->chcoeffs[0] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[2] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[1] *= clev * LEVEL_PLUS_3DB;
-                    ctx->chcoeffs[3] *= slev * LEVEL_MINUS_3DB;
+                    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:
-                    ctx->chcoeffs[1] *= clev;
-                    ctx->chcoeffs[3] *= slev * LEVEL_MINUS_3DB;
+                    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:
-                    ctx->chcoeffs[1] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[3] *= LEVEL_MINUS_3DB;
+                    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_INPUT_2F_2R:
             switch (to) {
                 case AC3_OUTPUT_MONO:
-                    ctx->chcoeffs[0] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[1] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[2] *= slev * LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[3] *= slev * LEVEL_MINUS_3DB;
+                    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:
-                    ctx->chcoeffs[2] *= slev;
-                    ctx->chcoeffs[3] *= slev;
+                    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:
-                    ctx->chcoeffs[2] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[3] *= LEVEL_MINUS_3DB;
+                    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_INPUT_3F_2R:
             switch (to) {
                 case AC3_OUTPUT_MONO:
-                    ctx->chcoeffs[0] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[2] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[1] *= clev * LEVEL_PLUS_3DB;
-                    ctx->chcoeffs[3] *= slev * LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[4] *= slev * LEVEL_MINUS_3DB;
+                    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:
-                    ctx->chcoeffs[1] *= clev;
-                    ctx->chcoeffs[3] *= slev;
-                    ctx->chcoeffs[4] *= slev;
+                    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:
-                    ctx->chcoeffs[1] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[3] *= LEVEL_MINUS_3DB;
-                    ctx->chcoeffs[4] *= LEVEL_MINUS_3DB;
+                    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;
@@ -1529,102 +1566,39 @@
     (pim) = _are * _bim + _aim * _bre;\
 }
 
-static void do_imdct_256(FFTContext *fft_ctx, float *coeffs, float *output,
-        float *delay, float *tmp_imdct, float *tmp_output)
+static void do_imdct_256(AC3DecodeContext *ctx, int chindex)
 {
-    int k, n2, n4, n8;
+    int k;
     float x1[128], x2[128];
-    FFTComplex *z1 = (FFTComplex *)tmp_imdct;
-    FFTComplex *z2 = (FFTComplex *)(tmp_imdct +  128);
 
-    n2 = N / 2;
-    n4 = N / 4;
-    n8 = N / 8;
-
-    for (k = 0; k < n4; k++) {
-        x1[k] = coeffs[2 * k];
-        x2[k] = coeffs[2 * k + 1];
-    }
-
-    /* Pre IFFT Complex Multiply Step. */
-    for (k = 0; k < n8; k++) {
-        CMUL(z1[k].re, z1[k].im, x1[n4 - 2 * k - 1], x1[2 * k], x_cos2[k], x_sin2[k]);
-        CMUL(z2[k].re, z2[k].im, x2[n4 - 2 * k - 1], x2[2 * k], x_cos2[k], x_sin2[k]);
+    for (k = 0; k < N / 4; k++) {
+        x1[k] = ctx->transform_coeffs[chindex][2 * k];
+        x2[k] = ctx->transform_coeffs[chindex][2 * k + 1];
     }
 
-    /* N/8 pointe complex IFFT. */
-    ff_fft_permute(fft_ctx, z1);
-    ff_fft_calc(fft_ctx, z1);
-    ff_fft_permute(fft_ctx, z2);
-    ff_fft_calc(fft_ctx, z2);
-
-
-    /* Post IFFT Complex Multiply Step. */
-    for (k = 0; k < n8; k++) {
-        CMUL(z1[k].re, z1[k].im, z1[k].re, z1[k].im, x_cos2[k], x_sin2[k]);
-        CMUL(z2[k].re, z2[k].im, z2[k].re, z2[k].im, x_cos2[k], x_sin2[k]);
-    }
+    ff_imdct_calc(&ctx->imdct_256, ctx->tmp_output, x1, ctx->tmp_imdct);
+    ff_imdct_calc(&ctx->imdct_256, ctx->tmp_output + 256, x2, ctx->tmp_imdct);
 
-    /* Windowing and de-interleaving step. */
-    for (k = 0; k < n8; k++) {
-        tmp_output[2 * k] = -z1[k].im * window[2 * k];
-        tmp_output[2 * k + 1] = z1[n8 - k - 1].re * window[2 * k + 1];
-        tmp_output[n4 + 2 * k] = -z1[k].re * window[n4 + 2 * k];
-        tmp_output[n4 + 2 * k + 1] = z1[n8 - k - 1].im * window[n4 + 2 * k + 1];
-        tmp_output[n2 + 2 * k] = -z2[k].re * window[n2 - 2 * k - 1];
-        tmp_output[n2 + 2* k + 1] = z2[n8 - k - 1].im * window[n2 - 2 * k - 2];
-        tmp_output[3 * n4 + 2 * k] = z2[k].im * window[n4 - 2 * k - 1] ;
-        tmp_output[3 * n4 + 2 * k + 1] = -z2[n8 - k - 1].re * window[n4 - 2 * k - 2] ;
-    }
-
-    /* Overlap and add step. */
-    for (k = 0; k < n2; k++) {
-        output[k] = 2 * (tmp_output[k] + delay[k]);
-        delay[k] = tmp_output[n2 + k];
+    for (k = 0; k < N / 2; k++) {
+        ctx->output[chindex][k] = ctx->tmp_output[k] * window[k] + ctx->delay[chindex][k];
+        //dump_floats("samples", 10, ctx->output[chindex], 256);
+        ctx->delay[chindex][k] = ctx->tmp_output[N / 2 + k] * window[255 - k];
     }
 }
 
-static void do_imdct_512(FFTContext *fft_ctx, float *coeffs, float *output,
-        float *delay, float *tmp_imdct, float *tmp_output)
+static void do_imdct_512(AC3DecodeContext *ctx, int chindex)
 {
-    int k, n2, n4, n8;
-    FFTComplex *z = (FFTComplex *)tmp_imdct;
-
-    n2 = N / 2;
-    n4 = N / 4;
-    n8 = N / 8;
-
-
-    /* Pre IFFT Complex Multiply Step. */
-    for (k = 0; k < n4; k++)
-        CMUL(z[k].re, z[k].im, coeffs[n2 - 2 * k - 1], coeffs[2 * k], x_cos1[k], x_sin1[k]);
-
-    /* Permutation needed before calling ff_fft_calc. */
-    ff_fft_permute(fft_ctx, z);
-
-    /* N/4 pointe complex IFFT. */
-    ff_fft_calc(fft_ctx, z);
+    int k;
 
-    /* Post IFFT Complex Multiply Step. */
-    for (k = 0; k < n4; k++)
-        CMUL(z[k].re, z[k].im, z[k].re, z[k].im, x_cos1[k], x_sin1[k]);
+    ff_imdct_calc(&ctx->imdct_512, ctx->tmp_output,
+            ctx->transform_coeffs[chindex], ctx->tmp_imdct);
+    //ff_imdct_calc_ac3_512(&ctx->imdct_512, ctx->tmp_output, ctx->transform_coeffs[chindex],
+    //        ctx->tmp_imdct, window);
 
-    /* Windowing and de-interleaving step. */
-    for (k = 0; k < n8; k++) {
-        tmp_output[2 * k] = -z[n8 + k].im * window[2 * k];
-        tmp_output[2 * k + 1] = z[n8 - k - 1].re * window[2 * k + 1];
-        tmp_output[n4 + 2 * k] = -z[k].re * window[n4 + 2 * k];
-        tmp_output[n4 + 2 * k + 1] = z[n4 - k - 1].im * window[n4 + 2 * k + 1];
-        tmp_output[n2 + 2 * k] = -z[n8 + k].re * window[n2 - 2 * k - 1];
-        tmp_output[n2 + 2* k + 1] = z[n8 - k - 1].im * window[n2 - 2 * k - 2];
-        tmp_output[3 * n4 + 2 * k] = z[k].im * window[n4 - 2 * k - 1] ;
-        tmp_output[3 * n4 + 2 * k + 1] = -z[n4 - k - 1].re * window[n4 - 2 * k - 2] ;
-    }
-
-    /* Overlap and add step. */
-    for (k = 0; k < n2; k++) {
-        output[k] = 2 * (tmp_output[k] + delay[k]);
-        delay[k] = tmp_output[n2 + k];
+    for (k = 0; k < N / 2; k++) {
+        ctx->output[chindex][k] = ctx->tmp_output[k] * window[k] + ctx->delay[chindex][k];
+        //dump_floats("samples", 10, ctx->output[chindex], 256);
+        ctx->delay[chindex][k] = ctx->tmp_output[N / 2 + k] * window[255 - k];
     }
 }
 
@@ -1633,18 +1607,13 @@
     int i;
 
     if (ctx->blkoutput & AC3_OUTPUT_LFEON) {
-        do_imdct_512(&ctx->fft_128, ctx->transform_coeffs[0], ctx->output[0],
-                ctx->delay[0], ctx->tmp_imdct, ctx->tmp_output);
+        do_imdct_512(ctx, 0);
     }
     for (i = 0; i < ctx->nfchans; i++) {
-        if (!((ctx->blksw >> i) & 1)) {
-            do_imdct_512(&ctx->fft_128, ctx->transform_coeffs[i + 1], ctx->output[i + 1],
-                    ctx->delay[i + 1], ctx->tmp_imdct, ctx->tmp_output);
-        } else {
-            av_log(NULL, AV_LOG_INFO, "block switching enabled.\n");
-            do_imdct_256(&ctx->fft_64, ctx->transform_coeffs[i + 1], ctx->output[i + 1],
-                    ctx->delay[i + 1], ctx->tmp_imdct, ctx->tmp_output);
-        }
+        if ((ctx->blksw >> i) & 1)
+            do_imdct_256(ctx, i + 1);
+        else
+            do_imdct_512(ctx, i + 1);
     }
 }
 
@@ -1661,7 +1630,7 @@
     int dynrng, chbwcod, ngrps, cplabsexp, skipl;
 
     for (i = 0; i < 5; i++)
-        ctx->chcoeffs[i] = 1.0;
+        ctx->chcoeffs[i] = 2.0;
 
     for (i = 0; i < nfchans; i++) /*block switch flag */
         ctx->blksw |= get_bits1(gb) << i;
@@ -1670,14 +1639,14 @@
         ctx->dithflag |= get_bits1(gb) << i;
 
     if (get_bits1(gb)) { /* dynamic range */
-        dynrng = get_bits(gb, 8);
+        dynrng = get_sbits(gb, 8);
         drange = ((((dynrng & 0x1f) | 0x20) << 13) * scale_factors[3 - (dynrng >> 5)]);
         for (i = 0; i < nfchans; i++)
             ctx->chcoeffs[i] *= drange;
     }
 
     if (acmod == 0x00 && get_bits1(gb)) { /* dynamic range 1+1 mode */
-        dynrng = get_bits(gb, 8);
+        dynrng = get_sbits(gb, 8);
         drange = ((((dynrng & 0x1f) | 0x20) << 13) * scale_factors[3 - (dynrng >> 5)]);
         ctx->chcoeffs[1] *= drange;
     }
@@ -1931,9 +1900,12 @@
 
 static inline int16_t convert(float f)
 {
-    int a;
-    a = lrintf(f * 32767.0);
-    return ((int16_t)a);
+    if (f >= 1.0)
+        return 32767;
+    else if (f <= -1.0)
+        return -32768;
+    else
+        return (lrintf(f * 32767.0));
 }
 
 static int frame_count = 0;
@@ -1943,7 +1915,8 @@
     AC3DecodeContext *ctx = (AC3DecodeContext *)avctx->priv_data;
     int frame_start;
     int16_t *out_samples = (int16_t *)data;
-    int i, j, k, value;
+    int i, j, k, value, fs_58;
+    uint16_t crc1;
 
     av_log(NULL, AV_LOG_INFO, "decoding frame %d buf_size = %d\n", frame_count++, buf_size);
 
@@ -1966,38 +1939,34 @@
         return buf_size;
     }
 
-    //Check for the errors.
-    /* if (ac3_error_check(ctx)) {
-        *data_size = 0;
-        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;
-    avctx->channels = 0;
+
     if (avctx->channels == 0) {
         ctx->blkoutput |= AC3_OUTPUT_UNMODIFIED;
-        avctx->channels = ctx->nfchans;
-    } else if (ctx->nfchans + ctx->lfeon < 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->nfchans + ctx->lfeon);
-        avctx->channels = ctx->nfchans;
-        ctx->blkoutput |= AC3_OUTPUT_UNMODIFIED;
-    } else if (avctx->channels == 1) {
+        if (ctx->lfeon)
+            ctx->blkoutput |= AC3_OUTPUT_LFEON;
+        avctx->channels = ctx->nfchans + ctx->lfeon;
+    }
+    else if (avctx->channels == 1)
         ctx->blkoutput |= AC3_OUTPUT_MONO;
-    } else if (avctx->channels == 2) {
+    else if (avctx->channels == 2) {
         if (ctx->dsurmod == 0x02)
             ctx->blkoutput |= AC3_OUTPUT_DOLBY;
         else
             ctx->blkoutput |= AC3_OUTPUT_STEREO;
     }
-    if (ctx->lfeon) {
-        avctx->channels++;
-        ctx->blkoutput |= AC3_OUTPUT_LFEON;
+    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;
     }
 
     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);
@@ -2009,10 +1978,9 @@
             *data_size = 0;
             return ctx->frame_size;
         }
-        j = ((ctx->blkoutput & AC3_OUTPUT_LFEON) ? 0 : 1);
         for (k = 0; k < BLOCK_SIZE; k++) {
-            j = ((ctx->blkoutput & AC3_OUTPUT_LFEON) ? 0 : 1);
-            for (;j < avctx->channels + 1; j++) {
+            j = (ctx->blkoutput & AC3_OUTPUT_LFEON) ? 0 : 1;
+            for (; j <= avctx->channels; j++) {
                 value = convert(ctx->output[j][k]);
                 *(out_samples++) = value;
             }