Commit c7cfc48f authored by Justin Ruggles's avatar Justin Ruggles

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
parent 860fe8c9
......@@ -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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment