changeset 18141:59b6fa5b4201

Update to faad2 cvs 20040915+MPlayer fixes Patch by me and Emanuele Giaquinta
author rtognimp
date Tue, 18 Apr 2006 19:39:34 +0000
parents e371c7e18402
children 1794a1b179c7
files libfaad2/Makefile libfaad2/README libfaad2/analysis.h libfaad2/bits.c libfaad2/cfft.c libfaad2/cfft.h libfaad2/cfft_tab.h libfaad2/common.c libfaad2/common.h libfaad2/decoder.c libfaad2/decoder.h libfaad2/drc.c libfaad2/drc.h libfaad2/drm_dec.c libfaad2/drm_dec.h libfaad2/error.c libfaad2/error.h libfaad2/filtbank.c libfaad2/filtbank.h libfaad2/fixed.h libfaad2/hcr.c libfaad2/huffman.c libfaad2/huffman.h libfaad2/ic_predict.c libfaad2/ic_predict.h libfaad2/iq_table.h libfaad2/is.c libfaad2/is.h libfaad2/kbd_win.h libfaad2/local_changes.diff libfaad2/lt_predict.c libfaad2/lt_predict.h libfaad2/mdct.c libfaad2/mdct.h libfaad2/mdct_tab.h libfaad2/mp4.c libfaad2/mp4.h libfaad2/ms.c libfaad2/ms.h libfaad2/neaacdec.h libfaad2/output.c libfaad2/output.h libfaad2/pns.c libfaad2/pns.h libfaad2/ps_dec.c libfaad2/ps_dec.h libfaad2/ps_syntax.c libfaad2/ps_tables.h libfaad2/pulse.c libfaad2/pulse.h libfaad2/rvlc.c libfaad2/rvlc.h libfaad2/sbr_dct.c libfaad2/sbr_dct.h libfaad2/sbr_dec.c libfaad2/sbr_dec.h libfaad2/sbr_e_nf.c libfaad2/sbr_e_nf.h libfaad2/sbr_fbt.c libfaad2/sbr_fbt.h libfaad2/sbr_hfadj.c libfaad2/sbr_hfadj.h libfaad2/sbr_hfgen.c libfaad2/sbr_hfgen.h libfaad2/sbr_huff.c libfaad2/sbr_huff.h libfaad2/sbr_noise.h libfaad2/sbr_qmf.c libfaad2/sbr_qmf.h libfaad2/sbr_qmf_c.h libfaad2/sbr_syntax.c libfaad2/sbr_syntax.h libfaad2/sbr_tf_grid.c libfaad2/sbr_tf_grid.h libfaad2/sine_win.h libfaad2/specrec.c libfaad2/specrec.h libfaad2/ssr.c libfaad2/ssr.h libfaad2/ssr_fb.c libfaad2/ssr_fb.h libfaad2/ssr_ipqf.c libfaad2/ssr_ipqf.h libfaad2/ssr_win.h libfaad2/structs.h libfaad2/syntax.c libfaad2/syntax.h libfaad2/tns.c libfaad2/tns.h
diffstat 89 files changed, 2147 insertions(+), 1431 deletions(-) [+]
line wrap: on
line diff
--- a/libfaad2/Makefile	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/Makefile	Tue Apr 18 19:39:34 2006 +0000
@@ -8,6 +8,7 @@
           common.c \
           decoder.c \
           drc.c \
+          drm_dec.c \
           error.c \
           filtbank.c \
           hcr.c \
--- a/libfaad2/README	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/README	Tue Apr 18 19:39:34 2006 +0000
@@ -1,3 +1,3 @@
-This is a FAAD2 2.1 beta CVS snapshot from 2004-07-12.
+This is a FAAD2 CVS snapshot from 2004-09-15.
 Only the content of the libfaad/ and include/ subdirectories is present here.
 MPlayer-specific modifications can be found in local_changes.diff.
--- a/libfaad2/analysis.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/analysis.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: analysis.h,v 1.12 2004/02/26 09:29:26 menno Exp $
+** $Id: analysis.h,v 1.14 2004/09/04 14:56:27 menno Exp $
 **/
 
 #ifndef __ANALYSIS_H__
--- a/libfaad2/bits.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/bits.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: bits.c,v 1.37 2004/02/26 09:29:26 menno Exp $
+** $Id: bits.c,v 1.39 2004/09/04 14:56:27 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/cfft.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/cfft.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: cfft.c,v 1.27 2004/06/30 12:45:55 menno Exp $
+** $Id: cfft.c,v 1.30 2004/09/08 09:43:11 gcp Exp $
 **/
 
 /*
@@ -44,14 +44,6 @@
 
 
 /* static function declarations */
-#ifdef USE_SSE
-static void passf2pos_sse(const uint16_t l1, const complex_t *cc,
-                          complex_t *ch, const complex_t *wa);
-static void passf2pos_sse_ido(const uint16_t ido, const uint16_t l1, const complex_t *cc,
-                              complex_t *ch, const complex_t *wa);
-static void passf4pos_sse_ido(const uint16_t ido, const uint16_t l1, const complex_t *cc, complex_t *ch,
-                              const complex_t *wa1, const complex_t *wa2, const complex_t *wa3);
-#endif
 static void passf2pos(const uint16_t ido, const uint16_t l1, const complex_t *cc,
                       complex_t *ch, const complex_t *wa);
 static void passf2neg(const uint16_t ido, const uint16_t l1, const complex_t *cc,
@@ -74,89 +66,6 @@
    passf2, passf3, passf4, passf5. Complex FFT passes fwd and bwd.
   ----------------------------------------------------------------------*/
 
-#if 0 //def USE_SSE
-static void passf2pos_sse(const uint16_t l1, const complex_t *cc,
-                          complex_t *ch, const complex_t *wa)
-{
-    uint16_t k, ah, ac;
-
-    for (k = 0; k < l1; k++)
-    {
-        ah = 2*k;
-        ac = 4*k;
-
-        RE(ch[ah])    = RE(cc[ac]) + RE(cc[ac+1]);
-        IM(ch[ah])    = IM(cc[ac]) + IM(cc[ac+1]);
-
-        RE(ch[ah+l1]) = RE(cc[ac]) - RE(cc[ac+1]);
-        IM(ch[ah+l1]) = IM(cc[ac]) - IM(cc[ac+1]);
-    }
-}
-
-static void passf2pos_sse_ido(const uint16_t ido, const uint16_t l1, const complex_t *cc,
-                              complex_t *ch, const complex_t *wa)
-{
-    uint16_t i, k, ah, ac;
-
-    for (k = 0; k < l1; k++)
-    {
-        ah = k*ido;
-        ac = 2*k*ido;
-
-        for (i = 0; i < ido; i+=4)
-        {
-            __m128 m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14;
-            __m128 m15, m16, m17, m18, m19, m20, m21, m22, m23, m24;
-            __m128 w1, w2, w3, w4;
-
-            m1 = _mm_load_ps(&RE(cc[ac+i]));
-            m2 = _mm_load_ps(&RE(cc[ac+ido+i]));
-            m5 = _mm_load_ps(&RE(cc[ac+i+2]));
-            m6 = _mm_load_ps(&RE(cc[ac+ido+i+2]));
-            w1 = _mm_load_ps(&RE(wa[i]));
-            w3 = _mm_load_ps(&RE(wa[i+2]));
-
-            m3 = _mm_add_ps(m1, m2);
-            m15 = _mm_add_ps(m5, m6);
-
-            m4 = _mm_sub_ps(m1, m2);
-            m16 = _mm_sub_ps(m5, m6);
-
-            _mm_store_ps(&RE(ch[ah+i]), m3);
-            _mm_store_ps(&RE(ch[ah+i+2]), m15);
-
-
-            w2 = _mm_shuffle_ps(w1, w1, _MM_SHUFFLE(2, 3, 0, 1));
-            w4 = _mm_shuffle_ps(w3, w3, _MM_SHUFFLE(2, 3, 0, 1));
-
-            m7 = _mm_mul_ps(m4, w1);
-            m17 = _mm_mul_ps(m16, w3);
-            m8 = _mm_mul_ps(m4, w2);
-            m18 = _mm_mul_ps(m16, w4);
-
-            m9  = _mm_shuffle_ps(m7, m8, _MM_SHUFFLE(2, 0, 2, 0));
-            m19 = _mm_shuffle_ps(m17, m18, _MM_SHUFFLE(2, 0, 2, 0));
-            m10 = _mm_shuffle_ps(m7, m8, _MM_SHUFFLE(3, 1, 3, 1));
-            m20 = _mm_shuffle_ps(m17, m18, _MM_SHUFFLE(3, 1, 3, 1));
-
-            m11 = _mm_add_ps(m9, m10);
-            m21 = _mm_add_ps(m19, m20);
-            m12 = _mm_sub_ps(m9, m10);
-            m22 = _mm_sub_ps(m19, m20);
-
-            m13 = _mm_shuffle_ps(m11, m11, _MM_SHUFFLE(0, 0, 3, 2));
-            m23 = _mm_shuffle_ps(m21, m21, _MM_SHUFFLE(0, 0, 3, 2));
-
-            m14 = _mm_unpacklo_ps(m12, m13);
-            m24 = _mm_unpacklo_ps(m22, m23);
-
-            _mm_store_ps(&RE(ch[ah+i+l1*ido]), m14);
-            _mm_store_ps(&RE(ch[ah+i+2+l1*ido]), m24);
-        }
-    }
-}
-#endif
-
 static void passf2pos(const uint16_t ido, const uint16_t l1, const complex_t *cc,
                       complex_t *ch, const complex_t *wa)
 {
@@ -385,218 +294,6 @@
     }
 }
 
-#ifdef USE_SSE
-ALIGN static const int32_t negate[4] = { 0x0, 0x0, 0x0, 0x80000000 };
-
-__declspec(naked) static void passf4pos_sse(const uint16_t l1, const complex_t *cc,
-                                     complex_t *ch, const complex_t *wa1, const complex_t *wa2,
-                                     const complex_t *wa3)
-{
-    __asm {
-        push      ebx
-        mov       ebx, esp
-        and       esp, -16
-        push      edi
-        push      esi
-        sub       esp, 8
-        movzx     edi, WORD PTR [ebx+8]
-
-        movaps    xmm1, XMMWORD PTR negate
-
-        test      edi, edi
-        jle       l1_is_zero
-
-        lea       esi, DWORD PTR [edi+edi]
-        add       esi, esi
-        sub       esi, edi
-        add       esi, esi
-        add       esi, esi
-        add       esi, esi
-        mov       eax, DWORD PTR [ebx+16]
-        add       esi, eax
-        lea       ecx, DWORD PTR [edi+edi]
-        add       ecx, ecx
-        add       ecx, ecx
-        add       ecx, ecx
-        add       ecx, eax
-        lea       edx, DWORD PTR [edi+edi]
-        add       edx, edx
-        add       edx, edx
-        add       edx, eax
-        xor       eax, eax
-        mov       DWORD PTR [esp], ebp
-        mov       ebp, DWORD PTR [ebx+12]
-
-fftloop:
-        lea       edi, DWORD PTR [eax+eax]
-        add       edi, edi
-        movaps    xmm2, XMMWORD PTR [ebp+edi*8]
-        movaps    xmm0, XMMWORD PTR [ebp+edi*8+16]
-        movaps    xmm7, XMMWORD PTR [ebp+edi*8+32]
-        movaps    xmm5, XMMWORD PTR [ebp+edi*8+48]
-        movaps    xmm6, xmm2
-        addps     xmm6, xmm0
-        movaps    xmm4, xmm1
-        xorps     xmm4, xmm7
-        movaps    xmm3, xmm1
-        xorps     xmm3, xmm5
-        xorps     xmm2, xmm1
-        xorps     xmm0, xmm1
-        addps     xmm7, xmm5
-        subps     xmm2, xmm0
-        movaps    xmm0, xmm6
-        shufps    xmm0, xmm7, 68
-        subps     xmm4, xmm3
-        shufps    xmm6, xmm7, 238
-        movaps    xmm5, xmm2
-        shufps    xmm5, xmm4, 68
-        movaps    xmm3, xmm0
-        addps     xmm3, xmm6
-        shufps    xmm2, xmm4, 187
-        subps     xmm0, xmm6
-        movaps    xmm4, xmm5
-        addps     xmm4, xmm2
-        mov       edi, DWORD PTR [ebx+16]
-        movaps    XMMWORD PTR [edi+eax*8], xmm3
-        subps     xmm5, xmm2
-        movaps    XMMWORD PTR [edx+eax*8], xmm4
-        movaps    XMMWORD PTR [ecx+eax*8], xmm0
-        movaps    XMMWORD PTR [esi+eax*8], xmm5
-        add       eax, 2
-        movzx     eax, ax
-        movzx     edi, WORD PTR [ebx+8]
-        cmp       eax, edi
-        jl        fftloop
-
-        mov       ebp, DWORD PTR [esp]
-
-l1_is_zero:
-
-        add       esp, 8
-        pop       esi
-        pop       edi
-        mov       esp, ebx
-        pop       ebx
-        ret
-    }
-}
-#endif
-
-#if 0
-static void passf4pos_sse_ido(const uint16_t ido, const uint16_t l1, const complex_t *cc,
-                              complex_t *ch, const complex_t *wa1, const complex_t *wa2,
-                              const complex_t *wa3)
-{
-    uint16_t i, k, ac, ah;
-
-    for (k = 0; k < l1; k++)
-    {
-        ac = 4*k*ido;
-        ah = k*ido;
-
-        for (i = 0; i < ido; i+=2)
-        {
-            __m128 m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15, m16;
-            __m128 n1, n2, n3, n4, n5, n6, n7, n8, n9, m17, m18, m19, m20, m21, m22, m23;
-            __m128 w1, w2, w3, w4, w5, w6, m24, m25, m26, m27, m28, m29, m30;
-            __m128 neg1 = _mm_set_ps(-1.0, 1.0, -1.0, 1.0);
-
-            m1 = _mm_load_ps(&RE(cc[ac+i]));
-            m2 = _mm_load_ps(&RE(cc[ac+i+2*ido]));
-            m3 = _mm_add_ps(m1, m2);
-            m4 = _mm_sub_ps(m1, m2);
-
-            n1 = _mm_load_ps(&RE(cc[ac+i+ido]));
-            n2 = _mm_load_ps(&RE(cc[ac+i+3*ido]));
-            n3 = _mm_add_ps(n1, n2);
-
-            n4 = _mm_mul_ps(neg1, n1);
-            n5 = _mm_mul_ps(neg1, n2);
-            n6 = _mm_sub_ps(n4, n5);
-
-            m5 = _mm_add_ps(m3, n3);
-
-            n7 = _mm_shuffle_ps(n6, n6, _MM_SHUFFLE(2, 3, 0, 1));
-            n8 = _mm_add_ps(m4, n7);
-
-            m6 = _mm_sub_ps(m3, n3);
-            n9 = _mm_sub_ps(m4, n7);
-
-            _mm_store_ps(&RE(ch[ah+i]), m5);
-
-#if 0
-            static INLINE void ComplexMult(real_t *y1, real_t *y2,
-                real_t x1, real_t x2, real_t c1, real_t c2)
-            {
-                *y1 = MUL_F(x1, c1) + MUL_F(x2, c2);
-                *y2 = MUL_F(x2, c1) - MUL_F(x1, c2);
-            }
-
-            m7.0 = RE(c2)*RE(wa1[i])
-            m7.1 = IM(c2)*IM(wa1[i])
-            m7.2 = RE(c6)*RE(wa1[i+1])
-            m7.3 = IM(c6)*IM(wa1[i+1])
-
-            m8.0 = RE(c2)*IM(wa1[i])
-            m8.1 = IM(c2)*RE(wa1[i])
-            m8.2 = RE(c6)*IM(wa1[i+1])
-            m8.3 = IM(c6)*RE(wa1[i+1])
-
-            RE(0) = m7.0 - m7.1
-            IM(0) = m8.0 + m8.1
-            RE(1) = m7.2 - m7.3
-            IM(1) = m8.2 + m8.3
-
-            ////
-            RE(0) = RE(c2)*RE(wa1[i])   - IM(c2)*IM(wa1[i])
-            IM(0) = RE(c2)*IM(wa1[i])   + IM(c2)*RE(wa1[i])
-            RE(1) = RE(c6)*RE(wa1[i+1]) - IM(c6)*IM(wa1[i+1])
-            IM(1) = RE(c6)*IM(wa1[i+1]) + IM(c6)*RE(wa1[i+1])
-#endif
-
-            w1 = _mm_load_ps(&RE(wa1[i]));
-            w3 = _mm_load_ps(&RE(wa2[i]));
-            w5 = _mm_load_ps(&RE(wa3[i]));
-
-            w2 = _mm_shuffle_ps(w1, w1, _MM_SHUFFLE(2, 3, 0, 1));
-            w4 = _mm_shuffle_ps(w3, w3, _MM_SHUFFLE(2, 3, 0, 1));
-            w6 = _mm_shuffle_ps(w5, w5, _MM_SHUFFLE(2, 3, 0, 1));
-
-            m7 = _mm_mul_ps(n8, w1);
-            m15 = _mm_mul_ps(m6, w3);
-            m23 = _mm_mul_ps(n9, w5);
-            m8 = _mm_mul_ps(n8, w2);
-            m16 = _mm_mul_ps(m6, w4);
-            m24 = _mm_mul_ps(n9, w6);
-
-            m9  = _mm_shuffle_ps(m7, m8, _MM_SHUFFLE(2, 0, 2, 0));
-            m17 = _mm_shuffle_ps(m15, m16, _MM_SHUFFLE(2, 0, 2, 0));
-            m25 = _mm_shuffle_ps(m23, m24, _MM_SHUFFLE(2, 0, 2, 0));
-            m10 = _mm_shuffle_ps(m7, m8, _MM_SHUFFLE(3, 1, 3, 1));
-            m18 = _mm_shuffle_ps(m15, m16, _MM_SHUFFLE(3, 1, 3, 1));
-            m26 = _mm_shuffle_ps(m23, m24, _MM_SHUFFLE(3, 1, 3, 1));
-
-            m11 = _mm_add_ps(m9, m10);
-            m19 = _mm_add_ps(m17, m18);
-            m27 = _mm_add_ps(m25, m26);
-            m12 = _mm_sub_ps(m9, m10);
-            m20 = _mm_sub_ps(m17, m18);
-            m28 = _mm_sub_ps(m25, m26);
-
-            m13 = _mm_shuffle_ps(m11, m11, _MM_SHUFFLE(0, 0, 3, 2));
-            m21 = _mm_shuffle_ps(m19, m19, _MM_SHUFFLE(0, 0, 3, 2));
-            m29 = _mm_shuffle_ps(m27, m27, _MM_SHUFFLE(0, 0, 3, 2));
-            m14 = _mm_unpacklo_ps(m12, m13);
-            m22 = _mm_unpacklo_ps(m20, m21);
-            m30 = _mm_unpacklo_ps(m28, m29);
-
-            _mm_store_ps(&RE(ch[ah+i+l1*ido]), m14);
-            _mm_store_ps(&RE(ch[ah+i+2*l1*ido]), m22);
-            _mm_store_ps(&RE(ch[ah+i+3*l1*ido]), m30);
-        }
-    }
-}
-#endif
 
 static void passf4pos(const uint16_t ido, const uint16_t l1, const complex_t *cc,
                       complex_t *ch, const complex_t *wa1, const complex_t *wa2,
@@ -992,101 +689,6 @@
    cfftf1, cfftf, cfftb, cffti1, cffti. Complex FFTs.
   ----------------------------------------------------------------------*/
 
-#ifdef USE_SSE
-
-#define CONV(A,B,C) ( (A<<2) | ((B & 0x1)<<1) | ((C==1)&0x1) )
-
-static INLINE void cfftf1pos_sse(uint16_t n, complex_t *c, complex_t *ch,
-                                 const uint16_t *ifac, const complex_t *wa,
-                                 const int8_t isign)
-{
-    uint16_t i;
-    uint16_t k1, l1, l2;
-    uint16_t na, nf, ip, iw, ix2, ix3, ix4, ido, idl1;
-
-    nf = ifac[1];
-    na = 0;
-    l1 = 1;
-    iw = 0;
-
-    for (k1 = 2; k1 <= nf+1; k1++)
-    {
-        ip = ifac[k1];
-        l2 = ip*l1;
-        ido = n / l2;
-        idl1 = ido*l1;
-
-        ix2 = iw + ido;
-        ix3 = ix2 + ido;
-        ix4 = ix3 + ido;
-
-        switch (CONV(ip,na,ido))
-        {
-        case CONV(4,0,0):
-            //passf4pos_sse_ido((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)c, ch, &wa[iw], &wa[ix2], &wa[ix3]);
-            passf4pos((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)c, ch, &wa[iw], &wa[ix2], &wa[ix3]);
-            break;
-        case CONV(4,0,1):
-            passf4pos_sse((const uint16_t)l1, (const complex_t*)c, ch, &wa[iw], &wa[ix2], &wa[ix3]);
-            break;
-        case CONV(4,1,0):
-            passf4pos((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)ch, c, &wa[iw], &wa[ix2], &wa[ix3]);
-            //passf4pos_sse_ido((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)ch, c, &wa[iw], &wa[ix2], &wa[ix3]);
-            break;
-        case CONV(4,1,1):
-            passf4pos_sse((const uint16_t)l1, (const complex_t*)ch, c, &wa[iw], &wa[ix2], &wa[ix3]);
-            break;
-        case CONV(2,0,0):
-            passf2pos((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)c, ch, &wa[iw]);
-            //passf2pos_sse_ido((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)c, ch, &wa[iw]);
-            break;
-        case CONV(2,0,1):
-            passf2pos((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)c, ch, &wa[iw]);
-            //passf2pos_sse((const uint16_t)l1, (const complex_t*)c, ch, &wa[iw]);
-            break;
-        case CONV(2,1,0):
-            passf2pos((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)ch, c, &wa[iw]);
-            //passf2pos_sse_ido((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)ch, c, &wa[iw]);
-            break;
-        case CONV(2,1,1):
-            passf2pos((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)ch, c, &wa[iw]);
-            //passf2pos_sse((const uint16_t)l1, (const complex_t*)ch, c, &wa[iw]);
-            break;
-        case CONV(3,0,0):
-        case CONV(3,0,1):
-            passf3((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)c, ch, &wa[iw], &wa[ix2], isign);
-            break;
-        case CONV(3,1,0):
-        case CONV(3,1,1):
-            passf3((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)ch, c, &wa[iw], &wa[ix2], isign);
-            break;
-        case CONV(5,0,0):
-        case CONV(5,0,1):
-            passf5((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)c, ch, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4], isign);
-            break;
-        case CONV(5,1,0):
-        case CONV(5,1,1):
-            passf5((const uint16_t)ido, (const uint16_t)l1, (const complex_t*)ch, c, &wa[iw], &wa[ix2], &wa[ix3], &wa[ix4], isign);
-            break;
-        }
-
-        na = 1 - na;
-
-        l1 = l2;
-        iw += (ip-1) * ido;
-    }
-
-    if (na == 0)
-        return;
-
-    for (i = 0; i < n; i++)
-    {
-        RE(c[i]) = RE(ch[i]);
-        IM(c[i]) = IM(ch[i]);
-    }
-}
-#endif
-
 static INLINE void cfftf1pos(uint16_t n, complex_t *c, complex_t *ch,
                              const uint16_t *ifac, const complex_t *wa,
                              const int8_t isign)
@@ -1255,13 +857,6 @@
     cfftf1pos(cfft->n, c, cfft->work, (const uint16_t*)cfft->ifac, (const complex_t*)cfft->tab, +1);
 }
 
-#ifdef USE_SSE
-void cfftb_sse(cfft_info *cfft, complex_t *c)
-{
-    cfftf1pos_sse(cfft->n, c, cfft->work, (const uint16_t*)cfft->ifac, (const complex_t*)cfft->tab, +1);
-}
-#endif
-
 static void cffti1(uint16_t n, complex_t *wa, uint16_t *ifac)
 {
     static uint16_t ntryh[4] = {3, 4, 2, 5};
@@ -1388,6 +983,7 @@
     case 240: cfft->tab = (complex_t*)cfft_tab_240; break;
 #endif
 #endif
+    case 128: cfft->tab = (complex_t*)cfft_tab_128; break;
     }
 #endif
 
--- a/libfaad2/cfft.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/cfft.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: cfft.h,v 1.17 2004/02/26 09:29:26 menno Exp $
+** $Id: cfft.h,v 1.20 2004/09/08 09:43:11 gcp Exp $
 **/
 
 #ifndef __CFFT_H__
@@ -46,10 +46,6 @@
 cfft_info *cffti(uint16_t n);
 void cfftu(cfft_info *cfft);
 
-#ifdef USE_SSE
-void cfftb_sse(cfft_info *cfft, complex_t *c);
-#endif
-
 
 #ifdef __cplusplus
 }
--- a/libfaad2/cfft_tab.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/cfft_tab.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: cfft_tab.h,v 1.15 2004/06/30 12:45:55 menno Exp $
+** $Id: cfft_tab.h,v 1.17 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __CFFT_TAB_H__
@@ -1680,6 +1680,138 @@
 
 #endif
 
