shithub: aacdec

Download patch

ref: fe96a4c620af18665c7097727ae1e50ebc4437d6
parent: 9027402e9c72bfd413bf9a94239ac331c25caf57
author: menno <menno>
date: Tue Jan 13 09:24:10 EST 2004

moved reading of SBR data for SBR to a better place (DRM may be broken again)
changed filterbank overlap data saving so that it uses seperate data
If this works SBR processing can be moved to channel reconstruction

--- a/libfaad/bits.c
+++ b/libfaad/bits.c
@@ -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.31 2004/01/10 18:52:47 menno Exp $
+** $Id: bits.c,v 1.34 2004/01/14 20:32:30 menno Exp $
 **/
 
 #include "common.h"
@@ -161,6 +161,20 @@
 
     return buffer;
 }
+
+#ifdef DRM
+/* return the original data buffer */
+void *faad_origbitbuffer(bitfile *ld)
+{
+    return (void*)ld->start;
+}
+
+/* return the original data buffer size */
+uint32_t faad_origbitbuffer_size(bitfile *ld)
+{
+    return ld->buffer_size;
+}
+#endif
 
 /* reversed bit reading routines, used for RVLC and HCR */
 void faad_initbits_rev(bitfile *ld, void *buffer,
--- a/libfaad/bits.h
+++ b/libfaad/bits.h
@@ -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.h,v 1.30 2004/01/10 18:52:47 menno Exp $
+** $Id: bits.h,v 1.31 2004/01/13 14:24:10 menno Exp $
 **/
 
 #ifndef __BITS_H__
@@ -83,6 +83,10 @@
 void faad_rewindbits(bitfile *ld);
 uint8_t *faad_getbitbuffer(bitfile *ld, uint32_t bits
                        DEBUGDEC);
+#ifdef DRM
+void *faad_origbitbuffer(bitfile *ld);
+uint32_t faad_origbitbuffer_size(bitfile *ld);
+#endif
 
 /* circumvent memory alignment errors on ARM */
 static INLINE uint32_t getdword(void *mem)
--- a/libfaad/common.h
+++ b/libfaad/common.h
@@ -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.h,v 1.43 2004/01/10 18:52:47 menno Exp $
+** $Id: common.h,v 1.46 2004/01/16 20:20:32 menno Exp $
 **/
 
 #ifndef __COMMON_H__
--- a/libfaad/decoder.c
+++ b/libfaad/decoder.c
@@ -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.87 2004/01/12 18:55:40 menno Exp $
+** $Id: decoder.c,v 1.88 2004/01/13 14:24:10 menno Exp $
 **/
 
 #include "common.h"
@@ -113,6 +113,7 @@
     {
         hDecoder->window_shape_prev[i] = 0;
         hDecoder->time_out[i] = NULL;
+        hDecoder->fb_intermed[i] = NULL;
 #ifdef SBR_DEC
         hDecoder->time_out2[i] = NULL;
 #endif
@@ -420,6 +421,8 @@
 
         if (hDecoder->time_out[i]) faad_free(hDecoder->time_out[i]);
         hDecoder->time_out[i] = NULL;
+        if (hDecoder->fb_intermed[i]) faad_free(hDecoder->fb_intermed[i]);
+        hDecoder->fb_intermed[i] = NULL;
 #ifdef SBR_DEC
         if (hDecoder->time_out2[i]) faad_free(hDecoder->time_out2[i]);
         hDecoder->time_out2[i] = NULL;
@@ -463,6 +466,7 @@
     for (i = 0; i < MAX_CHANNELS; i++)
     {
         if (hDecoder->time_out[i]) faad_free(hDecoder->time_out[i]);
+        if (hDecoder->fb_intermed[i]) faad_free(hDecoder->fb_intermed[i]);
 #ifdef SBR_DEC
         if (hDecoder->time_out2[i]) faad_free(hDecoder->time_out2[i]);
 #endif
@@ -725,11 +729,6 @@
     uint8_t output_channels = 0;
     bitfile ld;
     uint32_t bitsconsumed;
-#ifdef DRM
-    uint8_t *revbuffer;
-    uint8_t *prevbufstart;
-    uint8_t *pbufend;
-#endif
 
     /* local copy of globals */
     uint8_t sf_index, object_type, channelConfiguration, outputFormat;
@@ -849,58 +848,7 @@
     }
     faad_endbits(&ld);
 
-#ifdef DRM
-#ifdef SBR_DEC
-    if ((hDecoder->sbr_present_flag == 1) && (hDecoder->object_type == DRM_ER_LC))
-    {
-        uint32_t i;
-        uint16_t count = 0;
-        bitfile ld_sbr = {0};
 
-        if (bitsconsumed + 8 > buffer_size*8)
-        {
-            hInfo->error = 14;
-            goto error;
-        }
-
-        hDecoder->sbr_used[0] = 1;
-
-        if (!hDecoder->sbr[0])
-            hDecoder->sbr[0] = sbrDecodeInit(hDecoder->frameLength, 1);
-
-        /* Reverse bit reading of SBR data in DRM audio frame */
-        revbuffer = (uint8_t*)faad_malloc(buffer_size*sizeof(uint8_t));
-        prevbufstart = revbuffer;
-        pbufend = &buffer[buffer_size - 1];
-        for (i = 0; i < buffer_size; i++)
-            *prevbufstart++ = tabFlipbits[*pbufend--];
-
-        /* Set SBR data */
-        /* consider 8 bits from AAC-CRC */
-        count = (uint16_t)bit2byte(buffer_size*8 - bitsconsumed);
-        faad_initbits(&ld_sbr, revbuffer, count);
-
-        hDecoder->sbr[0]->lcstereo_flag = hDecoder->lcstereo_flag;
-
-        hDecoder->sbr[0]->sample_rate = get_sample_rate(hDecoder->sf_index);
-        hDecoder->sbr[0]->sample_rate *= 2;
-
-        hDecoder->sbr[0]->id_aac = hDecoder->element_id[0];
-
-        faad_getbits(&ld_sbr, 8); /* Skip 8-bit CRC */
-
-        hDecoder->sbr[0]->ret = sbr_extension_data(&ld_sbr, hDecoder->sbr[0], count);
-
-        /* check CRC */
-        /* no need to check it if there was already an error */
-        if (hDecoder->sbr[0]->ret == 0)
-            hDecoder->sbr[0]->ret = faad_check_CRC(&ld_sbr, faad_get_processed_bits(&ld_sbr) - 8);
-
-        faad_endbits(&ld_sbr);
-    }
-#endif
-#endif
-
     if (!hDecoder->adts_header_present && !hDecoder->adif_header_present)
     {
         if (channels != hDecoder->channelConfiguration)
@@ -997,19 +945,12 @@
                     memset(hDecoder->time_out2[ch+1], 0, hDecoder->frameLength*2*sizeof(real_t));
                 }
 
-                memcpy(time_out2[ch],
-                    time_out[ch], frame_len*sizeof(real_t));
-                memcpy(time_out2[ch+1],
-                    time_out[ch+1], frame_len*sizeof(real_t));
-                sbrDecodeFrame(hDecoder->sbr[i],
+                sbrDecodeCoupleFrame(hDecoder->sbr[i], time_out[ch], time_out[ch+1],
                     time_out2[ch], time_out2[ch+1],
                     hDecoder->postSeekResetFlag, hDecoder->forceUpSampling);
                 ch += 2;
             } else {
-                memcpy(time_out2[ch],
-                    time_out[ch], frame_len*sizeof(real_t));
-                sbrDecodeFrame(hDecoder->sbr[i],
-                    time_out2[ch], NULL,
+                sbrDecodeSingleFrame(hDecoder->sbr[i], time_out[ch], time_out2[ch],
                     hDecoder->postSeekResetFlag, hDecoder->forceUpSampling);
                 ch++;
             }
--- a/libfaad/filtbank.c
+++ b/libfaad/filtbank.c
@@ -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.34 2004/01/05 14:05:11 menno Exp $
+** $Id: filtbank.c,v 1.35 2004/01/13 14:24:10 menno Exp $
 **/
 
 #include "common.h"
@@ -194,7 +194,8 @@
 
 void ifilter_bank(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)
+                  real_t *time_out, real_t *overlap,
+                  uint8_t object_type, uint16_t frame_len)
 {
     int16_t i;
     ALIGN real_t transf_buf[2*1024] = {0};
@@ -229,6 +230,7 @@
     }
 #endif
 
+
     switch (window_sequence)
     {
     case ONLY_LONG_SEQUENCE:
@@ -235,17 +237,17 @@
         imdct_long(fb, freq_in, transf_buf, 2*nlong);
         for (i = 0; i < nlong; i+=4)
         {
-            time_out[i]   = time_out[nlong+i]   + MUL_F(transf_buf[i],window_long_prev[i]);
-            time_out[i+1] = time_out[nlong+i+1] + MUL_F(transf_buf[i+1],window_long_prev[i+1]);
-            time_out[i+2] = time_out[nlong+i+2] + MUL_F(transf_buf[i+2],window_long_prev[i+2]);
-            time_out[i+3] = time_out[nlong+i+3] + MUL_F(transf_buf[i+3],window_long_prev[i+3]);
+            time_out[i]   = overlap[i]   + MUL_F(transf_buf[i],window_long_prev[i]);
+            time_out[i+1] = overlap[i+1] + MUL_F(transf_buf[i+1],window_long_prev[i+1]);
+            time_out[i+2] = overlap[i+2] + MUL_F(transf_buf[i+2],window_long_prev[i+2]);
+            time_out[i+3] = overlap[i+3] + MUL_F(transf_buf[i+3],window_long_prev[i+3]);
         }
         for (i = 0; i < nlong; i+=4)
         {
-            time_out[nlong+i]   = MUL_F(transf_buf[nlong+i],window_long[nlong-1-i]);
-            time_out[nlong+i+1] = MUL_F(transf_buf[nlong+i+1],window_long[nlong-2-i]);
-            time_out[nlong+i+2] = MUL_F(transf_buf[nlong+i+2],window_long[nlong-3-i]);
-            time_out[nlong+i+3] = MUL_F(transf_buf[nlong+i+3],window_long[nlong-4-i]);
+            overlap[i]   = MUL_F(transf_buf[nlong+i],window_long[nlong-1-i]);
+            overlap[i+1] = MUL_F(transf_buf[nlong+i+1],window_long[nlong-2-i]);
+            overlap[i+2] = MUL_F(transf_buf[nlong+i+2],window_long[nlong-3-i]);
+            overlap[i+3] = MUL_F(transf_buf[nlong+i+3],window_long[nlong-4-i]);
         }
         break;
 
@@ -253,17 +255,17 @@
         imdct_long(fb, freq_in, transf_buf, 2*nlong);
         for (i = 0; i < nlong; i+=4)
         {
-            time_out[i]   = time_out[nlong+i]   + MUL_F(transf_buf[i],window_long_prev[i]);
-            time_out[i+1] = time_out[nlong+i+1] + MUL_F(transf_buf[i+1],window_long_prev[i+1]);
-            time_out[i+2] = time_out[nlong+i+2] + MUL_F(transf_buf[i+2],window_long_prev[i+2]);
-            time_out[i+3] = time_out[nlong+i+3] + MUL_F(transf_buf[i+3],window_long_prev[i+3]);
+            time_out[i]   = overlap[i]   + MUL_F(transf_buf[i],window_long_prev[i]);
+            time_out[i+1] = overlap[i+1] + MUL_F(transf_buf[i+1],window_long_prev[i+1]);
+            time_out[i+2] = overlap[i+2] + MUL_F(transf_buf[i+2],window_long_prev[i+2]);
+            time_out[i+3] = overlap[i+3] + MUL_F(transf_buf[i+3],window_long_prev[i+3]);
         }
         for (i = 0; i < nflat_ls; i++)
-            time_out[nlong+i] = transf_buf[nlong+i];
+            overlap[i] = transf_buf[nlong+i];
         for (i = 0; i < nshort; i++)
-            time_out[nlong+nflat_ls+i] = MUL_F(transf_buf[nlong+nflat_ls+i],window_short[nshort-i-1]);
+            overlap[nflat_ls+i] = MUL_F(transf_buf[nlong+nflat_ls+i],window_short[nshort-i-1]);
         for (i = 0; i < nflat_ls; i++)
-            time_out[nlong+nflat_ls+nshort+i] = 0;
+            overlap[nflat_ls+nshort+i] = 0;
         break;
 
     case EIGHT_SHORT_SEQUENCE:
@@ -276,36 +278,39 @@
         faad_imdct(fb->mdct256, freq_in+6*nshort, transf_buf+2*nshort*6);
         faad_imdct(fb->mdct256, freq_in+7*nshort, transf_buf+2*nshort*7);
         for (i = 0; i < nflat_ls; i++)
-            time_out[i] = time_out[nlong+i];
+            time_out[i] = overlap[i];
         for(i = 0; i < nshort; i++)
         {
-            time_out[nflat_ls+         i] = time_out[nlong+nflat_ls+         i] + MUL_F(transf_buf[nshort*0+i],window_short_prev[i]);
-            time_out[nflat_ls+1*nshort+i] = time_out[nlong+nflat_ls+nshort*1+i] + MUL_F(transf_buf[nshort*1+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*2+i],window_short[i]);
-            time_out[nflat_ls+2*nshort+i] = time_out[nlong+nflat_ls+nshort*2+i] + MUL_F(transf_buf[nshort*3+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*4+i],window_short[i]);
-            time_out[nflat_ls+3*nshort+i] = time_out[nlong+nflat_ls+nshort*3+i] + MUL_F(transf_buf[nshort*5+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*6+i],window_short[i]);
+            time_out[nflat_ls+         i] = overlap[nflat_ls+         i] + MUL_F(transf_buf[nshort*0+i],window_short_prev[i]);
+            time_out[nflat_ls+1*nshort+i] = overlap[nflat_ls+nshort*1+i] + MUL_F(transf_buf[nshort*1+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*2+i],window_short[i]);
+            time_out[nflat_ls+2*nshort+i] = overlap[nflat_ls+nshort*2+i] + MUL_F(transf_buf[nshort*3+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*4+i],window_short[i]);
+            time_out[nflat_ls+3*nshort+i] = overlap[nflat_ls+nshort*3+i] + MUL_F(transf_buf[nshort*5+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*6+i],window_short[i]);
             if (i < trans)
-                time_out[nflat_ls+4*nshort+i] = time_out[nlong+nflat_ls+nshort*4+i] + MUL_F(transf_buf[nshort*7+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*8+i],window_short[i]);
-            else
-                time_out[nflat_ls+4*nshort+i] = MUL_F(transf_buf[nshort*7+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*8+i],window_short[i]);
-            time_out[nflat_ls+5*nshort+i] = MUL_F(transf_buf[nshort*9+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*10+i],window_short[i]);
-            time_out[nflat_ls+6*nshort+i] = MUL_F(transf_buf[nshort*11+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*12+i],window_short[i]);
-            time_out[nflat_ls+7*nshort+i] = MUL_F(transf_buf[nshort*13+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*14+i],window_short[i]);
-            time_out[nflat_ls+8*nshort+i] = MUL_F(transf_buf[nshort*15+i],window_short[nshort-1-i]);
+                time_out[nflat_ls+4*nshort+i] = overlap[nflat_ls+nshort*4+i] + MUL_F(transf_buf[nshort*7+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*8+i],window_short[i]);
         }
+        for(i = 0; i < nshort; i++)
+        {
+            if (i >= trans)
+                overlap[nflat_ls+4*nshort+i-nlong] = MUL_F(transf_buf[nshort*7+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*8+i],window_short[i]);
+            overlap[nflat_ls+5*nshort+i-nlong] = MUL_F(transf_buf[nshort*9+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*10+i],window_short[i]);
+            overlap[nflat_ls+6*nshort+i-nlong] = MUL_F(transf_buf[nshort*11+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*12+i],window_short[i]);
+            overlap[nflat_ls+7*nshort+i-nlong] = MUL_F(transf_buf[nshort*13+i],window_short[nshort-1-i]) + MUL_F(transf_buf[nshort*14+i],window_short[i]);
+            overlap[nflat_ls+8*nshort+i-nlong] = MUL_F(transf_buf[nshort*15+i],window_short[nshort-1-i]);
+        }
         for (i = 0; i < nflat_ls; i++)
-            time_out[nlong+nflat_ls+nshort+i] = 0;
+            overlap[nflat_ls+nshort+i] = 0;
         break;
 
     case LONG_STOP_SEQUENCE:
         imdct_long(fb, freq_in, transf_buf, 2*nlong);
         for (i = 0; i < nflat_ls; i++)
-            time_out[i] = time_out[nlong+i];
+            time_out[i] = overlap[i];
         for (i = 0; i < nshort; i++)
-            time_out[nflat_ls+i] = time_out[nlong+nflat_ls+i] + MUL_F(transf_buf[nflat_ls+i],window_short_prev[i]);
+            time_out[nflat_ls+i] = overlap[nflat_ls+i] + MUL_F(transf_buf[nflat_ls+i],window_short_prev[i]);
         for (i = 0; i < nflat_ls; i++)
-            time_out[nflat_ls+nshort+i] = time_out[nlong+nflat_ls+nshort+i] + transf_buf[nflat_ls+nshort+i];
+            time_out[nflat_ls+nshort+i] = overlap[nflat_ls+nshort+i] + transf_buf[nflat_ls+nshort+i];
         for (i = 0; i < nlong; i++)
-            time_out[nlong+i] = MUL_F(transf_buf[nlong+i],window_long[nlong-1-i]);
+            overlap[i] = MUL_F(transf_buf[nlong+i],window_long[nlong-1-i]);
 		break;
     }
 
--- a/libfaad/filtbank.h
+++ b/libfaad/filtbank.h
@@ -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.19 2004/01/05 14:05:11 menno Exp $
+** $Id: filtbank.h,v 1.20 2004/01/13 14:24:10 menno Exp $
 **/
 
 #ifndef __FILTBANK_H__
@@ -47,14 +47,11 @@
                      uint16_t frame_len);
 #endif
 
-void ifilter_bank(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);
+void ifilter_bank(fb_info *fb, uint8_t window_sequence, uint8_t window_shape,
+                  uint8_t window_shape_prev, real_t *freq_in,
+                  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,
--- a/libfaad/huffman.c
+++ b/libfaad/huffman.c
@@ -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.11 2004/01/05 14:05:11 menno Exp $
+** $Id: huffman.c,v 1.12 2004/01/13 14:24:10 menno Exp $
 **/
 
 #include "common.h"
@@ -118,16 +118,6 @@
     }
 }
 
