diff options
-rw-r--r-- | liba52/Makefile | 3 | ||||
-rw-r--r-- | liba52/a52.h | 72 | ||||
-rw-r--r-- | liba52/a52_internal.h | 89 | ||||
-rw-r--r-- | liba52/bit_allocate.c | 25 | ||||
-rw-r--r-- | liba52/bitstream.c | 53 | ||||
-rw-r--r-- | liba52/bitstream.h | 45 | ||||
-rw-r--r-- | liba52/downmix.c | 24 | ||||
-rw-r--r-- | liba52/imdct.c | 1016 | ||||
-rw-r--r-- | liba52/imdct_3dnow.h | 2 | ||||
-rw-r--r-- | liba52/liba52_changes.diff | 2028 | ||||
-rw-r--r-- | liba52/mm_accel.h | 4 | ||||
-rw-r--r-- | liba52/parse.c | 417 | ||||
-rw-r--r-- | liba52/tables.h | 10 | ||||
-rw-r--r-- | libmpcodecs/ad_liba52.c | 23 |
14 files changed, 1521 insertions, 2290 deletions
diff --git a/liba52/Makefile b/liba52/Makefile index 9ddd8e6284..9296b32284 100644 --- a/liba52/Makefile +++ b/liba52/Makefile @@ -9,12 +9,11 @@ SRCS = crc.c \ bitstream.c \ downmix.c \ imdct.c \ - imdct_mlib.c \ parse.c \ OBJS = $(SRCS:.c=.o) -CFLAGS = $(MLIB_INC) $(OPTFLAGS) -I.. +CFLAGS = $(OPTFLAGS) -I.. .SUFFIXES: .c .o diff --git a/liba52/a52.h b/liba52/a52.h index f87abe9851..5c7a3d8656 100644 --- a/liba52/a52.h +++ b/liba52/a52.h @@ -1,6 +1,6 @@ /* * a52.h - * Copyright (C) 2000-2001 Michel Lespinasse <walken@zoy.org> + * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org> * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> * * This file is part of a52dec, a free ATSC A-52 stream decoder. @@ -34,69 +34,7 @@ typedef float sample_t; typedef double sample_t; #endif -typedef struct a52_ba_s { - uint16_t fsnroffst; /* fine SNR offset */ - uint16_t fgaincod; /* fast gain */ - uint16_t deltbae; /* delta bit allocation exists */ - int8_t deltba[50]; /* per-band delta bit allocation */ -} a52_ba_t; - -typedef struct a52_state_s { - uint8_t fscod; /* sample rate */ - uint8_t halfrate; /* halfrate factor */ - uint8_t acmod; /* coded channels */ - sample_t clev; /* centre channel mix level */ - sample_t slev; /* surround channels mix level */ - uint8_t lfeon; /* coded lfe channel */ - - int output; /* type of output */ - sample_t level; /* output level */ - sample_t bias; /* output bias */ - - int dynrnge; /* apply dynamic range */ - sample_t dynrng; /* dynamic range */ - void * dynrngdata; /* dynamic range callback funtion and data */ - sample_t (* dynrngcall) (sample_t range, void * dynrngdata); - - uint16_t cplinu; /* coupling in use */ - uint16_t chincpl[5]; /* channel coupled */ - uint16_t phsflginu; /* phase flags in use (stereo only) */ - uint16_t cplbndstrc[18]; /* coupling band structure */ - uint16_t cplstrtmant; /* coupling channel start mantissa */ - uint16_t cplendmant; /* coupling channel end mantissa */ - sample_t cplco[5][18]; /* coupling coordinates */ - - /* derived information */ - uint16_t cplstrtbnd; /* coupling start band (for bit allocation) */ - uint16_t ncplbnd; /* number of coupling bands */ - - uint16_t rematflg[4]; /* stereo rematrixing */ - - uint16_t endmant[5]; /* channel end mantissa */ - - uint8_t cpl_exp[256]; /* decoded coupling channel exponents */ - uint8_t fbw_exp[5][256]; /* decoded channel exponents */ - uint8_t lfe_exp[7]; /* decoded lfe channel exponents */ - - uint16_t sdcycod; /* slow decay */ - uint16_t fdcycod; /* fast decay */ - uint16_t sgaincod; /* slow gain */ - uint16_t dbpbcod; /* dB per bit - encodes the dbknee value */ - uint16_t floorcod; /* masking floor */ - - uint16_t csnroffst; /* coarse SNR offset */ - a52_ba_t cplba; /* coupling bit allocation parameters */ - a52_ba_t ba[5]; /* channel bit allocation parameters */ - a52_ba_t lfeba; /* lfe bit allocation parameters */ - - uint16_t cplfleak; /* coupling fast leak init */ - uint16_t cplsleak; /* coupling slow leak init */ - - /* derived bit allocation information */ - int8_t fbw_bap[5][256]; - int8_t cpl_bap[256]; - int8_t lfe_bap[7]; -} a52_state_t; +typedef struct a52_state_s a52_state_t; #define A52_CHANNEL 0 #define A52_MONO 1 @@ -114,14 +52,16 @@ typedef struct a52_state_s { #define A52_LFE 16 #define A52_ADJUST_LEVEL 32 -sample_t * a52_init (uint32_t mm_accel); +a52_state_t * a52_init (uint32_t mm_accel); +sample_t * a52_samples (a52_state_t * state); int a52_syncinfo (uint8_t * buf, int * flags, int * sample_rate, int * bit_rate); int a52_frame (a52_state_t * state, uint8_t * buf, int * flags, sample_t * level, sample_t bias); void a52_dynrng (a52_state_t * state, sample_t (* call) (sample_t, void *), void * data); -int a52_block (a52_state_t * state, sample_t * samples); +int a52_block (a52_state_t * state); +void a52_free (a52_state_t * state); void* a52_resample_init(uint32_t mm_accel,int flags,int chans); extern int (* a52_resample) (float * _f, int16_t * s16); diff --git a/liba52/a52_internal.h b/liba52/a52_internal.h index 91fc54a300..d420803699 100644 --- a/liba52/a52_internal.h +++ b/liba52/a52_internal.h @@ -1,6 +1,6 @@ /* * a52_internal.h - * Copyright (C) 2000-2001 Michel Lespinasse <walken@zoy.org> + * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org> * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> * * This file is part of a52dec, a free ATSC A-52 stream decoder. @@ -25,6 +25,72 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +typedef struct { + uint8_t bai; /* fine SNR offset, fast gain */ + uint8_t deltbae; /* delta bit allocation exists */ + int8_t deltba[50]; /* per-band delta bit allocation */ +} ba_t; + +typedef struct { + uint8_t exp[256]; /* decoded channel exponents */ + int8_t bap[256]; /* derived channel bit allocation */ +} expbap_t; + +struct a52_state_s { + uint8_t fscod; /* sample rate */ + uint8_t halfrate; /* halfrate factor */ + uint8_t acmod; /* coded channels */ + uint8_t lfeon; /* coded lfe channel */ + sample_t clev; /* centre channel mix level */ + sample_t slev; /* surround channels mix level */ + + int output; /* type of output */ + sample_t level; /* output level */ + sample_t bias; /* output bias */ + + int dynrnge; /* apply dynamic range */ + sample_t dynrng; /* dynamic range */ + void * dynrngdata; /* dynamic range callback funtion and data */ + sample_t (* dynrngcall) (sample_t range, void * dynrngdata); + + uint8_t chincpl; /* channel coupled */ + uint8_t phsflginu; /* phase flags in use (stereo only) */ + uint8_t cplstrtmant; /* coupling channel start mantissa */ + uint8_t cplendmant; /* coupling channel end mantissa */ + uint32_t cplbndstrc; /* coupling band structure */ + sample_t cplco[5][18]; /* coupling coordinates */ + + /* derived information */ + uint8_t cplstrtbnd; /* coupling start band (for bit allocation) */ + uint8_t ncplbnd; /* number of coupling bands */ + + uint8_t rematflg; /* stereo rematrixing */ + + uint8_t endmant[5]; /* channel end mantissa */ + + uint16_t bai; /* bit allocation information */ + + uint32_t * buffer_start; + uint16_t lfsr_state; /* dither state */ + uint32_t bits_left; + uint32_t current_word; + + uint8_t csnroffst; /* coarse SNR offset */ + ba_t cplba; /* coupling bit allocation parameters */ + ba_t ba[5]; /* channel bit allocation parameters */ + ba_t lfeba; /* lfe bit allocation parameters */ + + uint8_t cplfleak; /* coupling fast leak init */ + uint8_t cplsleak; /* coupling slow leak init */ + + expbap_t cpl_expbap; + expbap_t fbw_expbap[5]; + expbap_t lfe_expbap; + + sample_t * samples; + int downmixed; +}; + #define LEVEL_PLUS6DB 2.0 #define LEVEL_PLUS3DB 1.4142135623730951 #define LEVEL_3DB 0.7071067811865476 @@ -55,21 +121,20 @@ # define REG_BP "ebp" #endif -void bit_allocate (a52_state_t * state, a52_ba_t * ba, int bndstart, +void a52_bit_allocate (a52_state_t * state, ba_t * ba, int bndstart, int start, int end, int fastleak, int slowleak, - uint8_t * exp, int8_t * bap); + expbap_t * expbap); -int downmix_init (int input, int flags, sample_t * level, +int a52_downmix_init (int input, int flags, sample_t * level, sample_t clev, sample_t slev); void downmix_accel_init(uint32_t mm_accel); -int downmix_coeff (sample_t * coeff, int acmod, int output, sample_t level, +int a52_downmix_coeff (sample_t * coeff, int acmod, int output, sample_t level, sample_t clev, sample_t slev); -extern void (*downmix) (sample_t * samples, int acmod, int output, sample_t bias, +extern void (*a52_downmix) (sample_t * samples, int acmod, int output, sample_t bias, sample_t clev, sample_t slev); -extern void (*upmix) (sample_t * samples, int acmod, int output); +extern void (*a52_upmix) (sample_t * samples, int acmod, int output); -void imdct_init (uint32_t mm_accel); -extern void (* imdct_256) (sample_t * data, sample_t * delay, sample_t bias); -extern void (* imdct_512) (sample_t * data, sample_t * delay, sample_t bias); -void imdct_do_256_mlib (sample_t * data, sample_t * delay, sample_t bias); -void imdct_do_512_mlib (sample_t * data, sample_t * delay, sample_t bias); +void a52_imdct_init (uint32_t mm_accel); +void a52_imdct_256 (sample_t * data, sample_t * delay, sample_t bias); +extern void (*a52_imdct_512) (sample_t * data, sample_t * delay, sample_t bias); +void imdct_do_512 (sample_t * data, sample_t * delay, sample_t bias); diff --git a/liba52/bit_allocate.c b/liba52/bit_allocate.c index d0dd602156..a5f3b77024 100644 --- a/liba52/bit_allocate.c +++ b/liba52/bit_allocate.c @@ -1,6 +1,6 @@ /* * bit_allocate.c - * Copyright (C) 2000-2001 Michel Lespinasse <walken@zoy.org> + * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org> * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> * * This file is part of a52dec, a free ATSC A-52 stream decoder. @@ -121,9 +121,9 @@ do { \ mask -= floor; \ } while (0) -void bit_allocate (a52_state_t * state, a52_ba_t * ba, int bndstart, +void a52_bit_allocate (a52_state_t * state, ba_t * ba, int bndstart, int start, int end, int fastleak, int slowleak, - uint8_t * exp, int8_t * bap) + expbap_t * expbap) { static int slowgain[4] = {0x540, 0x4d8, 0x478, 0x410}; static int dbpbtab[4] = {0xc00, 0x500, 0x300, 0x100}; @@ -131,6 +131,8 @@ void bit_allocate (a52_state_t * state, a52_ba_t * ba, int bndstart, 0xa10, 0xa90, 0xb10, 0x1400}; int i, j; + uint8_t * exp; + int8_t * bap; int fdecay, fgain, sdecay, sgain, dbknee, floor, snroffset; int psd, mask; int8_t * deltba; @@ -138,21 +140,24 @@ void bit_allocate (a52_state_t * state, a52_ba_t * ba, int bndstart, int halfrate; halfrate = state->halfrate; - fdecay = (63 + 20 * state->fdcycod) >> halfrate; - fgain = 128 + 128 * ba->fgaincod; - sdecay = (15 + 2 * state->sdcycod) >> halfrate; - sgain = slowgain[state->sgaincod]; - dbknee = dbpbtab[state->dbpbcod]; + fdecay = (63 + 20 * ((state->bai >> 7) & 3)) >> halfrate; /* fdcycod */ + fgain = 128 + 128 * (ba->bai & 7); /* fgaincod */ + sdecay = (15 + 2 * (state->bai >> 9)) >> halfrate; /* sdcycod */ + sgain = slowgain[(state->bai >> 5) & 3]; /* sgaincod */ + dbknee = dbpbtab[(state->bai >> 3) & 3]; /* dbpbcod */ hth = hthtab[state->fscod]; /* * if there is no delta bit allocation, make deltba point to an area * known to contain zeroes. baptab+156 here. */ deltba = (ba->deltbae == DELTA_BIT_NONE) ? baptab + 156 : ba->deltba; - floor = floortab[state->floorcod]; - snroffset = 960 - 64 * state->csnroffst - 4 * ba->fsnroffst + floor; + floor = floortab[state->bai & 7]; /* floorcod */ + snroffset = 960 - 64 * state->csnroffst - 4 * (ba->bai >> 3) + floor; floor >>= 5; + exp = expbap->exp; + bap = expbap->bap; + i = bndstart; j = start; if (start == 0) { /* not the coupling channel */ diff --git a/liba52/bitstream.c b/liba52/bitstream.c index 3a25001c57..6c275109d1 100644 --- a/liba52/bitstream.c +++ b/liba52/bitstream.c @@ -1,6 +1,6 @@ /* * bitstream.c - * Copyright (C) 2000-2001 Michel Lespinasse <walken@zoy.org> + * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org> * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> * * This file is part of a52dec, a free ATSC A-52 stream decoder. @@ -37,34 +37,27 @@ #ifdef ALT_BITSTREAM_READER int indx=0; -uint32_t * buffer_start; -#else -static uint32_t * buffer_start; #endif -uint32_t bits_left; -uint32_t current_word; - -void bitstream_set_ptr (uint8_t * buf) +void a52_bitstream_set_ptr (a52_state_t * state, uint8_t * buf) { int align; - align = (int)buf & 3; - buffer_start = (uint32_t *) (buf - align); - bits_left = 0; + align = (long)buf & 3; + state->buffer_start = (uint32_t *) (buf - align); + state->bits_left = 0; #ifdef ALT_BITSTREAM_READER indx=0; #endif - bitstream_get (align * 8); + bitstream_get (state, align * 8); } -static inline void -bitstream_fill_current(void) +static inline void bitstream_fill_current (a52_state_t * state) { uint32_t tmp; - tmp = *(buffer_start++); - current_word = swab32 (tmp); + tmp = *(state->buffer_start++); + state->current_word = swab32 (tmp); } /* @@ -76,38 +69,38 @@ bitstream_fill_current(void) * -ah */ -uint32_t -bitstream_get_bh(uint32_t num_bits) +uint32_t a52_bitstream_get_bh (a52_state_t * state, uint32_t num_bits) { uint32_t result; - num_bits -= bits_left; - result = (current_word << (32 - bits_left)) >> (32 - bits_left); + num_bits -= state->bits_left; + result = ((state->current_word << (32 - state->bits_left)) >> + (32 - state->bits_left)); - bitstream_fill_current(); + bitstream_fill_current (state); if(num_bits != 0) - result = (result << num_bits) | (current_word >> (32 - num_bits)); + result = (result << num_bits) | (state->current_word >> (32 - num_bits)); - bits_left = 32 - num_bits; + state->bits_left = 32 - num_bits; return result; } -int32_t -bitstream_get_bh_2(uint32_t num_bits) +int32_t a52_bitstream_get_bh_2 (a52_state_t * state, uint32_t num_bits) { int32_t result; - num_bits -= bits_left; - result = (((int32_t)current_word) << (32 - bits_left)) >> (32 - bits_left); + num_bits -= state->bits_left; + result = ((((int32_t)state->current_word) << (32 - state->bits_left)) >> + (32 - state->bits_left)); - bitstream_fill_current(); + bitstream_fill_current(state); if(num_bits != 0) - result = (result << num_bits) | (current_word >> (32 - num_bits)); + result = (result << num_bits) | (state->current_word >> (32 - num_bits)); - bits_left = 32 - num_bits; + state->bits_left = 32 - num_bits; return result; } diff --git a/liba52/bitstream.h b/liba52/bitstream.h index 7e4ff676c8..8576f8b282 100644 --- a/liba52/bitstream.h +++ b/liba52/bitstream.h @@ -1,6 +1,6 @@ /* * bitstream.h - * Copyright (C) 2000-2001 Michel Lespinasse <walken@zoy.org> + * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org> * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> * * This file is part of a52dec, a free ATSC A-52 stream decoder. @@ -77,7 +77,7 @@ static inline uint32_t unaligned32(const void *v) { # if defined (__i386__) # define swab32(x) __i386_swab32(x) - static always_inline const uint32_t __i386_swab32(uint32_t x) + static inline const uint32_t __i386_swab32(uint32_t x) { __asm__("bswap %0" : "=r" (x) : "0" (x)); return x; @@ -95,23 +95,17 @@ static inline uint32_t unaligned32(const void *v) { #endif #ifdef ALT_BITSTREAM_READER -extern uint32_t *buffer_start; extern int indx; -#else -extern uint32_t bits_left; -extern uint32_t current_word; #endif -void bitstream_set_ptr (uint8_t * buf); -uint32_t bitstream_get_bh(uint32_t num_bits); -int32_t bitstream_get_bh_2(uint32_t num_bits); - +void a52_bitstream_set_ptr (a52_state_t * state, uint8_t * buf); +uint32_t a52_bitstream_get_bh (a52_state_t * state, uint32_t num_bits); +int32_t a52_bitstream_get_bh_2 (a52_state_t * state, uint32_t num_bits); -static inline uint32_t -bitstream_get(uint32_t num_bits) // note num_bits is practically a constant due to inlineing +static inline uint32_t bitstream_get (a52_state_t * state, uint32_t num_bits) { #ifdef ALT_BITSTREAM_READER - uint32_t result= swab32( unaligned32(((uint8_t *)buffer_start)+(indx>>3)) ); + uint32_t result= swab32( unaligned32(((uint8_t *)state->buffer_start)+(indx>>3)) ); result<<= (indx&0x07); result>>= 32 - num_bits; @@ -121,30 +115,29 @@ bitstream_get(uint32_t num_bits) // note num_bits is practically a constant due #else uint32_t result; - if(num_bits < bits_left) { - result = (current_word << (32 - bits_left)) >> (32 - num_bits); - bits_left -= num_bits; + if (num_bits < state->bits_left) { + result = (state->current_word << (32 - state->bits_left)) >> (32 - num_bits); + state->bits_left -= num_bits; return result; } - return bitstream_get_bh(num_bits); + return a52_bitstream_get_bh (state, num_bits); #endif } -static inline void bitstream_skip(int num_bits) +static inline void bitstream_skip(a52_state_t * state, int num_bits) { #ifdef ALT_BITSTREAM_READER indx+= num_bits; #else - bitstream_get(num_bits); + bitstream_get(state, num_bits); #endif } -static inline int32_t -bitstream_get_2(uint32_t num_bits) +static inline int32_t bitstream_get_2 (a52_state_t * state, uint32_t num_bits) { #ifdef ALT_BITSTREAM_READER - int32_t result= swab32( unaligned32(((uint8_t *)buffer_start)+(indx>>3)) ); + int32_t result= swab32( unaligned32(((uint8_t *)state->buffer_start)+(indx>>3)) ); result<<= (indx&0x07); result>>= 32 - num_bits; @@ -154,12 +147,12 @@ bitstream_get_2(uint32_t num_bits) #else int32_t result; - if(num_bits < bits_left) { - result = (((int32_t)current_word) << (32 - bits_left)) >> (32 - num_bits); - bits_left -= num_bits; + if (num_bits < state->bits_left) { + result = (((int32_t)state->current_word) << (32 - state->bits_left)) >> (32 - num_bits); + state->bits_left -= num_bits; return result; } - return bitstream_get_bh_2(num_bits); + return a52_bitstream_get_bh_2 (state, num_bits); #endif } diff --git a/liba52/downmix.c b/liba52/downmix.c index 67eee7a89e..5c61cee475 100644 --- a/liba52/downmix.c +++ b/liba52/downmix.c @@ -1,6 +1,6 @@ /* * downmix.c - * Copyright (C) 2000-2001 Michel Lespinasse <walken@zoy.org> + * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org> * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> * * This file is part of a52dec, a free ATSC A-52 stream decoder. @@ -40,9 +40,9 @@ #define CONVERT(acmod,output) (((output) << 3) + (acmod)) -void (*downmix)(sample_t * samples, int acmod, int output, sample_t bias, +void (*a52_downmix)(sample_t * samples, int acmod, int output, sample_t bias, sample_t clev, sample_t slev)= NULL; -void (*upmix)(sample_t * samples, int acmod, int output)= NULL; +void (*a52_upmix)(sample_t * samples, int acmod, int output)= NULL; static void downmix_SSE (sample_t * samples, int acmod, int output, sample_t bias, sample_t clev, sample_t slev); @@ -55,16 +55,16 @@ static void upmix_C (sample_t * samples, int acmod, int output); void downmix_accel_init(uint32_t mm_accel) { - upmix= upmix_C; - downmix= downmix_C; + a52_upmix= upmix_C; + a52_downmix= downmix_C; #if defined(ARCH_X86) || defined(ARCH_X86_64) - if(mm_accel & MM_ACCEL_X86_MMX) upmix= upmix_MMX; - if(mm_accel & MM_ACCEL_X86_SSE) downmix= downmix_SSE; - if(mm_accel & MM_ACCEL_X86_3DNOW) downmix= downmix_3dnow; + if(mm_accel & MM_ACCEL_X86_MMX) a52_upmix= upmix_MMX; + if(mm_accel & MM_ACCEL_X86_SSE) a52_downmix= downmix_SSE; + if(mm_accel & MM_ACCEL_X86_3DNOW) a52_downmix= downmix_3dnow; #endif } -int downmix_init (int input, int flags, sample_t * level, +int a52_downmix_init (int input, int flags, sample_t * level, sample_t clev, sample_t slev) { static uint8_t table[11][8] = { @@ -183,7 +183,7 @@ int downmix_init (int input, int flags, sample_t * level, return output; } -int downmix_coeff (sample_t * coeff, int acmod, int output, sample_t level, +int a52_downmix_coeff (sample_t * coeff, int acmod, int output, sample_t level, sample_t clev, sample_t slev) { switch (CONVERT (acmod, output & A52_CHANNEL_MASK)) { @@ -478,7 +478,7 @@ static void zero (sample_t * samples) samples[i] = 0; } -static void downmix_C (sample_t * samples, int acmod, int output, sample_t bias, +void downmix_C (sample_t * samples, int acmod, int output, sample_t bias, sample_t clev, sample_t slev) { switch (CONVERT (acmod, output & A52_CHANNEL_MASK)) { @@ -619,7 +619,7 @@ static void downmix_C (sample_t * samples, int acmod, int output, sample_t bias, } } -static void upmix_C (sample_t * samples, int acmod, int output) +void upmix_C (sample_t * samples, int acmod, int output) { switch (CONVERT (acmod, output & A52_CHANNEL_MASK)) { diff --git a/liba52/imdct.c b/liba52/imdct.c index a535823584..4909fc5ce9 100644 --- a/liba52/imdct.c +++ b/liba52/imdct.c @@ -1,8 +1,11 @@ /* * imdct.c - * Copyright (C) 2000-2001 Michel Lespinasse <walken@zoy.org> + * Copyright (C) 2000-2002 Michel Lespinasse <walken@zoy.org> * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca> * + * The ifft algorithms in this file have been largely inspired by Dan + * Bernstein's work, djbfft, available at http://cr.yp.to/djbfft.html + * * This file is part of a52dec, a free ATSC A-52 stream decoder. * See http://liba52.sourceforge.net/ for updates. * @@ -35,6 +38,9 @@ #include <math.h> #include <stdio.h> +#ifdef LIBA52_DJBFFT +#include <fftc4.h> +#endif #ifndef M_PI #define M_PI 3.1415926535897932384626433832795029 #endif @@ -45,22 +51,17 @@ #include "mm_accel.h" #include "mangle.h" +void (*a52_imdct_512) (sample_t * data, sample_t * delay, sample_t bias); + #ifdef RUNTIME_CPUDETECT #undef HAVE_3DNOWEX #endif -#define USE_AC3_C - -void (* imdct_256) (sample_t data[], sample_t delay[], sample_t bias); -void (* imdct_512) (sample_t data[], sample_t delay[], sample_t bias); - typedef struct complex_s { sample_t real; sample_t imag; } complex_t; -static void fft_128p(complex_t *a); - static const int pm128[128] attribute_used __attribute__((aligned(16))) = { 0, 16, 32, 48, 64, 80, 96, 112, 8, 40, 72, 104, 24, 56, 88, 120, @@ -73,7 +74,6 @@ static const int pm128[128] attribute_used __attribute__((aligned(16))) = 7, 23, 39, 55, 71, 87, 103, 119, 15, 31, 47, 63, 79, 95, 111, 127 }; -/* 128 point bit-reverse LUT */ static uint8_t attribute_used bit_reverse_512[] = { 0x00, 0x40, 0x20, 0x60, 0x10, 0x50, 0x30, 0x70, 0x08, 0x48, 0x28, 0x68, 0x18, 0x58, 0x38, 0x78, @@ -92,20 +92,36 @@ static uint8_t attribute_used bit_reverse_512[] = { 0x07, 0x47, 0x27, 0x67, 0x17, 0x57, 0x37, 0x77, 0x0f, 0x4f, 0x2f, 0x6f, 0x1f, 0x5f, 0x3f, 0x7f}; -static uint8_t bit_reverse_256[] = { - 0x00, 0x20, 0x10, 0x30, 0x08, 0x28, 0x18, 0x38, - 0x04, 0x24, 0x14, 0x34, 0x0c, 0x2c, 0x1c, 0x3c, - 0x02, 0x22, 0x12, 0x32, 0x0a, 0x2a, 0x1a, 0x3a, - 0x06, 0x26, 0x16, 0x36, 0x0e, 0x2e, 0x1e, 0x3e, - 0x01, 0x21, 0x11, 0x31, 0x09, 0x29, 0x19, 0x39, - 0x05, 0x25, 0x15, 0x35, 0x0d, 0x2d, 0x1d, 0x3d, - 0x03, 0x23, 0x13, 0x33, 0x0b, 0x2b, 0x1b, 0x3b, - 0x07, 0x27, 0x17, 0x37, 0x0f, 0x2f, 0x1f, 0x3f}; +static uint8_t fftorder[] = { + 0,128, 64,192, 32,160,224, 96, 16,144, 80,208,240,112, 48,176, + 8,136, 72,200, 40,168,232,104,248,120, 56,184, 24,152,216, 88, + 4,132, 68,196, 36,164,228,100, 20,148, 84,212,244,116, 52,180, + 252,124, 60,188, 28,156,220, 92, 12,140, 76,204,236,108, 44,172, + 2,130, 66,194, 34,162,226, 98, 18,146, 82,210,242,114, 50,178, + 10,138, 74,202, 42,170,234,106,250,122, 58,186, 26,154,218, 90, + 254,126, 62,190, 30,158,222, 94, 14,142, 78,206,238,110, 46,174, + 6,134, 70,198, 38,166,230,102,246,118, 54,182, 22,150,214, 86 +}; + +static complex_t __attribute__((aligned(16))) buf[128]; + +/* Twiddle factor LUT */ +static complex_t __attribute__((aligned(16))) w_1[1]; +static complex_t __attribute__((aligned(16))) w_2[2]; +static complex_t __attribute__((aligned(16))) w_4[4]; +static complex_t __attribute__((aligned(16))) w_8[8]; +static complex_t __attribute__((aligned(16))) w_16[16]; +static complex_t __attribute__((aligned(16))) w_32[32]; +static complex_t __attribute__((aligned(16))) w_64[64]; +static complex_t __attribute__((aligned(16))) * w[7] = {w_1, w_2, w_4, w_8, w_16, w_32, w_64}; + +/* Twiddle factors for IMDCT */ +static sample_t __attribute__((aligned(16))) xcos1[128]; +static sample_t __attribute__((aligned(16))) xsin1[128]; #if defined(ARCH_X86) || defined(ARCH_X86_64) // NOTE: SSE needs 16byte alignment or it will segfault // -static complex_t __attribute__((aligned(16))) buf[128]; static float __attribute__((aligned(16))) sseSinCos1c[256]; static float __attribute__((aligned(16))) sseSinCos1d[256]; static float attribute_used __attribute__((aligned(16))) ps111_1[4]={1,1,1,-1}; @@ -119,274 +135,234 @@ static float __attribute__((aligned(16))) sseW6[256]; static float __attribute__((aligned(16))) *sseW[7]= {NULL /*sseW0*/,sseW1,sseW2,sseW3,sseW4,sseW5,sseW6}; static float __attribute__((aligned(16))) sseWindow[512]; -#else -static complex_t __attribute__((aligned(16))) buf[128]; #endif -/* Twiddle factor LUT */ -static complex_t __attribute__((aligned(16))) w_1[1]; -static complex_t __attribute__((aligned(16))) w_2[2]; -static complex_t __attribute__((aligned(16))) w_4[4]; -static complex_t __attribute__((aligned(16))) w_8[8]; -static complex_t __attribute__((aligned(16))) w_16[16]; -static complex_t __attribute__((aligned(16))) w_32[32]; -static complex_t __attribute__((aligned(16))) w_64[64]; -static complex_t __attribute__((aligned(16))) * w[7] = {w_1, w_2, w_4, w_8, w_16, w_32, w_64}; +/* Root values for IFFT */ +static sample_t roots16[3]; +static sample_t roots32[7]; +static sample_t roots64[15]; +static sample_t roots128[31]; /* Twiddle factors for IMDCT */ -static sample_t __attribute__((aligned(16))) xcos1[128]; -static sample_t __attribute__((aligned(16))) xsin1[128]; -static sample_t __attribute__((aligned(16))) xcos2[64]; -static sample_t __attribute__((aligned(16))) xsin2[64]; - -/* Windowing function for Modified DCT - Thank you acroread */ -sample_t imdct_window[] = { - 0.00014, 0.00024, 0.00037, 0.00051, 0.00067, 0.00086, 0.00107, 0.00130, - 0.00157, 0.00187, 0.00220, 0.00256, 0.00297, 0.00341, 0.00390, 0.00443, - 0.00501, 0.00564, 0.00632, 0.00706, 0.00785, 0.00871, 0.00962, 0.01061, - 0.01166, 0.01279, 0.01399, 0.01526, 0.01662, 0.01806, 0.01959, 0.02121, - 0.02292, 0.02472, 0.02662, 0.02863, 0.03073, 0.03294, 0.03527, 0.03770, - 0.04025, 0.04292, 0.04571, 0.04862, 0.05165, 0.05481, 0.05810, 0.06153, - 0.06508, 0.06878, 0.07261, 0.07658, 0.08069, 0.08495, 0.08935, 0.09389, - 0.09859, 0.10343, 0.10842, 0.11356, 0.11885, 0.12429, 0.12988, 0.13563, - 0.14152, 0.14757, 0.15376, 0.16011, 0.16661, 0.17325, 0.18005, 0.18699, - 0.19407, 0.20130, 0.20867, 0.21618, 0.22382, 0.23161, 0.23952, 0.24757, - 0.25574, 0.26404, 0.27246, 0.28100, 0.28965, 0.29841, 0.30729, 0.31626, - 0.32533, 0.33450, 0.34376, 0.35311, 0.36253, 0.37204, 0.38161, 0.39126, - 0.40096, 0.41072, 0.42054, 0.43040, 0.44030, 0.45023, 0.46020, 0.47019, - 0.48020, 0.49022, 0.50025, 0.51028, 0.52031, 0.53033, 0.54033, 0.55031, - 0.56026, 0.57019, 0.58007, 0.58991, 0.59970, 0.60944, 0.61912, 0.62873, - 0.63827, 0.64774, 0.65713, 0.66643, 0.67564, 0.68476, 0.69377, 0.70269, - 0.71150, 0.72019, 0.72877, 0.73723, 0.74557, 0.75378, 0.76186, 0.76981, - 0.77762, 0.78530, 0.79283, 0.80022, 0.80747, 0.81457, 0.82151, 0.82831, - 0.83496, 0.84145, 0.84779, 0.85398, 0.86001, 0.86588, 0.87160, 0.87716, - 0.88257, 0.88782, 0.89291, 0.89785, 0.90264, 0.90728, 0.91176, 0.91610, - 0.92028, 0.92432, 0.92822, 0.93197, 0.93558, 0.93906, 0.94240, 0.94560, - 0.94867, 0.95162, 0.95444, 0.95713, 0.95971, 0.96217, 0.96451, 0.96674, - 0.96887, 0.97089, 0.97281, 0.97463, 0.97635, 0.97799, 0.97953, 0.98099, - 0.98236, 0.98366, 0.98488, 0.98602, 0.98710, 0.98811, 0.98905, 0.98994, - 0.99076, 0.99153, 0.99225, 0.99291, 0.99353, 0.99411, 0.99464, 0.99513, - 0.99558, 0.99600, 0.99639, 0.99674, 0.99706, 0.99736, 0.99763, 0.99788, - 0.99811, 0.99831, 0.99850, 0.99867, 0.99882, 0.99895, 0.99908, 0.99919, - 0.99929, 0.99938, 0.99946, 0.99953, 0.99959, 0.99965, 0.99969, 0.99974, - 0.99978, 0.99981, 0.99984, 0.99986, 0.99988, 0.99990, 0.99992, 0.99993, - 0.99994, 0.99995, 0.99996, 0.99997, 0.99998, 0.99998, 0.99998, 0.99999, - 0.99999, 0.99999, 0.99999, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, - 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000, 1.00000 }; - - -static inline void swap_cmplx(complex_t *a, complex_t *b) -{ - complex_t tmp; +static complex_t pre1[128]; +static complex_t post1[64]; +static complex_t pre2[64]; +static complex_t post2[32]; - tmp = *a; - *a = *b; - *b = tmp; -} +static sample_t a52_imdct_window[256]; +static void (* ifft128) (complex_t * buf); +static void (* ifft64) (complex_t * buf); +static inline void ifft2 (complex_t * buf) +{ + double r, i; + + r = buf[0].real; + i = buf[0].imag; + buf[0].real += buf[1].real; + buf[0].imag += buf[1].imag; + buf[1].real = r - buf[1].real; + buf[1].imag = i - buf[1].imag; +} -static inline complex_t cmplx_mult(complex_t a, complex_t b) +static inline void ifft4 (complex_t * buf) { - complex_t ret; + double tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; + + tmp1 = buf[0].real + buf[1].real; + tmp2 = buf[3].real + buf[2].real; + tmp3 = buf[0].imag + buf[1].imag; + tmp4 = buf[2].imag + buf[3].imag; + tmp5 = buf[0].real - buf[1].real; + tmp6 = buf[0].imag - buf[1].imag; + tmp7 = buf[2].imag - buf[3].imag; + tmp8 = buf[3].real - buf[2].real; + + buf[0].real = tmp1 + tmp2; + buf[0].imag = tmp3 + tmp4; + buf[2].real = tmp1 - tmp2; + buf[2].imag = tmp3 - tmp4; + buf[1].real = tmp5 + tmp7; + buf[1].imag = tmp6 + tmp8; + buf[3].real = tmp5 - tmp7; + buf[3].imag = tmp6 - tmp8; +} - ret.real = a.real * b.real - a.imag * b.imag; - ret.imag = a.real * b.imag + a.imag * b.real; +/* the basic split-radix ifft butterfly */ + +#define BUTTERFLY(a0,a1,a2,a3,wr,wi) do { \ + tmp5 = a2.real * wr + a2.imag * wi; \ + tmp6 = a2.imag * wr - a2.real * wi; \ + tmp7 = a3.real * wr - a3.imag * wi; \ + tmp8 = a3.imag * wr + a3.real * wi; \ + tmp1 = tmp5 + tmp7; \ + tmp2 = tmp6 + tmp8; \ + tmp3 = tmp6 - tmp8; \ + tmp4 = tmp7 - tmp5; \ + a2.real = a0.real - tmp1; \ + a2.imag = a0.imag - tmp2; \ + a3.real = a1.real - tmp3; \ + a3.imag = a1.imag - tmp4; \ + a0.real += tmp1; \ + a0.imag += tmp2; \ + a1.real += tmp3; \ + a1.imag += tmp4; \ +} while (0) + +/* split-radix ifft butterfly, specialized for wr=1 wi=0 */ + +#define BUTTERFLY_ZERO(a0,a1,a2,a3) do { \ + tmp1 = a2.real + a3.real; \ + tmp2 = a2.imag + a3.imag; \ + tmp3 = a2.imag - a3.imag; \ + tmp4 = a3.real - a2.real; \ + a2.real = a0.real - tmp1; \ + a2.imag = a0.imag - tmp2; \ + a3.real = a1.real - tmp3; \ + a3.imag = a1.imag - tmp4; \ + a0.real += tmp1; \ + a0.imag += tmp2; \ + a1.real += tmp3; \ + a1.imag += tmp4; \ +} while (0) + +/* split-radix ifft butterfly, specialized for wr=wi */ + +#define BUTTERFLY_HALF(a0,a1,a2,a3,w) do { \ + tmp5 = (a2.real + a2.imag) * w; \ + tmp6 = (a2.imag - a2.real) * w; \ + tmp7 = (a3.real - a3.imag) * w; \ + tmp8 = (a3.imag + a3.real) * w; \ + tmp1 = tmp5 + tmp7; \ + tmp2 = tmp6 + tmp8; \ + tmp3 = tmp6 - tmp8; \ + tmp4 = tmp7 - tmp5; \ + a2.real = a0.real - tmp1; \ + a2.imag = a0.imag - tmp2; \ + a3.real = a1.real - tmp3; \ + a3.imag = a1.imag - tmp4; \ + a0.real += tmp1; \ + a0.imag += tmp2; \ + a1.real += tmp3; \ + a1.imag += tmp4; \ +} while (0) + +static inline void ifft8 (complex_t * buf) +{ + double tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8; - return ret; + ifft4 (buf); + ifft2 (buf + 4); + ifft2 (buf + 6); + BUTTERFLY_ZERO (buf[0], buf[2], buf[4], buf[6]); + BUTTERFLY_HALF (buf[1], buf[3], buf[5], buf[7], roots |