+ALIGN static const complex_t cfft_tab_128[] =
+{
+    { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) },
+    { FRAC_CONST(0.998795449733734), FRAC_CONST(0.049067676067352) },
+    { FRAC_CONST(0.995184719562531), FRAC_CONST(0.098017141222954) },
+    { FRAC_CONST(0.989176511764526), FRAC_CONST(0.146730467677116) },
+    { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) },
+    { FRAC_CONST(0.970031261444092), FRAC_CONST(0.242980197072029) },
+    { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) },
+    { FRAC_CONST(0.941544055938721), FRAC_CONST(0.336889863014221) },
+    { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) },
+    { FRAC_CONST(0.903989315032959), FRAC_CONST(0.427555084228516) },
+    { FRAC_CONST(0.881921231746674), FRAC_CONST(0.471396744251251) },
+    { FRAC_CONST(0.857728600502014), FRAC_CONST(0.514102756977081) },
+    { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) },
+    { FRAC_CONST(0.803207516670227), FRAC_CONST(0.595699310302734) },
+    { FRAC_CONST(0.773010432720184), FRAC_CONST(0.634393334388733) },
+    { FRAC_CONST(0.740951120853424), FRAC_CONST(0.671558976173401) },
+    { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) },
+    { FRAC_CONST(0.671558916568756), FRAC_CONST(0.740951180458069) },
+    { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) },
+    { FRAC_CONST(0.595699310302734), FRAC_CONST(0.803207516670227) },
+    { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) },
+    { FRAC_CONST(0.514102697372437), FRAC_CONST(0.857728660106659) },
+    { FRAC_CONST(0.471396654844284), FRAC_CONST(0.881921291351318) },
+    { FRAC_CONST(0.427555114030838), FRAC_CONST(0.903989315032959) },
+    { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) },
+    { FRAC_CONST(0.336889833211899), FRAC_CONST(0.941544055938721) },
+    { FRAC_CONST(0.290284633636475), FRAC_CONST(0.956940352916718) },
+    { FRAC_CONST(0.242980122566223), FRAC_CONST(0.970031261444092) },
+    { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) },
+    { FRAC_CONST(0.146730497479439), FRAC_CONST(0.989176511764526) },
+    { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) },
+    { FRAC_CONST(0.049067649990320), FRAC_CONST(0.998795449733734) },
+    { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) },
+    { FRAC_CONST(-0.049067739397287), FRAC_CONST(0.998795449733734) },
+    { FRAC_CONST(-0.098017223179340), FRAC_CONST(0.995184719562531) },
+    { FRAC_CONST(-0.146730571985245), FRAC_CONST(0.989176511764526) },
+    { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) },
+    { FRAC_CONST(-0.242980197072029), FRAC_CONST(0.970031261444092) },
+    { FRAC_CONST(-0.290284723043442), FRAC_CONST(0.956940293312073) },
+    { FRAC_CONST(-0.336889922618866), FRAC_CONST(0.941544055938721) },
+    { FRAC_CONST(-0.382683515548706), FRAC_CONST(0.923879504203796) },
+    { FRAC_CONST(-0.427555084228516), FRAC_CONST(0.903989315032959) },
+    { FRAC_CONST(-0.471396833658218), FRAC_CONST(0.881921231746674) },
+    { FRAC_CONST(-0.514102756977081), FRAC_CONST(0.857728600502014) },
+    { FRAC_CONST(-0.555570363998413), FRAC_CONST(0.831469535827637) },
+    { FRAC_CONST(-0.595699369907379), FRAC_CONST(0.803207516670227) },
+    { FRAC_CONST(-0.634393274784088), FRAC_CONST(0.773010492324829) },
+    { FRAC_CONST(-0.671559035778046), FRAC_CONST(0.740951061248779) },
+    { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) },
+    { FRAC_CONST(-0.740951240062714), FRAC_CONST(0.671558856964111) },
+    { FRAC_CONST(-0.773010492324829), FRAC_CONST(0.634393274784088) },
+    { FRAC_CONST(-0.803207635879517), FRAC_CONST(0.595699131488800) },
+    { FRAC_CONST(-0.831469655036926), FRAC_CONST(0.555570185184479) },
+    { FRAC_CONST(-0.857728600502014), FRAC_CONST(0.514102756977081) },
+    { FRAC_CONST(-0.881921350955963), FRAC_CONST(0.471396625041962) },
+    { FRAC_CONST(-0.903989315032959), FRAC_CONST(0.427555054426193) },
+    { FRAC_CONST(-0.923879623413086), FRAC_CONST(0.382683277130127) },
+    { FRAC_CONST(-0.941544115543365), FRAC_CONST(0.336889803409576) },
+    { FRAC_CONST(-0.956940352916718), FRAC_CONST(0.290284723043442) },
+    { FRAC_CONST(-0.970031261444092), FRAC_CONST(0.242980077862740) },
+    { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) },
+    { FRAC_CONST(-0.989176511764526), FRAC_CONST(0.146730333566666) },
+    { FRAC_CONST(-0.995184719562531), FRAC_CONST(0.098017096519470) },
+    { FRAC_CONST(-0.998795449733734), FRAC_CONST(0.049067486077547) },
+    { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) },
+    { FRAC_CONST(0.995184719562531), FRAC_CONST(0.098017141222954) },
+    { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) },
+    { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) },
+    { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) },
+    { FRAC_CONST(0.881921231746674), FRAC_CONST(0.471396744251251) },
+    { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) },
+    { FRAC_CONST(0.773010432720184), FRAC_CONST(0.634393334388733) },
+    { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) },
+    { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) },
+    { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) },
+    { FRAC_CONST(0.471396654844284), FRAC_CONST(0.881921291351318) },
+    { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) },
+    { FRAC_CONST(0.290284633636475), FRAC_CONST(0.956940352916718) },
+    { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) },
+    { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) },
+    { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) },
+    { FRAC_CONST(0.980785250663757), FRAC_CONST(0.195090323686600) },
+    { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) },
+    { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) },
+    { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) },
+    { FRAC_CONST(0.555570185184479), FRAC_CONST(0.831469655036926) },
+    { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) },
+    { FRAC_CONST(0.195090234279633), FRAC_CONST(0.980785310268402) },
+    { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) },
+    { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) },
+    { FRAC_CONST(-0.382683515548706), FRAC_CONST(0.923879504203796) },
+    { FRAC_CONST(-0.555570363998413), FRAC_CONST(0.831469535827637) },
+    { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) },
+    { FRAC_CONST(-0.831469655036926), FRAC_CONST(0.555570185184479) },
+    { FRAC_CONST(-0.923879623413086), FRAC_CONST(0.382683277130127) },
+    { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) },
+    { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) },
+    { FRAC_CONST(0.956940352916718), FRAC_CONST(0.290284663438797) },
+    { FRAC_CONST(0.831469595432281), FRAC_CONST(0.555570244789124) },
+    { FRAC_CONST(0.634393274784088), FRAC_CONST(0.773010432720184) },
+    { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) },
+    { FRAC_CONST(0.098017133772373), FRAC_CONST(0.995184719562531) },
+    { FRAC_CONST(-0.195090323686600), FRAC_CONST(0.980785250663757) },
+    { FRAC_CONST(-0.471396833658218), FRAC_CONST(0.881921231746674) },
+    { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) },
+    { FRAC_CONST(-0.881921231746674), FRAC_CONST(0.471396833658218) },
+    { FRAC_CONST(-0.980785310268402), FRAC_CONST(0.195090308785439) },
+    { FRAC_CONST(-0.995184719562531), FRAC_CONST(-0.098017267882824) },
+    { FRAC_CONST(-0.923879504203796), FRAC_CONST(-0.382683426141739) },
+    { FRAC_CONST(-0.773010551929474), FRAC_CONST(-0.634393215179443) },
+    { FRAC_CONST(-0.555570006370544), FRAC_CONST(-0.831469774246216) },
+    { FRAC_CONST(-0.290284544229507), FRAC_CONST(-0.956940352916718) },
+    { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) },
+    { FRAC_CONST(0.923879504203796), FRAC_CONST(0.382683455944061) },
+    { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) },
+    { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) },
+    { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) },
+    { FRAC_CONST(0.707106769084930), FRAC_CONST(0.707106769084930) },
+    { FRAC_CONST(-0.000000043711388), FRAC_CONST(1.000000000000000) },
+    { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) },
+    { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) },
+    { FRAC_CONST(0.382683426141739), FRAC_CONST(0.923879504203796) },
+    { FRAC_CONST(-0.707106769084930), FRAC_CONST(0.707106769084930) },
+    { FRAC_CONST(-0.923879504203796), FRAC_CONST(-0.382683426141739) },
+    { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) },
+    { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) },
+    { FRAC_CONST(1.000000000000000), FRAC_CONST(0.000000000000000) },
+    { FRAC_CONST(0.000000011924881), FRAC_CONST(-1.000000000000000) }
+};
+
 #endif
 
 #ifdef __cplusplus
--- a/libfaad2/common.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/common.c	Tue Apr 18 19:39:34 2006 +0000
@@ -1,19 +1,19 @@
 /*
 ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
 ** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com
-**  
+**
 ** This program 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 of the License, or
 ** (at your option) any later version.
-** 
+**
 ** This program 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 this program; if not, write to the Free Software 
+** along with this program; if not, write to the Free Software
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
 ** Any non-GPL usage of this software or parts of this software is strictly
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: common.c,v 1.19 2004/06/30 12:45:56 menno Exp $
+** $Id: common.c,v 1.22 2004/09/08 09:43:11 gcp Exp $
 **/
 
 /* just some common functions that could be used anywhere */
@@ -33,67 +33,6 @@
 #include <stdlib.h>
 #include "syntax.h"
 
-#ifdef USE_SSE
-__declspec(naked) static int32_t __fastcall test_cpuid(void)
-{
-    __asm
-    {
-        pushf
-        pop eax
-        mov ecx,eax
-        xor eax,(1<<21)
-        push eax
-        popf
-        pushf
-        pop eax
-        push ecx
-        popf
-        cmp eax,ecx
-        mov eax,0
-        setne al
-        ret
-    }
-}
-
-__declspec(naked) static void __fastcall run_cpuid(int32_t param, int32_t out[4])
-{
-    __asm
-    {
-        pushad
-        push edx
-        mov eax,ecx
-        cpuid
-        pop edi
-        mov [edi+0],eax
-        mov [edi+4],ebx
-        mov [edi+8],ecx
-        mov [edi+12],edx
-        popad
-        ret
-    }
-}
-
-uint8_t cpu_has_sse()
-{
-    int32_t features[4];
-
-    if (test_cpuid())
-    {
-        run_cpuid(1, features);
-    }
-
-    /* check for SSE */
-    if (features[3] & 0x02000000)
-        return 1;
-
-    return 0;
-}
-#else
-uint8_t cpu_has_sse()
-{
-    return 0;
-}
-#endif
 
 /* Returns the sample rate index based on the samplerate */
 uint8_t get_sr_index(const uint32_t samplerate)
@@ -146,7 +85,7 @@
 uint8_t max_tns_sfb(const uint8_t sr_index, const uint8_t object_type,
                     const uint8_t is_short)
 {
-    /* entry for each sampling rate	
+    /* entry for each sampling rate
      * 1    Main/LC long window
      * 2    Main/LC short window
      * 3    SSR long window
@@ -230,14 +169,13 @@
     return -1;
 }
 
-/* common malloc function */
 void *faad_malloc(size_t size)
 {
 #if 0 // defined(_WIN32) && !defined(_WIN32_WCE)
     return _aligned_malloc(size, 16);
-#else
+#else   // #ifdef 0
     return malloc(size);
-#endif
+#endif  // #ifdef 0
 }
 
 /* common free function */
@@ -247,18 +185,18 @@
     _aligned_free(b);
 #else
     free(b);
+}
 #endif
-}
 
 static const  uint8_t    Parity [256] = {  // parity
-	0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
-	1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
-	1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
-	0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
-	1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
-	0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
-	0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
-	1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0
+    0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
+    1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
+    1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
+    0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
+    1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,
+    0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
+    0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0,1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,
+    1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1,0,1,1,0,1,0,0,1,1,0,0,1,0,1,1,0
 };
 
 static uint32_t  __r1 = 1;
@@ -293,14 +231,14 @@
  */
 uint32_t random_int(void)
 {
-	uint32_t  t1, t2, t3, t4;
+    uint32_t  t1, t2, t3, t4;
 
-	t3   = t1 = __r1;   t4   = t2 = __r2;       // Parity calculation is done via table lookup, this is also available
-	t1  &= 0xF5;        t2 >>= 25;              // on CPUs without parity, can be implemented in C and avoid unpredictable
-	t1   = Parity [t1]; t2  &= 0x63;            // jumps and slow rotate through the carry flag operations.
-	t1 <<= 31;          t2   = Parity [t2];
+    t3   = t1 = __r1;   t4   = t2 = __r2;       // Parity calculation is done via table lookup, this is also available
+    t1  &= 0xF5;        t2 >>= 25;              // on CPUs without parity, can be implemented in C and avoid unpredictable
+    t1   = Parity [t1]; t2  &= 0x63;            // jumps and slow rotate through the carry flag operations.
+    t1 <<= 31;          t2   = Parity [t2];
 
-	return (__r1 = (t3 >> 1) | t1 ) ^ (__r2 = (t4 + t4) | t2 );
+    return (__r1 = (t3 >> 1) | t1 ) ^ (__r2 = (t4 + t4) | t2 );
 }
 
 uint32_t ones32(uint32_t x)
@@ -496,7 +434,7 @@
 {
     uint32_t frac;
     uint32_t whole = (val);
-    int8_t exp = 0;
+    int32_t exp = 0;
     uint32_t index;
     uint32_t index_frac;
     uint32_t x1, x2;
@@ -534,4 +472,48 @@
 
     return ((exp+REAL_BITS) << REAL_BITS) + errcorr + x1;
 }
+
+/* ld(x) = ld(x*y/y) = ld(x/y) + ld(y), with y=2^N and [1 <= (x/y) < 2] */
+real_t log2_fix(uint32_t val)
+{
+    uint32_t frac;
+    uint32_t whole = (val >> REAL_BITS);
+    int8_t exp = 0;
+    uint32_t index;
+    uint32_t index_frac;
+    uint32_t x1, x2;
+    uint32_t errcorr;
+
+    /* error */
+    if (val == 0)
+        return -100000;
+
+    exp = floor_log2(val);
+    exp -= REAL_BITS;
+
+    /* frac = [1..2] */
+    if (exp >= 0)
+        frac = val >> exp;
+    else
+        frac = val << -exp;
+
+    /* index in the log2 table */
+    index = frac >> (REAL_BITS-TABLE_BITS);
+
+    /* leftover part for linear interpolation */
+    index_frac = frac & ((1<<(REAL_BITS-TABLE_BITS))-1);
+
+    /* leave INTERP_BITS bits */
+    index_frac = index_frac >> (REAL_BITS-TABLE_BITS-INTERP_BITS);
+
+    x1 = log2_tab[index & ((1<<TABLE_BITS)-1)];
+    x2 = log2_tab[(index & ((1<<TABLE_BITS)-1)) + 1];
+
+    /* linear interpolation */
+    /* retval = exp + ((index_frac)*x2 + (1-index_frac)*x1) */
+
+    errcorr = (index_frac * (x2-x1)) >> INTERP_BITS;
+
+    return (exp << REAL_BITS) + errcorr + x1;
+}
 #endif
--- a/libfaad2/common.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/common.h	Tue Apr 18 19:39:34 2006 +0000
@@ -134,12 +134,6 @@
 # endif
 #endif
 
-#if ((defined(_WIN32) && !defined(_WIN32_WCE)) /* || ((__GNUC__ >= 3) && defined(__i386__)) */ )
-#ifndef FIXED_POINT
-/* includes <xmmintrin.h> to enable SSE intrinsics */
-//#define USE_SSE
-#endif
-#endif
 
 #ifdef FIXED_POINT
 #define DIV_R(A, B) (((int64_t)A << REAL_BITS)/B)
@@ -307,10 +301,6 @@
 
   typedef float real_t;
 
-#ifdef USE_SSE
-# include <xmmintrin.h>
-#endif
-
   #define MUL_R(A,B) ((A)*(B))
   #define MUL_C(A,B) ((A)*(B))
   #define MUL_F(A,B) ((A)*(B))
@@ -341,7 +331,7 @@
         }
         return i;
     }
-  #elif (defined(__i386__) && defined(__GNUC__)) && !defined(__MINGW32__) && !defined(HAVE_LRINTF)
+  #elif (defined(__i386__) && defined(__GNUC__)) && !defined(HAVE_LRINTF)
     #define HAS_LRINTF
     // from http://www.stereopsis.com/FPU.html
     static INLINE int lrintf(float f)
@@ -426,6 +416,7 @@
 #ifdef FIXED_POINT
 #define LOG2_MIN_INF REAL_CONST(-10000)
 int32_t log2_int(uint32_t val);
+int32_t log2_fix(uint32_t val);
 int32_t pow2_int(real_t val);
 real_t pow2_fix(real_t val);
 #endif
--- a/libfaad2/decoder.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/decoder.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: decoder.c,v 1.104 2004/06/30 12:45:56 menno Exp $
+** $Id: decoder.c,v 1.107 2004/09/08 09:43:11 gcp Exp $
 **/
 
 #include "common.h"
@@ -143,15 +143,6 @@
 
     hDecoder->drc = drc_init(REAL_CONST(1.0), REAL_CONST(1.0));
 
-#ifdef USE_SSE
-    if (cpu_has_sse())
-    {
-        hDecoder->apply_sf_func = apply_scalefactors_sse;
-    } else {
-        hDecoder->apply_sf_func = apply_scalefactors;
-    }
-#endif
-
     return hDecoder;
 }
 
@@ -901,6 +892,9 @@
         hInfo->header_type = ADIF;
     if (hDecoder->adts_header_present)
         hInfo->header_type = ADTS;
+#if (defined(PS_DEC) || defined(DRM_PS))
+    hInfo->ps = hDecoder->ps_used_global;
+#endif
 
     /* check if frame has channel elements */
     if (channels == 0)