-#ifdef _WIN32
-static INLINE uint32_t bsr(uint32_t bits)
-{
-    __asm
-    {
-        bsr eax, dword ptr [bits]
-    }
-}
-#endif
-
 static INLINE int16_t huffman_getescape(bitfile *ld, int16_t sp)
 {
     uint8_t neg, i;
@@ -145,7 +135,6 @@
         neg = 0;
     }
 
-#ifndef _WIN32
     for (i = 4; ; i++)
     {
         if (faad_get1bit(ld
@@ -154,17 +143,6 @@
             break;
         }
     }
-#else
-    /* maximum quantised value is 8192,
-     * so the maximum number of bits for 1 value is log[2](8192)=13
-     * minimum bits used when escape is present is 4 bits
-     * this leaves a maximum of 9 bits to be read at this point
-     */
-    j = faad_showbits(ld, 9) | 0xFFFFFE00;
-    i = 12 - bsr(~j);
-    faad_getbits(ld, i-3
-        DEBUGVAR(1,6,"huffman_getescape(): escape size"));
-#endif
 
     off = faad_getbits(ld, i
         DEBUGVAR(1,9,"huffman_getescape(): escape"));
--- a/libfaad/sbr_dec.c
+++ b/libfaad/sbr_dec.c
@@ -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.c,v 1.21 2004/01/11 15:29:10 menno Exp $
+** $Id: sbr_dec.c,v 1.22 2004/01/13 14:24:10 menno Exp $
 **/
 
 
@@ -143,42 +143,16 @@
         sbr->prevEnvIsShort[ch] = -1;
 }
 
