changeset 5321:fcb2a52c88fe libavcodec

AC-3 decoder, soc revision 71, Sep 4 09:47:12 2006 UTC by cloud9 Redundant code cleanup. Optimized dither generation. Minor optimization in bit allocation. Comments.
author jbr
date Sat, 14 Jul 2007 16:04:17 +0000
parents 3348a76efb67
children b55b8c792066
files ac3dec.c
diffstat 1 files changed, 149 insertions(+), 87 deletions(-) [+]
line wrap: on
line diff
--- a/ac3dec.c	Sat Jul 14 16:03:47 2007 +0000
+++ b/ac3dec.c	Sat Jul 14 16:04:17 2007 +0000
@@ -13,8 +13,6 @@
  *
  * Thanks Makoto Matsumoto and Takuji Nishimura for the Mersenne Twister.
  *
- * Kaiser-Bessel derived window by Justin Ruggles.
- *
  * Copyright (c) 2006 Kartikey Mahendra BHATT (bhattkm at gmail dot com).
  * Something is wrong up on cloud # 9!
  *
@@ -95,7 +93,6 @@
 /* Mersenne Twister */
 
 typedef struct {
-    uint32_t flags;
     uint16_t crc1;
     uint8_t  fscod;
 
@@ -148,74 +145,81 @@
     int      bit_rate;
     int      frame_size;
 
-    int      nfchans;
-    int      lfeon;
+    int      nfchans;           //number of channels
+    int      lfeon;             //lfe channel in use
 
-    float    dynrng;
-    float    dynrng2;
-    float    chcoeffs[6];
-    float    cplco[5][18];
-    int      ncplbnd;
-    int      ncplsubnd;
-    int      cplstrtmant;
-    int      cplendmant;
-    int      endmant[5];
-    uint8_t  dcplexps[256];
-    uint8_t  dexps[5][256];
-    uint8_t  dlfeexps[256];
-    uint8_t  cplbap[256];
-    uint8_t  bap[5][256];
-    uint8_t  lfebap[256];
-    int      blkoutput;
+    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
 
-    DECLARE_ALIGNED_16(float, transform_coeffs[MAX_CHANNELS][BLOCK_SIZE]);
+    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
+
+    DECLARE_ALIGNED_16(float, transform_coeffs[MAX_CHANNELS][BLOCK_SIZE]);  //transform coefficients
 
     /* For IMDCT. */
-    MDCTContext imdct_512;  //N/8 point IFFT context
-    MDCTContext imdct_256;  //N/4 point IFFT context
+    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[MAX_CHANNELS][BLOCK_SIZE]);
-    DECLARE_ALIGNED_16(float, delay[MAX_CHANNELS][BLOCK_SIZE]);
-    DECLARE_ALIGNED_16(float, tmp_imdct[BLOCK_SIZE]);
-    DECLARE_ALIGNED_16(float, tmp_output[BLOCK_SIZE * 2]);
-    DECLARE_ALIGNED_16(float, window[BLOCK_SIZE]);
+
+    DECLARE_ALIGNED_16(float, output[MAX_CHANNELS][BLOCK_SIZE]);    //output after imdct transform and windowing
+    DECLARE_ALIGNED_16(float, delay[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
 
     /* Miscellaneous. */
     GetBitContext gb;
-    dither_state  dith_state;
+    dither_state  dith_state;   //for dither generation
 } AC3DecodeContext;
 
 
 /* BEGIN Mersenne Twister Code. */
 static void dither_seed(dither_state *state, uint32_t seed)
 {
-    if (seed == 0) seed = 0x1f2e3d4c;
+    static const uint32_t mag01[2] = { 0x00, MATRIX_A };
+    uint32_t y;
+    int kk;
+
+    if (seed == 0)
+        seed = 0x7ba05e;    //default seed to my birthday!
 
     state->mt[0] = seed;
     for (state->mti = 1; state->mti < NMT; state->mti++)
         state->mt[state->mti] = ((69069 * state->mt[state->mti - 1]) + 1);
+
+    for (kk = 0; kk < NMT - MMT; kk++) {
+        y = (state->mt[kk] & UPPER_MASK) | (state->mt[kk + 1] & LOWER_MASK);
+        state->mt[kk] = state->mt[kk + MMT] ^ (y >> 1) ^ mag01[y & 0x01];
+    }
+    for (;kk < NMT - 1; kk++) {
+        y = (state->mt[kk] & UPPER_MASK) | (state->mt[kk + 1] & LOWER_MASK);
+        state->mt[kk] = state->mt[kk + (MMT - NMT)] ^ (y >> 1) ^ mag01[y & 0x01];
+    }
+    y = (state->mt[NMT - 1] & UPPER_MASK) | (state->mt[0] & LOWER_MASK);
+    state->mt[NMT - 1] = state->mt[MMT - 1] ^ (y >> 1) ^ mag01[y & 0x01];
+
+    state->mti = 0;
 }
 
-static uint32_t dither_uint32(dither_state *state)
+static int16_t dither_int16(dither_state *state)
 {
     uint32_t y;
-    static const uint32_t mag01[2] = { 0x00, MATRIX_A };
-    int kk;
 
-    if (state->mti >= NMT) {
-        for (kk = 0; kk < NMT - MMT; kk++) {
-            y = (state->mt[kk] & UPPER_MASK) | (state->mt[kk + 1] & LOWER_MASK);
-            state->mt[kk] = state->mt[kk + MMT] ^ (y >> 1) ^ mag01[y & 0x01];
-        }
-        for (;kk < NMT - 1; kk++) {
-            y = (state->mt[kk] & UPPER_MASK) | (state->mt[kk + 1] & LOWER_MASK);
-            state->mt[kk] = state->mt[kk + (MMT - NMT)] ^ (y >> 1) ^ mag01[y & 0x01];
-        }
-        y = (state->mt[NMT - 1] & UPPER_MASK) | (state->mt[0] & LOWER_MASK);
-        state->mt[NMT - 1] = state->mt[MMT - 1] ^ (y >> 1) ^ mag01[y & 0x01];
-
+    if (state->mti >= NMT)
         state->mti = 0;
-    }
 
     y = state->mt[state->mti++];
     y ^= (y >> 11);
@@ -223,16 +227,11 @@
     y ^= ((y << 15) & 0xefc60000);
     y ^= (y >> 18);
 
-    return y;
+    return ((y << 16) >> 16);
 }
-
-static inline int16_t dither_int16(dither_state *state)
-{
-    return ((dither_uint32(state) << 16) >> 16);
-}
-
 /* END Mersenne Twister */
 
+/*********** BEGIN INIT HELPER FUNCTIONS ***********/
 /**
  * Generate a Kaiser-Bessel Derived Window.
  */
@@ -257,6 +256,9 @@
        window[i] = sqrt(local_window[i] / sum);
 }
 