--- a/libfaad2/decoder.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/decoder.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: decoder.h,v 1.42 2004/05/17 10:18:02 menno Exp $
+** $Id: decoder.h,v 1.44 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __DECODER_H__
--- a/libfaad2/drc.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/drc.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: drc.c,v 1.22 2004/02/26 09:29:26 menno Exp $
+** $Id: drc.c,v 1.24 2004/09/04 14:56:28 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/drc.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/drc.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: drc.h,v 1.16 2004/02/26 09:29:26 menno Exp $
+** $Id: drc.h,v 1.18 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __DRC_H__
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaad2/drm_dec.c	Tue Apr 18 19:39:34 2006 +0000
@@ -0,0 +1,990 @@
+/*
+** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR and PS decoding
+** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com
+**
+** This program 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 of the License, or
+** (at your option) any later version.
+**
+** This program 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 this program; if not, write to the Free Software
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** Any non-GPL usage of this software or parts of this software is strictly
+** forbidden.
+**
+** Commercial non-GPL licensing of this software is possible.
+** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
+**
+** $Id$
+**/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#include "common.h"
+
+#ifdef DRM
+
+#include "sbr_dec.h"
+#include "drm_dec.h"
+#include "bits.h"
+
+/* constants */
+#define DECAY_CUTOFF         3
+#define DECAY_SLOPE          0.05f
+
+/* type definitaions */
+typedef const int8_t (*drm_ps_huff_tab)[2];
+
+
+/* binary search huffman tables */
+static const int8_t f_huffman_sa[][2] = 
+{
+    { /*0*/ -15, 1 },             /* index 0: 1 bits:  x */
+    { 2, 3 },                     /* index 1: 2 bits:  1x */
+    { /*7*/ -8, 4 },              /* index 2: 3 bits:  10x */
+    { 5, 6 },                     /* index 3: 3 bits:  11x */
+    { /*1*/ -14, /*-1*/ -16 },    /* index 4: 4 bits:  101x */
+    { /*-2*/ -17, 7 },            /* index 5: 4 bits:  110x */
+    { 8, 9 },                     /* index 6: 4 bits:  111x */
+    { /*2*/ -13, /*-3*/ -18 },    /* index 7: 5 bits:  1101x */
+    { /*3*/ -12, 10 },            /* index 8: 5 bits:  1110x */
+    { 11, 12 },                   /* index 9: 5 bits:  1111x */
+    { /*4*/ -11, /*5*/ -10 },     /* index 10: 6 bits: 11101x */
+    { /*-4*/ -19, /*-5*/ -20 },   /* index 11: 6 bits: 11110x */
+    { /*6*/ -9, 13 },             /* index 12: 6 bits: 11111x */
+    { /*-7*/ -22, /*-6*/ -21 }    /* index 13: 7 bits: 111111x */
+};
+
+static const int8_t t_huffman_sa[][2] = 
+{
+    { /*0*/ -15, 1 },             /* index 0: 1 bits: x */
+    { 2, 3 },                     /* index 1: 2 bits: 1x */
+    { /*-1*/ -16, /*1*/ -14 },    /* index 2: 3 bits: 10x */
+    { 4, 5 },                     /* index 3: 3 bits: 11x */
+    { /*-2*/ -17, /*2*/ -13 },    /* index 4: 4 bits: 110x */
+    { 6, 7 },                     /* index 5: 4 bits: 111x */
+    { /*-3*/ -18, /*3*/ -12 },    /* index 6: 5 bits: 1110x */
+    { 8, 9 },                     /* index 7: 5 bits: 1111x */
+    { /*-4*/ -19, /*4*/ -11 },    /* index 8: 6 bits: 11110x */
+    { 10, 11 },                   /* index 9: 6 bits: 11111x */
+    { /*-5*/ -20, /*5*/ -10 },    /* index 10: 7 bits: 111110x */
+    { /*-6*/ -21, 12 },           /* index 11: 7 bits: 111111x */
+    { /*-7*/ -22, 13 },           /* index 12: 8 bits: 1111111x */
+    { /*6*/ -9, /*7*/ -8 }        /* index 13: 9 bits: 11111111x */
+};
+
+static const int8_t f_huffman_pan[][2] = 
+{
+    { /*0*/ -15, 1 },             /* index 0: 1 bits: x */
+    { /*-1*/ -16, 2 },            /* index 1: 2 bits: 1x */
+    { /*1*/ -14, 3 },             /* index 2: 3 bits: 11x */
+    { 4, 5 },                     /* index 3: 4 bits: 111x */
+    { /*-2*/ -17, /*2*/ -13 },    /* index 4: 5 bits: 1110x */
+    { 6, 7 },                     /* index 5: 5 bits: 1111x */
+    { /*-3*/ -18, /*3*/ -12 },    /* index 6: 6 bits: 11110x */
+    { 8, 9 },                     /* index 7: 6 bits: 11111x */
+    { /*-4*/ -19, /*4*/ -11 },    /* index 8: 7 bits: 111110x */
+    { 10, 11 },                   /* index 9: 7 bits: 111111x */
+    { /*-5*/ -20, /*5*/ -10 },    /* index 10: 8 bits: 1111110x */
+    { 12, 13 },                   /* index 11: 8 bits: 1111111x */
+    { /*-6*/ -21, /*6*/ -9 },     /* index 12: 9 bits: 11111110x */
+    { /*-7*/ -22, 14 },           /* index 13: 9 bits: 11111111x */
+    { /*7*/ -8, 15 },             /* index 14: 10 bits: 111111111x */
+    { 16, 17 },                   /* index 15: 11 bits: 1111111111x */
+    { /*-8*/ -23, /*8*/ -7 },     /* index 16: 12 bits: 11111111110x */
+    { 18, 19 },                   /* index 17: 12 bits: 11111111111x */
+    { /*-10*/ -25, 20 },          /* index 18: 13 bits: 111111111110x */
+    { 21, 22 },                   /* index 19: 13 bits: 111111111111x */
+    { /*-9*/ -24, /*9*/ -6 },     /* index 20: 14 bits: 1111111111101x */
+    { /*10*/ -5, 23 },            /* index 21: 14 bits: 1111111111110x */
+    { 24, 25 },                   /* index 22: 14 bits: 1111111111111x */
+    { /*-13*/ -28, /*-11*/ -26 }, /* index 23: 15 bits: 11111111111101x */
+    { /*11*/ -4, /*13*/ -2 },     /* index 24: 15 bits: 11111111111110x */
+    { 26, 27 },                   /* index 25: 15 bits: 11111111111111x */
+    { /*-14*/ -29, /*-12*/ -27 }, /* index 26: 16 bits: 111111111111110x */
+    { /*12*/ -3, /*14*/ -1 }      /* index 27: 16 bits: 111111111111111x */
+};
+
+static const int8_t t_huffman_pan[][2] = 
+{
+    { /*0*/ -15, 1 },             /* index 0: 1 bits: x */
+    { /*-1*/ -16, 2 },            /* index 1: 2 bits: 1x */
+    { /*1*/ -14, 3 },             /* index 2: 3 bits: 11x */
+    { /*-2*/ -17, 4 },            /* index 3: 4 bits: 111x */
+    { /*2*/ -13, 5 },             /* index 4: 5 bits: 1111x */
+    { /*-3*/ -18, 6 },            /* index 5: 6 bits: 11111x */
+    { /*3*/ -12, 7 },             /* index 6: 7 bits: 111111x */
+    { /*-4*/ -19, 8 },            /* index 7: 8 bits: 1111111x */
+    { /*4*/ -11, 9 },             /* index 8: 9 bits: 11111111x */
+    { 10, 11 },                   /* index 9: 10 bits: 111111111x */
+    { /*-5*/ -20, /*5*/ -10 },    /* index 10: 11 bits: 1111111110x */
+    { 12, 13 },                   /* index 11: 11 bits: 1111111111x */
+    { /*-6*/ -21, /*6*/ -9 },     /* index 12: 12 bits: 11111111110x */
+    { 14, 15 },                   /* index 13: 12 bits: 11111111111x */
+    { /*-7*/ -22, /*7*/ -8 },     /* index 14: 13 bits: 111111111110x */
+    { 16, 17 },                   /* index 15: 13 bits: 111111111111x */
+    { /*-8*/ -23, /*8*/ -7 },     /* index 16: 14 bits: 1111111111110x */
+    { 18, 19 },                   /* index 17: 14 bits: 1111111111111x */
+    { /*-10*/ -25, /*10*/ -5 },   /* index 18: 15 bits: 11111111111110x */
+    { 20, 21 },                   /* index 19: 15 bits: 11111111111111x */
+    { /*-9*/ -24, /*9*/ -6 },     /* index 20: 16 bits: 111111111111110x */
+    { 22, 23 },                   /* index 21: 16 bits: 111111111111111x */
+    { 24, 25 },                   /* index 22: 17 bits: 1111111111111110x */
+    { 26, 27 },                   /* index 23: 17 bits: 1111111111111111x */
+    { /*-14*/ -29, /*-13*/ -28 }, /* index 24: 18 bits: 11111111111111100x */
+    { /*-12*/ -27, /*-11*/ -26 }, /* index 25: 18 bits: 11111111111111101x */
+    { /*11*/ -4, /*12*/ -3 },     /* index 26: 18 bits: 11111111111111110x */
+    { /*13*/ -2, /*14*/ -1 }      /* index 27: 18 bits: 11111111111111111x */
+};
+
+/* There are 3 classes in the standard but the last 2 are identical */
+static const real_t sa_quant[8][2] = 
+{
+    { FRAC_CONST(0.0000), FRAC_CONST(0.0000) },
+    { FRAC_CONST(0.0501), FRAC_CONST(0.1778) },
+    { FRAC_CONST(0.0706), FRAC_CONST(0.2818) },
+    { FRAC_CONST(0.0995), FRAC_CONST(0.4467) },
+    { FRAC_CONST(0.1399), FRAC_CONST(0.5623) },
+    { FRAC_CONST(0.1957), FRAC_CONST(0.7079) },
+    { FRAC_CONST(0.2713), FRAC_CONST(0.8913) },
+    { FRAC_CONST(0.3699), FRAC_CONST(1.0000) },
+};
+
+/* We don't need the actual quantizer values */
+#if 0
+static const real_t pan_quant[8][5] = 
+{
+    { COEF_CONST(0.0000), COEF_CONST(0.0000), COEF_CONST(0.0000), COEF_CONST(0.0000), COEF_CONST(0.0000) },
+    { COEF_CONST(0.1661), COEF_CONST(0.1661), COEF_CONST(0.3322), COEF_CONST(0.3322), COEF_CONST(0.3322) },
+    { COEF_CONST(0.3322), COEF_CONST(0.3322), COEF_CONST(0.6644), COEF_CONST(0.8305), COEF_CONST(0.8305) },
+    { COEF_CONST(0.4983), COEF_CONST(0.6644), COEF_CONST(0.9966), COEF_CONST(1.4949), COEF_CONST(1.6610) },
+    { COEF_CONST(0.6644), COEF_CONST(0.9966), COEF_CONST(1.4949), COEF_CONST(2.1593), COEF_CONST(2.4914) },
+    { COEF_CONST(0.8305), COEF_CONST(1.3288), COEF_CONST(2.1593), COEF_CONST(2.9897), COEF_CONST(3.4880) },
+    { COEF_CONST(0.9966), COEF_CONST(1.8271), COEF_CONST(2.8236), COEF_CONST(3.8202), COEF_CONST(4.6507) },
+    { COEF_CONST(1.3288), COEF_CONST(2.3253), COEF_CONST(3.4880), COEF_CONST(4.6507), COEF_CONST(5.8134) },
+};
+#endif
+
+/* 2^(pan_quant[x][y] */
+static const real_t pan_pow_2_pos[8][5] = {
+    { REAL_CONST(1.0000000), REAL_CONST(1.0000000), REAL_CONST(1.0000000), REAL_CONST(1.0000000), REAL_CONST(1.0000000)  },
+    { REAL_CONST(1.1220021), REAL_CONST(1.1220021), REAL_CONST(1.2589312), REAL_CONST(1.2589312), REAL_CONST(1.2589312)  },
+    { REAL_CONST(1.2589312), REAL_CONST(1.2589312), REAL_CONST(1.5849090), REAL_CONST(1.7783016), REAL_CONST(1.7783016)  },
+    { REAL_CONST(1.4125481), REAL_CONST(1.5849090), REAL_CONST(1.9952921), REAL_CONST(2.8184461), REAL_CONST(3.1623565)  },
+    { REAL_CONST(1.5849090), REAL_CONST(1.9952922), REAL_CONST(2.8184461), REAL_CONST(4.4669806), REAL_CONST(5.6232337)  },
+    { REAL_CONST(1.7783016), REAL_CONST(2.5119365), REAL_CONST(4.4669806), REAL_CONST(7.9430881), REAL_CONST(11.219994)  },
+    { REAL_CONST(1.9952921), REAL_CONST(3.5482312), REAL_CONST(7.0792671), REAL_CONST(14.125206), REAL_CONST(25.118876)  },
+    { REAL_CONST(2.5119365), REAL_CONST(5.0116998), REAL_CONST(11.219994), REAL_CONST(25.118876), REAL_CONST(56.235140)  }
+};
+
+/* 2^(-pan_quant[x][y] */
+static const real_t pan_pow_2_neg[8][5] = {
+    { REAL_CONST(1),         REAL_CONST(1),         REAL_CONST(1),         REAL_CONST(1),         REAL_CONST(1)          },
+    { REAL_CONST(0.8912487), REAL_CONST(0.8912487), REAL_CONST(0.7943242), REAL_CONST(0.7943242), REAL_CONST(0.7943242)  },
+    { REAL_CONST(0.7943242), REAL_CONST(0.7943242), REAL_CONST(0.6309511), REAL_CONST(0.5623344), REAL_CONST(0.5623344)  },
+    { REAL_CONST(0.7079405), REAL_CONST(0.6309511), REAL_CONST(0.5011797), REAL_CONST(0.3548054), REAL_CONST(0.3162199)  },
+    { REAL_CONST(0.6309511), REAL_CONST(0.5011797), REAL_CONST(0.3548054), REAL_CONST(0.2238649), REAL_CONST(0.1778336)  },
+    { REAL_CONST(0.5623343), REAL_CONST(0.3980992), REAL_CONST(0.2238649), REAL_CONST(0.1258956), REAL_CONST(0.0891266)  },
+    { REAL_CONST(0.5011797), REAL_CONST(0.2818306), REAL_CONST(0.1412576), REAL_CONST(0.0707954), REAL_CONST(0.0398107)  },
+    { REAL_CONST(0.3980992), REAL_CONST(0.1995331), REAL_CONST(0.0891267), REAL_CONST(0.0398107), REAL_CONST(0.0177825)  }
+};
+
+/* 2^(pan_quant[x][y]/30) */
+static const real_t pan_pow_2_30_pos[8][5] = {
+    { COEF_CONST(1),           COEF_CONST(1),           COEF_CONST(1),           COEF_CONST(1),           COEF_CONST(1)           }, 
+    { COEF_CONST(1.003845098), COEF_CONST(1.003845098), COEF_CONST(1.007704982), COEF_CONST(1.007704982), COEF_CONST(1.007704982) }, 
+    { COEF_CONST(1.007704982), COEF_CONST(1.007704982), COEF_CONST(1.01546933),  COEF_CONST(1.019373909), COEF_CONST(1.019373909) }, 
+    { COEF_CONST(1.011579706), COEF_CONST(1.01546933),  COEF_CONST(1.023293502), COEF_CONST(1.035142941), COEF_CONST(1.039123167) }, 
+    { COEF_CONST(1.01546933),  COEF_CONST(1.023293502), COEF_CONST(1.035142941), COEF_CONST(1.051155908), COEF_CONST(1.059252598) },
+    { COEF_CONST(1.019373909), COEF_CONST(1.03117796),  COEF_CONST(1.051155908), COEF_CONST(1.071518432), COEF_CONST(1.0839263)   }, 
+    { COEF_CONST(1.023293502), COEF_CONST(1.043118698), COEF_CONST(1.067414119), COEF_CONST(1.092277933), COEF_CONST(1.113439626) }, 
+    { COEF_CONST(1.03117796),  COEF_CONST(1.055195268), COEF_CONST(1.0839263),   COEF_CONST(1.113439626), COEF_CONST(1.143756546) }
+};
+
+/* 2^(-pan_quant[x][y]/30) */
+static const real_t pan_pow_2_30_neg[8][5] = {
+    { COEF_CONST(1),           COEF_CONST(1),           COEF_CONST(1),           COEF_CONST(1),           COEF_CONST(1)           },
+    { COEF_CONST(0.99616963),  COEF_CONST(0.99616963),  COEF_CONST(0.992353931), COEF_CONST(0.992353931), COEF_CONST(0.99235393)  }, 
+    { COEF_CONST(0.992353931), COEF_CONST(0.992353931), COEF_CONST(0.984766325), COEF_CONST(0.980994305), COEF_CONST(0.980994305) }, 
+    { COEF_CONST(0.988552848), COEF_CONST(0.984766325), COEF_CONST(0.977236734), COEF_CONST(0.966050157), COEF_CONST(0.962349827) }, 
+    { COEF_CONST(0.984766325), COEF_CONST(0.977236734), COEF_CONST(0.966050157), COEF_CONST(0.951333663), COEF_CONST(0.944061881) }, 
+    { COEF_CONST(0.980994305), COEF_CONST(0.969764715), COEF_CONST(0.951333663), COEF_CONST(0.933255062), COEF_CONST(0.922571949) }, 
+    { COEF_CONST(0.977236734), COEF_CONST(0.958663671), COEF_CONST(0.936843519), COEF_CONST(0.915517901), COEF_CONST(0.898117847) }, 
+    { COEF_CONST(0.969764715), COEF_CONST(0.947691892), COEF_CONST(0.922571949), COEF_CONST(0.898117847), COEF_CONST(0.874311936) }
+};
+
+static const real_t g_decayslope[MAX_SA_BAND] = {
+    FRAC_CONST(1),   FRAC_CONST(1),   FRAC_CONST(1),   FRAC_CONST(0.95),FRAC_CONST(0.9), FRAC_CONST(0.85), FRAC_CONST(0.8), 
+    FRAC_CONST(0.75),FRAC_CONST(0.7), FRAC_CONST(0.65),FRAC_CONST(0.6), FRAC_CONST(0.55),FRAC_CONST(0.5),  FRAC_CONST(0.45), 
+    FRAC_CONST(0.4), FRAC_CONST(0.35),FRAC_CONST(0.3), FRAC_CONST(0.25),FRAC_CONST(0.2), FRAC_CONST(0.15), FRAC_CONST(0.1),
+    FRAC_CONST(0.05),FRAC_CONST(0),   FRAC_CONST(0),   FRAC_CONST(0),   FRAC_CONST(0),   FRAC_CONST(0),    FRAC_CONST(0), 
+    FRAC_CONST(0),   FRAC_CONST(0),   FRAC_CONST(0),   FRAC_CONST(0),   FRAC_CONST(0),   FRAC_CONST(0),    FRAC_CONST(0),  
+    FRAC_CONST(0),   FRAC_CONST(0),   FRAC_CONST(0),   FRAC_CONST(0),   FRAC_CONST(0),   FRAC_CONST(0),    FRAC_CONST(0),   
+    FRAC_CONST(0),   FRAC_CONST(0),   FRAC_CONST(0)
+};
+
+static const real_t sa_sqrt_1_minus[8][2] = {
+    { FRAC_CONST(1),            FRAC_CONST(1)           },
+    { FRAC_CONST(0.998744206),  FRAC_CONST(0.984066644) },
+    { FRAC_CONST(0.997504707),  FRAC_CONST(0.959473168) },
+    { FRAC_CONST(0.995037562),  FRAC_CONST(0.894683804) },
+    { FRAC_CONST(0.990165638),  FRAC_CONST(0.826933317) },
+    { FRAC_CONST(0.980663811),  FRAC_CONST(0.706312672) },
+    { FRAC_CONST(0.962494836),  FRAC_CONST(0.45341406)  },
+    { FRAC_CONST(0.929071574),  FRAC_CONST(0)           }
+};
+
+static const uint8_t sa_freq_scale[9][2] = 
+{
+    { 0, 0},  
+    { 1, 1},  
+    { 2, 2},  
+    { 3, 3},  
+    { 5, 5},  
+    { 7, 7},  
+    {10,10},  
+    {13,13},  
+    {46,23}
+};
+
+static const uint8_t pan_freq_scale[21] = 
+{
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+    11, 12, 13, 14, 15, 18, 22, 26, 32, 64
+};
+
+static const uint8_t pan_quant_class[20] = 
+{
+    0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+    2, 2, 2, 2, 3, 3, 3, 4, 4, 4
+};
+
+/* Inverse mapping lookup */
+static const uint8_t pan_inv_freq[64] = {
+     0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14, 15, 
+    15, 15, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 
+    19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19,
+    19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19, 19
+};
+
+static const uint8_t sa_inv_freq[MAX_SA_BAND] = {
+    0, 1, 2, 3, 3, 4, 4, 5, 5, 5, 6, 6, 6,
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
+    7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
+    7, 7, 7, 7, 7, 7, 7
+};
+
+static const real_t filter_coeff[] = 
+{
+    FRAC_CONST(0.65143905754106),
+    FRAC_CONST(0.56471812200776),
+    FRAC_CONST(0.48954165955695)
+};
+
+static const uint8_t delay_length[][2] = 
+{
+    { 1, 3 }, { 2, 4 }, { 3, 5 }
+};
+
+static const real_t delay_fraction[] = 
+{
+    FRAC_CONST(0.43), FRAC_CONST(0.75), FRAC_CONST(0.347)
+};
+
+static const real_t peak_decay[2] = 
+{
+    FRAC_CONST(0.58664621951003), FRAC_CONST(0.76592833836465)
+};
+
+static const real_t smooth_coeff[2] = 
+{
+    FRAC_CONST(0.6), FRAC_CONST(0.25)
+};
+
+/* Please note that these are the same tables as in plain PS */
+static const complex_t Q_Fract_allpass_Qmf[][3] = {
+    { { FRAC_CONST(0.7804303765), FRAC_CONST(0.6252426505) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.8550928831), FRAC_CONST(0.5184748173) } },
+    { { FRAC_CONST(-0.4399392009), FRAC_CONST(0.8980275393) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.0643581524), FRAC_CONST(0.9979268909) } },
+    { { FRAC_CONST(-0.9723699093), FRAC_CONST(-0.2334454209) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.9146071672), FRAC_CONST(0.4043435752) } },
+    { { FRAC_CONST(0.0157073960), FRAC_CONST(-0.9998766184) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.7814115286), FRAC_CONST(-0.6240159869) } },
+    { { FRAC_CONST(0.9792228341), FRAC_CONST(-0.2027871907) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.1920081824), FRAC_CONST(-0.9813933372) } },
+    { { FRAC_CONST(0.4115142524), FRAC_CONST(0.9114032984) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.9589683414), FRAC_CONST(-0.2835132182) } },
+    { { FRAC_CONST(-0.7996847630), FRAC_CONST(0.6004201174) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.6947838664), FRAC_CONST(0.7192186117) } },
+    { { FRAC_CONST(-0.7604058385), FRAC_CONST(-0.6494481564) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.3164770305), FRAC_CONST(0.9486001730) } },
+    { { FRAC_CONST(0.4679299891), FRAC_CONST(-0.8837655187) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.9874414206), FRAC_CONST(0.1579856575) } },
+    { { FRAC_CONST(0.9645573497), FRAC_CONST(0.2638732493) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.5966450572), FRAC_CONST(-0.8025052547) } },
+    { { FRAC_CONST(-0.0471066870), FRAC_CONST(0.9988898635) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.4357025325), FRAC_CONST(-0.9000906944) } },
+    { { FRAC_CONST(-0.9851093888), FRAC_CONST(0.1719288528) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.9995546937), FRAC_CONST(-0.0298405960) } },
+    { { FRAC_CONST(-0.3826831877), FRAC_CONST(-0.9238796234) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.4886211455), FRAC_CONST(0.8724960685) } },
+    { { FRAC_CONST(0.8181498647), FRAC_CONST(-0.5750049949) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.5477093458), FRAC_CONST(0.8366686702) } },
+    { { FRAC_CONST(0.7396308780), FRAC_CONST(0.6730127335) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.9951074123), FRAC_CONST(-0.0987988561) } },
+    { { FRAC_CONST(-0.4954589605), FRAC_CONST(0.8686313629) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.3725017905), FRAC_CONST(-0.9280315042) } },
+    { { FRAC_CONST(-0.9557929039), FRAC_CONST(-0.2940406799) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.6506417990), FRAC_CONST(-0.7593847513) } },
+    { { FRAC_CONST(0.0784594864), FRAC_CONST(-0.9969173074) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.9741733670), FRAC_CONST(0.2258014232) } },
+    { { FRAC_CONST(0.9900237322), FRAC_CONST(-0.1409008205) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.2502108514), FRAC_CONST(0.9681913853) } },
+    { { FRAC_CONST(0.3534744382), FRAC_CONST(0.9354441762) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.7427945137), FRAC_CONST(0.6695194840) } },
+    { { FRAC_CONST(-0.8358076215), FRAC_CONST(0.5490224361) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.9370992780), FRAC_CONST(-0.3490629196) } },
+    { { FRAC_CONST(-0.7181259394), FRAC_CONST(-0.6959131360) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.1237744763), FRAC_CONST(-0.9923103452) } },
+    { { FRAC_CONST(0.5224990249), FRAC_CONST(-0.8526399136) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.8226406574), FRAC_CONST(-0.5685616732) } },
+    { { FRAC_CONST(0.9460852146), FRAC_CONST(0.3239179254) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.8844994903), FRAC_CONST(0.4665412009) } },
+    { { FRAC_CONST(-0.1097348556), FRAC_CONST(0.9939609170) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.0047125919), FRAC_CONST(0.9999889135) } },
+    { { FRAC_CONST(-0.9939610362), FRAC_CONST(0.1097337380) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.8888573647), FRAC_CONST(0.4581840038) } },
+    { { FRAC_CONST(-0.3239168525), FRAC_CONST(-0.9460855722) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.8172453642), FRAC_CONST(-0.5762898922) } },
+    { { FRAC_CONST(0.8526405096), FRAC_CONST(-0.5224980116) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.1331215799), FRAC_CONST(-0.9910997152) } },
+    { { FRAC_CONST(0.6959123611), FRAC_CONST(0.7181267142) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.9403476119), FRAC_CONST(-0.3402152061) } },
+    { { FRAC_CONST(-0.5490233898), FRAC_CONST(0.8358070254) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.7364512086), FRAC_CONST(0.6764906645) } },
+    { { FRAC_CONST(-0.9354437590), FRAC_CONST(-0.3534754813) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.2593250275), FRAC_CONST(0.9657900929) } },
+    { { FRAC_CONST(0.1409019381), FRAC_CONST(-0.9900235534) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.9762582779), FRAC_CONST(0.2166097313) } },
+    { { FRAC_CONST(0.9969173670), FRAC_CONST(-0.0784583688) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.6434556246), FRAC_CONST(-0.7654833794) } },
+    { { FRAC_CONST(0.2940396070), FRAC_CONST(0.9557932615) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.3812320232), FRAC_CONST(-0.9244794250) } },
+    { { FRAC_CONST(-0.8686318994), FRAC_CONST(0.4954580069) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.9959943891), FRAC_CONST(-0.0894154981) } },
+    { { FRAC_CONST(-0.6730118990), FRAC_CONST(-0.7396316528) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.5397993922), FRAC_CONST(0.8417937160) } },
+    { { FRAC_CONST(0.5750059485), FRAC_CONST(-0.8181492686) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.4968227744), FRAC_CONST(0.8678520322) } },
+    { { FRAC_CONST(0.9238792062), FRAC_CONST(0.3826842010) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.9992290139), FRAC_CONST(-0.0392601527) } },
+    { { FRAC_CONST(-0.1719299555), FRAC_CONST(0.9851091504) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.4271997511), FRAC_CONST(-0.9041572809) } },
+    { { FRAC_CONST(-0.9988899231), FRAC_CONST(0.0471055657) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.6041822433), FRAC_CONST(-0.7968461514) } },
+    { { FRAC_CONST(-0.2638721764), FRAC_CONST(-0.9645576477) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.9859085083), FRAC_CONST(0.1672853529) } },
+    { { FRAC_CONST(0.8837660551), FRAC_CONST(-0.4679289758) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.3075223565), FRAC_CONST(0.9515408874) } },
+    { { FRAC_CONST(0.6494473219), FRAC_CONST(0.7604066133) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.7015317082), FRAC_CONST(0.7126382589) } },
+    { { FRAC_CONST(-0.6004210114), FRAC_CONST(0.7996840477) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.9562535882), FRAC_CONST(-0.2925389707) } },
+    { { FRAC_CONST(-0.9114028811), FRAC_CONST(-0.4115152657) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.1827499419), FRAC_CONST(-0.9831594229) } },
+    { { FRAC_CONST(0.2027882934), FRAC_CONST(-0.9792225957) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.7872582674), FRAC_CONST(-0.6166234016) } },
+    { { FRAC_CONST(0.9998766780), FRAC_CONST(-0.0157062728) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.9107555747), FRAC_CONST(0.4129458666) } },
+    { { FRAC_CONST(0.2334443331), FRAC_CONST(0.9723701477) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.0549497530), FRAC_CONST(0.9984891415) } },
+    { { FRAC_CONST(-0.8980280757), FRAC_CONST(0.4399381876) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.8599416018), FRAC_CONST(0.5103924870) } },
+    { { FRAC_CONST(-0.6252418160), FRAC_CONST(-0.7804310918) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(-0.8501682281), FRAC_CONST(-0.5265110731) } },
+    { { FRAC_CONST(0.6252435446), FRAC_CONST(-0.7804297209) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.0737608299), FRAC_CONST(-0.9972759485) } },
+    { { FRAC_CONST(0.8980270624), FRAC_CONST(0.4399402142) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.9183775187), FRAC_CONST(-0.3957053721) } },
+    { { FRAC_CONST(-0.2334465086), FRAC_CONST(0.9723696709) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.7754954696), FRAC_CONST(0.6313531399) } },
+    { { FRAC_CONST(-0.9998766184), FRAC_CONST(-0.0157085191) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.2012493610), FRAC_CONST(0.9795400500) } },
+    { { FRAC_CONST(-0.2027861029), FRAC_CONST(-0.9792230725) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.9615978599), FRAC_CONST(0.2744622827) } },
+    { { FRAC_CONST(0.9114037752), FRAC_CONST(-0.4115132093) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.6879743338), FRAC_CONST(-0.7257350087) } },
+    { { FRAC_CONST(0.6004192233), FRAC_CONST(0.7996854186) }, { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(0.3254036009), FRAC_CONST(-0.9455752373) } },
+    { { FRAC_CONST(-0.6494490504), FRAC_CONST(0.7604051232) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.9888865948), FRAC_CONST(-0.1486719251) } },
+    { { FRAC_CONST(-0.8837650418), FRAC_CONST(-0.4679309726) }, { FRAC_CONST(0.9238795042), FRAC_CONST(-0.3826834261) }, { FRAC_CONST(0.5890548825), FRAC_CONST(0.8080930114) } },
+    { { FRAC_CONST(0.2638743520), FRAC_CONST(-0.9645570517) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) }, { FRAC_CONST(-0.4441666007), FRAC_CONST(0.8959442377) } },
+    { { FRAC_CONST(0.9988898039), FRAC_CONST(0.0471078083) }, { FRAC_CONST(-0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(-0.9997915030), FRAC_CONST(0.0204183888) } },
+    { { FRAC_CONST(0.1719277352), FRAC_CONST(0.9851095676) }, { FRAC_CONST(0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(-0.4803760946), FRAC_CONST(-0.8770626187) } },
+    { { FRAC_CONST(-0.9238800406), FRAC_CONST(0.3826821446) }, { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) }, { FRAC_CONST(0.5555707216), FRAC_CONST(-0.8314692974) } },
+    { { FRAC_CONST(-0.5750041008), FRAC_CONST(-0.8181505203) }, { FRAC_CONST(0.3826834261), FRAC_CONST(-0.9238795042) }, { FRAC_CONST(0.9941320419), FRAC_CONST(0.1081734300) } }
+};
+
+static const complex_t Phi_Fract_Qmf[] = {
+    { FRAC_CONST(0.8181497455), FRAC_CONST(0.5750052333) },
+    { FRAC_CONST(-0.2638730407), FRAC_CONST(0.9645574093) },
+    { FRAC_CONST(-0.9969173074), FRAC_CONST(0.0784590989) },
+    { FRAC_CONST(-0.4115143716), FRAC_CONST(-0.9114032984) },
+    { FRAC_CONST(0.7181262970), FRAC_CONST(-0.6959127784) },
+    { FRAC_CONST(0.8980275989), FRAC_CONST(0.4399391711) },
+    { FRAC_CONST(-0.1097343117), FRAC_CONST(0.9939609766) },
+    { FRAC_CONST(-0.9723699093), FRAC_CONST(0.2334453613) },
+    { FRAC_CONST(-0.5490227938), FRAC_CONST(-0.8358073831) },
+    { FRAC_CONST(0.6004202366), FRAC_CONST(-0.7996846437) },
+    { FRAC_CONST(0.9557930231), FRAC_CONST(0.2940403223) },
+    { FRAC_CONST(0.0471064523), FRAC_CONST(0.9988898635) },
+    { FRAC_CONST(-0.9238795042), FRAC_CONST(0.3826834261) },
+    { FRAC_CONST(-0.6730124950), FRAC_CONST(-0.7396311164) },
+    { FRAC_CONST(0.4679298103), FRAC_CONST(-0.8837656379) },
+    { FRAC_CONST(0.9900236726), FRAC_CONST(0.1409012377) },
+    { FRAC_CONST(0.2027872950), FRAC_CONST(0.9792228341) },
+    { FRAC_CONST(-0.8526401520), FRAC_CONST(0.5224985480) },
+    { FRAC_CONST(-0.7804304361), FRAC_CONST(-0.6252426505) },
+    { FRAC_CONST(0.3239174187), FRAC_CONST(-0.9460853338) },
+    { FRAC_CONST(0.9998766184), FRAC_CONST(-0.0157073177) },
+    { FRAC_CONST(0.3534748554), FRAC_CONST(0.9354440570) },
+    { FRAC_CONST(-0.7604059577), FRAC_CONST(0.6494480371) },
+    { FRAC_CONST(-0.8686315417), FRAC_CONST(-0.4954586625) },
+    { FRAC_CONST(0.1719291061), FRAC_CONST(-0.9851093292) },
+    { FRAC_CONST(0.9851093292), FRAC_CONST(-0.1719291061) },
+    { FRAC_CONST(0.4954586625), FRAC_CONST(0.8686315417) },
+    { FRAC_CONST(-0.6494480371), FRAC_CONST(0.7604059577) },
+    { FRAC_CONST(-0.9354440570), FRAC_CONST(-0.3534748554) },
+    { FRAC_CONST(0.0157073177), FRAC_CONST(-0.9998766184) },
+    { FRAC_CONST(0.9460853338), FRAC_CONST(-0.3239174187) },
+    { FRAC_CONST(0.6252426505), FRAC_CONST(0.7804304361) },
+    { FRAC_CONST(-0.5224985480), FRAC_CONST(0.8526401520) },
+    { FRAC_CONST(-0.9792228341), FRAC_CONST(-0.2027872950) },
+    { FRAC_CONST(-0.1409012377), FRAC_CONST(-0.9900236726) },
+    { FRAC_CONST(0.8837656379), FRAC_CONST(-0.4679298103) },
+    { FRAC_CONST(0.7396311164), FRAC_CONST(0.6730124950) },
+    { FRAC_CONST(-0.3826834261), FRAC_CONST(0.9238795042) },
+    { FRAC_CONST(-0.9988898635), FRAC_CONST(-0.0471064523) },
+    { FRAC_CONST(-0.2940403223), FRAC_CONST(-0.9557930231) },
+    { FRAC_CONST(0.7996846437), FRAC_CONST(-0.6004202366) },
+    { FRAC_CONST(0.8358073831), FRAC_CONST(0.5490227938) },
+    { FRAC_CONST(-0.2334453613), FRAC_CONST(0.9723699093) },
+    { FRAC_CONST(-0.9939609766), FRAC_CONST(0.1097343117) },
+    { FRAC_CONST(-0.4399391711), FRAC_CONST(-0.8980275989) },
+    { FRAC_CONST(0.6959127784), FRAC_CONST(-0.7181262970) },
+    { FRAC_CONST(0.9114032984), FRAC_CONST(0.4115143716) },
+    { FRAC_CONST(-0.0784590989), FRAC_CONST(0.9969173074) },
+    { FRAC_CONST(-0.9645574093), FRAC_CONST(0.2638730407) },
+    { FRAC_CONST(-0.5750052333), FRAC_CONST(-0.8181497455) },
+    { FRAC_CONST(0.5750052333), FRAC_CONST(-0.8181497455) },
+    { FRAC_CONST(0.9645574093), FRAC_CONST(0.2638730407) },
+    { FRAC_CONST(0.0784590989), FRAC_CONST(0.9969173074) },
+    { FRAC_CONST(-0.9114032984), FRAC_CONST(0.4115143716) },
+    { FRAC_CONST(-0.6959127784), FRAC_CONST(-0.7181262970) },
+    { FRAC_CONST(0.4399391711), FRAC_CONST(-0.8980275989) },
+    { FRAC_CONST(0.9939609766), FRAC_CONST(0.1097343117) },
+    { FRAC_CONST(0.2334453613), FRAC_CONST(0.9723699093) },
+    { FRAC_CONST(-0.8358073831), FRAC_CONST(0.5490227938) },
+    { FRAC_CONST(-0.7996846437), FRAC_CONST(-0.6004202366) },
+    { FRAC_CONST(0.2940403223), FRAC_CONST(-0.9557930231) },
+    { FRAC_CONST(0.9988898635), FRAC_CONST(-0.0471064523) },
+    { FRAC_CONST(0.3826834261), FRAC_CONST(0.9238795042) },
+    { FRAC_CONST(-0.7396311164), FRAC_CONST(0.6730124950) }
+};
+
+
+/* static function declarations */
+static void drm_ps_sa_element(drm_ps_info *ps, bitfile *ld);
+static void drm_ps_pan_element(drm_ps_info *ps, bitfile *ld);
+static int8_t huff_dec(bitfile *ld, drm_ps_huff_tab huff);
+
+
+uint16_t drm_ps_data(drm_ps_info *ps, bitfile *ld)
+{
+    uint16_t bits = (uint16_t)faad_get_processed_bits(ld);
+
+    ps->drm_ps_data_available = 1;
+
+    ps->bs_enable_sa = faad_get1bit(ld);
+    ps->bs_enable_pan = faad_get1bit(ld);
+
+    if (ps->bs_enable_sa)
+    {
+        drm_ps_sa_element(ps, ld);
+    }
+
+    if (ps->bs_enable_pan)
+    {
+        drm_ps_pan_element(ps, ld);
+    }
+
+    bits = (uint16_t)faad_get_processed_bits(ld) - bits;
+
+    return bits;
+}
+
+static void drm_ps_sa_element(drm_ps_info *ps, bitfile *ld)
+{
+    drm_ps_huff_tab huff;
+    uint8_t band;
+
+    ps->bs_sa_dt_flag = faad_get1bit(ld);
+    if (ps->bs_sa_dt_flag)
+    {
+        huff = t_huffman_sa;
+    } else {
+        huff = f_huffman_sa;
+    }
+
+    for (band = 0; band < DRM_NUM_SA_BANDS; band++)
+    {
+        ps->bs_sa_data[band] = huff_dec(ld, huff);
+    }
+}
+
+static void drm_ps_pan_element(drm_ps_info *ps, bitfile *ld)
+{
+    drm_ps_huff_tab huff;
+    uint8_t band;
+
+    ps->bs_pan_dt_flag = faad_get1bit(ld);
+    if (ps->bs_pan_dt_flag)
+    {
+        huff = t_huffman_pan;
+    } else {
+        huff = f_huffman_pan;
+    }
+
+    for (band = 0; band < DRM_NUM_PAN_BANDS; band++)
+    {
+        ps->bs_pan_data[band] = huff_dec(ld, huff);
+    }
+}
+
+/* binary search huffman decoding */
+static int8_t huff_dec(bitfile *ld, drm_ps_huff_tab huff)
+{
+    uint8_t bit;
+    int16_t index = 0;
+
+    while (index >= 0)
+    {
+        bit = (uint8_t)faad_get1bit(ld);
+        index = huff[index][bit];
+    }
+
+    return index + 15;
+}
+
+
+static int8_t sa_delta_clip(drm_ps_info *ps, int8_t i)
+{
+    if (i < 0) {
+      /*  printf(" SAminclip %d", i); */
+        ps->sa_decode_error = 1;
+        return 0;
+    } else if (i > 7) {
+     /*   printf(" SAmaxclip %d", i); */
+        ps->sa_decode_error = 1;
+        return 7;
+    } else
+        return i;
+}
+
+static int8_t pan_delta_clip(drm_ps_info *ps, int8_t i)
+{   
+    if (i < -7) {
+        /* printf(" PANminclip %d", i); */
+        ps->pan_decode_error = 1;
+        return -7;
+    } else if (i > 7) {
+       /* printf(" PANmaxclip %d", i);  */
+        ps->pan_decode_error = 1;
+        return 7;
+    } else
+        return i;
+}
+
+static void drm_ps_delta_decode(drm_ps_info *ps) 
+{
+    uint8_t band;    
+
+    if (ps->bs_enable_sa) 
+    {    
+        if (ps->bs_sa_dt_flag && !ps->g_last_had_sa) 
+        {        
+            for (band = 0; band < DRM_NUM_SA_BANDS; band++)
+            {   
+                ps->g_prev_sa_index[band] = 0;
+            }           
+        }       
+        if (ps->bs_sa_dt_flag)
+        {
+            ps->g_sa_index[0] = sa_delta_clip(ps, ps->g_prev_sa_index[0]+ps->bs_sa_data[0]);            
+
+        } else {
+            ps->g_sa_index[0] = sa_delta_clip(ps,ps->bs_sa_data[0]);          
+        }
+        
+        for (band = 1; band < DRM_NUM_SA_BANDS; band++)
+        {   
+            if (ps->bs_sa_dt_flag)
+            {
+                ps->g_sa_index[band] = sa_delta_clip(ps, ps->g_prev_sa_index[band] + ps->bs_sa_data[band]);
+            } else {
+                ps->g_sa_index[band] = sa_delta_clip(ps, ps->g_sa_index[band-1] + ps->bs_sa_data[band]);                
+            }
+        }
+    }
+
+    /* An error during SA decoding implies PAN data will be undecodable, too */
+    /* Also, we don't like on/off switching in PS, so we force to last settings */
+    if (ps->sa_decode_error) {
+        ps->pan_decode_error = 1;
+        ps->bs_enable_pan = ps->g_last_had_pan;
+        ps->bs_enable_sa = ps->g_last_had_sa;
+    }
+    
+       
+    if (ps->bs_enable_sa) 
+    {    
+        if (ps->sa_decode_error) {
+            for (band = 0; band < DRM_NUM_SA_BANDS; band++)
+            {   
+                ps->g_sa_index[band] = ps->g_last_good_sa_index[band];
+            }
+        } else {
+            for (band = 0; band < DRM_NUM_SA_BANDS; band++)
+            {   
+                ps->g_last_good_sa_index[band] = ps->g_sa_index[band];
+            }
+        }
+    }
+    
+    if (ps->bs_enable_pan) 
+    {
+        if (ps->bs_pan_dt_flag && !ps->g_last_had_pan) 
+        {
+/* The DRM PS spec doesn't say anything about this case. (deltacoded in time without a previous frame)
+   AAC PS spec you must tread previous frame as 0, so that's what we try. 
+*/
+            for (band = 0; band < DRM_NUM_PAN_BANDS; band++)
+            {   
+                ps->g_prev_pan_index[band] = 0;
+            }
+        } 
+
+        if (ps->bs_pan_dt_flag)
+        {   
+             ps->g_pan_index[0] = pan_delta_clip(ps,  ps->g_prev_pan_index[0]+ps->bs_pan_data[0]);
+        } else {
+             ps->g_pan_index[0] = pan_delta_clip(ps, ps->bs_pan_data[0]);
+        }
+    
+        for (band = 1; band < DRM_NUM_PAN_BANDS; band++)
+        {   
+            if (ps->bs_pan_dt_flag)
+            {
+                ps->g_pan_index[band] = pan_delta_clip(ps, ps->g_prev_pan_index[band] + ps->bs_pan_data[band]);
+            } else {
+                ps->g_pan_index[band] = pan_delta_clip(ps, ps->g_pan_index[band-1] + ps->bs_pan_data[band]);
+            }
+        }
+ 
+        if (ps->pan_decode_error) {
+            for (band = 0; band < DRM_NUM_PAN_BANDS; band++)
+            {   
+                ps->g_pan_index[band] = ps->g_last_good_pan_index[band];
+            }
+        } else {
+            for (band = 0; band < DRM_NUM_PAN_BANDS; band++)
+            {   
+                ps->g_last_good_pan_index[band] = ps->g_pan_index[band];
+            }
+        }
+    }
+}
+
+static void drm_calc_sa_side_signal(drm_ps_info *ps, qmf_t X[38][64], uint8_t rateselect) 
+{      
+    uint8_t s, b, k;
+    complex_t qfrac, tmp0, tmp, in, R0;
+    real_t peakdiff;
+    real_t nrg;
+    real_t power;
+    real_t transratio;
+    real_t new_delay_slopes[NUM_OF_LINKS];
+    uint8_t temp_delay_ser[NUM_OF_LINKS];
+    complex_t Phi_Fract;
+#ifdef FIXED_POINT
+    uint32_t in_re, in_im;
+#endif
+
+    for (b = 0; b < sa_freq_scale[DRM_NUM_SA_BANDS][rateselect]; b++)
+    {
+        /* set delay indices */    
+        for (k = 0; k < NUM_OF_LINKS; k++)
+            temp_delay_ser[k] = ps->delay_buf_index_ser[k];
+
+        RE(Phi_Fract) = RE(Phi_Fract_Qmf[b]);
+        IM(Phi_Fract) = IM(Phi_Fract_Qmf[b]);
+
+        for (s = 0; s < NUM_OF_SUBSAMPLES; s++)
+        {            
+            const real_t gamma = REAL_CONST(1.5);
+            const real_t sigma = REAL_CONST(1.5625);
+
+            RE(in) = QMF_RE(X[s][b]);
+            IM(in) = QMF_IM(X[s][b]);
+
+#ifdef FIXED_POINT
+            /* NOTE: all input is scaled by 2^(-5) because of fixed point QMF
+            * meaning that P will be scaled by 2^(-10) compared to floating point version
+            */
+            in_re = ((abs(RE(in))+(1<<(REAL_BITS-1)))>>REAL_BITS);
+            in_im = ((abs(IM(in))+(1<<(REAL_BITS-1)))>>REAL_BITS);
+            power = in_re*in_re + in_im*in_im;
+#else
+            power = MUL_R(RE(in),RE(in)) + MUL_R(IM(in),IM(in));
+#endif
+
+            ps->peakdecay_fast[b] = MUL_F(ps->peakdecay_fast[b], peak_decay[rateselect]);
+            if (ps->peakdecay_fast[b] < power)
+                ps->peakdecay_fast[b] = power;
+
+            peakdiff = ps->prev_peakdiff[b];
+            peakdiff += MUL_F((ps->peakdecay_fast[b] - power - ps->prev_peakdiff[b]), smooth_coeff[rateselect]);
+            ps->prev_peakdiff[b] = peakdiff;
+
+            nrg = ps->prev_nrg[b];
+            nrg += MUL_F((power - ps->prev_nrg[b]), smooth_coeff[rateselect]);
+            ps->prev_nrg[b] = nrg;
+
+            if (MUL_R(peakdiff, gamma) <= nrg) {
+                transratio = sigma;
+            } else {
+                transratio = MUL_R(DIV_R(nrg, MUL_R(peakdiff, gamma)), sigma);
+            }
+            
+            for (k = 0; k < NUM_OF_LINKS; k++) 
+            {
+                new_delay_slopes[k] = MUL_F(g_decayslope[b], filter_coeff[k]);
+            }
+
+            RE(tmp0) = RE(ps->d_buff[0][b]);
+            IM(tmp0) = IM(ps->d_buff[0][b]);
+
+            RE(ps->d_buff[0][b]) = RE(ps->d_buff[1][b]);
+            IM(ps->d_buff[0][b]) = IM(ps->d_buff[1][b]);
+
+            RE(ps->d_buff[1][b]) = RE(in);
+            IM(ps->d_buff[1][b]) = IM(in);               
+
+            ComplexMult(&RE(tmp), &IM(tmp), RE(tmp0), IM(tmp0), RE(Phi_Fract), IM(Phi_Fract));
+
+            RE(R0) = RE(tmp);
+            IM(R0) = IM(tmp);
+
+            for (k = 0; k < NUM_OF_LINKS; k++) 
+            {
+                RE(qfrac) = RE(Q_Fract_allpass_Qmf[b][k]);
+                IM(qfrac) = IM(Q_Fract_allpass_Qmf[b][k]);
+
+                RE(tmp0) = RE(ps->d2_buff[k][temp_delay_ser[k]][b]);
+                IM(tmp0) = IM(ps->d2_buff[k][temp_delay_ser[k]][b]);
+
+                ComplexMult(&RE(tmp), &IM(tmp), RE(tmp0), IM(tmp0), RE(qfrac), IM(qfrac));
+
+                RE(tmp) += -MUL_F(new_delay_slopes[k], RE(R0));
+                IM(tmp) += -MUL_F(new_delay_slopes[k], IM(R0));
+
+                RE(ps->d2_buff[k][temp_delay_ser[k]][b]) = RE(R0) + MUL_F(new_delay_slopes[k], RE(tmp));
+                IM(ps->d2_buff[k][temp_delay_ser[k]][b]) = IM(R0) + MUL_F(new_delay_slopes[k], IM(tmp));
+
+                RE(R0) = RE(tmp);
+                IM(R0) = IM(tmp);
+            }
+
+            QMF_RE(ps->SA[s][b]) = MUL_R(RE(R0), transratio);
+            QMF_IM(ps->SA[s][b]) = MUL_R(IM(R0), transratio);
+
+            for (k = 0; k < NUM_OF_LINKS; k++)
+            {
+                if (++temp_delay_ser[k] >= delay_length[k][rateselect])
+                    temp_delay_ser[k] = 0;
+            }
+        }       
+    }
+
+    for (k = 0; k < NUM_OF_LINKS; k++)
+        ps->delay_buf_index_ser[k] = temp_delay_ser[k];
+}
+
+static void drm_add_ambiance(drm_ps_info *ps, uint8_t rateselect, qmf_t X_left[38][64], qmf_t X_right[38][64]) 
+{
+    uint8_t s, b, ifreq, qclass;    
+    real_t sa_map[MAX_SA_BAND], sa_dir_map[MAX_SA_BAND], k_sa_map[MAX_SA_BAND], k_sa_dir_map[MAX_SA_BAND];
+    real_t new_dir_map, new_sa_map;
+    
+    if (ps->bs_enable_sa)
+    {
+        /* Instead of dequantization and mapping, we use an inverse mapping
+           to look up all the values we need */
+        for (b = 0; b < sa_freq_scale[DRM_NUM_SA_BANDS][rateselect]; b++)
+        {
+            const real_t inv_f_num_of_subsamples = FRAC_CONST(0.03333333333);
+
+            ifreq = sa_inv_freq[b];
+            qclass = (b != 0);
+
+            sa_map[b]  = sa_quant[ps->g_prev_sa_index[ifreq]][qclass];
+            new_sa_map = sa_quant[ps->g_sa_index[ifreq]][qclass];
+
+            k_sa_map[b] = MUL_F(inv_f_num_of_subsamples, (new_sa_map - sa_map[b]));    
+            
+            sa_dir_map[b] = sa_sqrt_1_minus[ps->g_prev_sa_index[ifreq]][qclass];                        
+            new_dir_map   = sa_sqrt_1_minus[ps->g_sa_index[ifreq]][qclass];
+                                                   
+            k_sa_dir_map[b] = MUL_F(inv_f_num_of_subsamples, (new_dir_map - sa_dir_map[b]));
+
+        }
+
+        for (s = 0; s < NUM_OF_SUBSAMPLES; s++)
+        {
+            for (b = 0; b < sa_freq_scale[DRM_NUM_SA_BANDS][rateselect]; b++)
+            {                
+                QMF_RE(X_right[s][b]) = MUL_F(QMF_RE(X_left[s][b]), sa_dir_map[b]) - MUL_F(QMF_RE(ps->SA[s][b]), sa_map[b]);
+                QMF_IM(X_right[s][b]) = MUL_F(QMF_IM(X_left[s][b]), sa_dir_map[b]) - MUL_F(QMF_IM(ps->SA[s][b]), sa_map[b]);
+                QMF_RE(X_left[s][b]) = MUL_F(QMF_RE(X_left[s][b]), sa_dir_map[b]) + MUL_F(QMF_RE(ps->SA[s][b]), sa_map[b]);
+                QMF_IM(X_left[s][b]) = MUL_F(QMF_IM(X_left[s][b]), sa_dir_map[b]) + MUL_F(QMF_IM(ps->SA[s][b]), sa_map[b]);
+      
+                sa_map[b]     += k_sa_map[b];
+                sa_dir_map[b] += k_sa_dir_map[b];
+            }
+            for (b = sa_freq_scale[DRM_NUM_SA_BANDS][rateselect]; b < NUM_OF_QMF_CHANNELS; b++)
+            {                
+                QMF_RE(X_right[s][b]) = QMF_RE(X_left[s][b]);
+                QMF_IM(X_right[s][b]) = QMF_IM(X_left[s][b]);
+            }
+        }
+    } 
+    else {
+        for (s = 0; s < NUM_OF_SUBSAMPLES; s++)
+        {
+            for (b = 0; b < NUM_OF_QMF_CHANNELS; b++)
+            {
+                QMF_RE(X_right[s][b]) = QMF_RE(X_left[s][b]);
+                QMF_IM(X_right[s][b]) = QMF_IM(X_left[s][b]);                
+            }
+        }
+    }
+}
+
+static void drm_add_pan(drm_ps_info *ps, uint8_t rateselect, qmf_t X_left[38][64], qmf_t X_right[38][64]) 
+{
+    uint8_t s, b, qclass, ifreq;
+    real_t tmp, coeff1, coeff2;
+    real_t pan_base[MAX_PAN_BAND];
+    real_t pan_delta[MAX_PAN_BAND];
+    qmf_t temp_l, temp_r;
+
+    if (ps->bs_enable_pan)
+    {
+        for (b = 0; b < NUM_OF_QMF_CHANNELS; b++) 
+        {
+            /* Instead of dequantization, 20->64 mapping and 2^G(x,y) we do an
+               inverse mapping 64->20 and look up the 2^G(x,y) values directly */
+            ifreq = pan_inv_freq[b];
+            qclass = pan_quant_class[ifreq];
+
+            if (ps->g_prev_pan_index[ifreq] >= 0)
+            {
+                pan_base[b] = pan_pow_2_pos[ps->g_prev_pan_index[ifreq]][qclass]; 
+            } else {
+                pan_base[b] = pan_pow_2_neg[-ps->g_prev_pan_index[ifreq]][qclass];
+            }
+
+            /* 2^((a-b)/30) = 2^(a/30) * 1/(2^(b/30)) */
+            /* a en b can be negative so we may need to inverse parts */
+            if (ps->g_pan_index[ifreq] >= 0)
+            {
+                if (ps->g_prev_pan_index[ifreq] >= 0) 
+                {
+                    pan_delta[b] = MUL_C(pan_pow_2_30_pos[ps->g_pan_index[ifreq]][qclass],
+                                         pan_pow_2_30_neg[ps->g_prev_pan_index[ifreq]][qclass]);
+                } else {
+                    pan_delta[b] = MUL_C(pan_pow_2_30_pos[ps->g_pan_index[ifreq]][qclass],
+                                         pan_pow_2_30_pos[-ps->g_prev_pan_index[ifreq]][qclass]);
+                }
+            } else {
+                if (ps->g_prev_pan_index[ifreq] >= 0) 
+                {
+                    pan_delta[b] = MUL_C(pan_pow_2_30_neg[-ps->g_pan_index[ifreq]][qclass],
+                                         pan_pow_2_30_neg[ps->g_prev_pan_index[ifreq]][qclass]);
+                } else {
+                    pan_delta[b] = MUL_C(pan_pow_2_30_neg[-ps->g_pan_index[ifreq]][qclass],
+                                         pan_pow_2_30_pos[-ps->g_prev_pan_index[ifreq]][qclass]);
+                }
+            }
+        }
+
+        for (s = 0; s < NUM_OF_SUBSAMPLES; s++)
+        {
+            /* PAN always uses all 64 channels */
+            for (b = 0; b < NUM_OF_QMF_CHANNELS; b++)
+            {
+                tmp = pan_base[b];
+
+                coeff2 = DIV_R(REAL_CONST(2.0), (REAL_CONST(1.0) + tmp));
+                coeff1 = MUL_R(coeff2, tmp);                
+
+                QMF_RE(temp_l) = QMF_RE(X_left[s][b]);
+                QMF_IM(temp_l) = QMF_IM(X_left[s][b]);
+                QMF_RE(temp_r) = QMF_RE(X_right[s][b]);
+                QMF_IM(temp_r) = QMF_IM(X_right[s][b]);
+
+                QMF_RE(X_left[s][b]) = MUL_R(QMF_RE(temp_l), coeff1);
+                QMF_IM(X_left[s][b]) = MUL_R(QMF_IM(temp_l), coeff1);
+                QMF_RE(X_right[s][b]) = MUL_R(QMF_RE(temp_r), coeff2);
+                QMF_IM(X_right[s][b]) = MUL_R(QMF_IM(temp_r), coeff2);
+                
+                /* 2^(a+k*b) = 2^a * 2^b * ... * 2^b */
+                /*                   ^^^^^^^^^^^^^^^ k times */
+                pan_base[b] = MUL_C(pan_base[b], pan_delta[b]);
+            }           
+        }       
+    }     
+}
+
+drm_ps_info *drm_ps_init(void)
+{
+    drm_ps_info *ps = (drm_ps_info*)faad_malloc(sizeof(drm_ps_info));
+
+    memset(ps, 0, sizeof(drm_ps_info));     
+
+    return ps;
+}
+
+void drm_ps_free(drm_ps_info *ps)
+{
+    faad_free(ps);
+}
+
+/* main DRM PS decoding function */
+uint8_t drm_ps_decode(drm_ps_info *ps, uint8_t guess, uint32_t samplerate, qmf_t X_left[38][64], qmf_t X_right[38][64])
+{
+    uint8_t rateselect = (samplerate >= 24000);
+    
+    if (ps == NULL) 
+    {
+        memcpy(X_right, X_left, sizeof(qmf_t)*30*64);
+        return 0;    
+    }     
+
+    if (!ps->drm_ps_data_available && !guess) 
+    {
+        memcpy(X_right, X_left, sizeof(qmf_t)*30*64);
+        memset(ps->g_prev_sa_index, 0, sizeof(ps->g_prev_sa_index));
+        memset(ps->g_prev_pan_index, 0, sizeof(ps->g_prev_pan_index));
+        return 0;
+    }
+
+    /* if SBR CRC doesn't match out, we can assume decode errors to start with,
+       and we'll guess what the parameters should be */
+    if (!guess)
+    {
+        ps->sa_decode_error = 0;
+        ps->pan_decode_error = 0;
+        drm_ps_delta_decode(ps);
+    } else 
+    {
+        ps->sa_decode_error = 1;
+        ps->pan_decode_error = 1;
+        /* don't even bother decoding */
+    }
+  
+    ps->drm_ps_data_available = 0;
+
+    drm_calc_sa_side_signal(ps, X_left, rateselect);
+    drm_add_ambiance(ps, rateselect, X_left, X_right);
+
+    if (ps->bs_enable_sa)
+    {
+        ps->g_last_had_sa = 1;        
+
+        memcpy(ps->g_prev_sa_index, ps->g_sa_index, sizeof(int8_t) * DRM_NUM_SA_BANDS);       
+
+    } else {
+        ps->g_last_had_sa = 0;
+    }
+    
+    if (ps->bs_enable_pan)
+    {
+        drm_add_pan(ps, rateselect, X_left, X_right);
+    
+        ps->g_last_had_pan = 1;        
+
+        memcpy(ps->g_prev_pan_index, ps->g_pan_index, sizeof(int8_t) * DRM_NUM_PAN_BANDS);
+
+    } else {
+        ps->g_last_had_pan = 0;
+    }
+
+
+    return 0;
+}
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/libfaad2/drm_dec.h	Tue Apr 18 19:39:34 2006 +0000
@@ -0,0 +1,97 @@
+/*
+** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
+** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com
+**  
+** This program 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 of the License, or
+** (at your option) any later version.
+** 
+** This program 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 this program; if not, write to the Free Software 
+** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+**
+** Any non-GPL usage of this software or parts of this software is strictly
+** forbidden.
+**
+** Commercial non-GPL licensing of this software is possible.
+** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
+**
+** $Id$
+**/
+
+#ifndef __DRM_DEC_H__
+#define __DRM_DEC_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "bits.h"
+
+#define DRM_PARAMETRIC_STEREO    0
+#define DRM_NUM_SA_BANDS         8
+#define DRM_NUM_PAN_BANDS       20
+#define NUM_OF_LINKS             3
+#define NUM_OF_QMF_CHANNELS     64
+#define NUM_OF_SUBSAMPLES       30
+#define MAX_SA_BAND             46
+#define MAX_PAN_BAND            64
+#define MAX_DELAY                5
+
+typedef struct
+{   
+    uint8_t drm_ps_data_available;
+    uint8_t bs_enable_sa;
+    uint8_t bs_enable_pan;
+
+    uint8_t bs_sa_dt_flag;
+    uint8_t bs_pan_dt_flag;
+
+    uint8_t g_last_had_sa;
+    uint8_t g_last_had_pan;
+
+    int8_t bs_sa_data[DRM_NUM_SA_BANDS];
+    int8_t bs_pan_data[DRM_NUM_PAN_BANDS];
+        
+    int8_t g_sa_index[DRM_NUM_SA_BANDS];
+    int8_t g_pan_index[DRM_NUM_PAN_BANDS];                        
+    int8_t g_prev_sa_index[DRM_NUM_SA_BANDS];
+    int8_t g_prev_pan_index[DRM_NUM_PAN_BANDS];    
+
+    int8_t sa_decode_error;
+    int8_t pan_decode_error;
+
+    int8_t g_last_good_sa_index[DRM_NUM_SA_BANDS];
+    int8_t g_last_good_pan_index[DRM_NUM_PAN_BANDS];
+    
+    qmf_t SA[NUM_OF_SUBSAMPLES][MAX_SA_BAND];               
+
+    complex_t d_buff[2][MAX_SA_BAND];
+    complex_t d2_buff[NUM_OF_LINKS][MAX_DELAY][MAX_SA_BAND];
+
+    uint8_t delay_buf_index_ser[NUM_OF_LINKS];    
+            
+    real_t prev_nrg[MAX_SA_BAND];
+    real_t prev_peakdiff[MAX_SA_BAND];
+    real_t peakdecay_fast[MAX_SA_BAND]; 
+} drm_ps_info;
+
+
+uint16_t drm_ps_data(drm_ps_info *ps, bitfile *ld);
+
+drm_ps_info *drm_ps_init(void);
+void drm_ps_free(drm_ps_info *ps);
+
+uint8_t drm_ps_decode(drm_ps_info *ps, uint8_t guess, uint32_t samplerate, qmf_t X_left[38][64], qmf_t X_right[38][64]);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+
--- a/libfaad2/error.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/error.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: error.c,v 1.26 2004/05/17 10:18:02 menno Exp $
+** $Id: error.c,v 1.28 2004/09/04 14:56:28 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/error.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/error.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: error.h,v 1.20 2004/05/17 10:18:02 menno Exp $
+** $Id: error.h,v 1.22 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __ERROR_H__
--- a/libfaad2/filtbank.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/filtbank.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: filtbank.c,v 1.38 2004/06/30 12:45:56 menno Exp $
+** $Id: filtbank.c,v 1.41 2004/09/08 09:43:11 gcp Exp $
 **/
 
 #include "common.h"