-void sbrDecodeFrame(sbr_info *sbr, real_t *left_channel,
-                    real_t *right_channel,
-                    const uint8_t just_seeked, const uint8_t upsample_only)
+static void sbr_process_channel(sbr_info *sbr, real_t *ch_in_buf, real_t *ch_out_buf,
+                                uint8_t ch, uint8_t dont_process)
 {
     int16_t i, k, l;
 
-    uint8_t dont_process = 0;
-    uint8_t ch, channels;
-    real_t *ch_buf;
-
     ALIGN qmf_t X[MAX_NTSR][64];
 #ifdef SBR_LOW_POWER
     ALIGN real_t deg[64];
 #endif
 
-    channels = (sbr->id_aac == ID_CPE) ? 2 : 1;
-
-    if (sbr->ret || (sbr->header_count == 0))
-    {
-        /* don't process just upsample */
-        dont_process = 1;
-
-        /* Re-activate reset for next frame */
-        if (sbr->ret && sbr->Reset)
-            sbr->bs_start_freq_prev = -1;
-    }
-
-    if (just_seeked)
-    {
-        sbr->just_seeked = 1;
-    } else {
-        sbr->just_seeked = 0;
-    }
-
-    for (ch = 0; ch < channels; ch++)
-    {
         if (sbr->frame == 0)
         {
             uint8_t j;
@@ -195,16 +169,11 @@
             memset(sbr->Xcodec[ch], 0, (sbr->numTimeSlotsRate+sbr->tHFGen)*32 * sizeof(qmf_t));
         }
 
-        if (ch == 0)
-            ch_buf = left_channel;
-        else
-            ch_buf = right_channel;
-
         /* subband analysis */
         if (dont_process)
-            sbr_qmf_analysis_32(sbr, sbr->qmfa[ch], ch_buf, sbr->Xcodec[ch], sbr->tHFGen, 32);
+            sbr_qmf_analysis_32(sbr, sbr->qmfa[ch], ch_in_buf, sbr->Xcodec[ch], sbr->tHFGen, 32);
         else
-            sbr_qmf_analysis_32(sbr, sbr->qmfa[ch], ch_buf, sbr->Xcodec[ch], sbr->tHFGen, sbr->kx);
+            sbr_qmf_analysis_32(sbr, sbr->qmfa[ch], ch_in_buf, sbr->Xcodec[ch], sbr->tHFGen, sbr->kx);
 
         if (!dont_process)
         {
@@ -289,9 +258,9 @@
 
         /* subband synthesis */
 #ifndef USE_SSE
-        sbr_qmf_synthesis_64(sbr, sbr->qmfs[ch], X, ch_buf);
+        sbr_qmf_synthesis_64(sbr, sbr->qmfs[ch], X, ch_out_buf);
 #else
-        sbr->qmfs[ch]->qmf_func(sbr, sbr->qmfs[ch], X, ch_buf);
+        sbr->qmfs[ch]->qmf_func(sbr, sbr->qmfs[ch], X, ch_out_buf);
 #endif
 
         for (i = 0; i < sbr->tHFGen; i++)
@@ -299,15 +268,76 @@
             memmove(sbr->Xcodec[ch][i], sbr->Xcodec[ch][i+sbr->numTimeSlotsRate], 32 * sizeof(qmf_t));
             memmove(sbr->Xsbr[ch][i], sbr->Xsbr[ch][i+sbr->numTimeSlotsRate], 64 * sizeof(qmf_t));
         }
+}
+
+void sbrDecodeCoupleFrame(sbr_info *sbr, real_t *left_in, real_t *right_in,
+                          real_t *left_out, real_t *right_out,
+                          const uint8_t just_seeked, const uint8_t upsample_only)
+{
+    uint8_t dont_process = 0;
+
+    if (sbr->ret || (sbr->header_count == 0))
+    {
+        /* don't process just upsample */
+        dont_process = 1;
+
+        /* Re-activate reset for next frame */
+        if (sbr->ret && sbr->Reset)
+            sbr->bs_start_freq_prev = -1;
     }
 
+    if (just_seeked)
+    {
+        sbr->just_seeked = 1;
+    } else {
+        sbr->just_seeked = 0;
+    }
+
+    sbr_process_channel(sbr, left_in, left_out, 0, dont_process);
+    sbr_process_channel(sbr, right_in, right_out, 1, dont_process);
+
     if (sbr->bs_header_flag)
         sbr->just_seeked = 0;
 
     if (sbr->header_count != 0)
     {
-        for (ch = 0; ch < channels; ch++)
-            sbr_save_prev_data(sbr, ch);
+        sbr_save_prev_data(sbr, 0);
+        sbr_save_prev_data(sbr, 1);
+    }
+
+    sbr->frame++;
+}
+
+void sbrDecodeSingleFrame(sbr_info *sbr, real_t *left_in, real_t *left_out,
+                          const uint8_t just_seeked, const uint8_t upsample_only)
+{
+    uint8_t dont_process = 0;
+
+    if (sbr->ret || (sbr->header_count == 0))
+    {
+        /* don't process just upsample */
+        dont_process = 1;
+
+        /* Re-activate reset for next frame */
+        if (sbr->ret && sbr->Reset)
+            sbr->bs_start_freq_prev = -1;
+    }
+
+    if (just_seeked)
+    {
+        sbr->just_seeked = 1;
+    } else {
+        sbr->just_seeked = 0;
+    }
+
+    sbr_process_channel(sbr, left_in, left_out, 0, dont_process);
+
+    if (sbr->bs_header_flag)
+        sbr->just_seeked = 0;
+
+    if (sbr->header_count != 0)
+    {
+        sbr_save_prev_data(sbr, 0);
     }
 
     sbr->frame++;
--- a/libfaad/sbr_dec.h
+++ b/libfaad/sbr_dec.h
@@ -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.15 2004/01/10 18:52:47 menno Exp $
+** $Id: sbr_dec.h,v 1.16 2004/01/13 14:24:10 menno Exp $
 **/
 
 #ifndef __SBR_DEC_H__
@@ -212,9 +212,11 @@
 						);
 void sbrDecodeEnd(sbr_info *sbr);
 
-void sbrDecodeFrame(sbr_info *sbr, real_t *left_channel,
-                    real_t *right_channel,
-                    const uint8_t just_seeked, const uint8_t upsample_only);
+void sbrDecodeCoupleFrame(sbr_info *sbr, real_t *left_in, real_t *right_in,
+                          real_t *left_out, real_t *right_out,
+                          const uint8_t just_seeked, const uint8_t upsample_only);
+void sbrDecodeSingleFrame(sbr_info *sbr, real_t *left_in, real_t *left_out,
+                          const uint8_t just_seeked, const uint8_t upsample_only);
 
 
 #ifdef __cplusplus
--- a/libfaad/specrec.c
+++ b/libfaad/specrec.c
@@ -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.c,v 1.37 2004/01/05 14:05:12 menno Exp $
+** $Id: specrec.c,v 1.38 2004/01/13 14:24:10 menno Exp $
 **/
 
 /*
@@ -44,6 +44,7 @@
 #include "is.h"
 #include "pns.h"
 #include "tns.h"
+#include "drc.h"
 #include "lt_predict.h"
 #include "ic_predict.h"
 #ifdef SSR_DEC
@@ -778,10 +779,16 @@
 
     if (hDecoder->time_out[sce->channel] == NULL)
     {
-        hDecoder->time_out[sce->channel] = (real_t*)faad_malloc(hDecoder->frameLength*2*sizeof(real_t));
-        memset(hDecoder->time_out[sce->channel], 0, hDecoder->frameLength*2*sizeof(real_t));
+        hDecoder->time_out[sce->channel] = (real_t*)faad_malloc(hDecoder->frameLength*sizeof(real_t));
+        memset(hDecoder->time_out[sce->channel], 0, hDecoder->frameLength*sizeof(real_t));
     }
 
+    if (hDecoder->fb_intermed[sce->channel] == NULL)
+    {
+        hDecoder->fb_intermed[sce->channel] = (real_t*)faad_malloc(hDecoder->frameLength*sizeof(real_t));
+        memset(hDecoder->fb_intermed[sce->channel], 0, hDecoder->frameLength*sizeof(real_t));
+    }
+
     /* filter bank */
 #ifdef SSR_DEC
     if (hDecoder->object_type != SSR)
@@ -794,7 +801,8 @@
 #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->object_type, hDecoder->frameLength);
+            hDecoder->time_out[sce->channel], hDecoder->fb_intermed[sce->channel],
+            hDecoder->object_type, hDecoder->frameLength);
 #endif
 #ifdef SSR_DEC
     } else {
@@ -825,7 +833,7 @@
     if (is_ltp_ot(hDecoder->object_type))
     {
         lt_update_state(hDecoder->lt_pred_stat[sce->channel], hDecoder->time_out[sce->channel],
-            hDecoder->time_out[sce->channel]+hDecoder->frameLength, hDecoder->frameLength, hDecoder->object_type);
+            hDecoder->fb_intermed[sce->channel], hDecoder->frameLength, hDecoder->object_type);
     }
 #endif
 
