summaryrefslogtreecommitdiff
path: root/src/libac3
diff options
context:
space:
mode:
Diffstat (limited to 'src/libac3')
-rw-r--r--src/libac3/Makefile.am47
-rw-r--r--src/libac3/ac3.h54
-rw-r--r--src/libac3/ac3_internal.h359
-rw-r--r--src/libac3/bit_allocate.c509
-rw-r--r--src/libac3/bit_allocate.h24
-rw-r--r--src/libac3/bitstream.c79
-rw-r--r--src/libac3/bitstream.h46
-rw-r--r--src/libac3/bswap.h60
-rw-r--r--src/libac3/cmplx.h9
-rw-r--r--src/libac3/coeff.c437
-rw-r--r--src/libac3/coeff.h24
-rw-r--r--src/libac3/crc.c100
-rw-r--r--src/libac3/crc.h27
-rw-r--r--src/libac3/decode.c314
-rw-r--r--src/libac3/decode.h22
-rw-r--r--src/libac3/dither.c117
-rw-r--r--src/libac3/dither.h37
-rw-r--r--src/libac3/downmix.c158
-rw-r--r--src/libac3/downmix.h43
-rw-r--r--src/libac3/exponent.c138
-rw-r--r--src/libac3/exponent.h28
-rw-r--r--src/libac3/imdct.c661
-rw-r--r--src/libac3/imdct.h36
-rw-r--r--src/libac3/parse.c484
-rw-r--r--src/libac3/parse.h26
-rw-r--r--src/libac3/rematrix.c95
-rw-r--r--src/libac3/rematrix.h25
-rw-r--r--src/libac3/sanity_check.c128
-rw-r--r--src/libac3/sanity_check.h27
-rw-r--r--src/libac3/srfft.c309
-rw-r--r--src/libac3/srfft.h39
-rw-r--r--src/libac3/srfftp.h305
32 files changed, 4767 insertions, 0 deletions
diff --git a/src/libac3/Makefile.am b/src/libac3/Makefile.am
new file mode 100644
index 000000000..6318b3255
--- /dev/null
+++ b/src/libac3/Makefile.am
@@ -0,0 +1,47 @@
+CFLAGS = @BUILD_LIB_STATIC@ @GLOBAL_CFLAGS@
+
+noinst_LTLIBRARIES = libac3.la
+
+libac3_la_SOURCES = bitstream.c bit_allocate.c \
+ decode.c coeff.c exponent.c parse.c crc.c rematrix.c \
+ dither.c sanity_check.c srfft.c imdct.c downmix.c
+
+noinst_HEADERS = ac3.h ac3_internal.h bitstream.h \
+ imdct.h coeff.h exponent.h bit_allocate.h parse.h \
+ crc.h rematrix.h downmix.h dither.h \
+ sanity_check.h srfft.h srfftp.h cmplx.h decode.h \
+ bswap.h
+
+##
+## Install header files (default=$includedir/xine)
+##
+install-includeHEADERS: $(include_HEADERS)
+ @$(NORMAL_INSTALL)
+ $(mkinstalldirs) $(DESTDIR)$(includedir)/xine
+ @list='$(include_HEADERS)'; for p in $$list; do \
+ if test -f "$$p"; then d= ; else d="$(srcdir)/"; fi; \
+ echo " $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/xine/$$p"; \
+ $(INSTALL_DATA) $$d$$p $(DESTDIR)$(includedir)/xine/$$p; \
+ done
+
+
+##
+## Remove them
+##
+uninstall-includeHEADERS:
+ @$(NORMAL_UNINSTALL)
+ list='$(include_HEADERS)'; for p in $$list; do \
+ rm -f $(DESTDIR)$(includedir)/xine/$$p; \
+ done
+
+
+debug:
+ $(MAKE) CFLAGS="$(DEBUG_CFLAGS)"
+
+mostlyclean-generic:
+ -rm -f *~ \#* .*~ .\#*
+
+maintainer-clean-generic:
+ -@echo "This command is intended for maintainers to use;"
+ -@echo "it deletes files that may require special tools to rebuild."
+ -rm -f Makefile.in
diff --git a/src/libac3/ac3.h b/src/libac3/ac3.h
new file mode 100644
index 000000000..dcc125f85
--- /dev/null
+++ b/src/libac3/ac3.h
@@ -0,0 +1,54 @@
+/*
+ * ac3.h
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#ifndef __AC3_H__
+#define __AC3_H__
+
+#include <inttypes.h>
+#include "audio_out.h"
+
+#define AC3_DOLBY_SURR_ENABLE (1<<0)
+#define AC3_ALTIVEC_ENABLE (1<<1)
+#define AC3_3DNOW_ENABLE (1<<2)
+#define AC3_MMX_ENABLE (1<<3)
+#define AC3_SSE_ENABLE (1<<4)
+
+typedef struct ac3_config_s {
+ // Bit flags that enable various things
+ uint32_t flags;
+ //Callback that points the decoder to new stream data
+ void (*fill_buffer_callback)(uint8_t **, uint8_t **);
+ // Number of discrete channels in final output (for downmixing)
+ uint16_t num_output_ch;
+ // Which channel of a dual mono stream to select
+ uint16_t dual_mono_ch_sel;
+} ac3_config_t;
+
+void ac3_init(ac3_config_t *,ao_functions_t*);
+
+size_t ac3_decode_data(uint8_t *data_start,uint8_t *data_end,uint32_t pts);
+
+void ac3_reset(void);
+
+#endif
diff --git a/src/libac3/ac3_internal.h b/src/libac3/ac3_internal.h
new file mode 100644
index 000000000..cac0c7940
--- /dev/null
+++ b/src/libac3/ac3_internal.h
@@ -0,0 +1,359 @@
+/*
+ * ac3_internal.h
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef __GNUC__
+#define inline
+#endif
+
+#define FAST_ERROR
+#ifdef FAST_ERROR
+#include <setjmp.h>
+#endif
+
+/* Exponent strategy constants */
+#define EXP_REUSE (0)
+#define EXP_D15 (1)
+#define EXP_D25 (2)
+#define EXP_D45 (3)
+
+/* Delta bit allocation constants */
+#define DELTA_BIT_REUSE (0)
+#define DELTA_BIT_NEW (1)
+#define DELTA_BIT_NONE (2)
+#define DELTA_BIT_RESERVED (3)
+
+/* samples work structure */
+typedef float stream_samples_t[6][256];
+
+/* global config structure */
+extern ac3_config_t ac3_config;
+/* global error flag */
+#ifdef FAST_ERROR
+extern jmp_buf error_jmp_mark;
+#define HANDLE_ERROR() longjmp (error_jmp_mark, -1)
+#else
+extern uint32_t error_flag;
+#endif
+
+/* Everything you wanted to know about band structure */
+/*
+ * The entire frequency domain is represented by 256 real
+ * floating point fourier coefficients. Only the lower 253
+ * coefficients are actually utilized however. We use arrays
+ * of 256 to be efficient in some cases.
+ *
+ * The 5 full bandwidth channels (fbw) can have their higher
+ * frequencies coupled together. These coupled channels then
+ * share their high frequency components.
+ *
+ * This coupling band is broken up into 18 sub-bands starting
+ * at mantissa number 37. Each sub-band is 12 bins wide.
+ *
+ * There are 50 bit allocation sub-bands which cover the entire
+ * frequency range. The sub-bands are of non-uniform width, and
+ * approximate a 1/6 octave scale.
+ */
+
+/* The following structures are filled in by their corresponding parse_*
+ * functions. See http://www.atsc.org/Standards/A52/a_52.pdf for
+ * full details on each field. Indented fields are used to denote
+ * conditional fields.
+ */
+
+typedef struct syncinfo_s
+{
+ uint32_t magic;
+ /* Sync word == 0x0B77 */
+ uint16_t syncword;
+ /* crc for the first 5/8 of the sync block */
+ /* uint16_t crc1; */
+ /* Stream Sampling Rate (kHz) 0 = 48, 1 = 44.1, 2 = 32, 3 = reserved */
+ uint16_t fscod;
+ /* Frame size code */
+ uint16_t frmsizecod;
+
+ /* Information not in the AC-3 bitstream, but derived */
+ /* Frame size in 16 bit words */
+ uint16_t frame_size;
+ /* Bit rate in kilobits */
+ uint16_t bit_rate;
+ /* sampling rate in hertz */
+ uint32_t sampling_rate;
+} syncinfo_t;
+
+typedef struct bsi_s
+{
+ uint32_t magic;
+ /* Bit stream identification == 0x8 */
+ uint16_t bsid;
+ /* Bit stream mode */
+ uint16_t bsmod;
+ /* Audio coding mode */
+ uint16_t acmod;
+ /* If we're using the centre channel then */
+ /* centre mix level */
+ uint16_t cmixlev;
+ /* If we're using the surround channel then */
+ /* surround mix level */
+ uint16_t surmixlev;
+ /* If we're in 2/0 mode then */
+ /* Dolby surround mix level - NOT USED - */
+ uint16_t dsurmod;
+ /* Low frequency effects on */
+ uint16_t lfeon;
+ /* Dialogue Normalization level */
+ uint16_t dialnorm;
+ /* Compression exists */
+ uint16_t compre;
+ /* Compression level */
+ uint16_t compr;
+ /* Language code exists */
+ uint16_t langcode;
+ /* Language code */
+ uint16_t langcod;
+ /* Audio production info exists*/
+ uint16_t audprodie;
+ uint16_t mixlevel;
+ uint16_t roomtyp;
+ /* If we're in dual mono mode (acmod == 0) then extra stuff */
+ uint16_t dialnorm2;
+ uint16_t compr2e;
+ uint16_t compr2;
+ uint16_t langcod2e;
+ uint16_t langcod2;
+ uint16_t audprodi2e;
+ uint16_t mixlevel2;
+ uint16_t roomtyp2;
+ /* Copyright bit */
+ uint16_t copyrightb;
+ /* Original bit */
+ uint16_t origbs;
+ /* Timecode 1 exists */
+ uint16_t timecod1e;
+ /* Timecode 1 */
+ uint16_t timecod1;
+ /* Timecode 2 exists */
+ uint16_t timecod2e;
+ /* Timecode 2 */
+ uint16_t timecod2;
+ /* Additional bit stream info exists */
+ uint16_t addbsie;
+ /* Additional bit stream length - 1 (in bytes) */
+ uint16_t addbsil;
+ /* Additional bit stream information (max 64 bytes) */
+ uint8_t addbsi[64];
+
+ /* Information not in the AC-3 bitstream, but derived */
+ /* Number of channels (excluding LFE)
+ * Derived from acmod */
+ uint16_t nfchans;
+} bsi_t;
+
+
+/* more pain */
+typedef struct audblk_s
+{
+ uint32_t magic1;
+ /* block switch bit indexed by channel num */
+ uint16_t blksw[5];
+ /* dither enable bit indexed by channel num */
+ uint16_t dithflag[5];
+ /* dynamic range gain exists */
+ uint16_t dynrnge;
+ /* dynamic range gain */
+ uint16_t dynrng;
+ /* if acmod==0 then */
+ /* dynamic range 2 gain exists */
+ uint16_t dynrng2e;
+ /* dynamic range 2 gain */
+ uint16_t dynrng2;
+ /* coupling strategy exists */
+ uint16_t cplstre;
+ /* coupling in use */
+ uint16_t cplinu;
+ /* channel coupled */
+ uint16_t chincpl[5];
+ /* if acmod==2 then */
+ /* Phase flags in use */
+ uint16_t phsflginu;
+ /* coupling begin frequency code */
+ uint16_t cplbegf;
+ /* coupling end frequency code */
+ uint16_t cplendf;
+ /* coupling band structure bits */
+ uint16_t cplbndstrc[18];
+ /* Do coupling co-ords exist for this channel? */
+ uint16_t cplcoe[5];
+ /* Master coupling co-ordinate */
+ uint16_t mstrcplco[5];
+ /* Per coupling band coupling co-ordinates */
+ uint16_t cplcoexp[5][18];
+ uint16_t cplcomant[5][18];
+ /* Phase flags for dual mono */
+ uint16_t phsflg[18];
+ /* Is there a rematrixing strategy */
+ uint16_t rematstr;
+ /* Rematrixing bits */
+ uint16_t rematflg[4];
+ /* Coupling exponent strategy */
+ uint16_t cplexpstr;
+ /* Exponent strategy for full bandwidth channels */
+ uint16_t chexpstr[5];
+ /* Exponent strategy for lfe channel */
+ uint16_t lfeexpstr;
+ /* Channel bandwidth for independent channels */
+ uint16_t chbwcod[5];
+ /* The absolute coupling exponent */
+ uint16_t cplabsexp;
+ /* Coupling channel exponents (D15 mode gives 18 * 12 /3 encoded exponents */
+ uint16_t cplexps[18 * 12 / 3];
+ /* Sanity checking constant */
+ uint32_t magic2;
+ /* fbw channel exponents */
+ uint16_t exps[5][252 / 3];
+ /* channel gain range */
+ uint16_t gainrng[5];
+ /* low frequency exponents */
+ uint16_t lfeexps[3];
+
+ /* Bit allocation info */
+ uint16_t baie;
+ /* Slow decay code */
+ uint16_t sdcycod;
+ /* Fast decay code */
+ uint16_t fdcycod;
+ /* Slow gain code */
+ uint16_t sgaincod;
+ /* dB per bit code */
+ uint16_t dbpbcod;
+ /* masking floor code */
+ uint16_t floorcod;
+
+ /* SNR offset info */
+ uint16_t snroffste;
+ /* coarse SNR offset */
+ uint16_t csnroffst;
+ /* coupling fine SNR offset */
+ uint16_t cplfsnroffst;
+ /* coupling fast gain code */
+ uint16_t cplfgaincod;
+ /* fbw fine SNR offset */
+ uint16_t fsnroffst[5];
+ /* fbw fast gain code */
+ uint16_t fgaincod[5];
+ /* lfe fine SNR offset */
+ uint16_t lfefsnroffst;
+ /* lfe fast gain code */
+ uint16_t lfefgaincod;
+
+ /* Coupling leak info */
+ uint16_t cplleake;
+ /* coupling fast leak initialization */
+ uint16_t cplfleak;
+ /* coupling slow leak initialization */
+ uint16_t cplsleak;
+
+ /* delta bit allocation info */
+ uint16_t deltbaie;
+ /* coupling delta bit allocation exists */
+ uint16_t cpldeltbae;
+ /* fbw delta bit allocation exists */
+ uint16_t deltbae[5];
+ /* number of cpl delta bit segments */
+ uint16_t cpldeltnseg;
+ /* coupling delta bit allocation offset */
+ uint16_t cpldeltoffst[8];
+ /* coupling delta bit allocation length */
+ uint16_t cpldeltlen[8];
+ /* coupling delta bit allocation length */
+ uint16_t cpldeltba[8];
+ /* number of delta bit segments */
+ uint16_t deltnseg[5];
+ /* fbw delta bit allocation offset */
+ uint16_t deltoffst[5][8];
+ /* fbw delta bit allocation length */
+ uint16_t deltlen[5][8];
+ /* fbw delta bit allocation length */
+ uint16_t deltba[5][8];
+
+ /* skip length exists */
+ uint16_t skiple;
+ /* skip length */
+ uint16_t skipl;
+
+ //Removed Feb 2000 -ah
+ //added Jul 2000 ++dent
+ /* channel mantissas */
+ uint16_t chmant[5][256];
+
+ /* coupling mantissas */
+// uint16_t cplmant[256];
+
+ //Added Jun 2000 -MaXX
+ /* coupling floats */
+ float cpl_flt[ 256 ];
+
+ //Removed Feb 2000 -ah
+ //added Jul 2000 ++dent
+ /* coupling mantissas */
+ uint16_t lfemant[7];
+
+
+ /* -- Information not in the bitstream, but derived thereof -- */
+
+ /* Number of coupling sub-bands */
+ uint16_t ncplsubnd;
+
+ /* Number of combined coupling sub-bands
+ * Derived from ncplsubnd and cplbndstrc */
+ uint16_t ncplbnd;
+
+ /* Number of exponent groups by channel
+ * Derived from strmant, endmant */
+ uint16_t nchgrps[5];
+
+ /* Number of coupling exponent groups
+ * Derived from cplbegf, cplendf, cplexpstr */
+ uint16_t ncplgrps;
+
+ /* End mantissa numbers of fbw channels */
+ uint16_t endmant[5];
+
+ /* Start and end mantissa numbers for the coupling channel */
+ uint16_t cplstrtmant;
+ uint16_t cplendmant;
+
+ /* Decoded exponent info */
+ uint16_t fbw_exp[5][256];
+ uint16_t cpl_exp[256];
+ uint16_t lfe_exp[7];
+
+ /* Bit allocation pointer results */
+ uint16_t fbw_bap[5][256];
+ uint16_t cpl_bap[256];
+ uint16_t lfe_bap[7];
+
+ uint32_t magic3;
+} audblk_t;
+
+
diff --git a/src/libac3/bit_allocate.c b/src/libac3/bit_allocate.c
new file mode 100644
index 000000000..7a233a519
--- /dev/null
+++ b/src/libac3/bit_allocate.c
@@ -0,0 +1,509 @@
+/*
+ * bit_allocate.c
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include "ac3.h"
+#include "ac3_internal.h"
+
+
+
+static inline int16_t logadd(int16_t a,int16_t b);
+static int16_t calc_lowcomp(int16_t a,int16_t b0,int16_t b1,int16_t bin);
+static inline uint16_t min(int16_t a,int16_t b);
+static inline uint16_t max(int16_t a,int16_t b);
+static void ba_compute_psd(int16_t start, int16_t end, int16_t exps[],
+ int16_t psd[], int16_t bndpsd[]);
+
+static void ba_compute_excitation(int16_t start, int16_t end,int16_t fgain,
+ int16_t fastleak, int16_t slowleak, int16_t is_lfe, int16_t bndpsd[],
+ int16_t excite[]);
+static void ba_compute_mask(int16_t start, int16_t end, uint16_t fscod,
+ uint16_t deltbae, uint16_t deltnseg, uint16_t deltoffst[], uint16_t deltba[],
+ uint16_t deltlen[], int16_t excite[], int16_t mask[]);
+static void ba_compute_bap(int16_t start, int16_t end, int16_t snroffset,
+ int16_t psd[], int16_t mask[], int16_t bap[]);
+
+/* Misc LUTs for bit allocation process */
+
+static int16_t slowdec[] = { 0x0f, 0x11, 0x13, 0x15 };
+static int16_t fastdec[] = { 0x3f, 0x53, 0x67, 0x7b };
+static int16_t slowgain[] = { 0x540, 0x4d8, 0x478, 0x410 };
+static int16_t dbpbtab[] = { 0x000, 0x700, 0x900, 0xb00 };
+
+static uint16_t floortab[] = { 0x2f0, 0x2b0, 0x270, 0x230, 0x1f0, 0x170, 0x0f0, 0xf800 };
+static int16_t fastgain[] = { 0x080, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380, 0x400 };
+
+
+static int16_t bndtab[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
+ 20, 21, 22, 23, 24, 25, 26, 27, 28, 31,
+ 34, 37, 40, 43, 46, 49, 55, 61, 67, 73,
+ 79, 85, 97, 109, 121, 133, 157, 181, 205, 229 };
+
+static int16_t bndsz[] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 3, 3,
+ 3, 3, 3, 3, 3, 6, 6, 6, 6, 6,
+ 6, 12, 12, 12, 12, 24, 24, 24, 24, 24 };
+
+static int16_t masktab[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 28, 28, 29,
+ 29, 29, 30, 30, 30, 31, 31, 31, 32, 32, 32, 33, 33, 33, 34, 34,
+ 34, 35, 35, 35, 35, 35, 35, 36, 36, 36, 36, 36, 36, 37, 37, 37,
+ 37, 37, 37, 38, 38, 38, 38, 38, 38, 39, 39, 39, 39, 39, 39, 40,
+ 40, 40, 40, 40, 40, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41, 41,
+ 41, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 42, 43, 43, 43,
+ 43, 43, 43, 43, 43, 43, 43, 43, 43, 44, 44, 44, 44, 44, 44, 44,
+ 44, 44, 44, 44, 44, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45,
+ 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 45, 46, 46, 46,
+ 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, 46,
+ 46, 46, 46, 46, 46, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, 48, 48, 48,
+ 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48,
+ 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49,
+ 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 0, 0, 0 };
+
+
+static int16_t latab[] = { 0x0040, 0x003f, 0x003e, 0x003d, 0x003c, 0x003b, 0x003a, 0x0039,
+ 0x0038, 0x0037, 0x0036, 0x0035, 0x0034, 0x0034, 0x0033, 0x0032,
+ 0x0031, 0x0030, 0x002f, 0x002f, 0x002e, 0x002d, 0x002c, 0x002c,
+ 0x002b, 0x002a, 0x0029, 0x0029, 0x0028, 0x0027, 0x0026, 0x0026,
+ 0x0025, 0x0024, 0x0024, 0x0023, 0x0023, 0x0022, 0x0021, 0x0021,
+ 0x0020, 0x0020, 0x001f, 0x001e, 0x001e, 0x001d, 0x001d, 0x001c,
+ 0x001c, 0x001b, 0x001b, 0x001a, 0x001a, 0x0019, 0x0019, 0x0018,
+ 0x0018, 0x0017, 0x0017, 0x0016, 0x0016, 0x0015, 0x0015, 0x0015,
+ 0x0014, 0x0014, 0x0013, 0x0013, 0x0013, 0x0012, 0x0012, 0x0012,
+ 0x0011, 0x0011, 0x0011, 0x0010, 0x0010, 0x0010, 0x000f, 0x000f,
+ 0x000f, 0x000e, 0x000e, 0x000e, 0x000d, 0x000d, 0x000d, 0x000d,
+ 0x000c, 0x000c, 0x000c, 0x000c, 0x000b, 0x000b, 0x000b, 0x000b,
+ 0x000a, 0x000a, 0x000a, 0x000a, 0x000a, 0x0009, 0x0009, 0x0009,
+ 0x0009, 0x0009, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008,
+ 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0006, 0x0006,
+ 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0006, 0x0005, 0x0005,
+ 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0005, 0x0004, 0x0004,
+ 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004, 0x0004,
+ 0x0004, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003,
+ 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002, 0x0002,
+ 0x0002, 0x0002, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001, 0x0001,
+ 0x0001, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+ 0x0000, 0x0000, 0x0000, 0x0000};
+
+static int16_t hth[][50] = {{ 0x04d0, 0x04d0, 0x0440, 0x0400, 0x03e0, 0x03c0, 0x03b0, 0x03b0,
+ 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390, 0x0390,
+ 0x0380, 0x0380, 0x0370, 0x0370, 0x0360, 0x0360, 0x0350, 0x0350,
+ 0x0340, 0x0340, 0x0330, 0x0320, 0x0310, 0x0300, 0x02f0, 0x02f0,
+ 0x02f0, 0x02f0, 0x0300, 0x0310, 0x0340, 0x0390, 0x03e0, 0x0420,
+ 0x0460, 0x0490, 0x04a0, 0x0460, 0x0440, 0x0440, 0x0520, 0x0800,
+ 0x0840, 0x0840 },
+
+ { 0x04f0, 0x04f0, 0x0460, 0x0410, 0x03e0, 0x03d0, 0x03c0, 0x03b0,
+ 0x03b0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390,
+ 0x0390, 0x0380, 0x0380, 0x0380, 0x0370, 0x0370, 0x0360, 0x0360,
+ 0x0350, 0x0350, 0x0340, 0x0340, 0x0320, 0x0310, 0x0300, 0x02f0,
+ 0x02f0, 0x02f0, 0x02f0, 0x0300, 0x0320, 0x0350, 0x0390, 0x03e0,
+ 0x0420, 0x0450, 0x04a0, 0x0490, 0x0460, 0x0440, 0x0480, 0x0630,
+ 0x0840, 0x0840 },
+
+ { 0x0580, 0x0580, 0x04b0, 0x0450, 0x0420, 0x03f0, 0x03e0, 0x03d0,
+ 0x03c0, 0x03b0, 0x03b0, 0x03b0, 0x03a0, 0x03a0, 0x03a0, 0x03a0,
+ 0x03a0, 0x03a0, 0x03a0, 0x03a0, 0x0390, 0x0390, 0x0390, 0x0390,
+ 0x0380, 0x0380, 0x0380, 0x0370, 0x0360, 0x0350, 0x0340, 0x0330,
+ 0x0320, 0x0310, 0x0300, 0x02f0, 0x02f0, 0x02f0, 0x0300, 0x0310,
+ 0x0330, 0x0350, 0x03c0, 0x0410, 0x0470, 0x04a0, 0x0460, 0x0440,
+ 0x0450, 0x04e0 }};
+
+
+static int16_t baptab[] = { 0, 1, 1, 1, 1, 1, 2, 2, 3, 3, 3, 4, 4, 5, 5, 6,
+ 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10,
+ 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14,
+ 14, 14, 14, 14, 14, 14, 14, 15, 15, 15, 15, 15, 15, 15, 15, 15 };
+
+static int16_t sdecay;
+static int16_t fdecay;
+static int16_t sgain;
+static int16_t dbknee;
+static int16_t floor;
+static int16_t psd[256];
+static int16_t bndpsd[256];
+static int16_t excite[256];
+static int16_t mask[256];
+
+
+/**
+ *
+ **/
+
+static inline uint16_t max(int16_t a,int16_t b)
+{
+ return (a > b ? a : b);
+}
+
+
+/**
+ *
+ **/
+
+static inline uint16_t min(int16_t a,int16_t b)
+{
+ return (a < b ? a : b);
+}
+
+
+/**
+ *
+ **/
+
+static inline int16_t logadd(int16_t a,int16_t b)
+{
+ int16_t c;
+ int16_t address;
+
+ c = a - b;
+ address = min((abs(c) >> 1), 255);
+
+ if (c >= 0)
+ return(a + latab[address]);
+ else
+ return(b + latab[address]);
+}
+
+
+/**
+ *
+ **/
+
+void bit_allocate(uint16_t fscod, bsi_t *bsi, audblk_t *audblk)
+{
+ uint16_t i;
+ int16_t fgain;
+ int16_t snroffset;
+ int16_t start;
+ int16_t end;
+ int16_t fastleak;
+ int16_t slowleak;
+
+ /* Only perform bit_allocation if the exponents have changed or we
+ * have new sideband information */
+ if (audblk->chexpstr[0] == 0 && audblk->chexpstr[1] == 0 &&
+ audblk->chexpstr[2] == 0 && audblk->chexpstr[3] == 0 &&
+ audblk->chexpstr[4] == 0 && audblk->cplexpstr == 0 &&
+ audblk->lfeexpstr == 0 && audblk->baie == 0 &&
+ audblk->snroffste == 0 && audblk->deltbaie == 0)
+ return;
+
+ /* Do some setup before we do the bit alloc */
+ sdecay = slowdec[audblk->sdcycod];
+ fdecay = fastdec[audblk->fdcycod];
+ sgain = slowgain[audblk->sgaincod];
+ dbknee = dbpbtab[audblk->dbpbcod];
+ floor = floortab[audblk->floorcod];
+
+ /* if all the SNR offset constants are zero then the whole block is zero */
+ if(!audblk->csnroffst && !audblk->fsnroffst[0] &&
+ !audblk->fsnroffst[1] && !audblk->fsnroffst[2] &&
+ !audblk->fsnroffst[3] && !audblk->fsnroffst[4] &&
+ !audblk->cplfsnroffst && !audblk->lfefsnroffst) {
+ memset(audblk->fbw_bap,0,sizeof(uint16_t) * 256 * 5);
+ memset(audblk->cpl_bap,0,sizeof(uint16_t) * 256);
+ memset(audblk->lfe_bap,0,sizeof(uint16_t) * 7);
+ return;
+ }
+
+
+ for(i = 0; i < bsi->nfchans; i++)
+ {
+ start = 0;
+ end = audblk->endmant[i] ;
+ fgain = fastgain[audblk->fgaincod[i]];
+ snroffset = (((audblk->csnroffst - 15) << 4) + audblk->fsnroffst[i]) << 2 ;
+ fastleak = 0;
+ slowleak = 0;
+
+ ba_compute_psd(start, end, audblk->fbw_exp[i], psd, bndpsd);
+
+ ba_compute_excitation(start, end , fgain, fastleak, slowleak, 0, bndpsd, excite);
+
+ ba_compute_mask(start, end, fscod, audblk->deltbae[i], audblk->deltnseg[i],
+ audblk->deltoffst[i], audblk->deltba[i], audblk->deltlen[i], excite, mask);
+
+ ba_compute_bap(start, end, snroffset, psd, mask, audblk->fbw_bap[i]);
+ }
+
+ if(audblk->cplinu) {
+ start = audblk->cplstrtmant;
+ end = audblk->cplendmant;
+ fgain = fastgain[audblk->cplfgaincod];
+ snroffset = (((audblk->csnroffst - 15) << 4) + audblk->cplfsnroffst) << 2 ;
+ fastleak = (audblk->cplfleak << 8) + 768;
+ slowleak = (audblk->cplsleak << 8) + 768;
+
+ ba_compute_psd(start, end, audblk->cpl_exp, psd, bndpsd);
+
+ ba_compute_excitation(start, end , fgain, fastleak, slowleak, 0, bndpsd, excite);
+
+ ba_compute_mask(start, end, fscod, audblk->cpldeltbae, audblk->cpldeltnseg,
+ audblk->cpldeltoffst, audblk->cpldeltba, audblk->cpldeltlen, excite, mask);
+
+ ba_compute_bap(start, end, snroffset, psd, mask, audblk->cpl_bap);
+ }
+
+ if(bsi->lfeon) {
+ start = 0;
+ end = 7;
+ fgain = fastgain[audblk->lfefgaincod];
+ snroffset = (((audblk->csnroffst - 15) << 4) + audblk->lfefsnroffst) << 2 ;
+ fastleak = 0;
+ slowleak = 0;
+
+ ba_compute_psd(start, end, audblk->lfe_exp, psd, bndpsd);
+
+ ba_compute_excitation(start, end , fgain, fastleak, slowleak, 1, bndpsd, excite);
+
+ /* Perform no delta bit allocation for lfe */
+ ba_compute_mask(start, end, fscod, 2, 0, 0, 0, 0, excite, mask);
+
+ ba_compute_bap(start, end, snroffset, psd, mask, audblk->lfe_bap);
+ }
+}
+
+
+/**
+ *
+ **/
+
+static void ba_compute_psd(int16_t start, int16_t end, int16_t exps[],
+ int16_t psd[], int16_t bndpsd[])
+{
+ int bin,j,k;
+ int16_t lastbin = 0;
+
+ /* Map the exponents into dBs */
+ for (bin=start; bin<end; bin++) {
+ psd[bin] = (3072 - (exps[bin] << 7));
+ }
+
+ /* Integrate the psd function over each bit allocation band */
+ j = start;
+ k = masktab[start];
+
+ do {
+ lastbin = min(bndtab[k] + bndsz[k], end);
+ bndpsd[k] = psd[j];
+ j++;
+
+ for (; j < lastbin; j++) {
+ bndpsd[k] = logadd(bndpsd[k], psd[j]);
+ }
+
+ k++;
+ } while (end > lastbin);
+}
+
+
+/**
+ *
+ **/
+
+static void ba_compute_excitation(int16_t start, int16_t end,int16_t fgain,
+ int16_t fastleak, int16_t slowleak, int16_t is_lfe, int16_t bndpsd[],
+ int16_t excite[])
+{
+ int bin;
+ int16_t bndstrt;
+ int16_t bndend;
+ int16_t lowcomp = 0;
+ int16_t begin = 0;
+
+ /* Compute excitation function */
+ bndstrt = masktab[start];
+ bndend = masktab[end - 1] + 1;
+
+ if (bndstrt == 0) { /* For fbw and lfe channels */
+ lowcomp = calc_lowcomp(lowcomp, bndpsd[0], bndpsd[1], 0);
+ excite[0] = bndpsd[0] - fgain - lowcomp;
+ lowcomp = calc_lowcomp(lowcomp, bndpsd[1], bndpsd[2], 1);
+ excite[1] = bndpsd[1] - fgain - lowcomp;
+ begin = 7 ;
+
+// Note: Do not call calc_lowcomp() for the last band of the lfe channel,(bin=6)
+ for (bin = 2; bin < 7; bin++) {
+ if (!(is_lfe && (bin == 6)))
+ lowcomp = calc_lowcomp(lowcomp, bndpsd[bin], bndpsd[bin+1], bin);
+ fastleak = bndpsd[bin] - fgain;
+ slowleak = bndpsd[bin] - sgain;
+ excite[bin] = fastleak - lowcomp;
+
+ if (!(is_lfe && (bin == 6))) {
+ if (bndpsd[bin] <= bndpsd[bin+1]) {
+ begin = bin + 1 ;
+ break;
+ }
+ }
+ }
+
+ for (bin = begin; bin < min(bndend, 22); bin++) {
+ if (!(is_lfe && (bin == 6)))
+ lowcomp = calc_lowcomp(lowcomp, bndpsd[bin], bndpsd[bin+1], bin);
+ fastleak -= fdecay ;
+ fastleak = max(fastleak, bndpsd[bin] - fgain);
+ slowleak -= sdecay ;
+ slowleak = max(slowleak, bndpsd[bin] - sgain);
+ excite[bin] = max(fastleak - lowcomp, slowleak);
+ }
+ begin = 22;
+ }
+ else /* For coupling channel */
+ begin = bndstrt;
+
+ for (bin = begin; bin < bndend; bin++) {
+ fastleak -= fdecay;
+ fastleak = max(fastleak, bndpsd[bin] - fgain);
+ slowleak -= sdecay;
+ slowleak = max(slowleak, bndpsd[bin] - sgain);
+ excite[bin] = max(fastleak, slowleak) ;
+ }
+}
+
+
+/**
+ *
+ **/
+
+static void ba_compute_mask(int16_t start, int16_t end, uint16_t fscod,
+ uint16_t deltbae, uint16_t deltnseg, uint16_t deltoffst[], uint16_t deltba[],
+ uint16_t deltlen[], int16_t excite[], int16_t mask[])
+{
+ int bin,k;
+ int16_t bndstrt;
+ int16_t bndend;
+ int16_t delta;
+
+ bndstrt = masktab[start];
+ bndend = masktab[end - 1] + 1;
+
+ /* Compute the masking curve */
+
+ for (bin = bndstrt; bin < bndend; bin++) {
+ if (bndpsd[bin] < dbknee) {
+ excite[bin] += ((dbknee - bndpsd[bin]) >> 2);
+ }
+ mask[bin] = max(excite[bin], hth[fscod][bin]);
+ }
+
+ /* Perform delta bit modulation if necessary */
+ if ((deltbae == DELTA_BIT_REUSE) || (deltbae == DELTA_BIT_NEW)) {
+ int16_t band = 0;
+ int16_t seg = 0;
+
+ for (seg = 0; seg < deltnseg+1; seg++) {
+ band += deltoffst[seg];
+
+ if (deltba[seg] >= 4) {
+ delta = (deltba[seg] - 3) << 7;
+ } else {
+ delta = (deltba[seg] - 4) << 7;
+ }
+
+ for (k = 0; k < deltlen[seg]; k++) {
+ mask[band] += delta;
+ band++;
+ }
+ }
+ }
+}
+
+
+/**
+ *
+ **/
+
+static void ba_compute_bap(int16_t start, int16_t end, int16_t snroffset,
+ int16_t psd[], int16_t mask[], int16_t bap[])
+{
+ int i,j,k;
+ int16_t lastbin = 0;
+ int16_t address = 0;
+
+ /* Compute the bit allocation pointer for each bin */
+ i = start;
+ j = masktab[start];
+
+ do {
+ lastbin = min(bndtab[j] + bndsz[j], end);
+ mask[j] -= snroffset;
+ mask[j] -= floor;
+
+ if (mask[j] < 0)
+ mask[j] = 0;
+
+ mask[j] &= 0x1fe0;
+ mask[j] += floor;
+ for (k = i; k < lastbin; k++) {
+ address = (psd[i] - mask[j]) >> 5;
+ address = min(63, max(0, address));
+ bap[i] = baptab[address];
+ i++;
+ }
+ j++;
+ } while (end > lastbin);
+}
+
+
+/**
+ *
+ **/
+
+static int16_t calc_lowcomp (int16_t a, int16_t b0, int16_t b1, int16_t bin)
+{
+
+ if (bin < 7) {
+ if ((b0 + 256) == b1)
+ a = 384;
+ else if (b0 > b1)
+ a = max(0, a - 64);
+ } else if (bin < 20) {
+ if ((b0 + 256) == b1)
+ a = 320;
+ else if (b0 > b1)
+ a = max(0, a - 64) ;
+ } else
+ a = max(0, a - 128);
+
+ return(a);
+}
+
diff --git a/src/libac3/bit_allocate.h b/src/libac3/bit_allocate.h
new file mode 100644
index 000000000..a6a3c7703
--- /dev/null
+++ b/src/libac3/bit_allocate.h
@@ -0,0 +1,24 @@
+/*
+ * bit_allocate.h
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+void bit_allocate(uint16_t fscod, bsi_t *bsi, audblk_t *audblk);
diff --git a/src/libac3/bitstream.c b/src/libac3/bitstream.c
new file mode 100644
index 000000000..78ac0eca7
--- /dev/null
+++ b/src/libac3/bitstream.c
@@ -0,0 +1,79 @@
+/*
+ * bitstream.c
+ *
+ * Copyright (C) Aaron Holtzman - Dec 1999
+ *
+ * This file is part of ac3dec, a free AC-3 audio decoder
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+
+#include <bswap.h>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "ac3.h"
+#include "ac3_internal.h"
+#include "bitstream.h"
+
+
+uint32_t ac3bits_left = 0;
+uint64_t ac3current_word;
+uint64_t *buffer_start = 0;
+
+
+static inline uint64_t getdword (void)
+{
+ return be2me_64 (*buffer_start++);
+}
+
+
+static inline void bitstream_fill_current (void)
+{
+ //ac3current_word = bswap_64 (*buffer_start++);
+ ac3current_word = getdword ();
+}
+
+
+uint32_t bitstream_get_bh (uint32_t num_bits)
+{
+ uint32_t result;
+
+ num_bits -= ac3bits_left;
+ result = (ac3current_word << (64 - ac3bits_left)) >> (64 - ac3bits_left);
+
+ bitstream_fill_current();
+
+ if(num_bits != 0)
+ result = (result << num_bits) | (ac3current_word >> (64 - num_bits));
+
+ ac3bits_left = 64 - num_bits;
+
+ return result;
+}
+
+
+void bitstream_init (uint8_t *start)
+{
+ //initialize the start of the buffer
+ buffer_start = (uint64_t *) start;
+ ac3bits_left = 0;
+}
diff --git a/src/libac3/bitstream.h b/src/libac3/bitstream.h
new file mode 100644
index 000000000..392c7401c
--- /dev/null
+++ b/src/libac3/bitstream.h
@@ -0,0 +1,46 @@
+/*
+ * bitstream.h
+ *
+ * Copyright (C) Aaron Holtzman - Dec 1999
+ *
+ * This file is part of ac3dec, a free AC-3 audio decoder
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+#include <inttypes.h>
+
+extern uint32_t ac3bits_left;
+extern uint64_t ac3current_word;
+
+void bitstream_init(uint8_t *start);
+inline uint32_t bitstream_get_bh(uint32_t num_bits);
+
+static inline uint32_t bitstream_get (uint32_t num_bits)
+{
+ uint32_t result;
+
+ if (num_bits < ac3bits_left) {
+ result = (ac3current_word << (64 - ac3bits_left)) >> (64 - num_bits);
+ ac3bits_left -= num_bits;
+ return result;
+ }
+
+ return bitstream_get_bh (num_bits);
+}
+
+
diff --git a/src/libac3/bswap.h b/src/libac3/bswap.h
new file mode 100644
index 000000000..0fc325d64
--- /dev/null
+++ b/src/libac3/bswap.h
@@ -0,0 +1,60 @@
+#ifndef __BSWAP_H__
+#define __BSWAP_H__
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#ifdef HAVE_BYTESWAP_H
+#include <byteswap.h>
+#else
+
+#include <inttypes.h>
+
+#ifdef WORDS_BIGENDIAN
+// FIXME these need to actually swap ;)
+#define bswap_16(x) (x)
+#define bswap_32(x) (x)
+#define bswap_64(x) (x)
+#else
+// This is wrong, 'cannot take address of ...'
+#define bswap_16(x) ((((uint8_t*)&x)[2] << 8) \
+ | (((uint8_t*)&x)[3]))
+
+// code from bits/byteswap.h (C) 1997, 1998 Free Software Foundation, Inc.
+#define bswap_32(x) \
+ ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >> 8) | \
+ (((x) & 0x0000ff00) << 8) | (((x) & 0x000000ff) << 24))
+
+#define bswap_64(x) \
+ (__extension__ \
+ ({ union { __extension__ uint64_t __ll; \
+ uint32_t __l[2]; } __w, __r; \
+ __w.__ll = (x); \
+ __r.__l[0] = bswap_32 (__w.__l[1]); \
+ __r.__l[1] = bswap_32 (__w.__l[0]); \
+ __r.__ll; }))
+#endif
+
+#endif
+
+// be2me ... BigEndian to MachineEndian
+// le2me ... LittleEndian to MachineEndian
+
+#ifdef WORDS_BIGENDIAN
+#define be2me_16(x) (x)
+#define be2me_32(x) (x)
+#define be2me_64(x) (x)
+#define le2me_16(x) bswap_16(x)
+#define le2me_32(x) bswap_32(x)
+#define le2me_64(x) bswap_64(x)
+#else
+#define be2me_16(x) bswap_16(x)
+#define be2me_32(x) bswap_32(x)
+#define be2me_64(x) bswap_64(x)
+#define le2me_16(x) (x)
+#define le2me_32(x) (x)
+#define le2me_64(x) (x)
+#endif
+
+#endif
diff --git a/src/libac3/cmplx.h b/src/libac3/cmplx.h
new file mode 100644
index 000000000..a357fab38
--- /dev/null
+++ b/src/libac3/cmplx.h
@@ -0,0 +1,9 @@
+#ifndef __COMPLEX_H__
+#define __COMPLEX_H__
+
+typedef struct complex {
+ float re;
+ float im;
+} complex_t;
+
+#endif
diff --git a/src/libac3/coeff.c b/src/libac3/coeff.c
new file mode 100644
index 000000000..6c95f74a5
--- /dev/null
+++ b/src/libac3/coeff.c
@@ -0,0 +1,437 @@
+/*
+ * coeff.c
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "ac3.h"
+#include "ac3_internal.h"
+
+
+#include "bitstream.h"
+#include "dither.h"
+#include "coeff.h"
+
+//
+//Lookup tables of 0.15 two's complement quantization values
+//
+#define Q0 ((-2 << 15) / 3.0)
+#define Q1 (0)
+#define Q2 ((2 << 15) / 3.0)
+
+static const float q_1_0[ 32 ] =
+{
+ Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,
+ Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,
+ Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,
+ 0,0,0,0,0
+};
+
+static const float q_1_1[ 32 ] =
+{
+ Q0,Q0,Q0,Q1,Q1,Q1,Q2,Q2,Q2,
+ Q0,Q0,Q0,Q1,Q1,Q1,Q2,Q2,Q2,
+ Q0,Q0,Q0,Q1,Q1,Q1,Q2,Q2,Q2,
+ 0,0,0,0,0
+};
+
+static const float q_1_2[ 32 ] =
+{
+ Q0,Q1,Q2,Q0,Q1,Q2,Q0,Q1,Q2,
+ Q0,Q1,Q2,Q0,Q1,Q2,Q0,Q1,Q2,
+ Q0,Q1,Q2,Q0,Q1,Q2,Q0,Q1,Q2,
+ 0,0,0,0,0
+};
+
+#undef Q0
+#undef Q1
+#undef Q2
+
+#define Q0 ((-4 << 15) / 5.0)
+#define Q1 ((-2 << 15) / 5.0)
+#define Q2 (0)
+#define Q3 ((2 << 15) / 5.0)
+#define Q4 ((4 << 15) / 5.0)
+
+static const float q_2_0[ 128 ] =
+{
+ Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,
+ Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,Q0,
+ Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,
+ Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,Q1,
+ Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,
+ Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,Q2,
+ Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,
+ Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,Q3,
+ Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,
+ Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,Q4,
+ 0,0,0
+};
+
+static const float q_2_1[ 128 ] =
+{
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,
+ Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,
+ Q4,Q4,Q4,Q4,Q4,Q0,Q0,Q0,Q0,Q0,
+ Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,
+ Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,
+ Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,
+ Q4,Q4,Q4,Q4,Q4,Q0,Q0,Q0,Q0,Q0,
+ Q1,Q1,Q1,Q1,Q1,Q2,Q2,Q2,Q2,Q2,
+ Q3,Q3,Q3,Q3,Q3,Q4,Q4,Q4,Q4,Q4,
+ Q0,Q0,Q0,Q0,Q0,Q1,Q1,Q1,Q1,Q1,
+ Q2,Q2,Q2,Q2,Q2,Q3,Q3,Q3,Q3,Q3,
+ Q4,Q4,Q4,Q4,Q4,0,0,0
+ };
+
+static const float q_2_2[ 128 ] =
+ {
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,Q0,Q1,Q2,Q3,Q4,
+ Q0,Q1,Q2,Q3,Q4,0,0,0
+};
+
+#undef Q0
+#undef Q1
+#undef Q2
+#undef Q3
+#undef Q4
+
+static const float q_3[7] =
+{
+ (-6 << 15)/7.0, (-4 << 15)/7.0, (-2 << 15)/7.0, 0.0,
+ ( 2 << 15)/7.0, ( 4 << 15)/7.0, ( 6 << 15)/7.0
+};
+
+#define Q0 ((-10 << 15) / 11.0)
+#define Q1 ((-8 << 15) / 11.0)
+#define Q2 ((-6 << 15) / 11.0)
+#define Q3 ((-4 << 15) / 11.0)
+#define Q4 ((-2 << 15) / 11.0)
+#define Q5 (0)
+#define Q6 ((2 << 15) / 11.0)
+#define Q7 ((4 << 15) / 11.0)
+#define Q8 ((6 << 15) / 11.0)
+#define Q9 ((8 << 15) / 11.0)
+#define QA ((10 << 15) / 11.0)
+
+static const float q_4_0[ 128 ] =
+{
+ Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0, Q0,
+ Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1, Q1,
+ Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2, Q2,
+ Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3, Q3,
+ Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4, Q4,
+ Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5, Q5,
+ Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6, Q6,
+ Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7, Q7,
+ Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8, Q8,
+ Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9, Q9,
+ QA, QA, QA, QA, QA, QA, QA, QA, QA, QA, QA,
+ 0, 0, 0, 0, 0, 0, 0
+ };
+
+static const float q_4_1[ 128 ] =
+{
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7, Q8, Q9, QA,
+ 0, 0, 0, 0, 0, 0, 0
+};
+
+#undef Q0
+#undef Q1
+#undef Q2
+#undef Q3
+#undef Q4
+#undef Q5
+#undef Q6
+#undef Q7
+#undef Q8
+#undef Q9
+#undef QA
+
+static const float q_5[15] =
+{
+ (-14 << 15)/15.0,(-12 << 15)/15.0,(-10 << 15)/15.0,
+ ( -8 << 15)/15.0,( -6 << 15)/15.0,( -4 << 15)/15.0,
+ ( -2 << 15)/15.0, 0.0 ,( 2 << 15)/15.0,
+ ( 4 << 15)/15.0,( 6 << 15)/15.0,( 8 << 15)/15.0,
+ ( 10 << 15)/15.0,( 12 << 15)/15.0,( 14 << 15)/15.0
+};
+
+//
+// Scale factors for convert_to_float
+//
+
+static const uint32_t u32_scale_factors[25] =
+{
+ 0x38000000, //2 ^ -(0 + 15)
+ 0x37800000, //2 ^ -(1 + 15)
+ 0x37000000, //2 ^ -(2 + 15)
+ 0x36800000, //2 ^ -(3 + 15)
+ 0x36000000, //2 ^ -(4 + 15)
+ 0x35800000, //2 ^ -(5 + 15)
+ 0x35000000, //2 ^ -(6 + 15)
+ 0x34800000, //2 ^ -(7 + 15)
+ 0x34000000, //2 ^ -(8 + 15)
+ 0x33800000, //2 ^ -(9 + 15)
+ 0x33000000, //2 ^ -(10 + 15)
+ 0x32800000, //2 ^ -(11 + 15)
+ 0x32000000, //2 ^ -(12 + 15)
+ 0x31800000, //2 ^ -(13 + 15)
+ 0x31000000, //2 ^ -(14 + 15)
+ 0x30800000, //2 ^ -(15 + 15)
+ 0x30000000, //2 ^ -(16 + 15)
+ 0x2f800000, //2 ^ -(17 + 15)
+ 0x2f000000, //2 ^ -(18 + 15)
+ 0x2e800000, //2 ^ -(19 + 15)
+ 0x2e000000, //2 ^ -(20 + 15)
+ 0x2d800000, //2 ^ -(21 + 15)
+ 0x2d000000, //2 ^ -(22 + 15)
+ 0x2c800000, //2 ^ -(23 + 15)
+ 0x2c000000 //2 ^ -(24 + 15)
+};
+
+static float *scale_factor = (float*)u32_scale_factors;
+
+//These store the persistent state of the packed mantissas
+static float q_1[2];
+static float q_2[2];
+static float q_4[1];
+static int32_t q_1_pointer;
+static int32_t q_2_pointer;
+static int32_t q_4_pointer;
+static float __inline__
+coeff_get_float(uint16_t bap, uint16_t dithflag, uint16_t exp);
+
+//Conversion from bap to number of bits in the mantissas
+//zeros account for cases 0,1,2,4 which are special cased
+static uint16_t qnttztab[16] =
+{
+ 0, 0, 0, 3,
+ 0, 4, 5, 6,
+ 7, 8, 9, 10,
+ 11, 12, 14, 16
+};
+
+static void coeff_reset(void);
+static float coeff_get_float(uint16_t bap, uint16_t dithflag, uint16_t exp);
+static void coeff_uncouple_ch(float samples[],bsi_t *bsi,audblk_t *audblk,uint32_t ch);
+
+void coeff_unpack(bsi_t *bsi, audblk_t *audblk, stream_samples_t samples)
+{
+ uint16_t i,j;
+ uint32_t done_cpl = 0;
+
+ coeff_reset();
+
+ for(i=0; i< bsi->nfchans; i++) {
+ for(j=0; j < audblk->endmant[i]; j++)
+ samples[i][j] = coeff_get_float(audblk->fbw_bap[i][j], audblk->dithflag[i], audblk->fbw_exp[i][j]);
+
+ if(audblk->cplinu && audblk->chincpl[i] && !(done_cpl)) {
+ // ncplmant is equal to 12 * ncplsubnd
+ // Don't dither coupling channel until channel
+ // separation so that interchannel noise is uncorrelated
+ for(j=audblk->cplstrtmant; j < audblk->cplendmant; j++)
+ audblk->cpl_flt[j] = coeff_get_float(audblk->cpl_bap[j],0, audblk->cpl_exp[j]);
+ done_cpl = 1;
+ }
+ }
+
+ //uncouple the channel if necessary
+ if(audblk->cplinu) {
+ for(i=0; i< bsi->nfchans; i++) {
+ if(audblk->chincpl[i])
+ coeff_uncouple_ch(samples[i],bsi,audblk,i);
+ }
+
+ }
+
+ if(bsi->lfeon) {
+ // There are always 7 mantissas for lfe, no dither for lfe
+ for(j=0; j < 7 ; j++)
+ samples[5][j] = coeff_get_float(audblk->lfe_bap[j], 0, audblk->lfe_exp[j]);
+ }
+}
+
+
+/**
+ * Fetch a float from the bitstream
+ **/
+
+static float inline coeff_get_float (uint16_t bap, uint16_t dithflag, uint16_t exp)
+{
+ uint16_t dummy = 0;
+
+ //If the bap is 0-5 then we have special cases to take care of
+ switch(bap) {
+ case 0:
+ if(dithflag)
+ return (dither_gen() * scale_factor[exp]);
+ return 0.0;
+
+ case 1:
+ if (q_1_pointer >= 0)
+ return(q_1[q_1_pointer--] * scale_factor[exp]);
+
+ if ((dummy = bitstream_get (5)) > 26)
+ goto error;
+
+ q_1[1] = q_1_1[dummy];
+ q_1[0] = q_1_2[dummy];
+ q_1_pointer = 1;
+
+ return (q_1_0[dummy] * scale_factor[exp]);
+
+ case 2:
+ if(q_2_pointer >= 0)
+ return (q_2[q_2_pointer--] * scale_factor[exp]);
+
+ if ((dummy = bitstream_get (7)) > 124)
+ goto error;
+
+ q_2[1] = q_2_1[dummy];
+ q_2[0] = q_2_2[dummy];
+ q_2_pointer = 1;
+
+ return (q_2_0[dummy] * scale_factor[exp]);
+
+ case 3:
+ if ((dummy = bitstream_get (3)) > 6)
+ goto error;
+
+ return (q_3[dummy] * scale_factor[exp]);
+
+ case 4:
+ if(q_4_pointer >= 0)
+ return (q_4[q_4_pointer--] * scale_factor[exp]);
+
+ if ((dummy = bitstream_get (7)) > 120)
+ goto error;
+
+ q_4[0] = q_4_1[dummy];
+ q_4_pointer = 0;
+
+ return (q_4_0[dummy] * scale_factor[exp]);
+
+ case 5:
+ if ((dummy = bitstream_get (4)) > 14)
+ goto error;
+
+ return (q_5[dummy] * scale_factor[exp]);
+
+ default:
+ dummy = bitstream_get(qnttztab[bap]);
+ dummy <<= 16 - qnttztab[bap];
+ return ((int16_t)dummy * scale_factor[exp]);
+ }
+
+error:
+#ifdef FAST_ERROR
+ HANDLE_ERROR ();
+#else
+ if(!error_flag)
+ fprintf(stderr,"** Invalid mantissa - skipping frame **\n");
+ error_flag = 1;
+
+ return 0.0;
+#endif
+}
+
+
+/**
+ * Reset the mantissa state
+ **/
+
+static void coeff_reset(void)
+{
+ q_1_pointer = q_2_pointer = q_4_pointer = -1;
+}
+
+
+/**
+ * Uncouple the coupling channel into a fbw channel
+ **/
+
+static void coeff_uncouple_ch (float samples[],bsi_t *bsi,audblk_t *audblk,uint32_t ch)
+{
+ uint32_t bnd = 0;
+ uint32_t sub_bnd = 0;
+ uint32_t i,j;
+ float cpl_coord = 1.0;
+ uint32_t cpl_exp_tmp;
+ uint32_t cpl_mant_tmp;
+
+ for (i=audblk->cplstrtmant;i<audblk->cplendmant;) {
+ if (!audblk->cplbndstrc[sub_bnd++]) {
+ cpl_exp_tmp = audblk->cplcoexp[ch][bnd] + 3 * audblk->mstrcplco[ch];
+ if (audblk->cplcoexp[ch][bnd] == 15)
+ cpl_mant_tmp = (audblk->cplcomant[ch][bnd]) << 11;
+ else
+ cpl_mant_tmp = ((0x10) | audblk->cplcomant[ch][bnd]) << 10;
+
+ cpl_coord = (cpl_mant_tmp * scale_factor[cpl_exp_tmp]) * 8.0f;
+
+ //Invert the phase for the right channel if necessary
+ if(bsi->acmod == 0x2 && audblk->phsflginu && ch == 1 && audblk->phsflg[bnd])
+ cpl_coord *= -1;
+
+ bnd++;
+ }
+
+ for(j=0;j < 12; j++) {
+ // Get new dither values for each channel if necessary,
+ // so the channels are uncorrelated
+ if(audblk->dithflag[ch] && !audblk->cpl_bap[i])
+ samples[i] = cpl_coord * (dither_gen() * scale_factor[audblk->cpl_exp[i]]);
+ else
+ samples[i] = cpl_coord * audblk->cpl_flt[i];
+
+ i++;
+ }
+ }
+}
diff --git a/src/libac3/coeff.h b/src/libac3/coeff.h
new file mode 100644
index 000000000..dc822a9bd
--- /dev/null
+++ b/src/libac3/coeff.h
@@ -0,0 +1,24 @@
+/*
+ * coeff.h
+ *
+ * Copyright (C) Aaron Holtzman - Feb 2000
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+void coeff_unpack(bsi_t *bsi, audblk_t *audblk,stream_samples_t samples);
diff --git a/src/libac3/crc.c b/src/libac3/crc.c
new file mode 100644
index 000000000..c8ee478b6
--- /dev/null
+++ b/src/libac3/crc.c
@@ -0,0 +1,100 @@
+/*
+ * crc.c
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "ac3.h"
+#include "ac3_internal.h"
+
+#include <sys/time.h>
+
+#include "crc.h"
+
+static const uint16_t crc_lut[256] =
+{
+ 0x0000,0x8005,0x800f,0x000a,0x801b,0x001e,0x0014,0x8011,
+ 0x8033,0x0036,0x003c,0x8039,0x0028,0x802d,0x8027,0x0022,
+ 0x8063,0x0066,0x006c,0x8069,0x0078,0x807d,0x8077,0x0072,
+ 0x0050,0x8055,0x805f,0x005a,0x804b,0x004e,0x0044,0x8041,
+ 0x80c3,0x00c6,0x00cc,0x80c9,0x00d8,0x80dd,0x80d7,0x00d2,
+ 0x00f0,0x80f5,0x80ff,0x00fa,0x80eb,0x00ee,0x00e4,0x80e1,
+ 0x00a0,0x80a5,0x80af,0x00aa,0x80bb,0x00be,0x00b4,0x80b1,
+ 0x8093,0x0096,0x009c,0x8099,0x0088,0x808d,0x8087,0x0082,
+ 0x8183,0x0186,0x018c,0x8189,0x0198,0x819d,0x8197,0x0192,
+ 0x01b0,0x81b5,0x81bf,0x01ba,0x81ab,0x01ae,0x01a4,0x81a1,
+ 0x01e0,0x81e5,0x81ef,0x01ea,0x81fb,0x01fe,0x01f4,0x81f1,
+ 0x81d3,0x01d6,0x01dc,0x81d9,0x01c8,0x81cd,0x81c7,0x01c2,
+ 0x0140,0x8145,0x814f,0x014a,0x815b,0x015e,0x0154,0x8151,
+ 0x8173,0x0176,0x017c,0x8179,0x0168,0x816d,0x8167,0x0162,
+ 0x8123,0x0126,0x012c,0x8129,0x0138,0x813d,0x8137,0x0132,
+ 0x0110,0x8115,0x811f,0x011a,0x810b,0x010e,0x0104,0x8101,
+ 0x8303,0x0306,0x030c,0x8309,0x0318,0x831d,0x8317,0x0312,
+ 0x0330,0x8335,0x833f,0x033a,0x832b,0x032e,0x0324,0x8321,
+ 0x0360,0x8365,0x836f,0x036a,0x837b,0x037e,0x0374,0x8371,
+ 0x8353,0x0356,0x035c,0x8359,0x0348,0x834d,0x8347,0x0342,
+ 0x03c0,0x83c5,0x83cf,0x03ca,0x83db,0x03de,0x03d4,0x83d1,
+ 0x83f3,0x03f6,0x03fc,0x83f9,0x03e8,0x83ed,0x83e7,0x03e2,
+ 0x83a3,0x03a6,0x03ac,0x83a9,0x03b8,0x83bd,0x83b7,0x03b2,
+ 0x0390,0x8395,0x839f,0x039a,0x838b,0x038e,0x0384,0x8381,
+ 0x0280,0x8285,0x828f,0x028a,0x829b,0x029e,0x0294,0x8291,
+ 0x82b3,0x02b6,0x02bc,0x82b9,0x02a8,0x82ad,0x82a7,0x02a2,
+ 0x82e3,0x02e6,0x02ec,0x82e9,0x02f8,0x82fd,0x82f7,0x02f2,
+ 0x02d0,0x82d5,0x82df,0x02da,0x82cb,0x02ce,0x02c4,0x82c1,
+ 0x8243,0x0246,0x024c,0x8249,0x0258,0x825d,0x8257,0x0252,
+ 0x0270,0x8275,0x827f,0x027a,0x826b,0x026e,0x0264,0x8261,
+ 0x0220,0x8225,0x822f,0x022a,0x823b,0x023e,0x0234,0x8231,
+ 0x8213,0x0216,0x021c,0x8219,0x0208,0x820d,0x8207,0x0202
+};
+
+static uint16_t state;
+
+
+void crc_init(void)
+{
+ state = 0;
+}
+
+
+inline void crc_process_byte (uint8_t data)
+{
+ state = crc_lut[data ^ (state>>8)] ^ (state<<8);
+}
+
+
+void crc_process_frame (uint8_t *data,uint32_t num_bytes)
+{
+ uint32_t i;
+
+ for(i=0; i<num_bytes; i++)
+ crc_process_byte (data[i]);
+}
+
+
+int crc_validate(void)
+{
+ return (state == 0);
+}
diff --git a/src/libac3/crc.h b/src/libac3/crc.h
new file mode 100644
index 000000000..16489656c
--- /dev/null
+++ b/src/libac3/crc.h
@@ -0,0 +1,27 @@
+/*
+ * crc.h
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+int crc_validate(void);
+void crc_init(void);
+void crc_process_byte(uint8_t data);
+void crc_process_frame(uint8_t *data,uint32_t num_bytes);
diff --git a/src/libac3/decode.c b/src/libac3/decode.c
new file mode 100644
index 000000000..cca544933
--- /dev/null
+++ b/src/libac3/decode.c
@@ -0,0 +1,314 @@
+/*
+ * decode.c
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "ac3.h"
+#include "ac3_internal.h"
+#include "bitstream.h"
+#include "downmix.h"
+#include "srfft.h"
+#include "imdct.h"
+#include "exponent.h"
+#include "coeff.h"
+#include "bit_allocate.h"
+#include "parse.h"
+#include "crc.h"
+#include "rematrix.h"
+#include "sanity_check.h"
+
+#include "audio_out.h"
+#include "attributes.h"
+
+
+//our global config structure
+ac3_config_t ac3_config;
+#ifdef FAST_ERROR
+jmp_buf error_jmp_mark;
+#else
+uint32_t error_flag = 0;
+#endif
+
+static audblk_t audblk;
+static bsi_t bsi;
+static syncinfo_t syncinfo;
+static uint32_t frame_count = 0;
+static uint32_t is_output_initialized = 0;
+
+//the floating point samples for one audblk
+static stream_samples_t samples;
+
+//the integer samples for the entire frame (with enough space for 2 ch out)
+//if this size change, be sure to change the size when muting
+static int16_t s16_samples[2 * 6 * 256] __attribute__ ((aligned(16)));
+
+/* output buffer for spdiv output */
+static int16_t s16_samples_out[4 * 6 * 256] __attribute__ ((aligned(16)));
+
+static ao_functions_t ac3_output;
+
+// downmix stuff
+static float cmixlev_lut[4] = { 0.707, 0.595, 0.500, 0.707 };
+static float smixlev_lut[4] = { 0.707, 0.500, 0.0 , 0.500 };
+static dm_par_t dm_par;
+
+//Storage for the syncframe
+#define BUFFER_MAX_SIZE 4096
+static uint8_t buffer[BUFFER_MAX_SIZE];
+static uint32_t buffer_size = 0;;
+
+static uint32_t decode_buffer_syncframe (syncinfo_t *syncinfo, uint8_t **start, uint8_t *end)
+{
+ uint8_t *cur = *start;
+ uint16_t syncword = syncinfo->syncword;
+ uint32_t ret = 0;
+
+ //
+ // Find an ac3 sync frame.
+ //
+ while (syncword != 0x0b77) {
+ if (cur >= end)
+ goto done;
+ syncword = (syncword << 8) + *cur++;
+ }
+
+ //need the next 3 bytes to decide how big the frame is
+ while (buffer_size < 3) {
+ if(cur >= end)
+ goto done;
+ buffer[buffer_size++] = *cur++;
+ }
+
+ parse_syncinfo (syncinfo,buffer);
+
+ while (buffer_size < syncinfo->frame_size * 2 - 2) {
+ if(cur >= end)
+ goto done;
+
+ buffer[buffer_size++] = *cur++;
+ }
+
+#if 0
+ // Check the crc over the entire frame
+ crc_init();
+ crc_process_frame (buffer, syncinfo->frame_size * 2 - 2);
+
+ if (!crc_validate()) {
+#ifndef FAST_ERROR
+ error_flag = 1;
+#endif
+ fprintf(stderr,"** CRC failed - skipping frame **\n");
+ goto done;
+ }
+#endif
+
+ //
+ //if we got to this point, we found a valid ac3 frame to decode
+ //
+
+ if ((ac3_config.flags & AO_MODE_AC3) == 0) {
+ bitstream_init (buffer);
+ //get rid of the syncinfo struct as we already parsed it
+ bitstream_get (24);
+ }
+
+ //reset the syncword for next time
+ syncword = 0xffff;
+ buffer_size = 0;
+ ret = 1;
+
+done:
+ syncinfo->syncword = syncword;
+ *start = cur;
+ return ret;
+}
+
+
+void inline decode_mute (void)
+{
+ //mute the frame
+ memset (s16_samples, 0, sizeof(int16_t) * 256 * 2 * 6);
+#ifndef FAST_ERROR
+ error_flag = 0;
+#endif
+}
+
+
+void ac3_init(ac3_config_t *config ,ao_functions_t *foo)
+{
+ memcpy(&ac3_config,config,sizeof(ac3_config_t));
+ ac3_output = *foo;
+
+ imdct_init ();
+ /* downmix_init (); */
+ sanity_check_init (&syncinfo,&bsi,&audblk);
+ memset(s16_samples_out,0,4 * 6 * 256);
+
+}
+
+void ac3_reset ()
+{
+ printf ("ac3_reset\n");
+#ifndef FAST_ERROR
+ error_flag = 0;
+#endif
+
+ frame_count = 0;
+ is_output_initialized = 0;
+
+ buffer_size = 0;
+ syncinfo.syncword = 0;
+ imdct_init();
+ sanity_check_init(&syncinfo,&bsi,&audblk);
+
+}
+
+size_t ac3_decode_data (uint8_t *data_start, uint8_t *data_end, uint32_t pts_)
+{
+ uint32_t i;
+
+#ifdef FAST_ERROR
+ if (setjmp (error_jmp_mark) < 0) {
+ imdct_init ();
+ sanity_check_init(&syncinfo,&bsi,&audblk);
+ return 0;
+ }
+#endif
+
+ while (decode_buffer_syncframe (&syncinfo, &data_start, data_end)) {
+
+#ifndef FAST_ERROR
+ if (error_flag)
+ goto error;
+#endif
+
+ if ((ac3_config.flags & AO_MODE_AC3) == 0) {
+ parse_bsi (&bsi);
+
+ // compute downmix parameters
+ // downmix to two channels for now
+ dm_par.clev = 0.0; dm_par.slev = 0.0; dm_par.unit = 1.0;
+ if (bsi.acmod & 0x1) // have center
+ dm_par.clev = cmixlev_lut[bsi.cmixlev];
+
+ if (bsi.acmod & 0x4) // have surround channels
+ dm_par.slev = smixlev_lut[bsi.surmixlev];
+
+ dm_par.unit /= 1.0 + dm_par.clev + dm_par.slev;
+ dm_par.clev *= dm_par.unit;
+ dm_par.slev *= dm_par.unit;
+
+ for(i=0; i < 6; i++) {
+ //Initialize freq/time sample storage
+ memset (samples, 0, sizeof(float) * 256 * (bsi.nfchans + bsi.lfeon));
+
+ // Extract most of the audblk info from the bitstream
+ // (minus the mantissas
+ parse_audblk (&bsi,&audblk);
+
+ // Take the differential exponent data and turn it into
+ // absolute exponents
+ exponent_unpack (&bsi,&audblk);
+#ifndef FAST_ERROR
+ if (error_flag)
+ goto error;
+#endif
+
+ // Figure out how many bits per mantissa
+ bit_allocate (syncinfo.fscod,&bsi,&audblk);
+
+ // Extract the mantissas from the stream and
+ // generate floating point frequency coefficients
+ coeff_unpack (&bsi,&audblk,samples);
+#ifndef FAST_ERROR
+ if (error_flag)
+ goto error;
+#endif
+
+ if (bsi.acmod == 0x2)
+ rematrix (&audblk,samples);
+
+ // Convert the frequency samples into time samples
+ imdct (&bsi,&audblk,samples, &s16_samples[i * 2 * 256], &dm_par);
+
+ // Downmix into the requested number of channels
+ // and convert floating point to int16_t
+ // downmix(&bsi,samples,&s16_samples[i * 2 * 256]);
+
+ if (sanity_check(&syncinfo,&bsi,&audblk) < 0)
+ sanity_check_init (&syncinfo,&bsi,&audblk);
+
+ continue;
+ }
+ }
+ else {
+ s16_samples_out[0] = 0xf872; //spdif syncword
+ s16_samples_out[1] = 0x4e1f; // .............
+ s16_samples_out[2] = 0x0001; // AC3 data
+ s16_samples_out[3] = syncinfo.frame_size * 16;
+ s16_samples_out[4] = 0x0b77; // AC3 syncwork
+
+ // ac3 seems to be swabbed data
+ swab(buffer,&s16_samples_out[5], syncinfo.frame_size * 2 );
+
+ }
+
+ if (!is_output_initialized) {
+ ac3_output.open (16, syncinfo.sampling_rate,
+ (ac3_config.flags & AO_MODE_AC3) ? AO_MODE_AC3 : AO_MODE_STEREO);
+ is_output_initialized = 1;
+ }
+
+ if ((ac3_config.flags & AO_MODE_AC3) == 0) {
+ ac3_output.write_audio_data(s16_samples, 256*6, pts_);
+ }
+ else {
+ ac3_output.write_audio_data(s16_samples_out, 6 * 256, pts_);
+ }
+
+ pts_ = 0;
+
+#ifndef FAST_ERROR
+error:
+
+ //find a new frame
+ decode_mute (); //RMB CHECK
+#endif
+ }
+#ifdef FAST_ERROR
+ decode_mute ();
+#endif
+
+ return 0;
+}
+
diff --git a/src/libac3/decode.h b/src/libac3/decode.h
new file mode 100644
index 000000000..bb84a1105
--- /dev/null
+++ b/src/libac3/decode.h
@@ -0,0 +1,22 @@
+/*
+ * decode.h
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
diff --git a/src/libac3/dither.c b/src/libac3/dither.c
new file mode 100644
index 000000000..07fa2f596
--- /dev/null
+++ b/src/libac3/dither.c
@@ -0,0 +1,117 @@
+/*
+ * dither.c
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "ac3.h"
+#include "ac3_internal.h"
+
+
+#include "dither.h"
+
+
+const uint16_t dither_lut[256] =
+{
+ 0x0000, 0xa011, 0xe033, 0x4022, 0x6077, 0xc066, 0x8044, 0x2055,
+ 0xc0ee, 0x60ff, 0x20dd, 0x80cc, 0xa099, 0x0088, 0x40aa, 0xe0bb,
+ 0x21cd, 0x81dc, 0xc1fe, 0x61ef, 0x41ba, 0xe1ab, 0xa189, 0x0198,
+ 0xe123, 0x4132, 0x0110, 0xa101, 0x8154, 0x2145, 0x6167, 0xc176,
+ 0x439a, 0xe38b, 0xa3a9, 0x03b8, 0x23ed, 0x83fc, 0xc3de, 0x63cf,
+ 0x8374, 0x2365, 0x6347, 0xc356, 0xe303, 0x4312, 0x0330, 0xa321,
+ 0x6257, 0xc246, 0x8264, 0x2275, 0x0220, 0xa231, 0xe213, 0x4202,
+ 0xa2b9, 0x02a8, 0x428a, 0xe29b, 0xc2ce, 0x62df, 0x22fd, 0x82ec,
+ 0x8734, 0x2725, 0x6707, 0xc716, 0xe743, 0x4752, 0x0770, 0xa761,
+ 0x47da, 0xe7cb, 0xa7e9, 0x07f8, 0x27ad, 0x87bc, 0xc79e, 0x678f,
+ 0xa6f9, 0x06e8, 0x46ca, 0xe6db, 0xc68e, 0x669f, 0x26bd, 0x86ac,
+ 0x6617, 0xc606, 0x8624, 0x2635, 0x0660, 0xa671, 0xe653, 0x4642,
+ 0xc4ae, 0x64bf, 0x249d, 0x848c, 0xa4d9, 0x04c8, 0x44ea, 0xe4fb,
+ 0x0440, 0xa451, 0xe473, 0x4462, 0x6437, 0xc426, 0x8404, 0x2415,
+ 0xe563, 0x4572, 0x0550, 0xa541, 0x8514, 0x2505, 0x6527, 0xc536,
+ 0x258d, 0x859c, 0xc5be, 0x65af, 0x45fa, 0xe5eb, 0xa5c9, 0x05d8,
+ 0xae79, 0x0e68, 0x4e4a, 0xee5b, 0xce0e, 0x6e1f, 0x2e3d, 0x8e2c,
+ 0x6e97, 0xce86, 0x8ea4, 0x2eb5, 0x0ee0, 0xaef1, 0xeed3, 0x4ec2,
+ 0x8fb4, 0x2fa5, 0x6f87, 0xcf96, 0xefc3, 0x4fd2, 0x0ff0, 0xafe1,
+ 0x4f5a, 0xef4b, 0xaf69, 0x0f78, 0x2f2d, 0x8f3c, 0xcf1e, 0x6f0f,
+ 0xede3, 0x4df2, 0x0dd0, 0xadc1, 0x8d94, 0x2d85, 0x6da7, 0xcdb6,
+ 0x2d0d, 0x8d1c, 0xcd3e, 0x6d2f, 0x4d7a, 0xed6b, 0xad49, 0x0d58,
+ 0xcc2e, 0x6c3f, 0x2c1d, 0x8c0c, 0xac59, 0x0c48, 0x4c6a, 0xec7b,
+ 0x0cc0, 0xacd1, 0xecf3, 0x4ce2, 0x6cb7, 0xcca6, 0x8c84, 0x2c95,
+ 0x294d, 0x895c, 0xc97e, 0x696f, 0x493a, 0xe92b, 0xa909, 0x0918,
+ 0xe9a3, 0x49b2, 0x0990, 0xa981, 0x89d4, 0x29c5, 0x69e7, 0xc9f6,
+ 0x0880, 0xa891, 0xe8b3, 0x48a2, 0x68f7, 0xc8e6, 0x88c4, 0x28d5,
+ 0xc86e, 0x687f, 0x285d, 0x884c, 0xa819, 0x0808, 0x482a, 0xe83b,
+ 0x6ad7, 0xcac6, 0x8ae4, 0x2af5, 0x0aa0, 0xaab1, 0xea93, 0x4a82,
+ 0xaa39, 0x0a28, 0x4a0a, 0xea1b, 0xca4e, 0x6a5f, 0x2a7d, 0x8a6c,
+ 0x4b1a, 0xeb0b, 0xab29, 0x0b38, 0x2b6d, 0x8b7c, 0xcb5e, 0x6b4f,
+ 0x8bf4, 0x2be5, 0x6bc7, 0xcbd6, 0xeb83, 0x4b92, 0x0bb0, 0xaba1
+};
+
+uint16_t lfsr_state = 1;
+
+//
+// see dither_gen (inline-able) in dither.h
+//
+
+#if 0
+
+//
+// this is the old dither_gen with is much slower than the new inlined
+// lut version and is still here because it's easier to understand.
+//
+
+/*
+ * Generate eight bits of pseudo-entropy using a 16 bit linear
+ * feedback shift register (LFSR). The primitive polynomial used
+ * is 1 + x^4 + x^14 + x^16.
+ *
+ * The distribution is uniform, over the range [-0.707,0.707]
+ *
+ */
+
+uint16_t dither_gen(void)
+{
+ int i;
+ uint32_t state;
+
+ //explicitly bring the state into a local var as gcc > 3.0?
+ //doesn't know how to optimize out the stores
+ state = lfsr_state;
+
+ //Generate eight pseudo random bits
+ for(i=0;i<8;i++) {
+ state <<= 1;
+
+ if(state & 0x10000)
+ state ^= 0xa011;
+ }
+
+ lfsr_state = state;
+
+ return (((((int32_t)state<<8)>>8) * (int32_t) (0.707106 * 256.0))>>16);
+}
+
+#endif
diff --git a/src/libac3/dither.h b/src/libac3/dither.h
new file mode 100644
index 000000000..abb9f518e
--- /dev/null
+++ b/src/libac3/dither.h
@@ -0,0 +1,37 @@
+/*
+ * dither.h
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+
+extern uint16_t lfsr_state;
+extern const uint16_t dither_lut[256];
+
+static inline uint16_t dither_gen(void)
+{
+ int16_t state;
+
+ state = dither_lut[lfsr_state >> 8] ^ (lfsr_state << 8);
+
+ lfsr_state = (uint16_t) state;
+
+ return ((state * (int32_t) (0.707106 * 256.0))>>8);
+}
diff --git a/src/libac3/downmix.c b/src/libac3/downmix.c
new file mode 100644
index 000000000..df71d5e3d
--- /dev/null
+++ b/src/libac3/downmix.c
@@ -0,0 +1,158 @@
+/*
+ * imdct.c
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+
+#include "ac3.h"
+#include "ac3_internal.h"
+
+#include "downmix.h"
+
+void downmix_3f_2r_to_2ch (float *samples, dm_par_t *dm_par)
+{
+ int i;
+ float *left, *right, *center, *left_sur, *right_sur;
+ float left_tmp, right_tmp;
+
+ left = samples;
+ right = samples + 256 * 2;
+ center = samples + 256;
+ left_sur = samples + 256 * 3;
+ right_sur = samples + 256 * 4;
+
+ for (i=0; i < 256; i++) {
+ left_tmp = dm_par->unit * *left + dm_par->clev * *center + dm_par->slev * *left_sur++;
+ right_tmp= dm_par->unit * *right++ + dm_par->clev * *center + dm_par->slev * *right_sur++;
+ *left++ = left_tmp;
+ *center++ = right_tmp;
+ }
+}
+
+
+void downmix_2f_2r_to_2ch (float *samples, dm_par_t *dm_par)
+{
+ int i;
+ float *left, *right, *left_sur, *right_sur;
+ float left_tmp, right_tmp;
+
+ left = &samples[0];
+ right = &samples[256];
+ left_sur = &samples[512];
+ right_sur = &samples[768];
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = dm_par->unit * *left + dm_par->slev * *left_sur++;
+ right_tmp= dm_par->unit * *right + dm_par->slev * *right_sur++;
+ *left++ = left_tmp;
+ *right++ = right_tmp;
+ }
+}
+
+
+void downmix_3f_1r_to_2ch (float *samples, dm_par_t *dm_par)
+{
+ int i;
+ float *left, *right, *center, *right_sur;
+ float left_tmp, right_tmp;
+
+ left = &samples[0];
+ right = &samples[512];
+ center = &samples[256];
+ right_sur = &samples[768];
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = dm_par->unit * *left + dm_par->clev * *center - dm_par->slev * *right_sur;
+ right_tmp= dm_par->unit * *right++ + dm_par->clev * *center + dm_par->slev * *right_sur++;
+ *left++ = left_tmp;
+ *center++ = right_tmp;
+ }
+}
+
+
+void downmix_2f_1r_to_2ch (float *samples, dm_par_t *dm_par)
+{
+ int i;
+ float *left, *right, *right_sur;
+ float left_tmp, right_tmp;
+
+ left = &samples[0];
+ right = &samples[256];
+ right_sur = &samples[512];
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = dm_par->unit * *left - dm_par->slev * *right_sur;
+ right_tmp= dm_par->unit * *right + dm_par->slev * *right_sur++;
+ *left++ = left_tmp;
+ *right++ = right_tmp;
+ }
+}
+
+
+void downmix_3f_0r_to_2ch (float *samples, dm_par_t *dm_par)
+{
+ int i;
+ float *left, *right, *center;
+ float left_tmp, right_tmp;
+
+ left = &samples[0];
+ center = &samples[256];
+ right = &samples[512];
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = dm_par->unit * *left + dm_par->clev * *center;
+ right_tmp= dm_par->unit * *right++ + dm_par->clev * *center;
+ *left++ = left_tmp;
+ *center++ = right_tmp;
+ }
+}
+
+void stream_sample_2ch_to_s16 (int16_t *s16_samples, float *left, float *right)
+{
+ int i;
+
+ for (i=0; i < 256; i++) {
+ *s16_samples++ = (int16_t) *left++;
+ *s16_samples++ = (int16_t) *right++;
+ }
+}
+
+
+void stream_sample_1ch_to_s16 (int16_t *s16_samples, float *center)
+{
+ int i;
+ float tmp;
+
+ for (i=0; i < 256; i++) {
+ *s16_samples++ = tmp = (int16_t) (0.7071f * *center++);
+ *s16_samples++ = tmp;
+ }
+}
+
+
diff --git a/src/libac3/downmix.h b/src/libac3/downmix.h
new file mode 100644
index 000000000..7e6dea014
--- /dev/null
+++ b/src/libac3/downmix.h
@@ -0,0 +1,43 @@
+/*
+ *
+ * downmix.h
+ *
+ * Copyright (C) Aaron Holtzman - Sept 1999
+ *
+ * Originally based on code by Yeqing Deng.
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+typedef struct dm_par_s {
+ float unit;
+ float clev;
+ float slev;
+} dm_par_t;
+
+void downmix_3f_2r_to_2ch (float *samples, dm_par_t * dm_par);
+void downmix_3f_1r_to_2ch (float *samples, dm_par_t * dm_par);
+void downmix_2f_2r_to_2ch (float *samples, dm_par_t * dm_par);
+void downmix_2f_1r_to_2ch (float *samples, dm_par_t * dm_par);
+void downmix_3f_0r_to_2ch (float *samples, dm_par_t * dm_par);
+
+void stream_sample_2ch_to_s16 (int16_t *s16_samples, float *left, float *right);
+void stream_sample_1ch_to_s16 (int16_t *s16_samples, float *center);
+
+
diff --git a/src/libac3/exponent.c b/src/libac3/exponent.c
new file mode 100644
index 000000000..ebb35abd7
--- /dev/null
+++ b/src/libac3/exponent.c
@@ -0,0 +1,138 @@
+/*
+ * exponent.c
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "ac3.h"
+#include "ac3_internal.h"
+
+
+#include "exponent.h"
+
+
+static inline void exp_unpack_ch(uint16_t type,uint16_t expstr,uint16_t ngrps,uint16_t initial_exp, uint16_t exps[], uint16_t *dest);
+
+
+/**
+ *
+ **/
+
+void exponent_unpack( bsi_t *bsi, audblk_t *audblk)
+{
+ uint16_t i;
+
+ for(i=0; i< bsi->nfchans; i++)
+ exp_unpack_ch(UNPACK_FBW, audblk->chexpstr[i], audblk->nchgrps[i], audblk->exps[i][0], &audblk->exps[i][1], audblk->fbw_exp[i]);
+
+ if(audblk->cplinu)
+ exp_unpack_ch(UNPACK_CPL, audblk->cplexpstr, audblk->ncplgrps, audblk->cplabsexp << 1, audblk->cplexps, &audblk->cpl_exp[audblk->cplstrtmant]);
+
+ if(bsi->lfeon)
+ exp_unpack_ch(UNPACK_LFE, audblk->lfeexpstr, 2, audblk->lfeexps[0], &audblk->lfeexps[1], audblk->lfe_exp);
+}
+
+
+/**
+ *
+ **/
+
+static inline void exp_unpack_ch(uint16_t type,uint16_t expstr,uint16_t ngrps,uint16_t initial_exp,
+ uint16_t exps[], uint16_t *dest)
+{
+ uint16_t i,j;
+ int16_t exp_acc;
+ int16_t exp_1,exp_2,exp_3;
+
+ if (expstr == EXP_REUSE)
+ return;
+
+ /* Handle the initial absolute exponent */
+ exp_acc = initial_exp;
+ j = 0;
+
+ /* In the case of a fbw channel then the initial absolute values is
+ * also an exponent */
+ if(type != UNPACK_CPL)
+ dest[j++] = exp_acc;
+
+ /* Loop through the groups and fill the dest array appropriately */
+ for(i=0; i< ngrps; i++) {
+ if(exps[i] > 124)
+ goto error;
+
+ exp_1 = exps[i] / 25;
+ exp_2 = (exps[i] - (exp_1 * 25)) / 5;
+ exp_3 = exps[i] - (exp_1 * 25) - (exp_2 * 5) ;
+
+ exp_acc += (exp_1 - 2);
+
+ switch(expstr) {
+ case EXP_D45:
+ dest[j++] = exp_acc;
+ dest[j++] = exp_acc;
+ case EXP_D25:
+ dest[j++] = exp_acc;
+ case EXP_D15:
+ dest[j++] = exp_acc;
+ }
+
+ exp_acc += (exp_2 - 2);
+
+ switch(expstr) {
+ case EXP_D45:
+ dest[j++] = exp_acc;
+ dest[j++] = exp_acc;
+ case EXP_D25:
+ dest[j++] = exp_acc;
+ case EXP_D15:
+ dest[j++] = exp_acc;
+ }
+
+ exp_acc += (exp_3 - 2);
+
+ switch(expstr) {
+ case EXP_D45:
+ dest[j++] = exp_acc;
+ dest[j++] = exp_acc;
+ case EXP_D25:
+ dest[j++] = exp_acc;
+ case EXP_D15:
+ dest[j++] = exp_acc;
+ }
+ }
+
+ return;
+error:
+#ifdef FAST_ERROR
+ HANDLE_ERROR ();
+#else
+ if (!error_flag)
+ fprintf (stderr,"** Invalid exponent - skipping frame **\n");
+ error_flag = 1;
+#endif
+}
+
diff --git a/src/libac3/exponent.h b/src/libac3/exponent.h
new file mode 100644
index 000000000..06c59db03
--- /dev/null
+++ b/src/libac3/exponent.h
@@ -0,0 +1,28 @@
+/*
+ * exponent.h
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#define UNPACK_FBW 1
+#define UNPACK_CPL 2
+#define UNPACK_LFE 4
+
+void exponent_unpack( bsi_t *bsi, audblk_t *audblk);
diff --git a/src/libac3/imdct.c b/src/libac3/imdct.c
new file mode 100644
index 000000000..a055f3399
--- /dev/null
+++ b/src/libac3/imdct.c
@@ -0,0 +1,661 @@
+/*
+ * imdct.c
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include "ac3.h"
+#include "ac3_internal.h"
+
+#include "downmix.h"
+#include "imdct.h"
+#include "srfft.h"
+
+#define N 512
+
+/* static complex_t buf[128]; */
+//static complex_t buf[128] __attribute__((aligned(16)));
+complex_t buf[128] __attribute__((aligned(16)));
+
+/* Delay buffer for time domain interleaving */
+static float delay[6][256];
+static float delay1[6][256];
+
+/* Twiddle factors for IMDCT */
+static float xcos1[128] __attribute__((aligned(16)));
+static float xsin1[128] __attribute__((aligned(16)));
+
+/* more twiddle factors for IMDCT */
+static float xcos2[64];
+static float xsin2[64];
+
+/* Windowing function for Modified DCT - Thank you acroread */
+//static float window[] = {
+float 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 const int pm128[128] =
+const int pm128[128] =
+{
+ 0, 16, 32, 48, 64, 80, 96, 112, 8, 40, 72, 104, 24, 56, 88, 120,
+ 4, 20, 36, 52, 68, 84, 100, 116, 12, 28, 44, 60, 76, 92, 108, 124,
+ 2, 18, 34, 50, 66, 82, 98, 114, 10, 42, 74, 106, 26, 58, 90, 122,
+ 6, 22, 38, 54, 70, 86, 102, 118, 14, 46, 78, 110, 30, 62, 94, 126,
+ 1, 17, 33, 49, 65, 81, 97, 113, 9, 41, 73, 105, 25, 57, 89, 121,
+ 5, 21, 37, 53, 69, 85, 101, 117, 13, 29, 45, 61, 77, 93, 109, 125,
+ 3, 19, 35, 51, 67, 83, 99, 115, 11, 43, 75, 107, 27, 59, 91, 123,
+ 7, 23, 39, 55, 71, 87, 103, 119, 15, 31, 47, 63, 79, 95, 111, 127
+};
+
+static const int pm64[64] =
+{
+ 0, 8, 16, 24, 32, 40, 48, 56,
+ 4, 20, 36, 52, 12, 28, 44, 60,
+ 2, 10, 18, 26, 34, 42, 50, 58,
+ 6, 14, 22, 30, 38, 46, 54, 62,
+ 1, 9, 17, 25, 33, 41, 49, 57,
+ 5, 21, 37, 53, 13, 29, 45, 61,
+ 3, 11, 19, 27, 35, 43, 51, 59,
+ 7, 23, 39, 55, 15, 31, 47, 63
+};
+
+
+void imdct_init (void)
+ {
+ int i;
+ float scale = 255.99609372;
+
+ /* Twiddle factors to turn IFFT into IMDCT */
+
+ for (i=0; i < 128; i++) {
+ xcos1[i] = cos(2.0f * M_PI * (8*i+1)/(8*N)) * scale;
+ xsin1[i] = sin(2.0f * M_PI * (8*i+1)/(8*N)) * scale;
+ }
+
+ // More twiddle factors to turn IFFT into IMDCT */
+ for (i=0; i < 64; i++) {
+ xcos2[i] = cos(2.0f * M_PI * (8*i+1)/(4*N)) * scale;
+ xsin2[i] = sin(2.0f * M_PI * (8*i+1)/(4*N)) * scale;
+ }
+}
+
+
+void imdct_do_256 (float data[],float delay[])
+{
+ int i, j, k;
+ int p, q;
+
+ float tmp_a_i;
+ float tmp_a_r;
+
+ float *data_ptr;
+ float *delay_ptr;
+ float *window_ptr;
+
+ complex_t *buf1, *buf2;
+
+ buf1 = &buf[0];
+ buf2 = &buf[64];
+
+// Pre IFFT complex multiply plus IFFT complex conjugate
+ for (k=0; k<64; k++) {
+ /* X1[k] = X[2*k] */
+ /* X2[k] = X[2*k+1] */
+
+ j = pm64[k];
+ p = 2 * (128-2*j-1);
+ q = 2 * (2 * j);
+
+ /* Z1[k] = (X1[128-2*k-1] + j * X1[2*k]) * (xcos2[k] + j * xsin2[k]); */
+ buf1[k].re = data[p] * xcos2[j] - data[q] * xsin2[j];
+ buf1[k].im = -1.0f * (data[q] * xcos2[j] + data[p] * xsin2[j]);
+ /* Z2[k] = (X2[128-2*k-1] + j * X2[2*k]) * (xcos2[k] + j * xsin2[k]); */
+ buf2[k].re = data[p + 1] * xcos2[j] - data[q + 1] * xsin2[j];
+ buf2[k].im = -1.0f * ( data[q + 1] * xcos2[j] + data[p + 1] * xsin2[j]);
+ }
+
+ fft_64p(&buf1[0]);
+ fft_64p(&buf2[0]);
+
+#ifdef DEBUG
+ //DEBUG FFT
+#if 0
+ printf ("Post FFT, buf1\n");
+ for (i=0; i < 64; i++)
+ printf("%d %f %f\n", i, buf_1[i].re, buf_1[i].im);
+ printf ("Post FFT, buf2\n");
+ for (i=0; i < 64; i++)
+ printf("%d %f %f\n", i, buf_2[i].re, buf_2[i].im);
+#endif
+#endif
+
+
+ // Post IFFT complex multiply
+ for( i=0; i < 64; i++) {
+ tmp_a_r = buf1[i].re;
+ tmp_a_i = -buf1[i].im;
+ buf1[i].re =(tmp_a_r * xcos2[i]) - (tmp_a_i * xsin2[i]);
+ buf1[i].im =(tmp_a_r * xsin2[i]) + (tmp_a_i * xcos2[i]);
+ tmp_a_r = buf2[i].re;
+ tmp_a_i = -buf2[i].im;
+ buf2[i].re =(tmp_a_r * xcos2[i]) - (tmp_a_i * xsin2[i]);
+ buf2[i].im =(tmp_a_r * xsin2[i]) + (tmp_a_i * xcos2[i]);
+ }
+
+ data_ptr = data;
+ delay_ptr = delay;
+ window_ptr = window;
+
+ /* Window and convert to real valued signal */
+ for(i=0; i< 64; i++) {
+ *data_ptr++ = -buf1[i].im * *window_ptr++ + *delay_ptr++;
+ *data_ptr++ = buf1[64-i-1].re * *window_ptr++ + *delay_ptr++;
+ }
+
+ for(i=0; i< 64; i++) {
+ *data_ptr++ = -buf1[i].re * *window_ptr++ + *delay_ptr++;
+ *data_ptr++ = buf1[64-i-1].im * *window_ptr++ + *delay_ptr++;
+ }
+
+ delay_ptr = delay;
+
+ for(i=0; i< 64; i++) {
+ *delay_ptr++ = -buf2[i].re * *--window_ptr;
+ *delay_ptr++ = buf2[64-i-1].im * *--window_ptr;
+ }
+
+ for(i=0; i< 64; i++) {
+ *delay_ptr++ = buf2[i].im * *--window_ptr;
+ *delay_ptr++ = -buf2[64-i-1].re * *--window_ptr;
+ }
+}
+
+
+/**
+ *
+ **/
+
+void imdct_do_256_nol (float data[], float delay[])
+{
+ int i, j, k;
+ int p, q;
+
+ float tmp_a_i;
+ float tmp_a_r;
+
+ float *data_ptr;
+ float *delay_ptr;
+ float *window_ptr;
+
+ complex_t *buf1, *buf2;
+
+ buf1 = &buf[0];
+ buf2 = &buf[64];
+
+ /* Pre IFFT complex multiply plus IFFT cmplx conjugate */
+ for(k=0; k<64; k++) {
+ /* X1[k] = X[2*k] */
+ /* X2[k] = X[2*k+1] */
+ j = pm64[k];
+ p = 2 * (128-2*j-1);
+ q = 2 * (2 * j);
+
+ /* Z1[k] = (X1[128-2*k-1] + j * X1[2*k]) * (xcos2[k] + j * xsin2[k]); */
+ buf1[k].re = data[p] * xcos2[j] - data[q] * xsin2[j];
+ buf1[k].im = -1.0f * (data[q] * xcos2[j] + data[p] * xsin2[j]);
+ /* Z2[k] = (X2[128-2*k-1] + j * X2[2*k]) * (xcos2[k] + j * xsin2[k]); */
+ buf2[k].re = data[p + 1] * xcos2[j] - data[q + 1] * xsin2[j];
+ buf2[k].im = -1.0f * ( data[q + 1] * xcos2[j] + data[p + 1] * xsin2[j]);
+ }
+
+
+ fft_64p(&buf1[0]);
+ fft_64p(&buf2[0]);
+
+#ifdef DEBUG
+ //DEBUG FFT
+#if 0
+ printf("Post FFT, buf1\n");
+ for (i=0; i < 64; i++)
+ printf("%d %f %f\n", i, buf_1[i].re, buf_1[i].im);
+ printf("Post FFT, buf2\n");
+ for (i=0; i < 64; i++)
+ printf("%d %f %f\n", i, buf_2[i].re, buf_2[i].im);
+#endif
+#endif
+
+ /* Post IFFT complex multiply */
+ for( i=0; i < 64; i++) {
+ /* y1[n] = z1[n] * (xcos2[n] + j * xs in2[n]) ; */
+ tmp_a_r = buf1[i].re;
+ tmp_a_i = -buf1[i].im;
+ buf1[i].re =(tmp_a_r * xcos2[i]) - (tmp_a_i * xsin2[i]);
+ buf1[i].im =(tmp_a_r * xsin2[i]) + (tmp_a_i * xcos2[i]);
+ /* y2[n] = z2[n] * (xcos2[n] + j * xsin2[n]) ; */
+ tmp_a_r = buf2[i].re;
+ tmp_a_i = -buf2[i].im;
+ buf2[i].re =(tmp_a_r * xcos2[i]) - (tmp_a_i * xsin2[i]);
+ buf2[i].im =(tmp_a_r * xsin2[i]) + (tmp_a_i * xcos2[i]);
+ }
+
+ data_ptr = data;
+ delay_ptr = delay;
+ window_ptr = window;
+
+ /* Window and convert to real valued signal, no overlap */
+ for(i=0; i< 64; i++) {
+ *data_ptr++ = -buf1[i].im * *window_ptr++;
+ *data_ptr++ = buf1[64-i-1].re * *window_ptr++;
+ }
+
+ for(i=0; i< 64; i++) {
+ *data_ptr++ = -buf1[i].re * *window_ptr++ + *delay_ptr++;
+ *data_ptr++ = buf1[64-i-1].im * *window_ptr++ + *delay_ptr++;
+ }
+
+ delay_ptr = delay;
+
+ for(i=0; i< 64; i++) {
+ *delay_ptr++ = -buf2[i].re * *--window_ptr;
+ *delay_ptr++ = buf2[64-i-1].im * *--window_ptr;
+ }
+
+ for(i=0; i< 64; i++) {
+ *delay_ptr++ = buf2[i].im * *--window_ptr;
+ *delay_ptr++ = -buf2[64-i-1].re * *--window_ptr;
+ }
+}
+
+//FIXME remove - for timing code
+///#include <sys/time.h>
+//FIXME remove
+
+
+void imdct_do_512 (float data[], float delay[])
+{
+ int i, j;
+ float tmp_a_r, tmp_a_i;
+ float *data_ptr;
+ float *delay_ptr;
+ float *window_ptr;
+
+// 512 IMDCT with source and dest data in 'data'
+// Pre IFFT complex multiply plus IFFT complex conjugate
+
+ for( i=0; i < 128; i++) {
+ j = pm128[i];
+ //a = (data[256-2*j-1] - data[2*j]) * (xcos1[j] + xsin1[j]);
+ //c = data[2*j] * xcos1[j];
+ //b = data[256-2*j-1] * xsin1[j];
+ //buf1[i].re = a - b + c;
+ //buf1[i].im = b + c;
+ buf[i].re = (data[256-2*j-1] * xcos1[j]) - (data[2*j] * xsin1[j]);
+ buf[i].im = -1.0 * (data[2*j] * xcos1[j] + data[256-2*j-1] * xsin1[j]);
+ }
+
+ fft_128p (&buf[0]);
+
+// Post IFFT complex multiply plus IFFT complex conjugate
+ for (i=0; i < 128; i++) {
+ tmp_a_r = buf[i].re;
+ tmp_a_i = buf[i].im;
+ //a = (tmp_a_r - tmp_a_i) * (xcos1[j] + xsin1[j]);
+ //b = tmp_a_r * xsin1[j];
+ //c = tmp_a_i * xcos1[j];
+ //buf[j].re = a - b + c;
+ //buf[j].im = b + c;
+ buf[i].re =(tmp_a_r * xcos1[i]) + (tmp_a_i * xsin1[i]);
+ buf[i].im =(tmp_a_r * xsin1[i]) - (tmp_a_i * xcos1[i]);
+ }
+
+ data_ptr = data;
+ delay_ptr = delay;
+ window_ptr = window;
+
+// Window and convert to real valued signal
+ for (i=0; i< 64; i++) {
+ *data_ptr++ = -buf[64+i].im * *window_ptr++ + *delay_ptr++;
+ *data_ptr++ = buf[64-i-1].re * *window_ptr++ + *delay_ptr++;
+ }
+
+ for(i=0; i< 64; i++) {
+ *data_ptr++ = -buf[i].re * *window_ptr++ + *delay_ptr++;
+ *data_ptr++ = buf[128-i-1].im * *window_ptr++ + *delay_ptr++;
+ }
+
+// The trailing edge of the window goes into the delay line
+ delay_ptr = delay;
+
+ for(i=0; i< 64; i++) {
+ *delay_ptr++ = -buf[64+i].re * *--window_ptr;
+ *delay_ptr++ = buf[64-i-1].im * *--window_ptr;
+ }
+
+ for(i=0; i<64; i++) {
+ *delay_ptr++ = buf[i].im * *--window_ptr;
+ *delay_ptr++ = -buf[128-i-1].re * *--window_ptr;
+ }
+}
+
+
+void imdct_do_512_nol (float data[], float delay[])
+{
+ int i, j;
+
+ float tmp_a_i;
+ float tmp_a_r;
+
+ float *data_ptr;
+ float *delay_ptr;
+ float *window_ptr;
+
+ //
+ // 512 IMDCT with source and dest data in 'data'
+ //
+
+ // Pre IFFT complex multiply plus IFFT cmplx conjugate
+
+ for( i=0; i < 128; i++) {
+ /* z[i] = (X[256-2*i-1] + j * X[2*i]) * (xcos1[i] + j * xsin1[i]) */
+ j = pm128[i];
+ //a = (data[256-2*j-1] - data[2*j]) * (xcos1[j] + xsin1[j]);
+ //c = data[2*j] * xcos1[j];
+ //b = data[256-2*j-1] * xsin1[j];
+ //buf1[i].re = a - b + c;
+
+ //buf1[i].im = b + c;
+ buf[i].re = (data[256-2*j-1] * xcos1[j]) - (data[2*j] * xsin1[j]);
+ buf[i].im = -1.0 * (data[2*j] * xcos1[j] + data[256-2*j-1] * xsin1[j]);
+ }
+
+ fft_128p (&buf[0]);
+
+ /* Post IFFT complex multiply plus IFFT complex conjugate*/
+ for (i=0; i < 128; i++) {
+ /* y[n] = z[n] * (xcos1[n] + j * xsin1[n]) ; */
+ /* int j1 = i; */
+ tmp_a_r = buf[i].re;
+ tmp_a_i = buf[i].im;
+ //a = (tmp_a_r - tmp_a_i) * (xcos1[j] + xsin1[j]);
+ //b = tmp_a_r * xsin1[j];
+ //c = tmp_a_i * xcos1[j];
+ //buf[j].re = a - b + c;
+ //buf[j].im = b + c;
+ buf[i].re =(tmp_a_r * xcos1[i]) + (tmp_a_i * xsin1[i]);
+ buf[i].im =(tmp_a_r * xsin1[i]) - (tmp_a_i * xcos1[i]);
+ }
+
+ data_ptr = data;
+ delay_ptr = delay;
+ window_ptr = window;
+
+ /* Window and convert to real valued signal, no overlap here*/
+ for (i=0; i< 64; i++) {
+ *data_ptr++ = -buf[64+i].im * *window_ptr++;
+ *data_ptr++ = buf[64-i-1].re * *window_ptr++;
+ }
+
+ for(i=0; i< 64; i++) {
+ *data_ptr++ = -buf[i].re * *window_ptr++;
+ *data_ptr++ = buf[128-i-1].im * *window_ptr++;
+ }
+
+ /* The trailing edge of the window goes into the delay line */
+ delay_ptr = delay;
+
+ for(i=0; i< 64; i++) {
+ *delay_ptr++ = -buf[64+i].re * *--window_ptr;
+ *delay_ptr++ = buf[64-i-1].im * *--window_ptr;
+ }
+
+ for(i=0; i<64; i++) {
+ *delay_ptr++ = buf[i].im * *--window_ptr;
+ *delay_ptr++ = -buf[128-i-1].re * *--window_ptr;
+ }
+}
+
+void imdct (bsi_t *bsi,audblk_t *audblk, stream_samples_t samples, int16_t *s16_samples, dm_par_t* dm_par)
+{
+ int i;
+ int doable = 0;
+ float *center=NULL, *left, *right, *left_sur, *right_sur;
+ float *delay_left, *delay_right;
+ float *delay1_left, *delay1_right, *delay1_center, *delay1_sr, *delay1_sl;
+ float right_tmp, left_tmp;
+ void (*do_imdct)(float data[], float deley[]);
+
+ // test if dm in frequency is doable
+ if (!(doable = audblk->blksw[0]))
+ do_imdct = imdct_do_512;
+ else
+ do_imdct = imdct_do_256;
+
+ // downmix in the frequency domain if all the channels
+ // use the same imdct
+ for (i=0; i < bsi->nfchans; i++) {
+ if (doable != audblk->blksw[i]) {
+ do_imdct = NULL;
+ break;
+ }
+ }
+
+ if (do_imdct) {
+ //dowmix first and imdct
+ switch(bsi->acmod) {
+ case 7: // 3/2
+ downmix_3f_2r_to_2ch (samples[0], dm_par);
+ break;
+ case 6: // 2/2
+ downmix_2f_2r_to_2ch (samples[0], dm_par);
+ break;
+ case 5: // 3/1
+ downmix_3f_1r_to_2ch (samples[0], dm_par);
+ break;
+ case 4: // 2/1
+ downmix_2f_1r_to_2ch (samples[0], dm_par);
+ break;
+ case 3: // 3/0
+ downmix_3f_0r_to_2ch (samples[0], dm_par);
+ break;
+ case 2:
+ break;
+ default: // 1/0
+ if (bsi->acmod == 1)
+ center = samples[0];
+ else if (bsi->acmod == 0)
+ center = samples[ac3_config.dual_mono_ch_sel];
+ do_imdct(center, delay[0]); // no downmix
+
+ stream_sample_1ch_to_s16 (s16_samples, center);
+
+ return;
+ //goto done;
+ break;
+ }
+
+ do_imdct (samples[0], delay[0]);
+ do_imdct (samples[1], delay[1]);
+ stream_sample_2ch_to_s16(s16_samples, samples[0], samples[1]);
+
+ } else { //imdct and then dowmix
+ // delay and samples should be saved and mixed
+ //fprintf(stderr, "time domain downmix\n");
+ for (i=0; i<bsi->nfchans; i++) {
+ if (audblk->blksw[i])
+ imdct_do_256_nol (samples[i],delay1[i]);
+ else
+ imdct_do_512_nol (samples[i],delay1[i]);
+ }
+
+ // mix the sample, overlap
+ switch(bsi->acmod) {
+ case 7: // 3/2
+ left = samples[0];
+ center = samples[1];
+ right = samples[2];
+ left_sur = samples[3];
+ right_sur = samples[4];
+ delay_left = delay[0];
+ delay_right = delay[1];
+ delay1_left = delay1[0];
+ delay1_center = delay1[1];
+ delay1_right = delay1[2];
+ delay1_sl = delay1[3];
+ delay1_sr = delay1[4];
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = dm_par->unit * *left++ + dm_par->clev * *center + dm_par->slev * *left_sur++;
+ right_tmp= dm_par->unit * *right++ + dm_par->clev * *center++ + dm_par->slev * *right_sur++;
+ *s16_samples++ = (int16_t)(left_tmp + *delay_left);
+ *s16_samples++ = (int16_t)(right_tmp + *delay_right);
+ *delay_left++ = dm_par->unit * *delay1_left++ + dm_par->clev * *delay1_center + dm_par->slev * *delay1_sl++;
+ *delay_right++ = dm_par->unit * *delay1_right++ + dm_par->clev * *center++ + dm_par->slev * *delay1_sr++;
+ }
+ break;
+ case 6: // 2/2
+ left = samples[0];
+ right = samples[1];
+ left_sur = samples[2];
+ right_sur = samples[3];
+ delay_left = delay[0];
+ delay_right = delay[1];
+ delay1_left = delay1[0];
+ delay1_right = delay1[1];
+ delay1_sl = delay1[2];
+ delay1_sr = delay1[3];
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = dm_par->unit * *left++ + dm_par->slev * *left_sur++;
+ right_tmp= dm_par->unit * *right++ + dm_par->slev * *right_sur++;
+ *s16_samples++ = (int16_t)(left_tmp + *delay_left);
+ *s16_samples++ = (int16_t)(right_tmp + *delay_right);
+ *delay_left++ = dm_par->unit * *delay1_left++ + dm_par->slev * *delay1_sl++;
+ *delay_right++ = dm_par->unit * *delay1_right++ + dm_par->slev * *delay1_sr++;
+ }
+ break;
+ case 5: // 3/1
+ left = samples[0];
+ center = samples[1];
+ right = samples[2];
+ right_sur = samples[3];
+ delay_left = delay[0];
+ delay_right = delay[1];
+ delay1_left = delay1[0];
+ delay1_center = delay1[1];
+ delay1_right = delay1[2];
+ delay1_sl = delay1[3];
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = dm_par->unit * *left++ + dm_par->clev * *center - dm_par->slev * *right_sur;
+ right_tmp= dm_par->unit * *right++ + dm_par->clev * *center++ + dm_par->slev * *right_sur++;
+ *s16_samples++ = (int16_t)(left_tmp + *delay_left);
+ *s16_samples++ = (int16_t)(right_tmp + *delay_right);
+ *delay_left++ = dm_par->unit * *delay1_left++ + dm_par->clev * *delay1_center + dm_par->slev * *delay1_sl;
+ *delay_right++ = dm_par->unit * *delay1_right++ + dm_par->clev * *center++ + dm_par->slev * *delay1_sl++;
+ }
+ break;
+ case 4: // 2/1
+ left = samples[0];
+ right = samples[1];
+ right_sur = samples[2];
+ delay_left = delay[0];
+ delay_right = delay[1];
+ delay1_left = delay1[0];
+ delay1_right = delay1[1];
+ delay1_sl = delay1[2];
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = dm_par->unit * *left++ - dm_par->slev * *right_sur;
+ right_tmp= dm_par->unit * *right++ + dm_par->slev * *right_sur++;
+ *s16_samples++ = (int16_t)(left_tmp + *delay_left);
+ *s16_samples++ = (int16_t)(right_tmp + *delay_right);
+ *delay_left++ = dm_par->unit * *delay1_left++ + dm_par->slev * *delay1_sl;
+ *delay_right++ = dm_par->unit * *delay1_right++ + dm_par->slev * *delay1_sl++;
+ }
+ break;
+ case 3: // 3/0
+ left = samples[0];
+ center = samples[1];
+ right = samples[2];
+ delay_left = delay[0];
+ delay_right = delay[1];
+ delay1_left = delay1[0];
+ delay1_center = delay1[1];
+ delay1_right = delay1[2];
+
+ for (i = 0; i < 256; i++) {
+ left_tmp = dm_par->unit * *left++ + dm_par->clev * *center;
+ right_tmp= dm_par->unit * *right++ + dm_par->clev * *center++;
+ *s16_samples++ = (int16_t)(left_tmp + *delay_left);
+ *s16_samples++ = (int16_t)(right_tmp + *delay_right);
+ *delay_left++ = dm_par->unit * *delay1_left++ + dm_par->clev * *delay1_center;
+ *delay_right++ = dm_par->unit * *delay1_right++ + dm_par->clev * *center++;
+ }
+ break;
+ case 2: // copy to output
+ for (i = 0; i < 256; i++) {
+ *s16_samples++ = (int16_t)samples[0][i];
+ *s16_samples++ = (int16_t)samples[1][i];
+ }
+ break;
+ }
+ }
+}
+
diff --git a/src/libac3/imdct.h b/src/libac3/imdct.h
new file mode 100644
index 000000000..8a4479375
--- /dev/null
+++ b/src/libac3/imdct.h
@@ -0,0 +1,36 @@
+/*
+ * imdct.h
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#include "cmplx.h"
+
+void imdct_init(void);
+
+void imdct (bsi_t *bsi,audblk_t *audblk, stream_samples_t samples,
+ int16_t *s16_samples, dm_par_t *dm_par);
+
+void fft_64p (complex_t *);
+void imdct_do_512 (float data[],float delay[]);
+void imdct_do_512_nol (float data[], float delay[]);
+void imdct_do_256 (float data[],float delay[]);
+
diff --git a/src/libac3/parse.c b/src/libac3/parse.c
new file mode 100644
index 000000000..47ed3b407
--- /dev/null
+++ b/src/libac3/parse.c
@@ -0,0 +1,484 @@
+/*
+ * parse.c
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "ac3.h"
+#include "ac3_internal.h"
+
+
+#include "bitstream.h"
+#include "crc.h"
+#include "parse.h"
+
+/* Misc LUT */
+static const uint16_t nfchans[8] = {2,1,2,3,3,4,4,5};
+
+struct frmsize_s
+{
+ uint16_t bit_rate;
+ uint16_t frm_size[3];
+};
+
+static const struct frmsize_s frmsizecod_tbl[64] =
+{
+ { 32 ,{64 ,69 ,96 } },
+ { 32 ,{64 ,70 ,96 } },
+ { 40 ,{80 ,87 ,120 } },
+ { 40 ,{80 ,88 ,120 } },
+ { 48 ,{96 ,104 ,144 } },
+ { 48 ,{96 ,105 ,144 } },
+ { 56 ,{112 ,121 ,168 } },
+ { 56 ,{112 ,122 ,168 } },
+ { 64 ,{128 ,139 ,192 } },
+ { 64 ,{128 ,140 ,192 } },
+ { 80 ,{160 ,174 ,240 } },
+ { 80 ,{160 ,175 ,240 } },
+ { 96 ,{192 ,208 ,288 } },
+ { 96 ,{192 ,209 ,288 } },
+ { 112 ,{224 ,243 ,336 } },
+ { 112 ,{224 ,244 ,336 } },
+ { 128 ,{256 ,278 ,384 } },
+ { 128 ,{256 ,279 ,384 } },
+ { 160 ,{320 ,348 ,480 } },
+ { 160 ,{320 ,349 ,480 } },
+ { 192 ,{384 ,417 ,576 } },
+ { 192 ,{384 ,418 ,576 } },
+ { 224 ,{448 ,487 ,672 } },
+ { 224 ,{448 ,488 ,672 } },
+ { 256 ,{512 ,557 ,768 } },
+ { 256 ,{512 ,558 ,768 } },
+ { 320 ,{640 ,696 ,960 } },
+ { 320 ,{640 ,697 ,960 } },
+ { 384 ,{768 ,835 ,1152 } },
+ { 384 ,{768 ,836 ,1152 } },
+ { 448 ,{896 ,975 ,1344 } },
+ { 448 ,{896 ,976 ,1344 } },
+ { 512 ,{1024 ,1114 ,1536 } },
+ { 512 ,{1024 ,1115 ,1536 } },
+ { 576 ,{1152 ,1253 ,1728 } },
+ { 576 ,{1152 ,1254 ,1728 } },
+ { 640 ,{1280 ,1393 ,1920 } },
+ { 640 ,{1280 ,1394 ,1920 } }
+};
+
+/* Parse a syncinfo structure, minus the sync word */
+void parse_syncinfo(syncinfo_t *syncinfo, uint8_t *data)
+{
+ //
+ // We need to read in the entire syncinfo struct (0x0b77 + 24 bits)
+ // in order to determine how big the frame is
+ //
+
+ // Get the sampling rate
+ syncinfo->fscod = (data[2] >> 6) & 0x3;
+
+ if(syncinfo->fscod == 3) {
+ //invalid sampling rate code
+#ifndef FAST_ERROR
+ error_flag = 1;
+#endif
+ return;
+ }
+ else if(syncinfo->fscod == 2)
+ syncinfo->sampling_rate = 32000;
+ else if(syncinfo->fscod == 1)
+ syncinfo->sampling_rate = 44100;
+ else
+ syncinfo->sampling_rate = 48000;
+
+ // Get the frame size code
+ syncinfo->frmsizecod = data[2] & 0x3f;
+
+ // Calculate the frame size and bitrate
+ syncinfo->frame_size =
+ frmsizecod_tbl[syncinfo->frmsizecod].frm_size[syncinfo->fscod];
+ syncinfo->bit_rate = frmsizecod_tbl[syncinfo->frmsizecod].bit_rate;
+
+}
+
+
+/**
+ * This routine fills a bsi struct from the AC3 stream
+ **/
+
+void parse_bsi(bsi_t *bsi)
+{
+ /* Check the AC-3 version number */
+ bsi->bsid = bitstream_get(5);
+
+ /* Get the audio service provided by the steram */
+ bsi->bsmod = bitstream_get(3);
+
+ /* Get the audio coding mode (ie how many channels)*/
+ bsi->acmod = bitstream_get(3);
+ /* Predecode the number of full bandwidth channels as we use this
+ * number a lot */
+ bsi->nfchans = nfchans[bsi->acmod];
+
+ /* If it is in use, get the centre channel mix level */
+ if ((bsi->acmod & 0x1) && (bsi->acmod != 0x1))
+ bsi->cmixlev = bitstream_get(2);
+
+ /* If it is in use, get the surround channel mix level */
+ if (bsi->acmod & 0x4)
+ bsi->surmixlev = bitstream_get(2);
+
+ /* Get the dolby surround mode if in 2/0 mode */
+ if(bsi->acmod == 0x2)
+ bsi->dsurmod= bitstream_get(2);
+
+ /* Is the low frequency effects channel on? */
+ bsi->lfeon = bitstream_get(1);
+
+ /* Get the dialogue normalization level */
+ bsi->dialnorm = bitstream_get(5);
+
+ /* Does compression gain exist? */
+ if ((bsi->compre = bitstream_get(1))) {
+ /* Get compression gain */
+ bsi->compr = bitstream_get(8);
+ }
+
+ /* Does language code exist? */
+ if ((bsi->langcode = bitstream_get(1))) {
+ /* Get langauge code */
+ bsi->langcod = bitstream_get(8);
+ }
+
+ /* Does audio production info exist? */
+ if ((bsi->audprodie = bitstream_get(1))) {
+ /* Get mix level */
+ bsi->mixlevel = bitstream_get(5);
+
+ /* Get room type */
+ bsi->roomtyp = bitstream_get(2);
+ }
+
+ /* If we're in dual mono mode then get some extra info */
+ if (!bsi->acmod) {
+ /* Get the dialogue normalization level two */
+ bsi->dialnorm2 = bitstream_get(5);
+
+ /* Does compression gain two exist? */
+ if ((bsi->compr2e = bitstream_get(1))) {
+ /* Get compression gain two */
+ bsi->compr2 = bitstream_get(8);
+ }
+
+ /* Does language code two exist? */
+ if ((bsi->langcod2e = bitstream_get(1))) {
+ /* Get langauge code two */
+ bsi->langcod2 = bitstream_get(8);
+ }
+
+ /* Does audio production info two exist? */
+ if ((bsi->audprodi2e = bitstream_get(1))) {
+ /* Get mix level two */
+ bsi->mixlevel2 = bitstream_get(5);
+
+ /* Get room type two */
+ bsi->roomtyp2 = bitstream_get(2);
+ }
+ }
+
+ /* Get the copyright bit */
+ bsi->copyrightb = bitstream_get(1);
+
+ /* Get the original bit */
+ bsi->origbs = bitstream_get(1);
+
+ /* Does timecode one exist? */
+ if ((bsi->timecod1e = bitstream_get(1)))
+ bsi->timecod1 = bitstream_get(14);
+
+ /* Does timecode two exist? */
+ if ((bsi->timecod2e = bitstream_get(1)))
+ bsi->timecod2 = bitstream_get(14);
+
+ /* Does addition info exist? */
+ if ((bsi->addbsie = bitstream_get(1))) {
+ uint32_t i;
+
+ /* Get how much info is there */
+ bsi->addbsil = bitstream_get(6);
+
+ /* Get the additional info */
+ for(i=0;i<(bsi->addbsil + 1);i++)
+ bsi->addbsi[i] = bitstream_get(8);
+ }
+
+}
+
+
+/* More pain inducing parsing */
+void parse_audblk(bsi_t *bsi,audblk_t *audblk)
+{
+ int i,j;
+
+ for (i=0; i < bsi->nfchans; i++) {
+ /* Is this channel an interleaved 256 + 256 block ? */
+ audblk->blksw[i] = bitstream_get(1);
+ }
+
+ for (i=0;i < bsi->nfchans; i++) {
+ /* Should we dither this channel? */
+ audblk->dithflag[i] = bitstream_get(1);
+ }
+
+ /* Does dynamic range control exist? */
+ if ((audblk->dynrnge = bitstream_get(1))) {
+ /* Get dynamic range info */
+ audblk->dynrng = bitstream_get(8);
+ }
+
+ /* If we're in dual mono mode then get the second channel DR info */
+ if (bsi->acmod == 0) {
+ /* Does dynamic range control two exist? */
+ if ((audblk->dynrng2e = bitstream_get(1))) {
+ /* Get dynamic range info */
+ audblk->dynrng2 = bitstream_get(8);
+ }
+ }
+
+ /* Does coupling strategy exist? */
+ if ((audblk->cplstre = bitstream_get(1))) {
+ /* Is coupling turned on? */
+ if ((audblk->cplinu = bitstream_get(1))) {
+ for(i=0;i < bsi->nfchans; i++)
+ audblk->chincpl[i] = bitstream_get(1);
+ if(bsi->acmod == 0x2)
+ audblk->phsflginu = bitstream_get(1);
+ audblk->cplbegf = bitstream_get(4);
+ audblk->cplendf = bitstream_get(4);
+ audblk->ncplsubnd = (audblk->cplendf + 2) - audblk->cplbegf + 1;
+
+ /* Calculate the start and end bins of the coupling channel */
+ audblk->cplstrtmant = (audblk->cplbegf * 12) + 37 ;
+ audblk->cplendmant = ((audblk->cplendf + 3) * 12) + 37;
+
+ /* The number of combined subbands is ncplsubnd minus each combined
+ * band */
+ audblk->ncplbnd = audblk->ncplsubnd;
+
+ for(i=1; i< audblk->ncplsubnd; i++) {
+ audblk->cplbndstrc[i] = bitstream_get(1);
+ audblk->ncplbnd -= audblk->cplbndstrc[i];
+ }
+ }
+ }
+
+ if(audblk->cplinu) {
+ /* Loop through all the channels and get their coupling co-ords */
+ for(i=0;i < bsi->nfchans;i++) {
+ if(!audblk->chincpl[i])
+ continue;
+
+ /* Is there new coupling co-ordinate info? */
+ if ((audblk->cplcoe[i] = bitstream_get(1))) {
+ audblk->mstrcplco[i] = bitstream_get(2);
+ for(j=0;j < audblk->ncplbnd; j++) {
+ audblk->cplcoexp[i][j] = bitstream_get(4);
+ audblk->cplcomant[i][j] = bitstream_get(4);
+ }
+ }
+ }
+
+ /* If we're in dual mono mode, there's going to be some phase info */
+ if( (bsi->acmod == 0x2) && audblk->phsflginu &&
+ (audblk->cplcoe[0] || audblk->cplcoe[1])) {
+ for(j=0;j < audblk->ncplbnd; j++)
+ audblk->phsflg[j] = bitstream_get(1);
+
+ }
+ }
+
+ /* If we're in dual mono mode, there may be a rematrix strategy */
+ if(bsi->acmod == 0x2) {
+ if ((audblk->rematstr = bitstream_get(1))) {
+ if (!audblk->cplinu) {
+ for(i = 0; i < 4; i++)
+ audblk->rematflg[i] = bitstream_get(1);
+ }
+ if((audblk->cplbegf > 2) && audblk->cplinu) {
+ for(i = 0; i < 4; i++)
+ audblk->rematflg[i] = bitstream_get(1);
+ }
+ if((audblk->cplbegf <= 2) && audblk->cplinu) {
+ for(i = 0; i < 3; i++)
+ audblk->rematflg[i] = bitstream_get(1);
+ }
+ if((audblk->cplbegf == 0) && audblk->cplinu)
+ for(i = 0; i < 2; i++)
+ audblk->rematflg[i] = bitstream_get(1);
+
+ }
+ }
+
+ if (audblk->cplinu) {
+ /* Get the coupling channel exponent strategy */
+ audblk->cplexpstr = bitstream_get(2);
+ audblk->ncplgrps = (audblk->cplendmant - audblk->cplstrtmant) /
+ (((audblk->cplexpstr-1)>=0)?(3 << (audblk->cplexpstr-1)):(3 >> (-(audblk->cplexpstr-1))));
+ }
+
+ for(i = 0; i < bsi->nfchans; i++)
+ audblk->chexpstr[i] = bitstream_get(2);
+
+ /* Get the exponent strategy for lfe channel */
+ if(bsi->lfeon)
+ audblk->lfeexpstr = bitstream_get(1);
+
+ /* Determine the bandwidths of all the fbw channels */
+ for(i = 0; i < bsi->nfchans; i++) {
+ uint16_t grp_size;
+
+ if(audblk->chexpstr[i] != EXP_REUSE) {
+ if (audblk->cplinu && audblk->chincpl[i]) {
+ audblk->endmant[i] = audblk->cplstrtmant;
+ } else {
+ audblk->chbwcod[i] = bitstream_get(6);
+ audblk->endmant[i] = ((audblk->chbwcod[i] + 12) * 3) + 37;
+ }
+
+ /* Calculate the number of exponent groups to fetch */
+ grp_size = 3 * (1 << (audblk->chexpstr[i] - 1));
+ audblk->nchgrps[i] = (audblk->endmant[i] - 1 + (grp_size - 3)) / grp_size;
+ }
+ }
+
+ /* Get the coupling exponents if they exist */
+ if(audblk->cplinu && (audblk->cplexpstr != EXP_REUSE)) {
+ audblk->cplabsexp = bitstream_get(4);
+ for(i=0;i< audblk->ncplgrps;i++)
+ audblk->cplexps[i] = bitstream_get(7);
+ }
+
+ /* Get the fwb channel exponents */
+ for(i=0;i < bsi->nfchans; i++) {
+ if(audblk->chexpstr[i] != EXP_REUSE) {
+ audblk->exps[i][0] = bitstream_get(4);
+ for(j=1;j<=audblk->nchgrps[i];j++)
+ audblk->exps[i][j] = bitstream_get(7);
+ audblk->gainrng[i] = bitstream_get(2);
+ }
+ }
+
+ /* Get the lfe channel exponents */
+ if(bsi->lfeon && (audblk->lfeexpstr != EXP_REUSE)) {
+ audblk->lfeexps[0] = bitstream_get(4);
+ audblk->lfeexps[1] = bitstream_get(7);
+ audblk->lfeexps[2] = bitstream_get(7);
+ }
+
+ /* Get the parametric bit allocation parameters */
+ audblk->baie = bitstream_get(1);
+
+ if(audblk->baie) {
+ audblk->sdcycod = bitstream_get(2);
+ audblk->fdcycod = bitstream_get(2);
+ audblk->sgaincod = bitstream_get(2);
+ audblk->dbpbcod = bitstream_get(2);
+ audblk->floorcod = bitstream_get(3);
+ }
+
+ /* Get the SNR off set info if it exists */
+ audblk->snroffste = bitstream_get(1);
+
+ if(audblk->snroffste) {
+ audblk->csnroffst = bitstream_get(6);
+
+ if(audblk->cplinu) {
+ audblk->cplfsnroffst = bitstream_get(4);
+ audblk->cplfgaincod = bitstream_get(3);
+ }
+
+ for(i = 0;i < bsi->nfchans; i++) {
+ audblk->fsnroffst[i] = bitstream_get(4);
+ audblk->fgaincod[i] = bitstream_get(3);
+ }
+ if(bsi->lfeon) {
+
+ audblk->lfefsnroffst = bitstream_get(4);
+ audblk->lfefgaincod = bitstream_get(3);
+ }
+ }
+
+ /* Get coupling leakage info if it exists */
+ if(audblk->cplinu) {
+ audblk->cplleake = bitstream_get(1);
+
+ if(audblk->cplleake) {
+ audblk->cplfleak = bitstream_get(3);
+ audblk->cplsleak = bitstream_get(3);
+ }
+ }
+
+ /* Get the delta bit alloaction info */
+ audblk->deltbaie = bitstream_get(1);
+
+ if(audblk->deltbaie) {
+ if(audblk->cplinu)
+ audblk->cpldeltbae = bitstream_get(2);
+
+ for(i = 0;i < bsi->nfchans; i++)
+ audblk->deltbae[i] = bitstream_get(2);
+
+ if (audblk->cplinu && (audblk->cpldeltbae == DELTA_BIT_NEW)) {
+ audblk->cpldeltnseg = bitstream_get(3);
+ for(i = 0;i < audblk->cpldeltnseg + 1; i++) {
+ audblk->cpldeltoffst[i] = bitstream_get(5);
+ audblk->cpldeltlen[i] = bitstream_get(4);
+ audblk->cpldeltba[i] = bitstream_get(3);
+ }
+ }
+
+ for(i = 0;i < bsi->nfchans; i++) {
+ if (audblk->deltbae[i] == DELTA_BIT_NEW) {
+ audblk->deltnseg[i] = bitstream_get(3);
+ for(j = 0; j < audblk->deltnseg[i] + 1; j++) {
+ audblk->deltoffst[i][j] = bitstream_get(5);
+ audblk->deltlen[i][j] = bitstream_get(4);
+ audblk->deltba[i][j] = bitstream_get(3);
+ }
+ }
+ }
+ }
+
+ /* Check to see if there's any dummy info to get */
+ if((audblk->skiple = bitstream_get(1))) {
+ uint16_t skip_data;
+
+ audblk->skipl = bitstream_get(9);
+
+ for (i = 0; i < audblk->skipl; i++) {
+ skip_data = bitstream_get(8);
+ }
+ }
+
+}
diff --git a/src/libac3/parse.h b/src/libac3/parse.h
new file mode 100644
index 000000000..6264fea1d
--- /dev/null
+++ b/src/libac3/parse.h
@@ -0,0 +1,26 @@
+/*
+ * parse.h
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+void parse_syncinfo(syncinfo_t *syncinfo,uint8_t *data);
+void parse_audblk(bsi_t *bsi,audblk_t *audblk);
+void parse_bsi(bsi_t *bsi);
diff --git a/src/libac3/rematrix.c b/src/libac3/rematrix.c
new file mode 100644
index 000000000..95ce0117c
--- /dev/null
+++ b/src/libac3/rematrix.c
@@ -0,0 +1,95 @@
+/*
+ * rematrix.c
+ *
+ * Copyright (C) Aaron Holtzman - July 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "ac3.h"
+#include "ac3_internal.h"
+
+
+#include "rematrix.h"
+
+
+struct rematrix_band_s
+{
+ uint32_t start;
+ uint32_t end;
+} rematrix_band[] = {
+ {13, 24},
+ {25, 36},
+ {37, 60},
+ {61, 252}
+};
+
+
+/**
+ *
+ **/
+
+inline uint32_t min (uint32_t a, uint32_t b)
+{
+ return (a < b) ? a : b;
+}
+
+
+/**
+ * This routine simply does stereo remartixing for the 2 channel
+ * stereo mode
+ **/
+
+void rematrix (audblk_t *audblk, stream_samples_t samples)
+{
+ uint32_t num_bands;
+ uint32_t start;
+ uint32_t end;
+ int i,j;
+
+ if (!audblk->cplinu || audblk->cplbegf > 2)
+ num_bands = 4;
+ else if (audblk->cplbegf > 0)
+ num_bands = 3;
+ else
+ num_bands = 2;
+
+ for (i=0; i < num_bands; i++) {
+ if (!audblk->rematflg[i])
+ continue;
+
+ start = rematrix_band[i].start;
+ end = min (rematrix_band[i].end ,12 * audblk->cplbegf + 36);
+
+ for (j=start;j < end; j++) {
+ float left,right;
+
+ left = samples[0][j] + samples[1][j];
+ right = samples[0][j] - samples[1][j];
+ samples[0][j] = left;
+ samples[1][j] = right;
+ }
+ }
+}
diff --git a/src/libac3/rematrix.h b/src/libac3/rematrix.h
new file mode 100644
index 000000000..0be6528f6
--- /dev/null
+++ b/src/libac3/rematrix.h
@@ -0,0 +1,25 @@
+/*
+ * rematrix.h
+ *
+ * Copyright (C) Aaron Holtzman - July 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *
+ */
+
+void rematrix(audblk_t *audblk, stream_samples_t samples);
diff --git a/src/libac3/sanity_check.c b/src/libac3/sanity_check.c
new file mode 100644
index 000000000..ef0af0bd2
--- /dev/null
+++ b/src/libac3/sanity_check.c
@@ -0,0 +1,128 @@
+/*
+ * sanity_check.c
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include "ac3.h"
+#include "ac3_internal.h"
+#include "sanity_check.h"
+
+
+/**
+ *
+ **/
+
+void sanity_check_init(syncinfo_t *syncinfo, bsi_t *bsi, audblk_t *audblk)
+{
+ syncinfo->magic = AC3_MAGIC_NUMBER;
+ bsi->magic = AC3_MAGIC_NUMBER;
+ audblk->magic1 = AC3_MAGIC_NUMBER;
+ audblk->magic2 = AC3_MAGIC_NUMBER;
+ audblk->magic3 = AC3_MAGIC_NUMBER;
+}
+
+
+/**
+ *
+ **/
+
+int sanity_check(syncinfo_t *syncinfo, bsi_t *bsi, audblk_t *audblk)
+{
+ int i;
+
+ if(syncinfo->magic != AC3_MAGIC_NUMBER) {
+ fprintf(stderr,"\n** Sanity check failed -- syncinfo magic number **");
+ return -1;
+ }
+
+ if(bsi->magic != AC3_MAGIC_NUMBER) {
+ fprintf(stderr,"\n** Sanity check failed -- bsi magic number **");
+ return -1;
+ }
+
+ if(audblk->magic1 != AC3_MAGIC_NUMBER) {
+ fprintf(stderr,"\n** Sanity check failed -- audblk magic number 1 **");
+ return -1;
+ }
+
+ if(audblk->magic2 != AC3_MAGIC_NUMBER) {
+ fprintf(stderr,"\n** Sanity check failed -- audblk magic number 2 **");
+ return -1;
+ }
+
+ if(audblk->magic3 != AC3_MAGIC_NUMBER) {
+ fprintf(stderr,"\n** Sanity check failed -- audblk magic number 3 **");
+ return -1;
+ }
+
+ for(i = 0;i < 5 ; i++) {
+ if (audblk->fbw_exp[i][255] !=0 || audblk->fbw_exp[i][254] !=0 ||
+ audblk->fbw_exp[i][253] !=0) {
+ fprintf(stderr,"\n** Sanity check failed -- fbw_exp out of bounds **");
+ return -1;
+ }
+
+ if (audblk->fbw_bap[i][255] !=0 || audblk->fbw_bap[i][254] !=0 ||
+ audblk->fbw_bap[i][253] !=0) {
+ fprintf(stderr,"\n** Sanity check failed -- fbw_bap out of bounds **");
+ return -1;
+ }
+
+ }
+
+ if (audblk->cpl_exp[255] !=0 || audblk->cpl_exp[254] !=0 ||
+ audblk->cpl_exp[253] !=0) {
+ fprintf(stderr,"\n** Sanity check failed -- cpl_exp out of bounds **");
+ return -1;
+ }
+
+ if (audblk->cpl_bap[255] !=0 || audblk->cpl_bap[254] !=0 ||
+ audblk->cpl_bap[253] !=0) {
+ fprintf(stderr,"\n** Sanity check failed -- cpl_bap out of bounds **");
+ return -1;
+ }
+
+ if (audblk->cpl_flt[255] !=0 || audblk->cpl_flt[254] !=0 ||
+ audblk->cpl_flt[253] !=0) {
+ fprintf(stderr,"\n** Sanity check failed -- cpl_mant out of bounds **");
+ return -1;
+ }
+
+ if ((audblk->cplinu == 1) && (audblk->cplbegf > (audblk->cplendf+2))) {
+ fprintf(stderr,"\n** Sanity check failed -- cpl params inconsistent **");
+ return -1;
+ }
+
+ for(i=0; i < bsi->nfchans; i++) {
+ if((audblk->chincpl[i] == 0) && (audblk->chbwcod[i] > 60)) {
+ fprintf(stderr,"\n** Sanity check failed -- chbwcod too big **");
+ return -1;
+ }
+ }
+
+ return 0;
+}
diff --git a/src/libac3/sanity_check.h b/src/libac3/sanity_check.h
new file mode 100644
index 000000000..ead9399c9
--- /dev/null
+++ b/src/libac3/sanity_check.h
@@ -0,0 +1,27 @@
+/*
+ * sanity_check.h
+ *
+ * Copyright (C) Aaron Holtzman - May 1999
+ *
+ * This file is part of ac3dec, a free Dolby AC-3 stream decoder.
+ *
+ * ac3dec is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * ac3dec is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#define AC3_MAGIC_NUMBER 0xdeadbeef
+
+void sanity_check_init (syncinfo_t *syncinfo, bsi_t *bsi, audblk_t *audblk);
+int sanity_check (syncinfo_t *syncinfo, bsi_t *bsi, audblk_t *audblk);
diff --git a/src/libac3/srfft.c b/src/libac3/srfft.c
new file mode 100644
index 000000000..308fc2ccc
--- /dev/null
+++ b/src/libac3/srfft.c
@@ -0,0 +1,309 @@
+/*
+ * srfft.c
+ *
+ * Copyright (C) Yuqing Deng <Yuqing_Deng@brown.edu> - April 2000
+ *
+ * 64 and 128 point split radix fft for ac3dec
+ *
+ * The algorithm is desribed in the book:
+ * "Computational Frameworks of the Fast Fourier Transform".
+ *
+ * The ideas and the the organization of code borrowed from djbfft written by
+ * D. J. Bernstein <djb@cr.py.to>. djbff can be found at
+ * http://cr.yp.to/djbfft.html.
+ *
+ * srfft.c is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * srfft.c is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <stdio.h>
+
+#include "srfft.h"
+#include "srfftp.h"
+
+void fft_8 (complex_t *x);
+
+void fft_4(complex_t *x)
+{
+ /* delta_p = 1 here */
+ /* x[k] = sum_{i=0..3} x[i] * w^{i*k}, w=e^{-2*pi/4}
+ */
+
+ register float yt_r, yt_i, yb_r, yb_i, u_r, u_i, vi_r, vi_i;
+
+ yt_r = x[0].re;
+ yb_r = yt_r - x[2].re;
+ yt_r += x[2].re;
+
+ u_r = x[1].re;
+ vi_i = x[3].re - u_r;
+ u_r += x[3].re;
+
+ u_i = x[1].im;
+ vi_r = u_i - x[3].im;
+ u_i += x[3].im;
+
+ yt_i = yt_r;
+ yt_i += u_r;
+ x[0].re = yt_i;
+ yt_r -= u_r;
+ x[2].re = yt_r;
+ yt_i = yb_r;
+ yt_i += vi_r;
+ x[1].re = yt_i;
+ yb_r -= vi_r;
+ x[3].re = yb_r;
+
+ yt_i = x[0].im;
+ yb_i = yt_i - x[2].im;
+ yt_i += x[2].im;
+
+ yt_r = yt_i;
+ yt_r += u_i;
+ x[0].im = yt_r;
+ yt_i -= u_i;
+ x[2].im = yt_i;
+ yt_r = yb_i;
+ yt_r += vi_i;
+ x[1].im = yt_r;
+ yb_i -= vi_i;
+ x[3].im = yb_i;
+}
+
+
+void fft_8 (complex_t *x)
+{
+ /* delta_p = diag{1, sqrt(i)} here */
+ /* x[k] = sum_{i=0..7} x[i] * w^{i*k}, w=e^{-2*pi/8}
+ */
+ register float wT1_r, wT1_i, wB1_r, wB1_i, wT2_r, wT2_i, wB2_r, wB2_i;
+
+ wT1_r = x[1].re;
+ wT1_i = x[1].im;
+ wB1_r = x[3].re;
+ wB1_i = x[3].im;
+
+ x[1] = x[2];
+ x[2] = x[4];
+ x[3] = x[6];
+ fft_4(&x[0]);
+
+
+ /* x[0] x[4] */
+ wT2_r = x[5].re;
+ wT2_r += x[7].re;
+ wT2_r += wT1_r;
+ wT2_r += wB1_r;
+ wT2_i = wT2_r;
+ wT2_r += x[0].re;
+ wT2_i = x[0].re - wT2_i;
+ x[0].re = wT2_r;
+ x[4].re = wT2_i;
+
+ wT2_i = x[5].im;
+ wT2_i += x[7].im;
+ wT2_i += wT1_i;
+ wT2_i += wB1_i;
+ wT2_r = wT2_i;
+ wT2_r += x[0].im;
+ wT2_i = x[0].im - wT2_i;
+ x[0].im = wT2_r;
+ x[4].im = wT2_i;
+
+ /* x[2] x[6] */
+ wT2_r = x[5].im;
+ wT2_r -= x[7].im;
+ wT2_r += wT1_i;
+ wT2_r -= wB1_i;
+ wT2_i = wT2_r;
+ wT2_r += x[2].re;
+ wT2_i = x[2].re - wT2_i;
+ x[2].re = wT2_r;
+ x[6].re = wT2_i;
+
+ wT2_i = x[5].re;
+ wT2_i -= x[7].re;
+ wT2_i += wT1_r;
+ wT2_i -= wB1_r;
+ wT2_r = wT2_i;
+ wT2_r += x[2].im;
+ wT2_i = x[2].im - wT2_i;
+ x[2].im = wT2_i;
+ x[6].im = wT2_r;
+
+
+ /* x[1] x[5] */
+ wT2_r = wT1_r;
+ wT2_r += wB1_i;
+ wT2_r -= x[5].re;
+ wT2_r -= x[7].im;
+ wT2_i = wT1_i;
+ wT2_i -= wB1_r;
+ wT2_i -= x[5].im;
+ wT2_i += x[7].re;
+
+ wB2_r = wT2_r;
+ wB2_r += wT2_i;
+ wT2_i -= wT2_r;
+ wB2_r *= HSQRT2;
+ wT2_i *= HSQRT2;
+ wT2_r = wB2_r;
+ wB2_r += x[1].re;
+ wT2_r = x[1].re - wT2_r;
+
+ wB2_i = x[5].re;
+ x[1].re = wB2_r;
+ x[5].re = wT2_r;
+
+ wT2_r = wT2_i;
+ wT2_r += x[1].im;
+ wT2_i = x[1].im - wT2_i;
+ wB2_r = x[5].im;
+ x[1].im = wT2_r;
+ x[5].im = wT2_i;
+
+ /* x[3] x[7] */
+ wT1_r -= wB1_i;
+ wT1_i += wB1_r;
+ wB1_r = wB2_i - x[7].im;
+ wB1_i = wB2_r + x[7].re;
+ wT1_r -= wB1_r;
+ wT1_i -= wB1_i;
+ wB1_r = wT1_r + wT1_i;
+ wB1_r *= HSQRT2;
+ wT1_i -= wT1_r;
+ wT1_i *= HSQRT2;
+ wB2_r = x[3].re;
+ wB2_i = wB2_r + wT1_i;
+ wB2_r -= wT1_i;
+ x[3].re = wB2_i;
+ x[7].re = wB2_r;
+ wB2_i = x[3].im;
+ wB2_r = wB2_i + wB1_r;
+ wB2_i -= wB1_r;
+ x[3].im = wB2_i;
+ x[7].im = wB2_r;
+}
+
+
+void fft_asmb(int k, complex_t *x, complex_t *wTB,
+ const complex_t *d, const complex_t *d_3)
+{
+ register complex_t *x2k, *x3k, *x4k, *wB;
+ register float a_r, a_i, a1_r, a1_i, u_r, u_i, v_r, v_i;
+
+ x2k = x + 2 * k;
+ x3k = x2k + 2 * k;
+ x4k = x3k + 2 * k;
+ wB = wTB + 2 * k;
+
+ TRANSZERO(x[0],x2k[0],x3k[0],x4k[0]);
+ TRANS(x[1],x2k[1],x3k[1],x4k[1],wTB[1],wB[1],d[1],d_3[1]);
+
+ --k;
+ for(;;) {
+ TRANS(x[2],x2k[2],x3k[2],x4k[2],wTB[2],wB[2],d[2],d_3[2]);
+ TRANS(x[3],x2k[3],x3k[3],x4k[3],wTB[3],wB[3],d[3],d_3[3]);
+ if (!--k) break;
+ x += 2;
+ x2k += 2;
+ x3k += 2;
+ x4k += 2;
+ d += 2;
+ d_3 += 2;
+ wTB += 2;
+ wB += 2;
+ }
+
+}
+
+void fft_asmb16(complex_t *x, complex_t *wTB)
+{
+ register float a_r, a_i, a1_r, a1_i, u_r, u_i, v_r, v_i;
+ int k = 2;
+
+ /* transform x[0], x[8], x[4], x[12] */
+ TRANSZERO(x[0],x[4],x[8],x[12]);
+
+ /* transform x[1], x[9], x[5], x[13] */
+ TRANS(x[1],x[5],x[9],x[13],wTB[1],wTB[5],delta16[1],delta16_3[1]);
+
+ /* transform x[2], x[10], x[6], x[14] */
+ TRANSHALF_16(x[2],x[6],x[10],x[14]);
+
+ /* transform x[3], x[11], x[7], x[15] */
+ TRANS(x[3],x[7],x[11],x[15],wTB[3],wTB[7],delta16[3],delta16_3[3]);
+
+}
+
+
+void fft_64p (complex_t *a)
+{
+ fft_8(&a[0]); fft_4(&a[8]); fft_4(&a[12]);
+ fft_asmb16(&a[0], &a[8]);
+
+ fft_8(&a[16]), fft_8(&a[24]);
+ fft_asmb(4, &a[0], &a[16],&delta32[0], &delta32_3[0]);
+
+ fft_8(&a[32]); fft_4(&a[40]); fft_4(&a[44]);
+ fft_asmb16(&a[32], &a[40]);
+
+ fft_8(&a[48]); fft_4(&a[56]); fft_4(&a[60]);
+ fft_asmb16(&a[48], &a[56]);
+
+ fft_asmb(8, &a[0], &a[32],&delta64[0], &delta64_3[0]);
+}
+
+
+void fft_128p (complex_t *a)
+{
+ fft_8(&a[0]); fft_4(&a[8]); fft_4(&a[12]);
+ fft_asmb16(&a[0], &a[8]);
+
+ fft_8(&a[16]), fft_8(&a[24]);
+ fft_asmb(4, &a[0], &a[16],&delta32[0], &delta32_3[0]);
+
+ fft_8(&a[32]); fft_4(&a[40]); fft_4(&a[44]);
+ fft_asmb16(&a[32], &a[40]);
+
+ fft_8(&a[48]); fft_4(&a[56]); fft_4(&a[60]);
+ fft_asmb16(&a[48], &a[56]);
+
+ fft_asmb(8, &a[0], &a[32],&delta64[0], &delta64_3[0]);
+
+ fft_8(&a[64]); fft_4(&a[72]); fft_4(&a[76]);
+ /* fft_16(&a[64]); */
+ fft_asmb16(&a[64], &a[72]);
+
+ fft_8(&a[80]); fft_8(&a[88]);
+
+ /* fft_32(&a[64]); */
+ fft_asmb(4, &a[64], &a[80],&delta32[0], &delta32_3[0]);
+
+ fft_8(&a[96]); fft_4(&a[104]), fft_4(&a[108]);
+ /* fft_16(&a[96]); */
+ fft_asmb16(&a[96], &a[104]);
+
+ fft_8(&a[112]), fft_8(&a[120]);
+ /* fft_32(&a[96]); */
+ fft_asmb(4, &a[96], &a[112], &delta32[0], &delta32_3[0]);
+
+ /* fft_128(&a[0]); */
+ fft_asmb(16, &a[0], &a[64], &delta128[0], &delta128_3[0]);
+}
diff --git a/src/libac3/srfft.h b/src/libac3/srfft.h
new file mode 100644
index 000000000..ca85deda1
--- /dev/null
+++ b/src/libac3/srfft.h
@@ -0,0 +1,39 @@
+/*
+ * srfft.h
+ *
+ * Copyright (C) Yuqing Deng <Yuqing_Deng@brown.edu> - April 2000
+ *
+ * 64 and 128 point split radix fft for ac3dec
+ *
+ * The algorithm is desribed in the book:
+ * "Computational Frameworks of the Fast Fourier Transform".
+ *
+ * The ideas and the the organization of code borrowed from djbfft written by
+ * D. J. Bernstein <djb@cr.py.to>. djbff can be found at
+ * http://cr.yp.to/djbfft.html.
+ *
+ * srfft.h is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * srfft.h is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef SRFFT_H__
+#define SRFFT_H__
+
+#include "cmplx.h"
+
+void fft_64p (complex_t *x);
+void fft_128p (complex_t *x);
+
+#endif /* SRFFT_H__ */
diff --git a/src/libac3/srfftp.h b/src/libac3/srfftp.h
new file mode 100644
index 000000000..6f4471530
--- /dev/null
+++ b/src/libac3/srfftp.h
@@ -0,0 +1,305 @@
+
+/*
+ * srfftp.h
+ *
+ * Copyright (C) Yuqing Deng <Yuqing_Deng@brown.edu> - April 2000
+ *
+ * 64 and 128 point split radix fft for ac3dec
+ *
+ * The algorithm is desribed in the book:
+ * "Computational Frameworks of the Fast Fourier Transform".
+ *
+ * The ideas and the the organization of code borrowed from djbfft written by
+ * D. J. Bernstein <djb@cr.py.to>. djbff can be found at
+ * http://cr.yp.to/djbfft.html.
+ *
+ * srfftp.h is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * srfftp.h is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GNU Make; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+
+#ifndef SRFFTP_H__
+#define SRFFTP_H__
+
+#include "cmplx.h"
+
+static complex_t delta16[4] =
+ { {1.00000000000000, 0.00000000000000},
+ {0.92387953251129, -0.38268343236509},
+ {0.70710678118655, -0.70710678118655},
+ {0.38268343236509, -0.92387953251129}};
+
+static complex_t delta16_3[4] =
+ { {1.00000000000000, 0.00000000000000},
+ {0.38268343236509, -0.92387953251129},
+ {-0.70710678118655, -0.70710678118655},
+ {-0.92387953251129, 0.38268343236509}};
+
+static complex_t delta32[8] =
+ { {1.00000000000000, 0.00000000000000},
+ {0.98078528040323, -0.19509032201613},
+ {0.92387953251129, -0.38268343236509},
+ {0.83146961230255, -0.55557023301960},
+ {0.70710678118655, -0.70710678118655},
+ {0.55557023301960, -0.83146961230255},
+ {0.38268343236509, -0.92387953251129},
+ {0.19509032201613, -0.98078528040323}};
+
+static complex_t delta32_3[8] =
+ { {1.00000000000000, 0.00000000000000},
+ {0.83146961230255, -0.55557023301960},
+ {0.38268343236509, -0.92387953251129},
+ {-0.19509032201613, -0.98078528040323},
+ {-0.70710678118655, -0.70710678118655},
+ {-0.98078528040323, -0.19509032201613},
+ {-0.92387953251129, 0.38268343236509},
+ {-0.55557023301960, 0.83146961230255}};
+
+static complex_t delta64[16] =
+ { {1.00000000000000, 0.00000000000000},
+ {0.99518472667220, -0.09801714032956},
+ {0.98078528040323, -0.19509032201613},
+ {0.95694033573221, -0.29028467725446},
+ {0.92387953251129, -0.38268343236509},
+ {0.88192126434836, -0.47139673682600},
+ {0.83146961230255, -0.55557023301960},
+ {0.77301045336274, -0.63439328416365},
+ {0.70710678118655, -0.70710678118655},
+ {0.63439328416365, -0.77301045336274},
+ {0.55557023301960, -0.83146961230255},
+ {0.47139673682600, -0.88192126434835},
+ {0.38268343236509, -0.92387953251129},
+ {0.29028467725446, -0.95694033573221},
+ {0.19509032201613, -0.98078528040323},
+ {0.09801714032956, -0.99518472667220}};
+
+static complex_t delta64_3[16] =
+ { {1.00000000000000, 0.00000000000000},
+ {0.95694033573221, -0.29028467725446},
+ {0.83146961230255, -0.55557023301960},
+ {0.63439328416365, -0.77301045336274},
+ {0.38268343236509, -0.92387953251129},
+ {0.09801714032956, -0.99518472667220},
+ {-0.19509032201613, -0.98078528040323},
+ {-0.47139673682600, -0.88192126434836},
+ {-0.70710678118655, -0.70710678118655},
+ {-0.88192126434835, -0.47139673682600},
+ {-0.98078528040323, -0.19509032201613},
+ {-0.99518472667220, 0.09801714032956},
+ {-0.92387953251129, 0.38268343236509},
+ {-0.77301045336274, 0.63439328416365},
+ {-0.55557023301960, 0.83146961230255},
+ {-0.29028467725446, 0.95694033573221}};
+
+static complex_t delta128[32] =
+ { {1.00000000000000, 0.00000000000000},
+ {0.99879545620517, -0.04906767432742},
+ {0.99518472667220, -0.09801714032956},
+ {0.98917650996478, -0.14673047445536},
+ {0.98078528040323, -0.19509032201613},
+ {0.97003125319454, -0.24298017990326},
+ {0.95694033573221, -0.29028467725446},
+ {0.94154406518302, -0.33688985339222},
+ {0.92387953251129, -0.38268343236509},
+ {0.90398929312344, -0.42755509343028},
+ {0.88192126434836, -0.47139673682600},
+ {0.85772861000027, -0.51410274419322},
+ {0.83146961230255, -0.55557023301960},
+ {0.80320753148064, -0.59569930449243},
+ {0.77301045336274, -0.63439328416365},
+ {0.74095112535496, -0.67155895484702},
+ {0.70710678118655, -0.70710678118655},
+ {0.67155895484702, -0.74095112535496},
+ {0.63439328416365, -0.77301045336274},
+ {0.59569930449243, -0.80320753148064},
+ {0.55557023301960, -0.83146961230255},
+ {0.51410274419322, -0.85772861000027},
+ {0.47139673682600, -0.88192126434835},
+ {0.42755509343028, -0.90398929312344},
+ {0.38268343236509, -0.92387953251129},
+ {0.33688985339222, -0.94154406518302},
+ {0.29028467725446, -0.95694033573221},
+ {0.24298017990326, -0.97003125319454},
+ {0.19509032201613, -0.98078528040323},
+ {0.14673047445536, -0.98917650996478},
+ {0.09801714032956, -0.99518472667220},
+ {0.04906767432742, -0.99879545620517}};
+
+static complex_t delta128_3[32] =
+ { {1.00000000000000, 0.00000000000000},
+ {0.98917650996478, -0.14673047445536},
+ {0.95694033573221, -0.29028467725446},
+ {0.90398929312344, -0.42755509343028},
+ {0.83146961230255, -0.55557023301960},
+ {0.74095112535496, -0.67155895484702},
+ {0.63439328416365, -0.77301045336274},
+ {0.51410274419322, -0.85772861000027},
+ {0.38268343236509, -0.92387953251129},
+ {0.24298017990326, -0.97003125319454},
+ {0.09801714032956, -0.99518472667220},
+ {-0.04906767432742, -0.99879545620517},
+ {-0.19509032201613, -0.98078528040323},
+ {-0.33688985339222, -0.94154406518302},
+ {-0.47139673682600, -0.88192126434836},
+ {-0.59569930449243, -0.80320753148065},
+ {-0.70710678118655, -0.70710678118655},
+ {-0.80320753148065, -0.59569930449243},
+ {-0.88192126434835, -0.47139673682600},
+ {-0.94154406518302, -0.33688985339222},
+ {-0.98078528040323, -0.19509032201613},
+ {-0.99879545620517, -0.04906767432742},
+ {-0.99518472667220, 0.09801714032956},
+ {-0.97003125319454, 0.24298017990326},
+ {-0.92387953251129, 0.38268343236509},
+ {-0.85772861000027, 0.51410274419322},
+ {-0.77301045336274, 0.63439328416365},
+ {-0.67155895484702, 0.74095112535496},
+ {-0.55557023301960, 0.83146961230255},
+ {-0.42755509343028, 0.90398929312344},
+ {-0.29028467725446, 0.95694033573221},
+ {-0.14673047445536, 0.98917650996478}};
+
+#define HSQRT2 0.707106781188;
+
+#define TRANSZERO(A0,A4,A8,A12) { \
+ u_r = wTB[0].re; \
+ v_i = u_r - wTB[k*2].re; \
+ u_r += wTB[k*2].re; \
+ u_i = wTB[0].im; \
+ v_r = wTB[k*2].im - u_i; \
+ u_i += wTB[k*2].im; \
+ a_r = A0.re; \
+ a_i = A0.im; \
+ a1_r = a_r; \
+ a1_r += u_r; \
+ A0.re = a1_r; \
+ a_r -= u_r; \
+ A8.re = a_r; \
+ a1_i = a_i; \
+ a1_i += u_i; \
+ A0.im = a1_i; \
+ a_i -= u_i; \
+ A8.im = a_i; \
+ a1_r = A4.re; \
+ a1_i = A4.im; \
+ a_r = a1_r; \
+ a_r -= v_r; \
+ A4.re = a_r; \
+ a1_r += v_r; \
+ A12.re = a1_r; \
+ a_i = a1_i; \
+ a_i -= v_i; \
+ A4.im = a_i; \
+ a1_i += v_i; \
+ A12.im = a1_i; \
+ }
+
+#define TRANSHALF_16(A2,A6,A10,A14) {\
+ u_r = wTB[2].re; \
+ a_r = u_r; \
+ u_i = wTB[2].im; \
+ u_r += u_i; \
+ u_i -= a_r; \
+ a_r = wTB[6].re; \
+ a1_r = a_r; \
+ a_i = wTB[6].im; \
+ a_r = a_i - a_r; \
+ a_i += a1_r; \
+ v_i = u_r - a_r; \
+ u_r += a_r; \
+ v_r = u_i + a_i; \
+ u_i -= a_i; \
+ v_i *= HSQRT2; \
+ v_r *= HSQRT2; \
+ u_r *= HSQRT2; \
+ u_i *= HSQRT2; \
+ a_r = A2.re; \
+ a_i = A2.im; \
+ a1_r = a_r; \
+ a1_r += u_r; \
+ A2.re = a1_r; \
+ a_r -= u_r; \
+ A10.re = a_r; \
+ a1_i = a_i; \
+ a1_i += u_i; \
+ A2.im = a1_i; \
+ a_i -= u_i; \
+ A10.im = a_i; \
+ a1_r = A6.re; \
+ a1_i = A6.im; \
+ a_r = a1_r; \
+ a1_r += v_r; \
+ A6.re = a1_r; \
+ a_r -= v_r; \
+ A14.re = a_r; \
+ a_i = a1_i; \
+ a1_i -= v_i; \
+ A6.im = a1_i; \
+ a_i += v_i; \
+ A14.im = a_i; \
+ }
+
+#define TRANS(A1,A5,A9,A13,WT,WB,D,D3) { \
+ u_r = WT.re; \
+ a_r = u_r; \
+ a_r *= D.im; \
+ u_r *= D.re; \
+ a_i = WT.im; \
+ a1_i = a_i; \
+ a1_i *= D.re; \
+ a_i *= D.im; \
+ u_r -= a_i; \
+ u_i = a_r; \
+ u_i += a1_i; \
+ a_r = WB.re; \
+ a1_r = a_r; \
+ a1_r *= D3.re; \
+ a_r *= D3.im; \
+ a_i = WB.im; \
+ a1_i = a_i; \
+ a_i *= D3.re; \
+ a1_i *= D3.im; \
+ a1_r -= a1_i; \
+ a_r += a_i; \
+ v_i = u_r - a1_r; \
+ u_r += a1_r; \
+ v_r = a_r - u_i; \
+ u_i += a_r; \
+ a_r = A1.re; \
+ a_i = A1.im; \
+ a1_r = a_r; \
+ a1_r += u_r; \
+ A1.re = a1_r; \
+ a_r -= u_r; \
+ A9.re = a_r; \
+ a1_i = a_i; \
+ a1_i += u_i; \
+ A1.im = a1_i; \
+ a_i -= u_i; \
+ A9.im = a_i; \
+ a1_r = A5.re; \
+ a1_i = A5.im; \
+ a_r = a1_r; \
+ a1_r -= v_r; \
+ A5.re = a1_r; \
+ a_r += v_r; \
+ A13.re = a_r; \
+ a_i = a1_i; \
+ a1_i -= v_i; \
+ A5.im = a1_i; \
+ a_i += v_i; \
+ A13.im = a_i; \
+ }
+
+#endif