@@ -87,15 +87,6 @@
     }
 #endif
 
-#ifdef USE_SSE
-    if (cpu_has_sse())
-    {
-        fb->if_func = ifilter_bank_sse;
-    } else {
-        fb->if_func = ifilter_bank;
-    }
-#endif
-
     return fb;
 }
 
@@ -140,30 +131,6 @@
 #endif
 }
 
-#ifdef USE_SSE
-static INLINE void imdct_long_sse(fb_info *fb, real_t *in_data, real_t *out_data, uint16_t len)
-{
-#ifdef LD_DEC
-    mdct_info *mdct = NULL;
-
-    switch (len)
-    {
-    case 2048:
-    case 1920:
-        mdct = fb->mdct2048;
-        break;
-    case 1024:
-    case 960:
-        mdct = fb->mdct1024;
-        break;
-    }
-
-    faad_imdct_sse(mdct, in_data, out_data);
-#else
-    faad_imdct_sse(fb->mdct2048, in_data, out_data);
-#endif
-}
-#endif
 
 #ifdef LTP_DEC
 static INLINE void mdct(fb_info *fb, real_t *in_data, real_t *out_data, uint16_t len)
@@ -350,8 +317,8 @@
 #if 0
     for (i = 0; i < 1024; i++)
     {
-        //printf("%d\n", time_out[i]);
-        printf("0x%.8X\n", time_out[i]);
+        printf("%d\n", time_out[i]);
+        //printf("0x%.8X\n", time_out[i]);
     }
 #endif
 
@@ -362,334 +329,6 @@
 #endif
 }
 