@@ -981,15 +989,26 @@
 
     if (hDecoder->time_out[cpe->channel] == NULL)
     {
-        hDecoder->time_out[cpe->channel] = (real_t*)faad_malloc(hDecoder->frameLength*2*sizeof(real_t));
-        memset(hDecoder->time_out[cpe->channel], 0, hDecoder->frameLength*2*sizeof(real_t));
+        hDecoder->time_out[cpe->channel] = (real_t*)faad_malloc(hDecoder->frameLength*sizeof(real_t));
+        memset(hDecoder->time_out[cpe->channel], 0, hDecoder->frameLength*sizeof(real_t));
     }
     if (hDecoder->time_out[cpe->paired_channel] == NULL)
     {
-        hDecoder->time_out[cpe->paired_channel] = (real_t*)faad_malloc(hDecoder->frameLength*2*sizeof(real_t));
-        memset(hDecoder->time_out[cpe->paired_channel], 0, hDecoder->frameLength*2*sizeof(real_t));
+        hDecoder->time_out[cpe->paired_channel] = (real_t*)faad_malloc(hDecoder->frameLength*sizeof(real_t));
+        memset(hDecoder->time_out[cpe->paired_channel], 0, hDecoder->frameLength*sizeof(real_t));
     }
 
+    if (hDecoder->fb_intermed[cpe->channel] == NULL)
+    {
+        hDecoder->fb_intermed[cpe->channel] = (real_t*)faad_malloc(hDecoder->frameLength*sizeof(real_t));
+        memset(hDecoder->fb_intermed[cpe->channel], 0, hDecoder->frameLength*sizeof(real_t));
+    }
+    if (hDecoder->fb_intermed[cpe->paired_channel] == NULL)
+    {
+        hDecoder->fb_intermed[cpe->paired_channel] = (real_t*)faad_malloc(hDecoder->frameLength*sizeof(real_t));
+        memset(hDecoder->fb_intermed[cpe->paired_channel], 0, hDecoder->frameLength*sizeof(real_t));
+    }
+
     /* filter bank */
 #ifdef SSR_DEC
     if (hDecoder->object_type != SSR)