+/*
+ * Generate quantizer tables.
+ */
 static void generate_quantizers_table(int16_t quantizers[], int level, int length)
 {
     int i;
@@ -308,6 +310,9 @@
         quantizers[i] = 0;
 }
 
+/*
+ * Initialize tables at runtime.
+ */
 static void ac3_tables_init(void)
 {
     int i, j, k, l, v;
@@ -323,6 +328,10 @@
     masktab[253] = masktab[254] = masktab[255] = 0;
     bndtab[50] = 0;
 
+    /* PSD Table For Mapping Exponents To PSD. */
+    for (i = 0; i < 25; i++)
+        psdtab[i] = 3072 - (i << 7);
+
     /* Exponent Decoding Tables */
     for (i = 0; i < 5; i++) {
         v = i - 2;
@@ -366,6 +375,11 @@
 
     //for level-15 quantizers
     generate_quantizers_table(l15_quantizers, 15, 15);
+    /* End Quantizer ungrouping tables. */
+
+    //generate scale factors
+    for (i = 0; i < 25; i++)
+        scale_factors[i] = pow(2.0, -(i + 15));
 }
 
 
@@ -376,14 +390,21 @@
     ac3_tables_init();
     ff_mdct_init(&ctx->imdct_256, 8, 1);
     ff_mdct_init(&ctx->imdct_512, 9, 1);
-    /* Kaiser-Bessel derived window. */
     ac3_window_init(ctx->window);
     dsputil_init(&ctx->dsp, avctx);
     dither_seed(&ctx->dith_state, 0);
 
     return 0;
 }
+/*********** END INIT FUNCTIONS ***********/
 
+/* Synchronize to ac3 bitstream.
+ * This function searches for the syncword '0xb77'.
+ *
+ * @param buf Pointer to "probable" ac3 bitstream buffer
+ * @param buf_size Size of buffer
+ * @return Returns the position where syncword is found, -1 if no syncword is found
+ */
 static int ac3_synchronize(uint8_t *buf, int buf_size)
 {
     int i;
@@ -395,7 +416,14 @@
     return -1;
 }
 
-//Returns -1 when 'fscod' is not valid;
+/* 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;
@@ -434,6 +462,11 @@
     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
+ */
 static void ac3_parse_bsi(AC3DecodeContext *ctx)
 {
     GetBitContext *gb = &ctx->gb;
@@ -490,10 +523,16 @@
     }
 }
 
-/* Decodes the grouped exponents and stores them
- * in decoded exponents (dexps).
- * The code is derived from liba52.
- * Uses liba52 tables.
+/* Decodes the grouped exponents.
+ * This function decodes the coded exponents according to exponent strategy
+ * and stores them in the decoded exponents buffer.
+ *
+ * @param gb GetBitContext which points to start of coded exponents
+ * @param expstr Exponent coding strategy
+ * @param ngrps Number of grouped exponetns
+ * @param absexp Absolute exponent
+ * @param dexps Decoded exponents are stored in dexps
+ * @return Returns 0 if exponents are decoded successfully, -1 if error occurs
  */
 static int decode_exponents(GetBitContext *gb, int expstr, int ngrps, uint8_t absexp, uint8_t *dexps)
 {
@@ -551,6 +590,7 @@
     return 0;
 }
 