-#ifdef USE_SSE
-void ifilter_bank_sse(fb_info *fb, uint8_t window_sequence, uint8_t window_shape,
-                      uint8_t window_shape_prev, real_t *freq_in,
-                      real_t *time_out, uint8_t object_type, uint16_t frame_len)
-{
-    int16_t i;
-    ALIGN real_t transf_buf[2*1024] = {0};
-
-    const real_t *window_long = NULL;
-    const real_t *window_long_prev = NULL;
-    const real_t *window_short = NULL;
-    const real_t *window_short_prev = NULL;
-
-    uint16_t nlong = frame_len;
-    uint16_t nshort = frame_len/8;
-    uint16_t trans = nshort/2;
-
-    uint16_t nflat_ls = (nlong-nshort)/2;
-
-#ifdef PROFILE
-    int64_t count = faad_get_ts();
-#endif
-
-#ifdef LD_DEC
-    if (object_type == LD)
-    {
-        window_long       = fb->ld_window[window_shape];
-        window_long_prev  = fb->ld_window[window_shape_prev];
-    } else {
-#endif
-        window_long       = fb->long_window[window_shape];
-        window_long_prev  = fb->long_window[window_shape_prev];
-        window_short      = fb->short_window[window_shape];
-        window_short_prev = fb->short_window[window_shape_prev];
-#ifdef LD_DEC
-    }
-#endif
-
-    switch (window_sequence)
-    {
-    case ONLY_LONG_SEQUENCE:
-        imdct_long_sse(fb, freq_in, transf_buf, 2*nlong);
-        for (i = 0; i < nlong; i+=4)
-        {
-            __m128 m1, m2, m3, m4, m5, m6, m7, m8;
-
-            m1 = _mm_load_ps(&transf_buf[i]);
-            m2 = _mm_load_ps(&window_long_prev[i]);
-            m6 = _mm_load_ps(&window_long[nlong-4-i]);
-            m3 = _mm_load_ps(&time_out[nlong+i]);
-            m5 = _mm_load_ps(&transf_buf[nlong+i]);
-
-            m4 = _mm_mul_ps(m1, m2);
-            m7 = _mm_shuffle_ps(m6, m6, _MM_SHUFFLE(0, 1, 2, 3));
-
-            m4 = _mm_add_ps(m4, m3);
-            m8 = _mm_mul_ps(m5, m7);
-
-            _mm_store_ps(&time_out[i], m4);
-            _mm_store_ps(&time_out[nlong+i], m8);
-        }
-        break;
-
-    case LONG_START_SEQUENCE:
-        imdct_long_sse(fb, freq_in, transf_buf, 2*nlong);
-        for (i = 0; i < nlong; i+=4)
-        {
-            __m128 m1 = _mm_load_ps(&transf_buf[i]);
-            __m128 m2 = _mm_load_ps(&window_long_prev[i]);
-            __m128 m3 = _mm_load_ps(&time_out[nlong+i]);
-
-            __m128 m4 = _mm_mul_ps(m1, m2);
-            m4 = _mm_add_ps(m4, m3);
-
-            _mm_store_ps(&time_out[i], m4);
-        }
-        for (i = 0; i < nflat_ls; i+=4)
-        {
-            __m128 m1 = _mm_load_ps(&transf_buf[nlong+i]);
-            _mm_store_ps(&time_out[nlong+i], m1);
-        }
-        for (i = 0; i < nshort; i+=4)
-        {
-            __m128 m1 = _mm_load_ps(&transf_buf[nlong+nflat_ls+i]);
-            __m128 m2 = _mm_load_ps(&window_short[nshort-4-i]);
-            __m128 m3, m4;
-
-            m3 = _mm_shuffle_ps(m2, m2, _MM_SHUFFLE(0, 1, 2, 3));
-
-            m4 = _mm_mul_ps(m1, m3);
-
-            _mm_store_ps(&time_out[nlong+nflat_ls+i], m4);
-        }
-        for (i = 0; i < nflat_ls; i+=4)
-        {
-            __m128 m1 = _mm_setzero_ps();
-            _mm_store_ps(&time_out[nlong+nflat_ls+nshort+i], m1);
-        }
-        break;
-
-    case EIGHT_SHORT_SEQUENCE:
-        faad_imdct_sse(fb->mdct256, &freq_in[0*nshort], &transf_buf[2*nshort*0]);
-        faad_imdct_sse(fb->mdct256, &freq_in[1*nshort], &transf_buf[2*nshort*1]);
-        faad_imdct_sse(fb->mdct256, &freq_in[2*nshort], &transf_buf[2*nshort*2]);
-        faad_imdct_sse(fb->mdct256, &freq_in[3*nshort], &transf_buf[2*nshort*3]);
-        faad_imdct_sse(fb->mdct256, &freq_in[4*nshort], &transf_buf[2*nshort*4]);
-        faad_imdct_sse(fb->mdct256, &freq_in[5*nshort], &transf_buf[2*nshort*5]);
-        faad_imdct_sse(fb->mdct256, &freq_in[6*nshort], &transf_buf[2*nshort*6]);
-        faad_imdct_sse(fb->mdct256, &freq_in[7*nshort], &transf_buf[2*nshort*7]);
-        for (i = 0; i < nflat_ls; i+=4)
-        {
-            __m128 m1 = _mm_load_ps(&time_out[nlong+i]);
-            _mm_store_ps(&time_out[i], m1);
-        }
-        for (i = 0; i < nshort; i+=4)
-        {
-            __m128 m1 = _mm_load_ps(&transf_buf[nshort*0+i]);
-            __m128 m2 = _mm_load_ps(&window_short_prev[i]);
-            __m128 m3 = _mm_load_ps(&time_out[nlong+nflat_ls+i]);
-
-            __m128 m4 = _mm_mul_ps(m1, m2);
-            m4 = _mm_add_ps(m4, m3);
-
-            _mm_store_ps(&time_out[nflat_ls+i], m4);
-        }
-        for (i = 0; i < nshort; i+=4)
-        {
-            __m128 m1, m2, m3, m4, m5, m6, m7, m8;
-            m1 = _mm_load_ps(&transf_buf[nshort*1+i]);
-            m2 = _mm_load_ps(&window_short[nshort-4-i]);
-            m3 = _mm_load_ps(&time_out[nlong+nflat_ls+nshort*1+i]);
-            m6 = _mm_load_ps(&transf_buf[nshort*2+i]);
-            m7 = _mm_load_ps(&window_short[i]);
-
-            m5 = _mm_shuffle_ps(m2, m2, _MM_SHUFFLE(0, 1, 2, 3));
-
-            m4 = _mm_mul_ps(m1, m5);
-            m8 = _mm_mul_ps(m6, m7);
-            m4 = _mm_add_ps(m4, m3);
-            m4 = _mm_add_ps(m4, m8);
-
-            _mm_store_ps(&time_out[nflat_ls+1*nshort+i], m4);
-        }
-        for (i = 0; i < nshort; i+=4)
-        {
-            __m128 m1, m2, m3, m4, m5, m6, m7, m8;
-            m1 = _mm_load_ps(&transf_buf[nshort*3+i]);
-            m2 = _mm_load_ps(&window_short[nshort-4-i]);
-            m3 = _mm_load_ps(&time_out[nlong+nflat_ls+nshort*2+i]);
-            m6 = _mm_load_ps(&transf_buf[nshort*4+i]);
-            m7 = _mm_load_ps(&window_short[i]);
-
-            m5 = _mm_shuffle_ps(m2, m2, _MM_SHUFFLE(0, 1, 2, 3));
-
-            m4 = _mm_mul_ps(m1, m5);
-            m8 = _mm_mul_ps(m6, m7);
-            m4 = _mm_add_ps(m4, m3);
-            m4 = _mm_add_ps(m4, m8);
-
-            _mm_store_ps(&time_out[nflat_ls+2*nshort+i], m4);
-        }
-        for (i = 0; i < nshort; i+=4)
-        {
-            __m128 m1, m2, m3, m4, m5, m6, m7, m8;
-            m1 = _mm_load_ps(&transf_buf[nshort*5+i]);
-            m2 = _mm_load_ps(&window_short[nshort-4-i]);
-            m3 = _mm_load_ps(&time_out[nlong+nflat_ls+nshort*3+i]);
-            m6 = _mm_load_ps(&transf_buf[nshort*6+i]);
-            m7 = _mm_load_ps(&window_short[i]);
-
-            m5 = _mm_shuffle_ps(m2, m2, _MM_SHUFFLE(0, 1, 2, 3));
-
-            m4 = _mm_mul_ps(m1, m5);
-            m8 = _mm_mul_ps(m6, m7);
-            m4 = _mm_add_ps(m4, m3);
-            m4 = _mm_add_ps(m4, m8);
-
-            _mm_store_ps(&time_out[nflat_ls+3*nshort+i], m4);
-        }
-        for(i = 0; i < trans; i+=4)
-        {
-            __m128 m1, m2, m3, m4, m5, m6, m7, m8;
-            m1 = _mm_load_ps(&transf_buf[nshort*7+i]);
-            m2 = _mm_load_ps(&window_short[nshort-4-i]);
-            m3 = _mm_load_ps(&time_out[nlong+nflat_ls+nshort*4+i]);
-            m6 = _mm_load_ps(&transf_buf[nshort*8+i]);
-            m7 = _mm_load_ps(&window_short[i]);
-
-            m5 = _mm_shuffle_ps(m2, m2, _MM_SHUFFLE(0, 1, 2, 3));
-
-            m4 = _mm_mul_ps(m1, m5);
-            m8 = _mm_mul_ps(m6, m7);
-            m4 = _mm_add_ps(m4, m3);
-            m4 = _mm_add_ps(m4, m8);
-
-            _mm_store_ps(&time_out[nflat_ls+4*nshort+i], m4);
-        }
-        for (i = trans; i < nshort; i+=4)
-        {
-            __m128 m1, m2, m3, m4, m5, m6, m7, m8;
-            m1 = _mm_load_ps(&transf_buf[nshort*7+i]);
-            m2 = _mm_load_ps(&window_short[nshort-4-i]);
-            m6 = _mm_load_ps(&transf_buf[nshort*8+i]);
-            m7 = _mm_load_ps(&window_short[i]);
-
-            m5 = _mm_shuffle_ps(m2, m2, _MM_SHUFFLE(0, 1, 2, 3));
-
-            m4 = _mm_mul_ps(m1, m5);
-            m8 = _mm_mul_ps(m6, m7);
-            m3 = _mm_add_ps(m4, m8);
-
-            _mm_store_ps(&time_out[nflat_ls+4*nshort+i], m3);
-        }
-        for (i = 0; i < nshort; i+=4)
-        {
-            __m128 m1, m2, m3, m4, m5, m6, m7, m8;
-            m1 = _mm_load_ps(&transf_buf[nshort*9+i]);
-            m2 = _mm_load_ps(&window_short[nshort-4-i]);
-            m6 = _mm_load_ps(&transf_buf[nshort*10+i]);
-            m7 = _mm_load_ps(&window_short[i]);
-
-            m5 = _mm_shuffle_ps(m2, m2, _MM_SHUFFLE(0, 1, 2, 3));
-
-            m4 = _mm_mul_ps(m1, m5);
-            m8 = _mm_mul_ps(m6, m7);
-            m3 = _mm_add_ps(m4, m8);
-
-            _mm_store_ps(&time_out[nflat_ls+5*nshort+i], m3);
-        }
-        for (i = 0; i < nshort; i+=4)
-        {
-            __m128 m1, m2, m3, m4, m5, m6, m7, m8;
-            m1 = _mm_load_ps(&transf_buf[nshort*11+i]);
-            m2 = _mm_load_ps(&window_short[nshort-4-i]);
-            m6 = _mm_load_ps(&transf_buf[nshort*12+i]);
-            m7 = _mm_load_ps(&window_short[i]);
-
-            m5 = _mm_shuffle_ps(m2, m2, _MM_SHUFFLE(0, 1, 2, 3));
-
-            m4 = _mm_mul_ps(m1, m5);
-            m8 = _mm_mul_ps(m6, m7);
-            m3 = _mm_add_ps(m4, m8);
-
-            _mm_store_ps(&time_out[nflat_ls+6*nshort+i], m3);
-        }
-        for (i = 0; i < nshort; i+=4)
-        {
-            __m128 m1, m2, m3, m4, m5, m6, m7, m8;
-            m1 = _mm_load_ps(&transf_buf[nshort*13+i]);
-            m2 = _mm_load_ps(&window_short[nshort-4-i]);
-            m6 = _mm_load_ps(&transf_buf[nshort*14+i]);
-            m7 = _mm_load_ps(&window_short[i]);
-
-            m5 = _mm_shuffle_ps(m2, m2, _MM_SHUFFLE(0, 1, 2, 3));
-
-            m4 = _mm_mul_ps(m1, m5);
-            m8 = _mm_mul_ps(m6, m7);
-            m3 = _mm_add_ps(m4, m8);
-
-            _mm_store_ps(&time_out[nflat_ls+7*nshort+i], m3);
-        }
-        for (i = 0; i < nshort; i+=4)
-        {
-            __m128 m1, m2, m3, m5;
-            m1 = _mm_load_ps(&transf_buf[nshort*15+i]);
-            m2 = _mm_load_ps(&window_short[nshort-4-i]);
-
-            m5 = _mm_shuffle_ps(m2, m2, _MM_SHUFFLE(0, 1, 2, 3));
-
-            m3 = _mm_mul_ps(m1, m5);
-
-            _mm_store_ps(&time_out[nflat_ls+8*nshort+i], m3);
-        }
-        for (i = 0; i < nflat_ls; i+=4)
-        {
-            __m128 m1 = _mm_setzero_ps();
-            _mm_store_ps(&time_out[nlong+nflat_ls+nshort+i], m1);
-        }
-        break;
-
-    case LONG_STOP_SEQUENCE:
-        imdct_long_sse(fb, freq_in, transf_buf, 2*nlong);
-        for (i = 0; i < nflat_ls; i+=4)
-        {
-            __m128 m1 = _mm_load_ps(&time_out[nlong+i]);
-            _mm_store_ps(&time_out[i], m1);
-        }
-        for (i = 0; i < nshort; i+=4)
-        {
-            __m128 m1 = _mm_load_ps(&transf_buf[nflat_ls+i]);
-            __m128 m2 = _mm_load_ps(&window_short_prev[i]);
-            __m128 m3 = _mm_load_ps(&time_out[nlong+nflat_ls+i]);
-
-            __m128 m4 = _mm_mul_ps(m1, m2);
-            m4 = _mm_add_ps(m4, m3);
-
-            _mm_store_ps(&time_out[nflat_ls+i], m4);
-        }
-        for (i = 0; i < nflat_ls; i+=4)
-        {
-            __m128 m1 = _mm_load_ps(&transf_buf[nflat_ls+nshort+i]);
-            __m128 m2 = _mm_load_ps(&time_out[nlong+nflat_ls+nshort+i]);
-
-            __m128 m3 = _mm_add_ps(m1, m2);
-
-            _mm_store_ps(&time_out[nflat_ls+nshort+i], m3);
-        }
-        for (i = 0; i < nlong; i+=4)
-        {
-            __m128 m1 = _mm_load_ps(&transf_buf[nlong+i]);
-            __m128 m2 = _mm_load_ps(&window_long[nlong-4-i]);
-            __m128 m3, m4;
-
-            m3 = _mm_shuffle_ps(m2, m2, _MM_SHUFFLE(0, 1, 2, 3));
-
-            m4 = _mm_mul_ps(m1, m3);
-
-            _mm_store_ps(&time_out[nlong+i], m4);
-        }
-		break;
-    }
-
-#ifdef PROFILE
-    count = faad_get_ts() - count;
-    fb->cycles += count;
-#endif
-}
-#endif
 
 #ifdef LTP_DEC
 /* only works for LTP -> no overlapping, no short blocks */
--- a/libfaad2/filtbank.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/filtbank.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: filtbank.h,v 1.20 2004/01/13 14:24:10 menno Exp $
+** $Id: filtbank.h,v 1.23 2004/09/08 09:43:11 gcp Exp $
 **/
 
 #ifndef __FILTBANK_H__
@@ -52,12 +52,6 @@
                   real_t *time_out, real_t *overlap,
                   uint8_t object_type, uint16_t frame_len);
 
-#ifdef USE_SSE
-void ifilter_bank_sse(fb_info *fb, uint8_t window_sequence, uint8_t window_shape,
-                      uint8_t window_shape_prev, real_t *freq_in,
-                      real_t *time_out, uint8_t object_type, uint16_t frame_len);
-#endif
-
 #ifdef __cplusplus
 }
 #endif
--- a/libfaad2/fixed.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/fixed.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: fixed.h,v 1.24 2004/06/30 12:45:56 menno Exp $
+** $Id: fixed.h,v 1.26 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __FIXED_H__
--- a/libfaad2/hcr.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/hcr.c	Tue Apr 18 19:39:34 2006 +0000
@@ -1,6 +1,6 @@
 /*
 ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
-** Copyright (C) 2002-2004 A. Kurpiers
+** Copyright (C) 2004 G.C. Pascutto, Ahead Software AG, http://www.nero.com
 **  
 ** This program is free software; you can redistribute it and/or modify
 ** it under the terms of the GNU General Public License as published by
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: hcr.c,v 1.15 2004/03/02 20:09:58 menno Exp $
+** $Id: hcr.c,v 1.18 2004/09/04 14:56:28 menno Exp $
 **/
 
 #include "common.h"
@@ -31,295 +31,337 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include "syntax.h"
 #include "specrec.h"
-#include "bits.h"
-#include "pulse.h"
-#include "analysis.h"
-#include "bits.h"
 #include "huffman.h"
 
-/* Implements the HCR11 tool as described in ISO/IEC 14496-3/Amd.1, 8.5.3.3 */
+/* ISO/IEC 14496-3/Amd.1 
+ * 8.5.3.3: Huffman Codeword Reordering for AAC spectral data (HCR) 
+ *
+ * HCR devides the spectral data in known fixed size segments, and 
+ * sorts it by the importance of the data. The importance is firstly 
+ * the (lower) position in the spectrum, and secondly the largest 
+ * value in the used codebook. 
+ * The most important data is written at the start of each segment
+ * (at known positions), the remaining data is interleaved inbetween, 
+ * with the writing direction alternating.
+ * Data length is not increased.
+*/
 
 #ifdef ERROR_RESILIENCE
 
-/* rewind len (max. 32) bits so that the MSB becomes LSB */
+/* 8.5.3.3.1 Pre-sorting */
+
+#define NUM_CB      6
+#define NUM_CB_ER   22
+#define MAX_CB      32
+#define VCB11_FIRST 16
+#define VCB11_LAST  31
 