@@ -1005,10 +1024,12 @@
 #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->object_type, hDecoder->frameLength);
+            hDecoder->time_out[cpe->channel], hDecoder->fb_intermed[cpe->channel],
+            hDecoder->object_type, hDecoder->frameLength);
         ifilter_bank(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);
+            hDecoder->time_out[cpe->paired_channel], hDecoder->fb_intermed[cpe->paired_channel],
+            hDecoder->object_type, hDecoder->frameLength);
 #endif
 #ifdef SSR_DEC
     } else {
@@ -1056,10 +1077,9 @@
     if (is_ltp_ot(hDecoder->object_type))
     {
         lt_update_state(hDecoder->lt_pred_stat[cpe->channel], hDecoder->time_out[cpe->channel],
-            hDecoder->time_out[cpe->channel]+hDecoder->frameLength, hDecoder->frameLength, hDecoder->object_type);
+            hDecoder->fb_intermed[cpe->channel], hDecoder->frameLength, hDecoder->object_type);
         lt_update_state(hDecoder->lt_pred_stat[cpe->paired_channel], hDecoder->time_out[cpe->paired_channel],
-            hDecoder->time_out[cpe->paired_channel]+hDecoder->frameLength, hDecoder->frameLength,
-            hDecoder->object_type);
+            hDecoder->fb_intermed[cpe->paired_channel], hDecoder->frameLength, hDecoder->object_type);
     }
 #endif
 