+/*********** HELPER FUNCTIONS FOR BIT ALLOCATION ***********/
 static inline int logadd(int a, int b)
 {
     int c = a - b;
@@ -583,11 +623,10 @@
 
     return a;
 }
+/*********** END HELPER FUNCTIONS FOR BIT ALLOCATION ***********/
 
-/* do the bit allocation for chnl.
- * chnl = 0 to 4 - fbw channel
- * chnl = 5 coupling channel
- * chnl = 6 lfe channel
+/* Performs bit allocation.
+ * This function performs bit allocation for the requested chanenl.
  */
 static void do_bit_allocation(AC3DecodeContext *ctx, int chnl)
 {
@@ -655,7 +694,7 @@
     }
 
     for (bin = start; bin < end; bin++) /* exponent mapping into psd */
-        psd[bin] = (3072 - (exps[bin] << 7));
+        psd[bin] = psdtab[exps[bin]];
 
     /* psd integration */
     j = start;
@@ -972,6 +1011,10 @@
     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.
+ */
 static int get_transform_coeffs(AC3DecodeContext * ctx)
 {
     int i, end;
@@ -1011,6 +1054,7 @@
     return 0;
 }
 
+/* Rematrixing routines. */
 static void do_rematrixing1(AC3DecodeContext *ctx, int start, int end)
 {
     float tmp0, tmp1;
@@ -1050,6 +1094,10 @@
     }
 }
 
+/* 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;
@@ -1217,6 +1265,7 @@
     }
 }
 
+/*********** BEGIN DOWNMIX FUNCTIONS ***********/
 static inline void mix_dualmono_to_mono(AC3DecodeContext *ctx)
 {
     int i;
@@ -1433,12 +1482,20 @@
     memset(output[4], 0, sizeof(output[4]));
     memset(output[5], 0, sizeof(output[5]));
 }
+/*********** END DOWNMIX FUNCTIONS ***********/
 
+/* 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_INPUT_DUALMONO:
             switch (to) {
@@ -1545,16 +1602,9 @@
         av_log(NULL, AV_LOG_INFO, "\n");
 }
 
-#define CMUL(pre, pim, are, aim, bre, bim) \
-{\
-    float _are = (are);\
-    float _aim = (aim);\
-    float _bre = (bre);\
-    float _bim = (bim);\
-    (pre) = _are * _bre - _aim * _bim;\
-    (pim) = _are * _bim + _aim * _bre;\
-}
-
+/* This function performs the imdct on 256 sample transform
+ * coefficients.
+ */
 static void do_imdct_256(AC3DecodeContext *ctx, int chindex)
 {
     int k;
@@ -1575,6 +1625,9 @@
     ctx->dsp.vector_fmul_reverse(ptr, ctx->tmp_output + 256, ctx->window, BLOCK_SIZE);
 }
 
+/* This function performs the imdct on 512 sample transform
+ * coefficients.
+ */
 static void do_imdct_512(AC3DecodeContext *ctx, int chindex)
 {
     float *ptr;
@@ -1587,6 +1640,7 @@
     ctx->dsp.vector_fmul_reverse(ptr, ctx->tmp_output + 256, ctx->window, BLOCK_SIZE);
 }
 
+/* IMDCT Transform. */
 static inline void do_imdct(AC3DecodeContext *ctx)
 {
     int i;
@@ -1602,6 +1656,11 @@
     }
 }
 
+/* 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.
+ */
 static int ac3_parse_audio_block(AC3DecodeContext * ctx)
 {
     int nfchans = ctx->nfchans;
@@ -1609,7 +1668,6 @@
     int i, bnd, rbnd, seg, grpsize;
     GetBitContext *gb = &ctx->gb;
     int bit_alloc_flags = 0;
-    float drange;
     uint8_t *dexps;
     int mstrcplco, cplcoexp, cplcomant;
     int dynrng, chbwcod, ngrps, cplabsexp, skipl;
@@ -1879,16 +1937,6 @@
     return 0;
 }
 
-/*static inline int16_t convert(float f)
-{
-    if (f >= 1.0)
-        return 32767;
-    else if (f <= -1.0)
-        return -32768;
-    else
-        return (lrintf(f * 32767.0));
-}*/
-
 static inline int16_t convert(int32_t i)
 {
     if (i > 0x43c07fff)
@@ -1901,6 +1949,14 @@
 
 static int frame_count = 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
+ */
 static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size, uint8_t *buf, int buf_size)
 {
     AC3DecodeContext *ctx = (AC3DecodeContext *)avctx->priv_data;
@@ -1981,8 +2037,14 @@
     return ctx->frame_size;
 }
 
-static int ac3_decode_end(AVCodecContext *ctx)
+/* Uninitialize ac3 decoder.
+ */
+static int ac3_decode_end(AVCodecContext *avctx)
 {
+    AC3DecodeContext *ctx = (AC3DecodeContext *)avctx->priv_data;
+    ff_mdct_end(&ctx->imdct_512);
+    ff_mdct_end(&ctx->imdct_256);
+
     return 0;
 }