-static uint32_t rewind_word( uint32_t W, uint8_t len)
-{
-    uint8_t i;
-    uint32_t tmp_W=0;
+static const uint8_t PreSortCB_STD[NUM_CB] = 
+    { 11, 9, 7, 5, 3, 1};
+
+static const uint8_t PreSortCB_ER[NUM_CB_ER] = 
+    { 11, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 9, 7, 5, 3, 1};
+
+/* 8.5.3.3.2 Derivation of segment width */
+
+static const uint8_t maxCwLen[MAX_CB] = {0, 11, 9, 20, 16, 13, 11, 14, 12, 17, 14, 49,
+    0, 0, 0, 0, 14, 17, 21, 21, 25, 25, 29, 29, 29, 29, 33, 33, 33, 37, 37, 41};
+
+#define segmentWidth(cb)    min(maxCwLen[cb], ics->length_of_longest_codeword)
 
-    for ( i=0; i<len; i++ )
-    {
-        tmp_W<<=1;
-        if (W & (1<<i)) tmp_W |= 1;
-    }
-    return tmp_W;
+/* bit-twiddling helpers */
+static const uint8_t  S[] = {1, 2, 4, 8, 16};    
+static const uint32_t B[] = {0x55555555, 0x33333333, 0x0F0F0F0F, 0x00FF00FF, 0x0000FFFF};
+
+typedef struct
+{
+    uint8_t     cb;
+    uint8_t     decoded;
+    uint16_t	sp_offset;
+    bits_t      bits;
+} codeword_t;
+
+/* rewind and reverse */
+/* 32 bit version */
+static uint32_t rewrev_word(uint32_t v, const uint8_t len)
+{  
+    /* 32 bit reverse */
+    v = ((v >> S[0]) & B[0]) | ((v << S[0]) & ~B[0]); 
+    v = ((v >> S[1]) & B[1]) | ((v << S[1]) & ~B[1]); 
+    v = ((v >> S[2]) & B[2]) | ((v << S[2]) & ~B[2]); 
+    v = ((v >> S[3]) & B[3]) | ((v << S[3]) & ~B[3]);
+    v = ((v >> S[4]) & B[4]) | ((v << S[4]) & ~B[4]);
+
+    /* shift off low bits */
+    v >>= (32 - len);
+
+    return v;
 }
 
-static void rewind_lword( uint32_t *highW, uint32_t *lowW, uint8_t len)
-{
-    uint32_t tmp_lW=0;
-
-    if (len > 32)
+/* 64 bit version */
+static void rewrev_lword(uint32_t *hi, uint32_t *lo, const uint8_t len)
+{   
+    if (len <= 32) {
+        *hi = 0;
+        *lo = rewrev_word(*lo, len);
+    } else
     {
-        tmp_lW = rewind_word( (*highW << (64-len)) | (*lowW >> (len-32)), 32);
-        *highW = rewind_word( *lowW << (64-len) , 32);
-        *lowW = tmp_lW;
-    } else {
-        *highW = 0;
-        *lowW = rewind_word( *lowW, len);
-    }
-}    
+        uint32_t t = *hi, v = *lo;
 
-/* Takes a codeword as stored in r, rewinds the remaining bits and stores it back */
-static void rewind_bits(bits_t * r)
-{
-    uint32_t hw, lw;
-
-    if (r->len == 0) return;
+        /* double 32 bit reverse */
+        v = ((v >> S[0]) & B[0]) | ((v << S[0]) & ~B[0]); 
+        t = ((t >> S[0]) & B[0]) | ((t << S[0]) & ~B[0]); 
+        v = ((v >> S[1]) & B[1]) | ((v << S[1]) & ~B[1]); 
+        t = ((t >> S[1]) & B[1]) | ((t << S[1]) & ~B[1]); 
+        v = ((v >> S[2]) & B[2]) | ((v << S[2]) & ~B[2]); 
+        t = ((t >> S[2]) & B[2]) | ((t << S[2]) & ~B[2]); 
+        v = ((v >> S[3]) & B[3]) | ((v << S[3]) & ~B[3]);
+        t = ((t >> S[3]) & B[3]) | ((t << S[3]) & ~B[3]);
+        v = ((v >> S[4]) & B[4]) | ((v << S[4]) & ~B[4]);                
+        t = ((t >> S[4]) & B[4]) | ((t << S[4]) & ~B[4]);
 
-    if (r->len >32)
-    {
-        lw = r->bufa;
-        hw = r->bufb & (0xFFFFFFFF >> (64 - r->len));
-        rewind_lword( &hw, &lw, r->len );
-        r->bufa = lw;
-        r->bufb = hw;
-
-    } else {
-        lw = showbits_hcr(r, r->len );
-        r->bufa = rewind_word( lw, r->len);
-        r->bufb = 0;
+        /* last 32<>32 bit swap is implicit below */
+        
+        /* shift off low bits (this is really only one 64 bit shift) */
+        *lo = (t >> (64 - len)) | (v << (len - 32));
+        *hi = v >> (64 - len);          
     }
 }
 
-/* takes codewords from a and b, concatenate them and store them in b */
-static void concat_bits( bits_t * a, bits_t * b)
+
+/* bits_t version */
+static void rewrev_bits(bits_t *bits)
 {
-    uint32_t	hwa, lwa, hwb, lwb;
+    if (bits->len == 0) return;
+    rewrev_lword(&bits->bufb, &bits->bufa,  bits->len);
+}
+
+
+/* merge bits of a to b */
+static void concat_bits(bits_t *b, bits_t *a)
+{
+    uint32_t bl, bh, al, ah;
 
     if (a->len == 0) return;
 
-    if (a->len >32)
+    al = a->bufa;
+    ah = a->bufb;
+    
+    if (b->len > 32)
     {
-        lwa = a->bufa;
-        hwa = a->bufb & (0xFFFFFFFF >> (64 - a->len));
+        /* maskoff superfluous high b bits */
+        bl = b->bufa;
+        bh = b->bufb & ((1 << (b->len-32)) - 1);
+        /* left shift a b->len bits */
+        ah = al << (b->len - 32);
+        al = 0;
     } else {
-        lwa = showbits_hcr(a, a->len );
-        hwa = 0;
-    }
-    if (b->len >=32) {
-        lwb = b->bufa;
-        hwb = (b->bufb & (0xFFFFFFFF >> (64 - b->len)) ) | ( lwa << (b->len - 32));
-    } else {
-        lwb = showbits_hcr(b, b->len ) | (lwa << (b->len));
-        hwb = (lwa >> (32 - b->len)) | (hwa << (b->len));
+        bl = b->bufa & ((1 << (b->len)) - 1);
+        bh = 0;   
+        ah = (ah << (b->len)) | (al >> (32 - b->len));
+        al = al << b->len;
     }
 
-    b->bufa = lwb;
-    b->bufb = hwb;
+    /* merge */
+    b->bufa = bl | al;
+    b->bufb = bh | ah;
+
     b->len += a->len;
 }
+     
+uint8_t is_good_cb(uint8_t this_CB, uint8_t this_sec_CB)
+{
+    /* only want spectral data CB's */
+    if ((this_sec_CB > ZERO_HCB && this_sec_CB <= ESC_HCB) || (this_sec_CB >= VCB11_FIRST && this_sec_CB <= VCB11_LAST))
+    {
+        if (this_CB < ESC_HCB)
+        {
+            /* normal codebook pairs */
+            return ((this_sec_CB == this_CB) || (this_sec_CB == this_CB + 1));
+        } else
+        {
+            /* escape codebook */
+            return (this_sec_CB == this_CB);
+        }
+    }
+    return 0;
+}
+                    
+void read_segment(bits_t *segment, uint8_t segwidth, bitfile *ld)
+{
+    segment->len = segwidth;
+
+     if (segwidth > 32)
+     {
+        segment->bufb = faad_getbits(ld, segwidth - 32);        
+        segment->bufa = faad_getbits(ld, 32);        
+
+    } else {
+        segment->bufa = faad_getbits(ld, segwidth);
+        segment->bufb = 0;        
+    }    
+}
 
-/* 8.5.3.3.1 */
-
-static const uint8_t PresortedCodebook_VCB11[] = { 11, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18, 17, 16, 9, 7, 5, 3, 1};
-static const uint8_t PresortedCodebook[] = { 11, 9, 7, 5, 3, 1};
-
-static const uint8_t maxCwLen[32] = {0, 11, 9, 20, 16, 13, 11, 14, 12, 17, 14, 49,
-    0, 0, 0, 0, 14, 17, 21, 21, 25, 25, 29, 29, 29, 29, 33, 33, 33, 37, 37, 41};
-
-typedef struct
+void fill_in_codeword(codeword_t *codeword, uint16_t index, uint16_t sp, uint8_t cb)
 {
-    bits_t		bits;
-    uint8_t		decoded;
-    uint16_t	sp_offset;
-    uint8_t		cb;
-} codeword_state;
+    codeword[index].sp_offset = sp;
+    codeword[index].cb = cb;
+    codeword[index].decoded = 0;
+    codeword[index].bits.len = 0;
+}
 
+uint8_t reordered_spectral_data(NeAACDecHandle hDecoder, ic_stream *ics, 
+                                bitfile *ld, int16_t *spectral_data)
+{   
+    uint16_t PCWs_done;
+    uint16_t numberOfSegments, numberOfSets, numberOfCodewords;  
 
-#define segmentWidth( codebook )	min( maxCwLen[codebook], ics->length_of_longest_codeword )
-     
-uint8_t reordered_spectral_data(NeAACDecHandle hDecoder, ic_stream *ics, bitfile *ld,
-                                int16_t *spectral_data)
-{
+    codeword_t codeword[512];
+    bits_t segment[512];
+
     uint16_t sp_offset[8];
-    uint16_t g,i, presort;
-    uint16_t NrCodeWords=0, numberOfSegments=0, BitsRead=0;
-    uint8_t numberOfSets, set;
-    codeword_state Codewords[ 1024 ];	// FIXME max length? PCWs are not stored, so index is Codewordnr - numberOfSegments!, maybe malloc()?
-    bits_t	Segment[ 512 ];
-
-    uint8_t PCW_decoded=0;
-    uint16_t nshort = hDecoder->frameLength/8;
-
-
-    /*memset (spectral_data, 0, hDecoder->frameLength*sizeof(uint16_t));*/
+    uint16_t g, i, sortloop, set, bitsread;
+    uint8_t w_idx, sfb, this_CB, last_CB, this_sec_CB; 
+    
+    const uint16_t nshort = hDecoder->frameLength/8;
+    const uint16_t sp_data_len = ics->length_of_reordered_spectral_data;
+    
+    const uint8_t *PreSortCb;
 
-    if (ics->length_of_reordered_spectral_data == 0)
-        return 0; /* nothing to do */
+    /* no data (e.g. silence) */
+    if (sp_data_len == 0)
+        return 0;
 
-    /* if we have a corrupted bitstream this can happen... */
-    if ((ics->length_of_longest_codeword == 0) ||
-        (ics->length_of_reordered_spectral_data <
-        ics->length_of_longest_codeword) ||
-        (ics->max_sfb == 0))
-    {
-        return 10; /* this is not good... */
-    }
-
-    /* store the offset into the spectral data for all the window groups because we can't do it later */
+    /* since there is spectral data, at least one codeword has nonzero length */
+    if (ics->length_of_longest_codeword == 0)
+        return 10;
+    
+    if (sp_data_len < ics->length_of_longest_codeword)
+        return 10; 
 
     sp_offset[0] = 0;
-    for (g=1; g < ics->num_window_groups; g++)
+    for (g = 1; g < ics->num_window_groups; g++)
     {
         sp_offset[g] = sp_offset[g-1] + nshort*ics->window_group_length[g-1];
     }
 
-    /* All data is sorted according to the codebook used */        
-    for (presort = 0; presort < (hDecoder->aacSectionDataResilienceFlag ? 22 : 6); presort++)
-    {
-        uint8_t sfb;
-
-        /* next codebook that has to be processed according to presorting */
-        uint8_t nextCB = hDecoder->aacSectionDataResilienceFlag ? PresortedCodebook_VCB11[ presort ] : PresortedCodebook[ presort ];
+    PCWs_done = 0;
+    numberOfSegments = 0;
+    numberOfCodewords = 0;
+    bitsread = 0;
 
-        /* Data belonging to the same spectral unit and having the same codebook comes in consecutive codewords.
-           This is done by scanning all sfbs for possible codewords. For sfbs with more than 4 elements this has to be
-           repeated */
-
-        for (sfb=0; sfb<ics->max_sfb; sfb ++)
+    /* VCB11 code books in use */
+    if (hDecoder->aacSectionDataResilienceFlag)
+    {
+        PreSortCb = PreSortCB_ER;
+        last_CB = NUM_CB_ER;
+    } else
+    {
+        PreSortCb = PreSortCB_STD;
+        last_CB = NUM_CB;
+    }
+ 
+    /* step 1: decode PCW's (set 0), and stuff data in easier-to-use format */
+    for (sortloop = 0; sortloop < last_CB; sortloop++)
+    {
+        /* select codebook to process this pass */
+        this_CB = PreSortCb[sortloop];
+        
+        /* loop over sfbs */
+        for (sfb = 0; sfb < ics->max_sfb; sfb++)
         {
-            uint8_t sect_cb, w;
-
-            for (w=0; w< (ics->swb_offset[sfb+1] - ics->swb_offset[sfb]); w+=4)
+            /* loop over all in this sfb, 4 lines per loop */
+            for (w_idx = 0; 4*w_idx < (ics->swb_offset[sfb+1] - ics->swb_offset[sfb]); w_idx++)
             {
                 for(g = 0; g < ics->num_window_groups; g++)
                 {
                     for (i = 0; i < ics->num_sec[g]; i++)
                     {
-                        sect_cb = ics->sect_cb[g][i];
-
-                        if (
-                            /* process only sections that are due now */
-                            (( sect_cb == nextCB ) || (( nextCB < ESC_HCB ) && ( sect_cb == nextCB+1)) ) &&
-
-                            /* process only sfb's that are due now */
-                            ((ics->sect_start[g][i] <= sfb) && (ics->sect_end[g][i] > sfb))
-                            )
-                        {
-                            if ((sect_cb != ZERO_HCB) &&
-                                (sect_cb != NOISE_HCB) &&
-                                (sect_cb != INTENSITY_HCB) &&
-                                (sect_cb != INTENSITY_HCB2))
+                        /* check whether sfb used here is the one we want to process */
+                        if ((ics->sect_start[g][i] <= sfb) && (ics->sect_end[g][i] > sfb))
+                        {                            
+                            /* check whether codebook used here is the one we want to process */
+                            this_sec_CB = ics->sect_cb[g][i];
+                 
+                            if (is_good_cb(this_CB, this_sec_CB))                              
                             {
-                                uint8_t inc = (sect_cb < FIRST_PAIR_HCB) ? QUAD_LEN : PAIR_LEN;
-                                uint16_t k;
-
-                                uint32_t	hw, lw;
-
-                                for  (k=0; (k < (4/inc)*ics->window_group_length[g]) &&
-                                    ( (k+w*ics->window_group_length[g]/inc) < (ics->sect_sfb_offset[g][sfb+1] - ics->sect_sfb_offset[g][sfb])); k++)
-                                {
-                                    uint16_t sp = sp_offset[g] + ics->sect_sfb_offset[g][sfb] + inc*(k+w*ics->window_group_length[g]/inc);
+                                /* precalculate some stuff */
+                                uint16_t sect_sfb_size = ics->sect_sfb_offset[g][sfb+1] - ics->sect_sfb_offset[g][sfb];
+                                uint8_t inc = (this_sec_CB < FIRST_PAIR_HCB) ? QUAD_LEN : PAIR_LEN;
+                                uint16_t group_cws_count = (4*ics->window_group_length[g])/inc;
+                                uint8_t segwidth = segmentWidth(this_sec_CB);
+                                uint16_t cws;                                
 
-                                    if (!PCW_decoded)
-                                    {
-                                        /* if we haven't yet read until the end of the buffer, we can directly decode the so-called PCWs */
-                                        if ((BitsRead + segmentWidth( sect_cb ))<= ics->length_of_reordered_spectral_data)
-                                        {
-                                            Segment[ numberOfSegments ].len = segmentWidth( sect_cb );
+                                /* read codewords until end of sfb or end of window group (shouldn't only 1 trigger?) */                                 
+                                for (cws = 0; (cws < group_cws_count) && ((cws + w_idx*group_cws_count) < sect_sfb_size); cws++)
+                                {
+                                    uint16_t sp = sp_offset[g] + ics->sect_sfb_offset[g][sfb] + inc * (cws + w_idx*group_cws_count);                                   
 
-                                            if (segmentWidth( sect_cb ) > 32)
-                                            {
-                                                Segment[ numberOfSegments ].bufb = faad_showbits(ld, segmentWidth( sect_cb ) - 32);
-                                                faad_flushbits(ld, segmentWidth( sect_cb) - 32);
-                                                Segment[ numberOfSegments ].bufa = faad_showbits(ld, 32),
-                                                    faad_flushbits(ld, 32 );
+                                    /* read and decode PCW */
+                                    if (!PCWs_done)
+                                    {         
+                                        /* read in normal segments */
+                                        if (bitsread + segwidth <= sp_data_len)
+                                        {                                            
+                                            read_segment(&segment[numberOfSegments], segwidth, ld);                          
+                                            bitsread += segwidth;
+                                            
+                                            huffman_spectral_data_2(this_sec_CB, &segment[numberOfSegments], &spectral_data[sp]);                                            
 
-                                            } else {
-                                                Segment[ numberOfSegments ].bufa = faad_showbits(ld,  segmentWidth( sect_cb ));
-                                                Segment[ numberOfSegments ].bufb = 0;
-                                                faad_flushbits(ld, segmentWidth( sect_cb) );
-                                            }
-
-                                            huffman_spectral_data_2(sect_cb, &Segment[ numberOfSegments ], &spectral_data[sp]);
-
-                                            BitsRead += segmentWidth( sect_cb );
-
-                                            /* skip to next segment, but store left bits in new buffer */
-                                            rewind_bits( &Segment[ numberOfSegments ]);
+                                            /* keep leftover bits */
+                                            rewrev_bits(&segment[numberOfSegments]);
 
                                             numberOfSegments++;
                                         } else {
-
-                                            /* the last segment is extended until length_of_reordered_spectral_data */
-
-                                            if (BitsRead < ics->length_of_reordered_spectral_data)
-                                            {
-
-                                                uint8_t additional_bits = (ics->length_of_reordered_spectral_data - BitsRead);
+                                            /* remaining stuff after last segment, we unfortunately couldn't read
+                                               this in earlier because it might not fit in 64 bits. since we already
+                                               decoded (and removed) the PCW it is now guaranteed to fit */
+                                            if (bitsread < sp_data_len)
+                                            {                                                
+                                                const uint8_t additional_bits = sp_data_len - bitsread;                                               
 
-                                                if ( additional_bits > 32)
-                                                {
-                                                    hw = faad_showbits(ld, additional_bits - 32);
-                                                    faad_flushbits(ld, additional_bits - 32);
-                                                    lw = faad_showbits(ld, 32);
-                                                    faad_flushbits(ld, 32 );
-                                                } else {
-                                                    lw = faad_showbits(ld, additional_bits);
-                                                    hw = 0;
-                                                    faad_flushbits(ld, additional_bits );
-                                                }
-                                                rewind_lword( &hw, &lw, additional_bits + Segment[ numberOfSegments-1 ].len );
-                                                if (Segment[ numberOfSegments-1 ].len > 32)
+                                                read_segment(&segment[numberOfSegments], additional_bits, ld);                                                
+                                                segment[numberOfSegments].len += segment[numberOfSegments-1].len;
+                                                rewrev_bits(&segment[numberOfSegments]);                                               
+
+                                                if (segment[numberOfSegments-1].len > 32)
                                                 {
-                                                    Segment[ numberOfSegments-1 ].bufb = hw + 
-                                                        showbits_hcr(&Segment[ numberOfSegments-1 ], Segment[ numberOfSegments-1 ].len - 32);
-                                                    Segment[ numberOfSegments-1 ].bufa = lw + 
-                                                        showbits_hcr(&Segment[ numberOfSegments-1 ], 32);
+                                                    segment[numberOfSegments-1].bufb = segment[numberOfSegments].bufb + 
+                                                        showbits_hcr(&segment[numberOfSegments-1], segment[numberOfSegments-1].len - 32);
+                                                    segment[numberOfSegments-1].bufa = segment[numberOfSegments].bufa + 
+                                                        showbits_hcr(&segment[numberOfSegments-1], 32);
                                                 } else {
-                                                    Segment[ numberOfSegments-1 ].bufa = lw + 
-                                                        showbits_hcr(&Segment[ numberOfSegments-1 ], Segment[ numberOfSegments-1 ].len);
-                                                    Segment[ numberOfSegments-1 ].bufb = hw;
-                                                }
-                                                Segment[ numberOfSegments-1 ].len += additional_bits;
+                                                    segment[numberOfSegments-1].bufa = segment[numberOfSegments].bufa + 
+                                                        showbits_hcr(&segment[numberOfSegments-1], segment[numberOfSegments-1].len);
+                                                    segment[numberOfSegments-1].bufb = segment[numberOfSegments].bufb;
+                                                }                                                
+                                                segment[numberOfSegments-1].len += additional_bits;
                                             }
-                                            BitsRead = ics->length_of_reordered_spectral_data;
-                                            PCW_decoded = 1;
+                                            bitsread = sp_data_len;
+                                            PCWs_done = 1;
 
-                                            Codewords[ 0 ].sp_offset = sp;
-                                            Codewords[ 0 ].cb = sect_cb;
-                                            Codewords[ 0 ].decoded = 0;
-                                            Codewords[ 0 ].bits.len = 0;
+                                            fill_in_codeword(codeword, 0, sp, this_sec_CB);                                            
                                         }
-                                    } else {
-                                        Codewords[ NrCodeWords - numberOfSegments ].sp_offset = sp;
-                                        Codewords[ NrCodeWords - numberOfSegments ].cb = sect_cb;
-                                        Codewords[ NrCodeWords - numberOfSegments ].decoded = 0;
-                                        Codewords[ NrCodeWords - numberOfSegments ].bits.len = 0;
-
-                                    } /* PCW decoded */
-                                    NrCodeWords++;
-                                } /* of k */
+                                    } else {    
+                                        fill_in_codeword(codeword, numberOfCodewords - numberOfSegments, sp, this_sec_CB);                                         
+                                    }
+                                    numberOfCodewords++;
+                                }                             
                             }
                         }
-                    } /* of i */
-                 } /* of g */
-             } /* of w */
-         } /* of sfb */
-    } /* of presort */
+                    } 
+                 } 
+             }
+         }
+    }
 
-    /* Avoid divide by zero */
     if (numberOfSegments == 0)
-        return 10; /* this is not good... */
+        return 10; 
 
-    numberOfSets = NrCodeWords / numberOfSegments;     
+    numberOfSets = numberOfCodewords / numberOfSegments;     
 
-    /* second step: decode nonPCWs */
-
+    /* step 2: decode nonPCWs */
     for (set = 1; set <= numberOfSets; set++)
     {
         uint16_t trial;
@@ -327,85 +369,40 @@
         for (trial = 0; trial < numberOfSegments; trial++)
         {
             uint16_t codewordBase;
-            uint16_t set_decoded=numberOfSegments;
-
-            if (set == numberOfSets)
-                set_decoded = NrCodeWords - set*numberOfSegments;	/* last set is shorter than the rest */
 
             for (codewordBase = 0; codewordBase < numberOfSegments; codewordBase++)
             {
-                uint16_t segment_index = (trial + codewordBase) % numberOfSegments;
-                uint16_t codeword_index = codewordBase + set*numberOfSegments - numberOfSegments;
-
-                if ((codeword_index + numberOfSegments) >= NrCodeWords)
-                    break;
-                if (!Codewords[ codeword_index ].decoded)
-                {
-                    if ( Segment[ segment_index ].len > 0)
-                    {
-                        uint8_t tmplen;
+                const uint16_t segment_idx = (trial + codewordBase) % numberOfSegments;
+                const uint16_t codeword_idx = codewordBase + set*numberOfSegments - numberOfSegments;
 
-                        if (Codewords[ codeword_index ].bits.len != 0)
-                        {
-                            /* on the first trial the data is only stored in Segment[], not in Codewords[]. 
-                               On next trials first collect the data stored for this codeword and
-                               concatenate the new data from Segment[] */
+                /* data up */
+                if (codeword_idx >= numberOfCodewords - numberOfSegments) break;
 
-                            concat_bits( &Codewords[ codeword_index ].bits, &Segment[ segment_index ]);                            
-                            /* Now everthing is stored in Segment[] */
-                        }
-                        tmplen = Segment[ segment_index ].len;
-                        if ( huffman_spectral_data_2(Codewords[ codeword_index ].cb, &Segment[ segment_index ],
-                            &spectral_data[ Codewords[ codeword_index ].sp_offset ]) >=0)
-                        {
-                            /* CW did fit into segment */
-
-                            Codewords[ codeword_index ].decoded = 1;
-                            set_decoded--;
-                        } else {
-
-                            /* CW did not fit, so store for later use */
+                if (!codeword[codeword_idx].decoded && segment[segment_idx].len > 0)
+                {
+                    uint8_t tmplen;
 
-                            Codewords[ codeword_index ].bits.len = tmplen;
-                            Codewords[ codeword_index ].bits.bufa = Segment[ segment_index ].bufa;
-                            Codewords[ codeword_index ].bits.bufb = Segment[ segment_index ].bufb;
-                        }
-                    }                        
-                }
-            } /* of codewordBase */
-
-            if (set_decoded == 0) break;	/* no undecoded codewords left in this set */
-
-        } /* of trial */
+                    if (codeword[codeword_idx].bits.len != 0)                   
+                        concat_bits(&segment[segment_idx], &codeword[codeword_idx].bits);                            
+                    
+                    tmplen = segment[segment_idx].len;
 
-        /* rewind all bits in remaining segments with len>0 */
-        for (i=0; i < numberOfSegments; i++)
-            rewind_bits( &Segment[ i ] );
-    }
-
-#if 0
-    {
-        int i, r=0, c=0;
-        for (i=0; i< numberOfSegments; i++)
-            r += Segment[ i ].len;
-        if (r != 0)
-        {
-            printf("reordered_spectral_data: %d bits remaining!\n", r);
-        }
-        for (i=0; i< NrCodeWords - numberOfSegments; i++)
-        {
-            if (Codewords[ i ].decoded == 0)
-            {
-                c++;
+                    if (huffman_spectral_data_2(codeword[codeword_idx].cb, &segment[segment_idx],
+                                               &spectral_data[codeword[codeword_idx].sp_offset]) >= 0)
+                    {
+                        codeword[codeword_idx].decoded = 1;
+                    } else 
+                    {   
+                        codeword[codeword_idx].bits = segment[segment_idx];
+                        codeword[codeword_idx].bits.len = tmplen;                        
+                    }
+                                            
+                }
             }
         }
-        if (c != 0)
-        {
-            printf("reordered_spectral_data: %d Undecoded Codewords remaining!\n",c );
-        }
-        if ((r !=0) || (c!=0))	return 10;
+        for (i = 0; i < numberOfSegments; i++)
+            rewrev_bits(&segment[i]);
     }
-#endif
 
     return 0;
 }
--- a/libfaad2/huffman.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/huffman.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: huffman.c,v 1.20 2004/03/10 19:45:41 menno Exp $
+** $Id: huffman.c,v 1.22 2004/09/04 14:56:28 menno Exp $
 **/
 
 #include "common.h"
@@ -50,6 +50,7 @@
 static uint8_t huffman_binary_pair(uint8_t cb, bitfile *ld, int16_t *sp);
 static uint8_t huffman_binary_pair_sign(uint8_t cb, bitfile *ld, int16_t *sp);
 static int16_t huffman_codebook(uint8_t i);
+static void vcb11_check_LAV(uint8_t cb, int16_t *sp);
 
 int8_t huffman_scale_factor(bitfile *ld)
 {
@@ -310,6 +311,26 @@
     else        return (int16_t)data & 0xFFFF;
 }
 
+static void vcb11_check_LAV(uint8_t cb, int16_t *sp)
+{
+    static const uint16_t vcb11_LAV_tab[] = {
+        16, 31, 47, 63, 95, 127, 159, 191, 223,
+        255, 319, 383, 511, 767, 1023, 2047
+    };
+    uint16_t max = 0;
+
+    if (cb < 16 || cb > 31)
+        return;
+
+    max = vcb11_LAV_tab[cb - 16];
+
+    if ((abs(sp[0]) > max) || (abs(sp[1]) > max))
+    {
+        sp[0] = 0;
+        sp[1] = 0;
+    }
+}
+
 uint8_t huffman_spectral_data(uint8_t cb, bitfile *ld, int16_t *sp)
 {
     switch (cb)
@@ -336,18 +357,28 @@
         sp[0] = huffman_codebook(0); sp[1] = huffman_codebook(1); 
         return err; }
     case 11:
-#ifdef ERROR_RESILIENCE
-    /* VCB11 uses codebook 11 */
-    case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23:
-    case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31:
-        /* TODO: If ER is used, some extra error checking should be done */
-#endif
     {
         uint8_t err = huffman_2step_pair_sign(11, ld, sp);
         sp[0] = huffman_getescape(ld, sp[0]);
         sp[1] = huffman_getescape(ld, sp[1]);
         return err;
     }
+#ifdef ERROR_RESILIENCE
+    /* VCB11 uses codebook 11 */
+    case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23:
+    case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31:
+    {
+        uint8_t err = huffman_2step_pair_sign(11, ld, sp);
+        sp[0] = huffman_getescape(ld, sp[0]);
+        sp[1] = huffman_getescape(ld, sp[1]);
+
+        /* check LAV (Largest Absolute Value) */
+        /* this finds errors in the ESCAPE signal */
+        vcb11_check_LAV(cb, sp);
+
+        return err;
+    }
+#endif
     default:
         /* Non existent codebook number, something went wrong */
         return 11;
@@ -369,7 +400,7 @@
     uint32_t cw;
     uint16_t offset = 0;
     uint8_t extra_bits;
-    uint8_t i;
+    uint8_t i, vcb11 = 0;
 
 
     switch (cb)
@@ -406,9 +437,12 @@
     case 16: case 17: case 18: case 19: case 20: case 21: case 22: case 23:
     case 24: case 25: case 26: case 27: case 28: case 29: case 30: case 31:
 
-        /* TODO: If ER is used, some extra error checking should be done */
         if (cb >= 16)
+        {
+            /* store the virtual codebook */
+            vcb11 = cb;
             cb = 11;
+        }
             
         cw = showbits_hcr(ld, hcbN[cb]);
         offset = hcb_table[cb][cw].offset;
@@ -463,8 +497,8 @@
     }
 
 	/* decode sign bits */
-    if (unsigned_cb[cb]) {
-
+    if (unsigned_cb[cb])
+    {
         for(i = 0; i < ((cb < FIRST_PAIR_HCB) ? QUAD_LEN : PAIR_LEN); i++)
         {
             if(sp[i])
@@ -500,13 +534,20 @@
                     if (b == 0)
                         break;
                 }
-// TODO: here we would need to test "off" if VCB11 is used!
+
                 if (getbits_hcr(ld, i, &off))
                     return -1;
                 j = off + (1<<i);
                 sp[k] = (int16_t)((neg) ? -j : j);
             }
         }
+
+        if (vcb11 != 0)
+        {
+            /* check LAV (Largest Absolute Value) */
+            /* this finds errors in the ESCAPE signal */
+            vcb11_check_LAV(vcb11, sp);
+        }
     }    
     return ld->len;
 }
--- a/libfaad2/huffman.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/huffman.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: huffman.h,v 1.22 2004/02/26 09:29:27 menno Exp $
+** $Id: huffman.h,v 1.24 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __HUFFMAN_H__
--- a/libfaad2/ic_predict.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/ic_predict.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: ic_predict.c,v 1.21 2004/02/26 09:29:27 menno Exp $
+** $Id: ic_predict.c,v 1.23 2004/09/04 14:56:28 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/ic_predict.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/ic_predict.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: ic_predict.h,v 1.17 2004/02/26 09:29:27 menno Exp $
+** $Id: ic_predict.h,v 1.19 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifdef MAIN_DEC
--- a/libfaad2/iq_table.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/iq_table.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: iq_table.h,v 1.14 2004/05/17 10:18:02 menno Exp $
+** $Id: iq_table.h,v 1.16 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef IQ_TABLE_H__
--- a/libfaad2/is.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/is.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: is.c,v 1.22 2004/04/03 10:49:14 menno Exp $
+** $Id: is.c,v 1.24 2004/09/04 14:56:28 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/is.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/is.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: is.h,v 1.14 2004/02/26 09:29:27 menno Exp $
+** $Id: is.h,v 1.16 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __IS_H__
--- a/libfaad2/kbd_win.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/kbd_win.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: kbd_win.h,v 1.15 2004/05/17 10:18:02 menno Exp $
+** $Id: kbd_win.h,v 1.17 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __KBD_WIN_H__
--- a/libfaad2/local_changes.diff	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/local_changes.diff	Tue Apr 18 19:39:34 2006 +0000
@@ -1,5 +1,16 @@
---- libfaad/bits.h	2004-03-11 14:32:39.000000000 +0100
-+++ libfaad2/bits.h	2004-06-24 10:47:02.000000000 +0200
+--- libfaad2.orig/bits.h	2006-03-16 20:15:04.000000000 +0100
++++ libfaad2/bits.h	2006-03-16 20:37:21.000000000 +0100
+@@ -22,7 +22,10 @@
+ ** Commercial non-GPL licensing of this software is possible.
+ ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
+ **
++** Initially modified for use with MPlayer by Arpad Gereöffy on 2003/08/30
+ ** $Id: bits.h,v 1.40 2004/09/04 14:56:27 menno Exp $
++** detailed CVS changelog at http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
++** local_changes.diff contains the exact changes to this file.
+ **/
+ 
+ #ifndef __BITS_H__
 @@ -58,7 +61,7 @@
  
  #if defined (_WIN32) && !defined(_WIN32_WCE) && !defined(__MINGW32__)
@@ -9,8 +20,19 @@
  #define BSWAP(a) __asm__ ( "bswapl %0\n" : "=r" (a) : "0" (a) )
  #else
  #define BSWAP(a) \
---- libfaad/common.h	2004-06-30 14:45:56.000000000 +0200
-+++ libfaad2/common.h	2004-10-19 03:16:03.000000000 +0200
+--- libfaad2.orig/common.h	2006-03-16 20:15:04.000000000 +0100
++++ libfaad2/common.h	2006-03-16 20:56:56.000000000 +0100
+@@ -22,7 +22,10 @@
+ ** Commercial non-GPL licensing of this software is possible.
+ ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
+ **
++** Initially modified for use with MPlayer by Arpad Gereöffy on 2003/08/30
+ ** $Id: common.h,v 1.65 2004/09/08 09:43:11 gcp Exp $
++** detailed CVS changelog at http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
++** local_changes.diff contains the exact changes to this file.
+ **/
+ 
+ #ifndef __COMMON_H__
 @@ -32,10 +35,13 @@
  extern "C" {
  #endif
@@ -27,7 +49,7 @@
  #define INLINE __inline
  #if 0 //defined(_WIN32) && !defined(_WIN32_WCE)
  #define ALIGN __declspec(align(16))
-@@ -67,6 +67,6 @@
+@@ -61,7 +67,7 @@
  /* Use if target platform has address generators with autoincrement */
  //#define PREFER_POINTERS
  
@@ -35,6 +57,7 @@
 +#if defined(_WIN32_WCE) || defined(__arm__)
  #define FIXED_POINT
  #endif
+ 
 @@ -117,6 +123,9 @@
  # ifdef MAIN_DEC
  #  undef MAIN_DEC
@@ -45,7 +68,7 @@
  #endif // FIXED_POINT
  
  #ifdef DRM
-@@ -157,6 +166,7 @@
+@@ -151,6 +160,7 @@
  
  #include <stdlib.h>
  
@@ -53,7 +76,7 @@
  typedef unsigned __int64 uint64_t;
  typedef unsigned __int32 uint32_t;
  typedef unsigned __int16 uint16_t;
-@@ -165,11 +175,31 @@
+@@ -159,11 +169,31 @@
  typedef __int32 int32_t;
  typedef __int16 int16_t;
  typedef __int8  int8_t;
@@ -85,7 +108,7 @@
  #include <stdio.h>
  #if HAVE_SYS_TYPES_H
  # include <sys/types.h>
-@@ -329,7 +329,7 @@
+@@ -289,7 +319,7 @@
    }
  
  
@@ -94,16 +117,16 @@
      #define HAS_LRINTF
      static INLINE int lrintf(float f)
      {
-@@ -341,7 +341,7 @@
+@@ -301,7 +331,7 @@
          }
          return i;
      }
--  #elif (defined(__i386__) && defined(__GNUC__)) && !defined(__MINGW32__)
-+  #elif (defined(__i386__) && defined(__GNUC__)) && !defined(__MINGW32__) && !defined(HAVE_LRINTF)
+-  #elif (defined(__i386__) && defined(__GNUC__))
++  #elif (defined(__i386__) && defined(__GNUC__)) && !defined(HAVE_LRINTF)
      #define HAS_LRINTF
      // from http://www.stereopsis.com/FPU.html
      static INLINE int lrintf(float f)
-@@ -340,6 +370,8 @@
+@@ -330,6 +360,8 @@
  
    #else
  
@@ -112,7 +135,7 @@
  #ifdef HAVE_LRINTF
  #  define HAS_LRINTF
  #  define _ISOC9X_SOURCE 1
-@@ -348,8 +380,6 @@
+@@ -338,8 +370,6 @@
  #  define __USE_ISOC99   1
  #endif
  
@@ -121,8 +144,8 @@
  #ifdef HAVE_SINF
  #  define sin sinf
  #error