--- a/libfaad/structs.h
+++ b/libfaad/structs.h
@@ -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.25 2004/01/06 11:59:48 menno Exp $
+** $Id: structs.h,v 1.26 2004/01/13 14:24:10 menno Exp $
 **/
 
 #ifndef __STRUCTS_H__
@@ -394,6 +394,7 @@
     drc_info *drc;
 
     real_t *time_out[MAX_CHANNELS];
+    real_t *fb_intermed[MAX_CHANNELS];
 
 #ifdef SBR_DEC
     int8_t sbr_present_flag;
--- a/libfaad/syntax.c
+++ b/libfaad/syntax.c
@@ -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.65 2004/01/10 18:52:47 menno Exp $
+** $Id: syntax.c,v 1.66 2004/01/13 14:24:10 menno Exp $
 **/
 
 /*
@@ -324,8 +324,6 @@
         return;
     }
 
-    hInfo->error = single_lfe_channel_element(hDecoder, ld, channels, &tag);
-
     if (hDecoder->pce_set)
         hDecoder->internal_channel[hDecoder->pce.sce_channel[tag]] = channels;
     else
@@ -337,6 +335,8 @@
         hDecoder->channel_element[channels] = hDecoder->fr_ch_ele;
     hDecoder->element_id[hDecoder->fr_ch_ele] = id_syn_ele;
 
+    hInfo->error = single_lfe_channel_element(hDecoder, ld, channels, &tag);
+
     hDecoder->fr_channels++;
     hDecoder->fr_ch_ele++;
 }
@@ -358,8 +358,6 @@
         return;
     }
 
-    hInfo->error = channel_pair_element(hDecoder, ld, channels, &tag);
-
     if (hDecoder->pce_set)
     {
         hDecoder->internal_channel[hDecoder->pce.cpe_channel[tag]] = channels;
@@ -373,6 +371,8 @@
     hDecoder->channel_element[channels+1] = hDecoder->fr_ch_ele;
     hDecoder->element_id[hDecoder->fr_ch_ele] = id_syn_ele;
 
+    hInfo->error = channel_pair_element(hDecoder, ld, channels, &tag);
+
     hDecoder->fr_channels += 2;
     hDecoder->fr_ch_ele++;
 }
@@ -563,6 +563,21 @@
     if (retval > 0)
         return retval;
 
+#ifdef SBR_DEC
+    /* check if next bitstream element is a fill element */
+    /* if so, read it now so SBR decoding can be done in case of a file with SBR */
+    if (faad_showbits(ld, LEN_SE_ID) == ID_FIL)
+    {
+        faad_flushbits(ld, LEN_SE_ID);
+
+        /* one sbr_info describes a channel_element not a channel! */
+        if ((retval = fill_element(hDecoder, ld, hDecoder->drc, hDecoder->fr_ch_ele)) > 0)
+        {
+            return retval;
+        }
+    }
+#endif
+
     /* noiseless coding is done, spectral reconstruction is done now */
     retval = reconstruct_single_channel(hDecoder, ics, &sce, spec_data);
     if (retval > 0)
