summaryrefslogtreecommitdiff
path: root/libavcodec/ac3dec.c
diff options
context:
space:
mode:
authorJustin Ruggles <justin.ruggles@gmail.com>2007-07-14 16:04:17 +0000
committerJustin Ruggles <justin.ruggles@gmail.com>2007-07-14 16:04:17 +0000
commitc7cfc48f37fa78f82f0bf6ccf8a4ebfcf2ca4461 (patch)
tree79b49b65fe2f69f614cbdb60d74db2d6cf04c81c /libavcodec/ac3dec.c
parent860fe8c908202ec8b553dac1ca39a1e9c78b71e6 (diff)
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. Originally committed as revision 9669 to svn://svn.ffmpeg.org/ffmpeg/trunk
Diffstat (limited to 'libavcodec/ac3dec.c')
-rw-r--r--libavcodec/ac3dec.c240
1 files changed, 151 insertions, 89 deletions
diff --git a/libavcodec/ac3dec.c b/libavcodec/ac3dec.c
index 7553ad8f9d..388afd4e78 100644
--- a/libavcodec/ac3dec.c
+++ b/libavcodec/ac3dec.c
@@ -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 @@ typedef struct {
/* Mersenne Twister */
typedef struct {
- uint32_t flags;
uint16_t crc1;
uint8_t fscod;
@@ -148,74 +145,81 @@ typedef struct {
int bit_rate;
int frame_size;
- int nfchans;
- int lfeon;
-
- 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;
-
- DECLARE_ALIGNED_16(float, transform_coeffs[MAX_CHANNELS][BLOCK_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
+
+ 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 @@ static uint32_t dither_uint32(dither_state *state)
y ^= ((y << 15) & 0xefc60000);
y ^= (y >> 18);
- return y;
-}
-
-static inline int16_t dither_int16(dither_state *state)
-{
- return ((dither_uint32(state) << 16) >> 16);
+ return ((y << 16) >> 16);
}
-
/* END Mersenne Twister */
+/*********** BEGIN INIT HELPER FUNCTIONS ***********/
/**
* Generate a Kaiser-Bessel Derived Window.
*/
@@ -257,6 +256,9 @@ static void ac3_window_init(float *window)
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 @@ static void generate_quantizers_table_3(int16_t quantizers[], int level, int len
quantizers[i] = 0;
}
+/*
+ * Initialize tables at runtime.
+ */
static void ac3_tables_init(void)
{
int i, j, k, l, v;
@@ -323,6 +328,10 @@ static void ac3_tables_init(void)
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 @@ static void ac3_tables_init(void)
//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 @@ static int ac3_decode_init(AVCodecContext *avctx)
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 @@ static int ac3_synchronize(uint8_t *buf, int buf_size)
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 @@ static int ac3_parse_sync_info(AC3DecodeContext *ctx)
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 @@ static void ac3_parse_bsi(AC3DecodeContext *ctx)
}
}
-/* 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 @@ static int decode_exponents(GetBitContext *gb, int expstr, int ngrps, uint8_t ab
return 0;
}
+/*********** HELPER FUNCTIONS FOR BIT ALLOCATION ***********/
static inline int logadd(int a, int b)
{
int c = a - b;
@@ -583,11 +623,10 @@ static inline int calc_lowcomp(int a, int b0, int b1, int bin)
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 @@ static void do_bit_allocation(AC3DecodeContext *ctx, int chnl)
}
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 @@ static int get_transform_coeffs_ch(AC3DecodeContext *ctx, int ch_index, mant_gro
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 @@ static int get_transform_coeffs(AC3DecodeContext * ctx)
return 0;
}
+/* Rematrixing routines. */
static void do_rematrixing1(AC3DecodeContext *ctx, int start, int end)
{
float tmp0, tmp1;
@@ -1050,6 +1094,10 @@ static void do_rematrixing(AC3DecodeContext *ctx)
}
}
+/* 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 @@ static void get_downmix_coeffs(AC3DecodeContext *ctx)
}
}
+/*********** BEGIN DOWNMIX FUNCTIONS ***********/
static inline void mix_dualmono_to_mono(AC3DecodeContext *ctx)
{
int i;
@@ -1433,12 +1482,20 @@ static inline void mix_3f_2r_to_dolby(AC3DecodeContext *ctx)
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 @@ static void dump_floats(const char *name, int prec, const float *tab, int n)
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 @@ static void do_imdct_256(AC3DecodeContext *ctx, int chindex)
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 @@ static void do_imdct_512(AC3DecodeContext *ctx, int chindex)
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 @@ static inline void do_imdct(AC3DecodeContext *ctx)
}
}
+/* 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 @@ static int ac3_parse_audio_block(AC3DecodeContext * ctx)
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 @@ static int ac3_parse_audio_block(AC3DecodeContext * ctx)
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 inline int16_t convert(int32_t i)
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 @@ static int ac3_decode_frame(AVCodecContext * avctx, void *data, int *data_size,
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;
}