---- libfaad2/output.c	2005/02/19 01:21:19	1.7
-+++ libfaad2/output.c	2005/03/29 18:14:24	1.8
+--- libfaad2.orig/output.c	2006-03-16 20:15:04.000000000 +0100
++++ libfaad2/output.c	2006-04-18 19:50:26.000000000 +0200
 @@ -19,10 +19,9 @@
  ** Any non-GPL usage of this software or parts of this software is strictly
  ** forbidden.
@@ -137,7 +160,7 @@
  **/
  
  #include "common.h"
-@@ -462,7 +462,7 @@
+@@ -463,7 +462,7 @@
      }
  }
  
@@ -146,7 +169,7 @@
                      real_t **input, void *sample_buffer, uint8_t channels,
                      uint16_t frame_len, uint8_t format)
  {
-@@ -553,4 +553,51 @@
+@@ -554,4 +553,51 @@
      return sample_buffer;
  }
  
@@ -186,7 +209,7 @@
 +    {
 +        for (ch = 0; ch < channels; ch++)
 +        {
-+            int32_t tmp = input[ch][i];
++            int32_t tmp = input[hDecoder->internal_channel[ch]][i];
 +            tmp += (1 << (REAL_BITS-1));
 +            tmp >>= REAL_BITS;
 +	    if ((tmp+0x8000) & ~0xffff) tmp = ~(tmp>>31)-0x8000;
@@ -198,9 +221,38 @@
 +}
 +
  #endif
---- libfaad/ps_dec.c	2005-02-01 14:15:58.000000000 +0100
-+++ libfaad2/ps_dec.c	2005-12-07 22:52:31.000000000 +0100
-@@ -1960,8 +1935,8 @@
+--- libfaad2.orig/ps_dec.c	2006-03-16 20:15:04.000000000 +0100
++++ libfaad2/ps_dec.c	2006-04-18 20:29:38.000000000 +0200
+@@ -22,7 +22,10 @@
+ ** Commercial non-GPL licensing of this software is possible.
+ ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
+ **
++** Initially modified for use with MPlayer on 2005/12/05
+ ** $Id: ps_dec.c,v 1.10 2004/09/04 14:56:28 menno Exp $
++** detailed CVS changelog at http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
++** local_changes.diff contains the exact changes to this file.
+ **/
+ 
+ #include "common.h"
+@@ -159,7 +162,7 @@
+ 
+ /* static function declarations */
+ static void ps_data_decode(ps_info *ps);
+-static hyb_info *hybrid_init();
++static hyb_info *hybrid_init(void);
+ static void channel_filter2(hyb_info *hyb, uint8_t frame_len, const real_t *filter,
+                             qmf_t *buffer, qmf_t **X_hybrid);
+ static void INLINE DCT3_4_unscaled(real_t *y, real_t *x);
+@@ -189,7 +192,7 @@
+ /*  */
+ 
+ 
+-static hyb_info *hybrid_init()
++static hyb_info *hybrid_init(void)
+ {
+     uint8_t i;
+ 
+@@ -1935,8 +1938,8 @@
  /* main Parametric Stereo decoding function */
  uint8_t ps_decode(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64])
  {
@@ -211,9 +263,20 @@
  
      /* delta decoding of the bitstream data */
      ps_data_decode(ps);
---- libfaad/sbr_dec.c	2005-12-07 22:52:03.000000000 +0100
-+++ libfaad2/sbr_dec.c	2005-12-07 22:52:31.000000000 +0100
-@@ -604,8 +527,8 @@
+--- libfaad2.orig/sbr_dec.c	2006-03-16 20:15:04.000000000 +0100
++++ libfaad2/sbr_dec.c	2006-04-18 20:33:57.000000000 +0200
+@@ -22,7 +22,10 @@
+ ** Commercial non-GPL licensing of this software is possible.
+ ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
+ **
++** Initially modified for use with MPlayer on 2005/12/05
+ ** $Id: sbr_dec.c,v 1.39 2004/09/04 14:56:28 menno Exp $
++** detailed CVS changelog at http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
++** local_changes.diff contains the exact changes to this file.
+ **/
+ 
+ 
+@@ -526,8 +529,8 @@
      uint8_t l, k;
      uint8_t dont_process = 0;
      uint8_t ret = 0;
@@ -224,3 +287,145 @@
  
      if (sbr == NULL)
          return 20;
+--- libfaad2.orig/specrec.c	2006-03-16 20:15:04.000000000 +0100
++++ libfaad2/specrec.c	2006-04-18 20:38:09.000000000 +0200
+@@ -19,10 +19,10 @@
+ ** Any non-GPL usage of this software or parts of this software is strictly
+ ** forbidden.
+ **
+-** Commercial non-GPL licensing of this software is possible.
+-** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
+-**
++** Initially modified for use with MPlayer on 2006/04/18
+ ** $Id: specrec.c,v 1.56 2004/09/08 09:43:11 gcp Exp $
++** detailed CVS changelog at http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
++** local_changes.diff contains the exact changes to this file.
+ **/
+ 
+ /*
+@@ -673,29 +673,19 @@
+     /* MAIN object type prediction */
+     if (hDecoder->object_type == MAIN)
+     {
+-        /* allocate the state only when needed */
+-        if (hDecoder->pred_stat[channel] == NULL)
+-        {
+-            hDecoder->pred_stat[channel] = (pred_state*)faad_malloc(hDecoder->frameLength * sizeof(pred_state));
++            hDecoder->pred_stat[channel] = (pred_state*)realloc(hDecoder->pred_stat[channel], hDecoder->frameLength * sizeof(pred_state));
+             reset_all_predictors(hDecoder->pred_stat[channel], hDecoder->frameLength);
+-        }
+     }
+ #endif
+ 
+ #ifdef LTP_DEC
+     if (is_ltp_ot(hDecoder->object_type))
+     {
+-        /* allocate the state only when needed */
+-        if (hDecoder->lt_pred_stat[channel] == NULL)
+-        {
+-            hDecoder->lt_pred_stat[channel] = (int16_t*)faad_malloc(hDecoder->frameLength*4 * sizeof(int16_t));
++            hDecoder->lt_pred_stat[channel] = (int16_t*)realloc(hDecoder->lt_pred_stat[channel], hDecoder->frameLength*4 * sizeof(int16_t));
+             memset(hDecoder->lt_pred_stat[channel], 0, hDecoder->frameLength*4 * sizeof(int16_t));
+-        }
+     }
+ #endif
+ 
+-    if (hDecoder->time_out[channel] == NULL)
+-    {
+         mul = 1;
+ #ifdef SBR_DEC
+         hDecoder->sbr_alloced[hDecoder->fr_ch_ele] = 0;
+@@ -706,41 +696,28 @@
+             hDecoder->sbr_alloced[hDecoder->fr_ch_ele] = 1;
+         }
+ #endif
+-        hDecoder->time_out[channel] = (real_t*)faad_malloc(mul*hDecoder->frameLength*sizeof(real_t));
++        hDecoder->time_out[channel] = (real_t*)realloc(hDecoder->time_out[channel], mul*hDecoder->frameLength*sizeof(real_t));
+         memset(hDecoder->time_out[channel], 0, mul*hDecoder->frameLength*sizeof(real_t));
+-    }
+ #if (defined(PS_DEC) || defined(DRM_PS))
+     if (output_channels == 2)
+     {
+-        if (hDecoder->time_out[channel+1] == NULL)
+-        {
+-            hDecoder->time_out[channel+1] = (real_t*)faad_malloc(mul*hDecoder->frameLength*sizeof(real_t));
++            hDecoder->time_out[channel+1] = (real_t*)realloc(hDecoder->time_out[channel+1], mul*hDecoder->frameLength*sizeof(real_t));
+             memset(hDecoder->time_out[channel+1], 0, mul*hDecoder->frameLength*sizeof(real_t));
+-        }
+     }
+ #endif
+ 
+-    if (hDecoder->fb_intermed[channel] == NULL)
+-    {
+-        hDecoder->fb_intermed[channel] = (real_t*)faad_malloc(hDecoder->frameLength*sizeof(real_t));
++        hDecoder->fb_intermed[channel] = (real_t*)realloc(hDecoder->fb_intermed[channel], hDecoder->frameLength*sizeof(real_t));
+         memset(hDecoder->fb_intermed[channel], 0, hDecoder->frameLength*sizeof(real_t));
+-    }
+ 
+ #ifdef SSR_DEC
+     if (hDecoder->object_type == SSR)
+     {
+-        if (hDecoder->ssr_overlap[channel] == NULL)
+-        {
+-            hDecoder->ssr_overlap[channel] = (real_t*)faad_malloc(2*hDecoder->frameLength*sizeof(real_t));
+-            memset(hDecoder->ssr_overlap[channel], 0, 2*hDecoder->frameLength*sizeof(real_t));
+-        }
+-        if (hDecoder->prev_fmd[channel] == NULL)
+-        {
+             uint16_t k;
+-            hDecoder->prev_fmd[channel] = (real_t*)faad_malloc(2*hDecoder->frameLength*sizeof(real_t));
++            hDecoder->ssr_overlap[channel] = (real_t*)realloc(hDecoder->ssr_overlap[channel], 2*hDecoder->frameLength*sizeof(real_t));
++            memset(hDecoder->ssr_overlap[channel], 0, 2*hDecoder->frameLength*sizeof(real_t));
++            hDecoder->prev_fmd[channel] = (real_t*)realloc(hDecoder->prev_fmd[channel], 2*hDecoder->frameLength*sizeof(real_t));
+             for (k = 0; k < 2*hDecoder->frameLength; k++)
+                 hDecoder->prev_fmd[channel][k] = REAL_CONST(-1);
+-        }
+     }
+ #endif
+ 
+@@ -865,22 +842,13 @@
+ 
+     /* always allocate 2 channels, PS can always "suddenly" turn up */
+ #if (defined(PS_DEC) || defined(DRM_PS))
+-    output_channels = 2;
++    output_channels = hDecoder->ps_used[hDecoder->fr_ch_ele] ? 2 : 1;
+ #else
+     output_channels = 1;
+ #endif
+ 
+-    if (hDecoder->element_output_channels[hDecoder->fr_ch_ele] == 0)
+-    {
+-        /* element_output_channels not set yet */
++    if (hDecoder->element_output_channels[hDecoder->fr_ch_ele] < output_channels) {
+         hDecoder->element_output_channels[hDecoder->fr_ch_ele] = output_channels;
+-    } else if (hDecoder->element_output_channels[hDecoder->fr_ch_ele] != output_channels) {
+-        /* element inconsistency */
+-        return 21;
+-    }
+-
+-    if (hDecoder->element_alloced[hDecoder->fr_ch_ele] == 0)
+-    {
+         retval = allocate_single_channel(hDecoder, sce->channel, output_channels);
+         if (retval > 0)
+             return retval;
+@@ -1026,11 +994,10 @@
+     {
+         return 23;
+     }
+-#endif
+ 
+     /* copy L to R when no PS is used */
+ #if (defined(PS_DEC) || defined(DRM_PS))
+-    if ((hDecoder->ps_used[hDecoder->fr_ch_ele] == 0))
++    if ((hDecoder->ps_used[hDecoder->fr_ch_ele] == 0) && (output_channels == 2))
+     {
+         uint8_t ele = hDecoder->fr_ch_ele;
+         uint8_t ch = sce->channel;
+@@ -1040,6 +1007,7 @@
+         memcpy(hDecoder->time_out[ch+1], hDecoder->time_out[ch], frame_size);
+     }
+ #endif
++#endif
+ 
+     return 0;
+ }
--- a/libfaad2/lt_predict.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/lt_predict.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: lt_predict.c,v 1.21 2004/02/26 09:29:27 menno Exp $
+** $Id: lt_predict.c,v 1.23 2004/09/04 14:56:28 menno Exp $
 **/
 
 
--- a/libfaad2/lt_predict.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/lt_predict.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: lt_predict.h,v 1.14 2004/02/26 09:29:27 menno Exp $
+** $Id: lt_predict.h,v 1.16 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifdef LTP_DEC
--- a/libfaad2/mdct.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/mdct.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: mdct.c,v 1.41 2004/06/30 12:45:56 menno Exp $
+** $Id: mdct.c,v 1.43 2004/09/04 14:56:28 menno Exp $
 **/
 
 /*
--- a/libfaad2/mdct.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/mdct.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: mdct.h,v 1.23 2004/02/26 09:29:27 menno Exp $
+** $Id: mdct.h,v 1.26 2004/09/08 09:43:11 gcp Exp $
 **/
 
 #ifndef __MDCT_H__
@@ -36,9 +36,6 @@
 mdct_info *faad_mdct_init(uint16_t N);
 void faad_mdct_end(mdct_info *mdct);
 void faad_imdct(mdct_info *mdct, real_t *X_in, real_t *X_out);
-#ifdef USE_SSE
-void faad_imdct_sse(mdct_info *mdct, real_t *X_in, real_t *X_out);
-#endif
 void faad_mdct(mdct_info *mdct, real_t *X_in, real_t *X_out);
 
 
--- a/libfaad2/mdct_tab.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/mdct_tab.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: mdct_tab.h,v 1.1 2004/05/17 20:32:45 menno Exp $
+** $Id: mdct_tab.h,v 1.3 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __MDCT_TAB_H__
--- a/libfaad2/mp4.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/mp4.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: mp4.c,v 1.30 2004/05/17 10:18:03 menno Exp $
+** $Id: mp4.c,v 1.32 2004/09/04 14:56:28 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/mp4.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/mp4.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: mp4.h,v 1.19 2004/03/02 20:09:58 menno Exp $
+** $Id: mp4.h,v 1.21 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __MP4_H__
--- a/libfaad2/ms.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/ms.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: ms.c,v 1.15 2004/04/03 10:49:14 menno Exp $
+** $Id: ms.c,v 1.17 2004/09/04 14:56:28 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/ms.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/ms.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: ms.h,v 1.13 2004/02/26 09:29:27 menno Exp $
+** $Id: ms.h,v 1.15 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __MS_H__
--- a/libfaad2/neaacdec.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/neaacdec.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: neaacdec.h,v 1.4 2004/04/03 10:49:14 menno Exp $
+** $Id: neaacdec.h,v 1.5 2004/09/04 14:56:27 menno Exp $
 **/
 
 #ifndef __NEAACDEC_H__
@@ -189,6 +189,9 @@
     unsigned char num_back_channels;
     unsigned char num_lfe_channels;
     unsigned char channel_position[64];
+
+    /* PS: 0: off, 1: on */
+    unsigned char ps;
 } NeAACDecFrameInfo;
 
 char* NEAACDECAPI NeAACDecGetErrorMessage(unsigned char errcode);
@@ -227,6 +230,13 @@
                                  unsigned char *buffer,
                                  unsigned long buffer_size);
 
+void* NEAACDECAPI NeAACDecDecode2(NeAACDecHandle hDecoder,
+                                  NeAACDecFrameInfo *hInfo,
+                                  unsigned char *buffer,
+                                  unsigned long buffer_size,
+                                  void **sample_buffer,
+                                  unsigned long sample_buffer_size);
+
 char NEAACDECAPI NeAACDecAudioSpecificConfig(unsigned char *pBuffer,
                                              unsigned long buffer_size,
                                              mp4AudioSpecificConfig *mp4ASC);