@@ -657,6 +672,21 @@
         return result;
     }
 
+#ifdef SBR_DEC
+    /* check if next bitstream element is a fill element */
+    /* if so, read it now so SBR decoding can be done in case of a file with SBR */
+    if (faad_showbits(ld, LEN_SE_ID) == ID_FIL)
+    {
+        faad_flushbits(ld, LEN_SE_ID);
+
+        /* one sbr_info describes a channel_element not a channel! */
+        if ((result = fill_element(hDecoder, ld, hDecoder->drc, hDecoder->fr_ch_ele)) > 0)
+        {
+            return result;
+        }
+    }
+#endif
+
     /* noiseless coding is done, spectral reconstruction is done now */
     if ((result = reconstruct_channel_pair(hDecoder, ics1, ics2, &cpe,
         spec_data1, spec_data2)) > 0)
@@ -1116,6 +1146,67 @@
         if (hInfo->error > 0)
             return;
     }
+
+#ifdef DRM
+#ifdef SBR_DEC
+    /* In case of DRM we need to read the SBR info before channel reconstruction */
+    if ((hDecoder->sbr_present_flag == 1) && (hDecoder->object_type == DRM_ER_LC))
+    {
+        bitfile ld_sbr = {0};
+        uint32_t i;
+        uint16_t count = 0;
+        uint8_t *revbuffer;
+        uint8_t *prevbufstart;
+        uint8_t *pbufend;
+
+        /* all forward bitreading should be finished at this point */
+        uint32_t bitsconsumed = faad_get_processed_bits(ld);
+        uint32_t buffer_size = faad_origbitbuffer_size(ld);
+        uint8_t *buffer = (uint8_t*)faad_origbitbuffer(ld);
+
+        if (bitsconsumed + 8 > buffer_size*8)
+        {
+            hInfo->error = 14;
+            return;
+        }
+
+        hDecoder->sbr_used[0] = 1;
+
+        if (!hDecoder->sbr[0])
+            hDecoder->sbr[0] = sbrDecodeInit(hDecoder->frameLength, 1);
+
+        /* Reverse bit reading of SBR data in DRM audio frame */
+        revbuffer = (uint8_t*)faad_malloc(buffer_size*sizeof(uint8_t));
+        prevbufstart = revbuffer;
+        pbufend = &buffer[buffer_size - 1];
+        for (i = 0; i < buffer_size; i++)
+            *prevbufstart++ = tabFlipbits[*pbufend--];
+
+        /* Set SBR data */
+        /* consider 8 bits from AAC-CRC */
+        count = (uint16_t)bit2byte(buffer_size*8 - bitsconsumed);
+        faad_initbits(&ld_sbr, revbuffer, count);
+
+        hDecoder->sbr[0]->lcstereo_flag = hDecoder->lcstereo_flag;
+
+        hDecoder->sbr[0]->sample_rate = get_sample_rate(hDecoder->sf_index);
+        hDecoder->sbr[0]->sample_rate *= 2;
+
+        hDecoder->sbr[0]->id_aac = hDecoder->element_id[0];
+
+        faad_getbits(&ld_sbr, 8); /* Skip 8-bit CRC */
+
+        hDecoder->sbr[0]->ret = sbr_extension_data(&ld_sbr, hDecoder->sbr[0], count);
+
+        /* check CRC */
+        /* no need to check it if there was already an error */
+        if (hDecoder->sbr[0]->ret == 0)
+            hDecoder->sbr[0]->ret = faad_check_CRC(&ld_sbr, faad_get_processed_bits(&ld_sbr) - 8);
+
+        faad_endbits(&ld_sbr);
+    }
+#endif
+#endif
 
     if (this_layer_stereo)
     {