--- a/libfaad2/output.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/output.c	Tue Apr 18 19:39:34 2006 +0000
@@ -589,7 +589,7 @@
     {
         for (ch = 0; ch < channels; ch++)
         {
-            int32_t tmp = input[ch][i];
+            int32_t tmp = input[hDecoder->internal_channel[ch]][i];
             tmp += (1 << (REAL_BITS-1));
             tmp >>= REAL_BITS;
 	    if ((tmp+0x8000) & ~0xffff) tmp = ~(tmp>>31)-0x8000;
--- a/libfaad2/output.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/output.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: output.h,v 1.19 2004/03/02 20:09:58 menno Exp $
+** $Id: output.h,v 1.21 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __OUTPUT_H__
--- a/libfaad2/pns.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/pns.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: pns.c,v 1.32 2004/04/03 10:49:14 menno Exp $
+** $Id: pns.c,v 1.34 2004/09/04 14:56:28 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/pns.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/pns.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: pns.h,v 1.21 2004/04/03 10:49:14 menno Exp $
+** $Id: pns.h,v 1.23 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __PNS_H__
--- a/libfaad2/ps_dec.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/ps_dec.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,10 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: ps_dec.c,v 1.8 2004/06/30 12:45:56 menno Exp $
+** Initially modified for use with MPlayer on 2005/12/05
+** $Id: ps_dec.c,v 1.10 2004/09/04 14:56:28 menno Exp $
+** detailed CVS changelog at http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
+** local_changes.diff contains the exact changes to this file.
 **/
 
 #include "common.h"
--- a/libfaad2/ps_dec.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/ps_dec.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: ps_dec.h,v 1.5 2004/05/17 10:18:03 menno Exp $
+** $Id: ps_dec.h,v 1.8 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __PS_DEC_H__
@@ -83,6 +83,9 @@
     /* ps data was correctly read */
     uint8_t ps_data_available;
 
+    /* a header has been read */
+    uint8_t header_read;
+
     /* hybrid filterbank parameters */
     void *hyb;
     uint8_t use34hybrid_bands;
@@ -129,7 +132,7 @@
 } ps_info;
 
 /* ps_syntax.c */
-uint16_t ps_data(ps_info *ps, bitfile *ld);
+uint16_t ps_data(ps_info *ps, bitfile *ld, uint8_t *header);
 
 /* ps_dec.c */
 ps_info *ps_init(uint8_t sr_index);
--- a/libfaad2/ps_syntax.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/ps_syntax.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: ps_syntax.c,v 1.3 2004/06/30 12:45:56 menno Exp $
+** $Id: ps_syntax.c,v 1.6 2004/09/04 14:56:28 menno Exp $
 **/
 
 #include "common.h"
@@ -322,15 +322,21 @@
 static INLINE int8_t ps_huff_dec(bitfile *ld, ps_huff_tab t_huff);
 
 
-uint16_t ps_data(ps_info *ps, bitfile *ld)
+uint16_t ps_data(ps_info *ps, bitfile *ld, uint8_t *header)
 {
     uint8_t tmp, n;
     uint16_t bits = (uint16_t)faad_get_processed_bits(ld);
 
+    *header = 0;
+
     /* check for new PS header */
     if (faad_get1bit(ld
         DEBUGVAR(1,1000,"ps_data(): enable_ps_header")))
     {
+        *header = 1;
+
+        ps->header_read = 1;
+
         ps->use34hybrid_bands = 0;
 
         /* Inter-channel Intensity Difference (IID) parameters enabled */
@@ -372,6 +378,10 @@
             DEBUGVAR(1,1005,"ps_data(): enable_ext"));
     }
 
+    /* we are here, but no header has been read yet */
+    if (ps->header_read == 0)
+        return 1;
+
     ps->frame_class = (uint8_t)faad_get1bit(ld
         DEBUGVAR(1,1006,"ps_data(): frame_class"));
     tmp = (uint8_t)faad_getbits(ld, 2
--- a/libfaad2/ps_tables.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/ps_tables.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: ps_tables.h,v 1.1 2004/03/19 10:37:56 menno Exp $
+** $Id: ps_tables.h,v 1.3 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __PS_TABLES_H__
--- a/libfaad2/pulse.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/pulse.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: pulse.c,v 1.15 2004/02/26 09:29:27 menno Exp $
+** $Id: pulse.c,v 1.17 2004/09/04 14:56:28 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/pulse.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/pulse.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: pulse.h,v 1.14 2004/02/26 09:29:27 menno Exp $
+** $Id: pulse.h,v 1.16 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __PULSE_H__
--- a/libfaad2/rvlc.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/rvlc.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: rvlc.c,v 1.15 2004/02/26 09:29:27 menno Exp $
+** $Id: rvlc.c,v 1.17 2004/09/04 14:56:28 menno Exp $
 **/
 
 /* RVLC scalefactor decoding
--- a/libfaad2/rvlc.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/rvlc.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: rvlc.h,v 1.11 2004/02/26 09:29:27 menno Exp $
+** $Id: rvlc.h,v 1.13 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __RVLC_SCF_H__
--- a/libfaad2/sbr_dct.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_dct.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_dct.c,v 1.13 2004/06/30 12:45:56 menno Exp $
+** $Id: sbr_dct.c,v 1.15 2004/09/04 14:56:28 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/sbr_dct.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_dct.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_dct.h,v 1.13 2004/06/30 12:45:56 menno Exp $
+** $Id: sbr_dct.h,v 1.15 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __SBR_DCT_H__
--- a/libfaad2/sbr_dec.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_dec.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,10 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_dec.c,v 1.37 2004/06/30 12:45:56 menno Exp $
+** Initially modified for use with MPlayer on 2005/12/05
+** $Id: sbr_dec.c,v 1.39 2004/09/04 14:56:28 menno Exp $
+** detailed CVS changelog at http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
+** local_changes.diff contains the exact changes to this file.
 **/
 
 
@@ -79,7 +82,6 @@
 #ifdef DRM
     sbr->Is_DRM_SBR = IsDRM;
 #endif
-    sbr->bs_samplerate_mode = 1;
     sbr->tHFGen = T_HFGEN;
     sbr->tHFAdj = T_HFADJ;
 
@@ -575,7 +577,7 @@
 #ifdef DRM_PS
     if (sbr->Is_DRM_SBR)
     {
-        drm_ps_decode(sbr->drm_ps, sbr->sample_rate, X_left, X_right);
+        drm_ps_decode(sbr->drm_ps, (sbr->ret > 0), sbr->sample_rate, X_left, X_right);
     } else {
 #endif
 #ifdef PS_DEC
--- a/libfaad2/sbr_dec.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_dec.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_dec.h,v 1.33 2004/06/30 12:45:57 menno Exp $
+** $Id: sbr_dec.h,v 1.35 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __SBR_DEC_H__
--- a/libfaad2/sbr_e_nf.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_e_nf.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_e_nf.c,v 1.15 2004/05/17 10:18:03 menno Exp $
+** $Id: sbr_e_nf.c,v 1.17 2004/09/04 14:56:28 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/sbr_e_nf.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_e_nf.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_e_nf.h,v 1.12 2004/05/17 10:18:03 menno Exp $
+** $Id: sbr_e_nf.h,v 1.14 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __SBR_E_NF_H__
--- a/libfaad2/sbr_fbt.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_fbt.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_fbt.c,v 1.14 2004/05/17 10:18:03 menno Exp $
+** $Id: sbr_fbt.c,v 1.17 2004/09/08 09:43:11 gcp Exp $
 **/
 
 /* Calculate frequency band tables */
@@ -197,7 +197,7 @@
     if (k2 <= k0)
     {
         sbr->N_master = 0;
-        return 0;
+        return 1;
     }
 
     dk = bs_alter_scale ? 2 : 1;
@@ -363,7 +363,7 @@
     if (k2 <= k0)
     {
         sbr->N_master = 0;
-        return 0;
+        return 1;
     }
 
     bands = temp1[bs_freq_scale-1];
--- a/libfaad2/sbr_fbt.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_fbt.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_fbt.h,v 1.12 2004/03/10 19:45:41 menno Exp $
+** $Id: sbr_fbt.h,v 1.14 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __SBR_FBT_H__
--- a/libfaad2/sbr_hfadj.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_hfadj.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_hfadj.c,v 1.16 2004/06/30 12:45:57 menno Exp $
+** $Id: sbr_hfadj.c,v 1.18 2004/09/04 14:56:28 menno Exp $
 **/
 
 /* High Frequency adjustment */
--- a/libfaad2/sbr_hfadj.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_hfadj.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_hfadj.h,v 1.13 2004/05/17 10:18:03 menno Exp $
+** $Id: sbr_hfadj.h,v 1.15 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __SBR_HFADJ_H__
--- a/libfaad2/sbr_hfgen.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_hfgen.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_hfgen.c,v 1.19 2004/06/30 12:45:57 menno Exp $
+** $Id: sbr_hfgen.c,v 1.22 2004/09/08 09:43:11 gcp Exp $
 **/
 
 /* High Frequency generation */
@@ -617,6 +617,15 @@
         k = sbr->N_master;
     }
 
+    if (sbr->N_master == 0)
+    {
+        sbr->noPatches = 0;
+        sbr->patchNoSubbands[0] = 0;
+        sbr->patchStartSubband[0] = 0;
+
+        return;
+    }
+
     do
     {
         uint8_t j = k + 1;
--- a/libfaad2/sbr_hfgen.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_hfgen.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_hfgen.h,v 1.14 2004/06/30 12:45:57 menno Exp $
+** $Id: sbr_hfgen.h,v 1.16 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __SBR_HFGEN_H__
--- a/libfaad2/sbr_huff.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_huff.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_huff.c,v 1.15 2004/03/10 19:45:42 menno Exp $
+** $Id: sbr_huff.c,v 1.17 2004/09/04 14:56:28 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/sbr_huff.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_huff.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_huff.h,v 1.15 2004/03/10 19:45:42 menno Exp $
+** $Id: sbr_huff.h,v 1.17 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __SBR_HUFF_H__
--- a/libfaad2/sbr_noise.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_noise.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_noise.h,v 1.11 2004/03/10 19:45:42 menno Exp $
+** $Id: sbr_noise.h,v 1.13 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __SBR_NOISE_H__
--- a/libfaad2/sbr_qmf.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_qmf.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_qmf.c,v 1.25 2004/06/30 12:45:57 menno Exp $
+** $Id: sbr_qmf.c,v 1.27 2004/09/04 14:56:28 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/sbr_qmf.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_qmf.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_qmf.h,v 1.18 2004/06/30 12:45:57 menno Exp $
+** $Id: sbr_qmf.h,v 1.21 2004/09/08 09:43:11 gcp Exp $
 **/
 
 #ifndef __SBR_QMF_H__
@@ -43,10 +43,6 @@
                           real_t *output);
 void sbr_qmf_synthesis_64(sbr_info *sbr, qmfs_info *qmfs, qmf_t X[MAX_NTSRHFG][64],
                           real_t *output);
-#ifdef USE_SSE
-void sbr_qmf_synthesis_64_sse(sbr_info *sbr, qmfs_info *qmfs, qmf_t X[MAX_NTSRHFG][64],
-                              real_t *output);
-#endif
 
 
 #ifdef __cplusplus
--- a/libfaad2/sbr_qmf_c.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_qmf_c.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_qmf_c.h,v 1.11 2004/03/10 19:45:42 menno Exp $
+** $Id: sbr_qmf_c.h,v 1.13 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __SBR_QMF_C_H__
--- a/libfaad2/sbr_syntax.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_syntax.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_syntax.c,v 1.31 2004/05/17 10:18:03 menno Exp $
+** $Id: sbr_syntax.c,v 1.34 2004/09/04 14:56:28 menno Exp $
 **/
 
 #include "common.h"
@@ -76,16 +76,6 @@
     if ((sbr->bs_start_freq != sbr->bs_start_freq_prev) ||
         (sbr->bs_stop_freq != sbr->bs_stop_freq_prev) ||
         (sbr->bs_freq_scale != sbr->bs_freq_scale_prev) ||
-        (sbr->bs_alter_scale != sbr->bs_alter_scale_prev))
-    {
-        sbr->Reset = 1;
-    } else {
-        sbr->Reset = 0;
-    }
-
-    if ((sbr->bs_start_freq != sbr->bs_start_freq_prev) ||
-        (sbr->bs_stop_freq != sbr->bs_stop_freq_prev) ||
-        (sbr->bs_freq_scale != sbr->bs_freq_scale_prev) ||
         (sbr->bs_alter_scale != sbr->bs_alter_scale_prev) ||
         (sbr->bs_xover_band != sbr->bs_xover_band_prev) ||
         (sbr->bs_noise_bands != sbr->bs_noise_bands_prev))
@@ -401,6 +391,9 @@
     if (sbr->bs_extended_data)
     {
         uint16_t nr_bits_left;
+#if (defined(PS_DEC) || defined(DRM_PS))
+        uint8_t ps_ext_read = 0;
+#endif
         uint16_t cnt = (uint16_t)faad_getbits(ld, 4
             DEBUGVAR(1,225,"sbr_single_channel_element(): bs_extension_size"));
         if (cnt == 15)
@@ -417,6 +410,32 @@
             sbr->bs_extension_id = (uint8_t)faad_getbits(ld, 2
                 DEBUGVAR(1,227,"sbr_single_channel_element(): bs_extension_id"));
             tmp_nr_bits += 2;
+
+            /* allow only 1 PS extension element per extension data */
+#if (defined(PS_DEC) || defined(DRM_PS))
+#if (defined(PS_DEC) && defined(DRM_PS))
+            if (sbr->bs_extension_id == EXTENSION_ID_PS || sbr->bs_extension_id == DRM_PARAMETRIC_STEREO)
+#else
+#ifdef PS_DEC
+            if (sbr->bs_extension_id == EXTENSION_ID_PS)
+#else
+#ifdef DRM_PS
+            if (sbr->bs_extension_id == DRM_PARAMETRIC_STEREO)
+#endif
+#endif
+#endif
+            {
+                if (ps_ext_read == 0)
+                {
+                    ps_ext_read = 1;
+                } else {
+                    /* to be safe make it 3, will switch to "default"
+                     * in sbr_extension() */
+                    sbr->bs_extension_id = 3;
+                }
+            }
+#endif
+
             tmp_nr_bits += sbr_extension(ld, sbr, sbr->bs_extension_id, nr_bits_left);
 
             /* check if the data read is bigger than the number of available bits */
@@ -797,16 +816,28 @@
 static uint16_t sbr_extension(bitfile *ld, sbr_info *sbr,
                               uint8_t bs_extension_id, uint16_t num_bits_left)
 {
+#ifdef PS_DEC
+    uint8_t header;
+    uint16_t ret;
+#endif
+
     switch (bs_extension_id)
     {
 #ifdef PS_DEC
     case EXTENSION_ID_PS:
-        sbr->ps_used = 1;
         if (!sbr->ps)
         {
             sbr->ps = ps_init(get_sr_index(sbr->sample_rate));
         }
-        return ps_data(sbr->ps, ld);
+        ret = ps_data(sbr->ps, ld, &header);
+
+        /* enable PS if and only if: a header has been decoded */
+        if (sbr->ps_used == 0 && header == 1)
+        {
+            sbr->ps_used = 1;
+        }
+
+        return ret;
 #endif
 #ifdef DRM_PS
     case DRM_PARAMETRIC_STEREO:
--- a/libfaad2/sbr_syntax.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_syntax.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_syntax.h,v 1.17 2004/03/10 19:45:42 menno Exp $
+** $Id: sbr_syntax.h,v 1.19 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __SBR_SYNTAX_H__
--- a/libfaad2/sbr_tf_grid.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_tf_grid.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_tf_grid.c,v 1.13 2004/03/19 10:37:55 menno Exp $
+** $Id: sbr_tf_grid.c,v 1.15 2004/09/04 14:56:28 menno Exp $
 **/
 
 /* Time/Frequency grid */
--- a/libfaad2/sbr_tf_grid.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sbr_tf_grid.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sbr_tf_grid.h,v 1.11 2004/03/10 19:45:42 menno Exp $
+** $Id: sbr_tf_grid.h,v 1.13 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __SBR_TF_GRID_H__
--- a/libfaad2/sine_win.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/sine_win.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: sine_win.h,v 1.13 2004/05/17 10:18:03 menno Exp $
+** $Id: sine_win.h,v 1.15 2004/09/04 14:56:28 menno Exp $
 **/
 
 #ifndef __SINE_WIN_H__
--- a/libfaad2/specrec.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/specrec.c	Tue Apr 18 19:39:34 2006 +0000
@@ -19,10 +19,10 @@
 ** Any non-GPL usage of this software or parts of this software is strictly
 ** forbidden.
 **
-** Commercial non-GPL licensing of this software is possible.
-** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
-**
-** $Id: specrec.c,v 1.51 2004/06/30 12:45:57 menno Exp $
+** Initially modified for use with MPlayer on 2006/04/18
+** $Id: specrec.c,v 1.56 2004/09/08 09:43:11 gcp Exp $
+** detailed CVS changelog at http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
+** local_changes.diff contains the exact changes to this file.
 **/
 
 /*
@@ -544,9 +544,11 @@
     const real_t *tab = iq_table;
 
     uint8_t g, sfb, win;
-    uint16_t width, bin, k, gindex;
+    uint16_t width, bin, k, gindex, wa, wb;
     uint8_t error = 0; /* Init error flag */
-
+#ifndef FIXED_POINT
+    real_t scf;
+#endif
 
     k = 0;
     gindex = 0;
@@ -590,57 +592,69 @@
             }
 #endif
 
+            wa = gindex + j;
+
+#ifndef FIXED_POINT
+            scf = pow2sf_tab[exp/*+25*/] * pow2_table[frac];
+#endif
+
             for (win = 0; win < ics->window_group_length[g]; win++)
             {
                 for (bin = 0; bin < width; bin += 4)
                 {
 #ifndef FIXED_POINT
-                    spec_data[gindex+(win*win_inc)+j+bin+0] = iquant(quant_data[k+0], tab, &error) *
-                        pow2sf_tab[exp/*+25*/] * pow2_table[frac];
-                    spec_data[gindex+(win*win_inc)+j+bin+1] = iquant(quant_data[k+1], tab, &error) *
-                        pow2sf_tab[exp/*+25*/] * pow2_table[frac];
-                    spec_data[gindex+(win*win_inc)+j+bin+2] = iquant(quant_data[k+2], tab, &error) *
-                        pow2sf_tab[exp/*+25*/] * pow2_table[frac];
-                    spec_data[gindex+(win*win_inc)+j+bin+3] = iquant(quant_data[k+3], tab, &error) *
-                        pow2sf_tab[exp/*+25*/] * pow2_table[frac];
+                    wb = wa + bin;
+
+                    spec_data[wb+0] = iquant(quant_data[k+0], tab, &error) * scf;
+                    spec_data[wb+1] = iquant(quant_data[k+1], tab, &error) * scf;                        
+                    spec_data[wb+2] = iquant(quant_data[k+2], tab, &error) * scf;                        
+                    spec_data[wb+3] = iquant(quant_data[k+3], tab, &error) * scf;
+                        
 #else
                     real_t iq0 = iquant(quant_data[k+0], tab, &error);
                     real_t iq1 = iquant(quant_data[k+1], tab, &error);
                     real_t iq2 = iquant(quant_data[k+2], tab, &error);
                     real_t iq3 = iquant(quant_data[k+3], tab, &error);
+
+                    wb = wa + bin;
+
                     if (exp < 0)
                     {
-                        spec_data[gindex+(win*win_inc)+j+bin+0] = iq0 >>= -exp;
-                        spec_data[gindex+(win*win_inc)+j+bin+1] = iq1 >>= -exp;
-                        spec_data[gindex+(win*win_inc)+j+bin+2] = iq2 >>= -exp;
-                        spec_data[gindex+(win*win_inc)+j+bin+3] = iq3 >>= -exp;
+                        spec_data[wb+0] = iq0 >>= -exp;
+                        spec_data[wb+1] = iq1 >>= -exp;
+                        spec_data[wb+2] = iq2 >>= -exp;
+                        spec_data[wb+3] = iq3 >>= -exp;
                     } else {
-                        spec_data[gindex+(win*win_inc)+j+bin+0] = iq0 <<= exp;
-                        spec_data[gindex+(win*win_inc)+j+bin+1] = iq1 <<= exp;
-                        spec_data[gindex+(win*win_inc)+j+bin+2] = iq2 <<= exp;
-                        spec_data[gindex+(win*win_inc)+j+bin+3] = iq3 <<= exp;
+                        spec_data[wb+0] = iq0 <<= exp;
+                        spec_data[wb+1] = iq1 <<= exp;
+                        spec_data[wb+2] = iq2 <<= exp;
+                        spec_data[wb+3] = iq3 <<= exp;
                     }
-                    spec_data[gindex+(win*win_inc)+j+bin+0] = MUL_C(spec_data[gindex+(win*win_inc)+j+bin+0],pow2_table[frac]);
-                    spec_data[gindex+(win*win_inc)+j+bin+1] = MUL_C(spec_data[gindex+(win*win_inc)+j+bin+1],pow2_table[frac]);
-                    spec_data[gindex+(win*win_inc)+j+bin+2] = MUL_C(spec_data[gindex+(win*win_inc)+j+bin+2],pow2_table[frac]);
-                    spec_data[gindex+(win*win_inc)+j+bin+3] = MUL_C(spec_data[gindex+(win*win_inc)+j+bin+3],pow2_table[frac]);
+                    if (frac != 0)
+                    {
+                        spec_data[wb+0] = MUL_C(spec_data[wb+0],pow2_table[frac]);
+                        spec_data[wb+1] = MUL_C(spec_data[wb+1],pow2_table[frac]);
+                        spec_data[wb+2] = MUL_C(spec_data[wb+2],pow2_table[frac]);
+                        spec_data[wb+3] = MUL_C(spec_data[wb+3],pow2_table[frac]);
+                    }
 
 //#define SCFS_PRINT
 #ifdef SCFS_PRINT
-                    //printf("%d\n", spec_data[gindex+(win*win_inc)+j+bin+0]);
-                    //printf("%d\n", spec_data[gindex+(win*win_inc)+j+bin+1]);
-                    //printf("%d\n", spec_data[gindex+(win*win_inc)+j+bin+2]);
-                    //printf("%d\n", spec_data[gindex+(win*win_inc)+j+bin+3]);
-                    printf("0x%.8X\n", spec_data[gindex+(win*win_inc)+j+bin+0]);
-                    printf("0x%.8X\n", spec_data[gindex+(win*win_inc)+j+bin+1]);
-                    printf("0x%.8X\n", spec_data[gindex+(win*win_inc)+j+bin+2]);
-                    printf("0x%.8X\n", spec_data[gindex+(win*win_inc)+j+bin+3]);
+                    printf("%d\n", spec_data[gindex+(win*win_inc)+j+bin+0]);
+                    printf("%d\n", spec_data[gindex+(win*win_inc)+j+bin+1]);
+                    printf("%d\n", spec_data[gindex+(win*win_inc)+j+bin+2]);
+                    printf("%d\n", spec_data[gindex+(win*win_inc)+j+bin+3]);
+                    //printf("0x%.8X\n", spec_data[gindex+(win*win_inc)+j+bin+0]);
+                    //printf("0x%.8X\n", spec_data[gindex+(win*win_inc)+j+bin+1]);
+                    //printf("0x%.8X\n", spec_data[gindex+(win*win_inc)+j+bin+2]);
+                    //printf("0x%.8X\n", spec_data[gindex+(win*win_inc)+j+bin+3]);
 #endif
 #endif
 
                     gincrease += 4;
                     k += 4;
                 }
+                wa += win_inc;
             }
             j += width;
         }
@@ -659,29 +673,19 @@
     /* MAIN object type prediction */
     if (hDecoder->object_type == MAIN)
     {
-        /* allocate the state only when needed */
-        if (hDecoder->pred_stat[channel] == NULL)
-        {
-            hDecoder->pred_stat[channel] = (pred_state*)faad_malloc(hDecoder->frameLength * sizeof(pred_state));
+            hDecoder->pred_stat[channel] = (pred_state*)realloc(hDecoder->pred_stat[channel], hDecoder->frameLength * sizeof(pred_state));
             reset_all_predictors(hDecoder->pred_stat[channel], hDecoder->frameLength);
-        }
     }
 #endif
 
 #ifdef LTP_DEC
     if (is_ltp_ot(hDecoder->object_type))
     {
-        /* allocate the state only when needed */
-        if (hDecoder->lt_pred_stat[channel] == NULL)
-        {
-            hDecoder->lt_pred_stat[channel] = (int16_t*)faad_malloc(hDecoder->frameLength*4 * sizeof(int16_t));
+            hDecoder->lt_pred_stat[channel] = (int16_t*)realloc(hDecoder->lt_pred_stat[channel], hDecoder->frameLength*4 * sizeof(int16_t));
             memset(hDecoder->lt_pred_stat[channel], 0, hDecoder->frameLength*4 * sizeof(int16_t));
-        }
     }
 #endif
 
-    if (hDecoder->time_out[channel] == NULL)
-    {
         mul = 1;
 #ifdef SBR_DEC
         hDecoder->sbr_alloced[hDecoder->fr_ch_ele] = 0;
@@ -692,41 +696,28 @@
             hDecoder->sbr_alloced[hDecoder->fr_ch_ele] = 1;
         }
 #endif
-        hDecoder->time_out[channel] = (real_t*)faad_malloc(mul*hDecoder->frameLength*sizeof(real_t));
+        hDecoder->time_out[channel] = (real_t*)realloc(hDecoder->time_out[channel], mul*hDecoder->frameLength*sizeof(real_t));
         memset(hDecoder->time_out[channel], 0, mul*hDecoder->frameLength*sizeof(real_t));
-    }
 #if (defined(PS_DEC) || defined(DRM_PS))
     if (output_channels == 2)
     {
-        if (hDecoder->time_out[channel+1] == NULL)
-        {
-            hDecoder->time_out[channel+1] = (real_t*)faad_malloc(mul*hDecoder->frameLength*sizeof(real_t));
+            hDecoder->time_out[channel+1] = (real_t*)realloc(hDecoder->time_out[channel+1], mul*hDecoder->frameLength*sizeof(real_t));
             memset(hDecoder->time_out[channel+1], 0, mul*hDecoder->frameLength*sizeof(real_t));
-        }
     }
 #endif
 
-    if (hDecoder->fb_intermed[channel] == NULL)
-    {
-        hDecoder->fb_intermed[channel] = (real_t*)faad_malloc(hDecoder->frameLength*sizeof(real_t));
+        hDecoder->fb_intermed[channel] = (real_t*)realloc(hDecoder->fb_intermed[channel], hDecoder->frameLength*sizeof(real_t));
         memset(hDecoder->fb_intermed[channel], 0, hDecoder->frameLength*sizeof(real_t));
-    }
 
 #ifdef SSR_DEC
     if (hDecoder->object_type == SSR)
     {
-        if (hDecoder->ssr_overlap[channel] == NULL)
-        {
-            hDecoder->ssr_overlap[channel] = (real_t*)faad_malloc(2*hDecoder->frameLength*sizeof(real_t));
+            uint16_t k;
+            hDecoder->ssr_overlap[channel] = (real_t*)realloc(hDecoder->ssr_overlap[channel], 2*hDecoder->frameLength*sizeof(real_t));
             memset(hDecoder->ssr_overlap[channel], 0, 2*hDecoder->frameLength*sizeof(real_t));
-        }
-        if (hDecoder->prev_fmd[channel] == NULL)
-        {
-            uint16_t k;
-            hDecoder->prev_fmd[channel] = (real_t*)faad_malloc(2*hDecoder->frameLength*sizeof(real_t));
+            hDecoder->prev_fmd[channel] = (real_t*)realloc(hDecoder->prev_fmd[channel], 2*hDecoder->frameLength*sizeof(real_t));
             for (k = 0; k < 2*hDecoder->frameLength; k++)
                 hDecoder->prev_fmd[channel][k] = REAL_CONST(-1);
-        }
     }
 #endif
 
@@ -849,29 +840,15 @@
 #endif
 
 
-    /* determine whether some mono->stereo tool is used */
+    /* always allocate 2 channels, PS can always "suddenly" turn up */
 #if (defined(PS_DEC) || defined(DRM_PS))
     output_channels = hDecoder->ps_used[hDecoder->fr_ch_ele] ? 2 : 1;
 #else
     output_channels = 1;
 #endif
-#ifdef DRM_PS
-    /* for DRM error recovery is crucial */
-    /* simply always allocate 2 channels, you never know when PS will pop up */
-    if (hDecoder->object_type == DRM_ER_LC)
-        output_channels = 2;
-#endif
-    if (hDecoder->element_output_channels[hDecoder->fr_ch_ele] == 0)
-    {
-        /* element_output_channels not set yet */
+
+    if (hDecoder->element_output_channels[hDecoder->fr_ch_ele] < output_channels) {
         hDecoder->element_output_channels[hDecoder->fr_ch_ele] = output_channels;
-    } else if (hDecoder->element_output_channels[hDecoder->fr_ch_ele] != output_channels) {
-        /* element inconsistency */
-        return 21;
-    }
-
-    if (hDecoder->element_alloced[hDecoder->fr_ch_ele] == 0)
-    {
         retval = allocate_single_channel(hDecoder, sce->channel, output_channels);
         if (retval > 0)
             return retval;
@@ -948,16 +925,10 @@
     if (hDecoder->object_type != SSR)
     {
 #endif
-#ifdef USE_SSE
-        hDecoder->fb->if_func(hDecoder->fb, ics->window_sequence, ics->window_shape,
-            hDecoder->window_shape_prev[sce->channel], spec_coef,
-            hDecoder->time_out[sce->channel], hDecoder->object_type, hDecoder->frameLength);
-#else
         ifilter_bank(hDecoder->fb, ics->window_sequence, ics->window_shape,
             hDecoder->window_shape_prev[sce->channel], spec_coef,
             hDecoder->time_out[sce->channel], hDecoder->fb_intermed[sce->channel],
             hDecoder->object_type, hDecoder->frameLength);
-#endif
 #ifdef SSR_DEC
     } else {
         ssr_decode(&(ics->ssr), hDecoder->fb, ics->window_sequence, ics->window_shape,
@@ -1023,12 +994,10 @@
     {
         return 23;
     }
-#endif
 
-#ifdef DRM_PS
-    /* copy L to R for DRM when no PS is used */
-    if ((hDecoder->object_type == DRM_ER_LC) &&
-        (hDecoder->ps_used[hDecoder->fr_ch_ele] == 0))
+    /* copy L to R when no PS is used */
+#if (defined(PS_DEC) || defined(DRM_PS))
+    if ((hDecoder->ps_used[hDecoder->fr_ch_ele] == 0) && (output_channels == 2))
     {
         uint8_t ele = hDecoder->fr_ch_ele;
         uint8_t ch = sce->channel;
@@ -1038,6 +1007,7 @@
         memcpy(hDecoder->time_out[ch+1], hDecoder->time_out[ch], frame_size);
     }
 #endif
+#endif
 
     return 0;
 }
@@ -1087,9 +1057,41 @@
     /* mid/side decoding */
     ms_decode(ics1, ics2, spec_coef1, spec_coef2, hDecoder->frameLength);
 
+#if 0
+    {
+        int i;
+        for (i = 0; i < 1024; i++)
+        {
+            //printf("%d\n", spec_coef1[i]);
+            printf("0x%.8X\n", spec_coef1[i]);
+        }
+        for (i = 0; i < 1024; i++)
+        {
+            //printf("%d\n", spec_coef2[i]);
+            printf("0x%.8X\n", spec_coef2[i]);
+        }
+    }
+#endif
+
     /* intensity stereo decoding */
     is_decode(ics1, ics2, spec_coef1, spec_coef2, hDecoder->frameLength);
 
+#if 0
+    {
+        int i;
+        for (i = 0; i < 1024; i++)
+        {
+            printf("%d\n", spec_coef1[i]);
+            //printf("0x%.8X\n", spec_coef1[i]);
+        }
+        for (i = 0; i < 1024; i++)
+        {
+            printf("%d\n", spec_coef2[i]);
+            //printf("0x%.8X\n", spec_coef2[i]);
+        }
+    }
+#endif
+
 #ifdef MAIN_DEC
     /* MAIN object type prediction */
     if (hDecoder->object_type == MAIN)
@@ -1162,14 +1164,6 @@
     if (hDecoder->object_type != SSR)
     {
 #endif
-#ifdef USE_SSE
-        hDecoder->fb->if_func(hDecoder->fb, ics1->window_sequence, ics1->window_shape,
-            hDecoder->window_shape_prev[cpe->channel], spec_coef1,
-            hDecoder->time_out[cpe->channel], hDecoder->object_type, hDecoder->frameLength);
-        hDecoder->fb->if_func(hDecoder->fb, ics2->window_sequence, ics2->window_shape,
-            hDecoder->window_shape_prev[cpe->paired_channel], spec_coef2,
-            hDecoder->time_out[cpe->paired_channel], hDecoder->object_type, hDecoder->frameLength);
-#else
         ifilter_bank(hDecoder->fb, ics1->window_sequence, ics1->window_shape,
             hDecoder->window_shape_prev[cpe->channel], spec_coef1,
             hDecoder->time_out[cpe->channel], hDecoder->fb_intermed[cpe->channel],
@@ -1178,7 +1172,6 @@
             hDecoder->window_shape_prev[cpe->paired_channel], spec_coef2,
             hDecoder->time_out[cpe->paired_channel], hDecoder->fb_intermed[cpe->paired_channel],
             hDecoder->object_type, hDecoder->frameLength);
-#endif
 #ifdef SSR_DEC
     } else {
         ssr_decode(&(ics1->ssr), hDecoder->fb, ics1->window_sequence, ics1->window_shape,
--- a/libfaad2/specrec.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/specrec.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: specrec.h,v 1.26 2004/05/17 10:18:03 menno Exp $
+** $Id: specrec.h,v 1.28 2004/09/04 14:56:29 menno Exp $
 **/
 
 #ifndef __SPECREC_H__
--- a/libfaad2/ssr.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/ssr.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: ssr.c,v 1.13 2004/02/26 09:29:28 menno Exp $
+** $Id: ssr.c,v 1.15 2004/09/04 14:56:29 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/ssr.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/ssr.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: ssr.h,v 1.13 2004/02/26 09:29:28 menno Exp $
+** $Id: ssr.h,v 1.15 2004/09/04 14:56:29 menno Exp $
 **/
 
 #ifndef __SSR_H__
--- a/libfaad2/ssr_fb.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/ssr_fb.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: ssr_fb.c,v 1.11 2004/02/26 09:29:28 menno Exp $
+** $Id: ssr_fb.c,v 1.13 2004/09/04 14:56:29 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/ssr_fb.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/ssr_fb.h	Tue Apr 18 19:39:34 2006 +0000
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software 
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
-** $Id: ssr_fb.h,v 1.11 2004/02/26 09:29:28 menno Exp $
+** $Id: ssr_fb.h,v 1.13 2004/09/04 14:56:29 menno Exp $
 **/
 
 #ifndef __SSR_FB_H__
--- a/libfaad2/ssr_ipqf.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/ssr_ipqf.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: ssr_ipqf.c,v 1.12 2004/02/26 09:29:28 menno Exp $
+** $Id: ssr_ipqf.c,v 1.14 2004/09/04 14:56:29 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/ssr_ipqf.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/ssr_ipqf.h	Tue Apr 18 19:39:34 2006 +0000
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software 
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
-** $Id: ssr_ipqf.h,v 1.12 2004/02/26 09:29:28 menno Exp $
+** $Id: ssr_ipqf.h,v 1.14 2004/09/04 14:56:29 menno Exp $
 **/
 
 #ifndef __SSR_IPQF_H__
--- a/libfaad2/ssr_win.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/ssr_win.h	Tue Apr 18 19:39:34 2006 +0000
@@ -16,7 +16,7 @@
 ** along with this program; if not, write to the Free Software 
 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 **
-** $Id: ssr_win.h,v 1.11 2004/02/26 09:29:28 menno Exp $
+** $Id: ssr_win.h,v 1.13 2004/09/04 14:56:29 menno Exp $
 **/
 
 #ifndef __SSR_WIN_H__
--- a/libfaad2/structs.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/structs.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: structs.h,v 1.39 2004/05/17 10:18:03 menno Exp $
+** $Id: structs.h,v 1.42 2004/09/08 09:43:11 gcp Exp $
 **/
 
 #ifndef __STRUCTS_H__
@@ -77,9 +77,6 @@
 #ifdef PROFILE
     int64_t cycles;
 #endif
-#ifdef USE_SSE
-    void (*if_func)(void *a, uint8_t b, uint8_t c, uint8_t d, real_t *e, real_t *f, uint8_t g, uint16_t h);
-#endif
 } fb_info;
 
 typedef struct
@@ -366,6 +363,9 @@
     /*uint8_t*/ unsigned char num_back_channels;
     /*uint8_t*/ unsigned char num_lfe_channels;
     /*uint8_t*/ unsigned char channel_position[MAX_CHANNELS];
+
+    /* PS: 0: off, 1: on */
+    /*uint8_t*/ unsigned char ps;
 } NeAACDecFrameInfo;
 
 typedef struct
@@ -431,6 +431,7 @@
 #endif
 #if (defined(PS_DEC) || defined(DRM_PS))
     uint8_t ps_used[MAX_SYNTAX_ELEMENTS];
+    uint8_t ps_used_global;
 #endif
 
 #ifdef SSR_DEC
@@ -455,10 +456,6 @@
     /* Configuration data */
     NeAACDecConfiguration config;
 
-#ifdef USE_SSE
-    void (*apply_sf_func)(void *a, void *b, void *c, uint16_t d);
-#endif
-
 #ifdef PROFILE
     int64_t cycles;
     int64_t spectral_cycles;
--- a/libfaad2/syntax.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/syntax.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: syntax.c,v 1.80 2004/06/30 12:45:57 menno Exp $
+** $Id: syntax.c,v 1.82 2004/09/04 14:56:29 menno Exp $
 **/
 
 /*
@@ -1042,6 +1042,9 @@
             if (hDecoder->sbr[sbr_ele]->ps_used)
             {
                 hDecoder->ps_used[sbr_ele] = 1;
+
+                /* set element independent flag to 1 as well */
+                hDecoder->ps_used_global = 1;
             }
 #endif
         } else {
@@ -1254,13 +1257,20 @@
         if (hDecoder->sbr[0]->ps_used)
         {
             hDecoder->ps_used[0] = 1;
+            hDecoder->ps_used_global = 1;
         }
 #endif
 
         /* check CRC */
         /* no need to check it if there was already an error */
-//        if (hDecoder->sbr[0]->ret == 0)
-//            hDecoder->sbr[0]->ret = (uint8_t)faad_check_CRC(&ld_sbr, (uint16_t)faad_get_processed_bits(&ld_sbr) - 8);
+        if (hDecoder->sbr[0]->ret == 0)
+            hDecoder->sbr[0]->ret = (uint8_t)faad_check_CRC(&ld_sbr, (uint16_t)faad_get_processed_bits(&ld_sbr) - 8);
+
+        /* SBR data was corrupted, disable it until the next header */
+        if (hDecoder->sbr[0]->ret != 0)
+        {
+            hDecoder->sbr[0]->header_count = 0;  
+        }
 
         faad_endbits(&ld_sbr);
 
--- a/libfaad2/syntax.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/syntax.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: syntax.h,v 1.52 2004/03/10 19:45:42 menno Exp $
+** $Id: syntax.h,v 1.54 2004/09/04 14:56:29 menno Exp $
 **/
 
 #ifndef __SYNTAX_H__
--- a/libfaad2/tns.c	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/tns.c	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: tns.c,v 1.33 2004/06/30 12:45:57 menno Exp $
+** $Id: tns.c,v 1.35 2004/09/04 14:56:29 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad2/tns.h	Tue Apr 18 19:33:46 2006 +0000
+++ b/libfaad2/tns.h	Tue Apr 18 19:39:34 2006 +0000
@@ -22,7 +22,7 @@
 ** Commercial non-GPL licensing of this software is possible.
 ** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
 **
-** $Id: tns.h,v 1.17 2004/02/26 09:29:29 menno Exp $
+** $Id: tns.h,v 1.19 2004/09/04 14:56:29 menno Exp $
 **/
 
 #ifndef __TNS_H__