shithub: aacdec

Download patch

ref: cac7ac2ce53d263d07f7203479f35d007218cee3
parent: fe96a4c620af18665c7097727ae1e50ebc4437d6
author: menno <menno>
date: Tue Jan 13 15:35:14 EST 2004

SBR decoding now done together with AAC channel reconstruction, saves some buffering and memcpying

--- 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.88 2004/01/13 14:24:10 menno Exp $
+** $Id: decoder.c,v 1.89 2004/01/13 20:35:14 menno Exp $
 **/
 
 #include "common.h"
@@ -114,9 +114,6 @@
         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
 #ifdef SSR_DEC
         hDecoder->ssr_overlap[i] = NULL;
         hDecoder->prev_fmd[i] = NULL;
@@ -467,9 +464,6 @@
     {
         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
 #ifdef SSR_DEC
         if (hDecoder->ssr_overlap[i]) faad_free(hDecoder->ssr_overlap[i]);
         if (hDecoder->prev_fmd[i]) faad_free(hDecoder->prev_fmd[i]);
@@ -724,30 +718,11 @@
                             faacDecFrameInfo *hInfo,
                             uint8_t *buffer, uint32_t buffer_size)
 {
-    adts_header adts;
-    uint8_t channels = 0, ch_ele = 0;
+    uint8_t channels = 0;
     uint8_t output_channels = 0;
     bitfile ld;
     uint32_t bitsconsumed;
-
-    /* local copy of globals */
-    uint8_t sf_index, object_type, channelConfiguration, outputFormat;
-    uint8_t *window_shape_prev;
     uint16_t frame_len;
-#ifdef MAIN_DEC
-    pred_state **pred_stat;
-#endif
-    real_t **time_out;
-#ifdef SBR_DEC
-    real_t **time_out2;
-#endif
-#ifdef SSR_DEC
-    real_t **ssr_overlap, **prev_fmd;
-#endif
-    fb_info *fb;
-    drc_info *drc;
-    program_config *pce;
-
     void *sample_buffer;
 
 #ifdef PROFILE
@@ -760,25 +735,6 @@
         return NULL;
     }
 
-    sf_index = hDecoder->sf_index;
-    object_type = hDecoder->object_type;
-    channelConfiguration = hDecoder->channelConfiguration;
-#ifdef MAIN_DEC
-    pred_stat = hDecoder->pred_stat;
-#endif
-    window_shape_prev = hDecoder->window_shape_prev;
-    time_out = hDecoder->time_out;
-#ifdef SBR_DEC
-    time_out2 = hDecoder->time_out2;
-#endif
-#ifdef SSR_DEC
-    ssr_overlap = hDecoder->ssr_overlap;
-    prev_fmd = hDecoder->prev_fmd;
-#endif
-    fb = hDecoder->fb;
-    drc = hDecoder->drc;
-    outputFormat = hDecoder->config.outputFormat;
-    pce = &hDecoder->pce;
     frame_len = hDecoder->frameLength;
 
 
@@ -805,6 +761,8 @@
 
     if (hDecoder->adts_header_present)
     {
+        adts_header adts;
+
         adts.old_format = hDecoder->config.useOldADTSFormat;
         if ((hInfo->error = adts_frame(&adts, &ld)) > 0)
             goto error;
@@ -823,15 +781,14 @@
 #ifdef SCALABLE_DEC
     if ((hDecoder->object_type == 6) || (hDecoder->object_type == DRM_ER_LC))
     {
-        aac_scalable_main_element(hDecoder, hInfo, &ld, pce, drc);
+        aac_scalable_main_element(hDecoder, hInfo, &ld, &hDecoder->pce, hDecoder->drc);
     } else {
 #endif
-        raw_data_block(hDecoder, hInfo, &ld, pce, drc);
+        raw_data_block(hDecoder, hInfo, &ld, &hDecoder->pce, hDecoder->drc);
 #ifdef SCALABLE_DEC
     }
 #endif
 
-    ch_ele = hDecoder->fr_ch_ele;
     channels = hDecoder->fr_channels;
 
     if (hInfo->error > 0)
@@ -902,7 +859,7 @@
             sizeof(float32_t), sizeof(double), sizeof(int16_t), sizeof(int16_t),
             sizeof(int16_t), sizeof(int16_t), 0, 0, 0
         };
-        uint8_t stride = str[outputFormat-1];
+        uint8_t stride = str[hDecoder->config.outputFormat-1];
 #ifdef SBR_DEC
         if ((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1))
             stride = 2 * stride;
@@ -915,49 +872,11 @@
 #ifdef SBR_DEC
     if ((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1))
     {
-        uint8_t i, ch = 0;
-        for (i = 0; i < ch_ele; i++)
-        {
-            /* following case can happen when forceUpSampling == 1 */
-            if (hDecoder->sbr[i] == NULL)
-            {
-                hDecoder->sbr[i] = sbrDecodeInit(hDecoder->frameLength
-#ifdef DRM
-                    , 0
-#endif
-                    );
-                hDecoder->sbr[i]->id_aac = hDecoder->element_id[i];
-            }
-
-            /* Allocate space for SBR output */
-            if (hDecoder->time_out2[ch] == NULL)
-            {
-                hDecoder->time_out2[ch] = (real_t*)faad_malloc(hDecoder->frameLength*2*sizeof(real_t));
-                memset(hDecoder->time_out2[ch], 0, hDecoder->frameLength*2*sizeof(real_t));
-            }
-
-            if (hDecoder->sbr[i]->id_aac == ID_CPE)
-            {
-                /* space for 2 channels needed */
-                if (hDecoder->time_out2[ch+1] == NULL)
-                {
-                    hDecoder->time_out2[ch+1] = (real_t*)faad_malloc(hDecoder->frameLength*2*sizeof(real_t));
-                    memset(hDecoder->time_out2[ch+1], 0, hDecoder->frameLength*2*sizeof(real_t));
-                }
-
-                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 {
-                sbrDecodeSingleFrame(hDecoder->sbr[i], time_out[ch], time_out2[ch],
-                    hDecoder->postSeekResetFlag, hDecoder->forceUpSampling);
-                ch++;
-            }
-        }
+        /* this data is different when SBR is used or when the data is upsampled */
         frame_len *= 2;
         hInfo->samples *= 2;
         hInfo->samplerate *= 2;
+
         /* sbr */
         if (hDecoder->sbr_present_flag == 1)
         {
@@ -966,22 +885,18 @@
         } else {
             hInfo->sbr = NO_SBR_UPSAMPLED;
         }
-
-        sample_buffer = output_to_PCM(hDecoder, time_out2, sample_buffer,
-            output_channels, frame_len, outputFormat);
-    } else {
-#endif
-        sample_buffer = output_to_PCM(hDecoder, time_out, sample_buffer,
-            output_channels, frame_len, outputFormat);
-#ifdef SBR_DEC
     }
 #endif
 
+    sample_buffer = output_to_PCM(hDecoder, hDecoder->time_out, sample_buffer,
+        output_channels, frame_len, hDecoder->config.outputFormat);
+
+
     hDecoder->postSeekResetFlag = 0;
 
     hDecoder->frame++;
 #ifdef LD_DEC
-    if (object_type != LD)
+    if (hDecoder->object_type != LD)
     {
 #endif
         if (hDecoder->frame <= 1)
--- 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.22 2004/01/13 14:24:10 menno Exp $
+** $Id: sbr_dec.c,v 1.23 2004/01/13 20:35:14 menno Exp $
 **/
 
 
@@ -143,7 +143,7 @@
         sbr->prevEnvIsShort[ch] = -1;
 }
 
-static void sbr_process_channel(sbr_info *sbr, real_t *ch_in_buf, real_t *ch_out_buf,
+static void sbr_process_channel(sbr_info *sbr, real_t *channel_buf,
                                 uint8_t ch, uint8_t dont_process)
 {
     int16_t i, k, l;
@@ -153,125 +153,124 @@
     ALIGN real_t deg[64];
 #endif
 
-        if (sbr->frame == 0)
-        {
-            uint8_t j;
-            sbr->qmfa[ch] = qmfa_init(32);
-            sbr->qmfs[ch] = qmfs_init(64);
+    if (sbr->frame == 0)
+    {
+        uint8_t j;
+        sbr->qmfa[ch] = qmfa_init(32);
+        sbr->qmfs[ch] = qmfs_init(64);
 
-            for (j = 0; j < 5; j++)
-            {
-                sbr->G_temp_prev[ch][j] = faad_malloc(64*sizeof(real_t));
-                sbr->Q_temp_prev[ch][j] = faad_malloc(64*sizeof(real_t));
-            }
-
-            memset(sbr->Xsbr[ch], 0, (sbr->numTimeSlotsRate+sbr->tHFGen)*64 * sizeof(qmf_t));
-            memset(sbr->Xcodec[ch], 0, (sbr->numTimeSlotsRate+sbr->tHFGen)*32 * sizeof(qmf_t));
+        for (j = 0; j < 5; j++)
+        {
+            sbr->G_temp_prev[ch][j] = faad_malloc(64*sizeof(real_t));
+            sbr->Q_temp_prev[ch][j] = faad_malloc(64*sizeof(real_t));
         }
 
-        /* subband analysis */
-        if (dont_process)
-            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_in_buf, sbr->Xcodec[ch], sbr->tHFGen, sbr->kx);
+        memset(sbr->Xsbr[ch], 0, (sbr->numTimeSlotsRate+sbr->tHFGen)*64 * sizeof(qmf_t));
+        memset(sbr->Xcodec[ch], 0, (sbr->numTimeSlotsRate+sbr->tHFGen)*32 * sizeof(qmf_t));
+    }
 
-        if (!dont_process)
-        {
+    /* subband analysis */
+    if (dont_process)
+        sbr_qmf_analysis_32(sbr, sbr->qmfa[ch], channel_buf, sbr->Xcodec[ch], sbr->tHFGen, 32);
+    else
+        sbr_qmf_analysis_32(sbr, sbr->qmfa[ch], channel_buf, sbr->Xcodec[ch], sbr->tHFGen, sbr->kx);
+
+    if (!dont_process)
+    {
 #if 1
-            /* insert high frequencies here */
-            /* hf generation using patching */
-            hf_generation(sbr, sbr->Xcodec[ch], sbr->Xsbr[ch]
+        /* insert high frequencies here */
+        /* hf generation using patching */
+        hf_generation(sbr, sbr->Xcodec[ch], sbr->Xsbr[ch]
 #ifdef SBR_LOW_POWER
-                ,deg
+            ,deg
 #endif
-                ,ch);
+            ,ch);
 #endif
 
 #ifdef SBR_LOW_POWER
-            for (l = sbr->t_E[ch][0]; l < sbr->t_E[ch][sbr->L_E[ch]]; l++)
+        for (l = sbr->t_E[ch][0]; l < sbr->t_E[ch][sbr->L_E[ch]]; l++)
+        {
+            for (k = 0; k < sbr->kx; k++)
             {
-                for (k = 0; k < sbr->kx; k++)
-                {
-                    QMF_RE(sbr->Xsbr[ch][sbr->tHFAdj + l][k]) = 0;
-                }
+                QMF_RE(sbr->Xsbr[ch][sbr->tHFAdj + l][k]) = 0;
             }
+        }
 #endif
 
 #if 1
-            /* hf adjustment */
-            hf_adjustment(sbr, sbr->Xsbr[ch]
+        /* hf adjustment */
+        hf_adjustment(sbr, sbr->Xsbr[ch]
 #ifdef SBR_LOW_POWER
-                ,deg
+            ,deg
 #endif
-                ,ch);
+            ,ch);
 #endif
-        }
+    }
 
-        if ((sbr->just_seeked != 0) || dont_process)
+    if ((sbr->just_seeked != 0) || dont_process)
+    {
+        for (l = 0; l < sbr->numTimeSlotsRate; l++)
         {
-            for (l = 0; l < sbr->numTimeSlotsRate; l++)
+            for (k = 0; k < 32; k++)
             {
-                for (k = 0; k < 32; k++)
-                {
-                    QMF_RE(X[l][k]) = QMF_RE(sbr->Xcodec[ch][l + sbr->tHFAdj][k]);
+                QMF_RE(X[l][k]) = QMF_RE(sbr->Xcodec[ch][l + sbr->tHFAdj][k]);
 #ifndef SBR_LOW_POWER
-                    QMF_IM(X[l][k]) = QMF_IM(sbr->Xcodec[ch][l + sbr->tHFAdj][k]);
+                QMF_IM(X[l][k]) = QMF_IM(sbr->Xcodec[ch][l + sbr->tHFAdj][k]);
 #endif
-                }
-                for (k = 32; k < 64; k++)
-                {
-                    QMF_RE(X[l][k]) = 0;
+            }
+            for (k = 32; k < 64; k++)
+            {
+                QMF_RE(X[l][k]) = 0;
 #ifndef SBR_LOW_POWER
-                    QMF_IM(X[l][k]) = 0;
+                QMF_IM(X[l][k]) = 0;
 #endif
-                }
             }
-        } else {
-            for (l = 0; l < sbr->numTimeSlotsRate; l++)
-            {
-                uint8_t xover_band;
+        }
+    } else {
+        for (l = 0; l < sbr->numTimeSlotsRate; l++)
+        {
+            uint8_t xover_band;
 
-                if (l < sbr->t_E[ch][0])
-                    xover_band = sbr->kx_prev;
-                else
-                    xover_band = sbr->kx;
+            if (l < sbr->t_E[ch][0])
+                xover_band = sbr->kx_prev;
+            else
+                xover_band = sbr->kx;
 
-                for (k = 0; k < xover_band; k++)
-                {
-                    QMF_RE(X[l][k]) = QMF_RE(sbr->Xcodec[ch][l + sbr->tHFAdj][k]);
+            for (k = 0; k < xover_band; k++)
+            {
+                QMF_RE(X[l][k]) = QMF_RE(sbr->Xcodec[ch][l + sbr->tHFAdj][k]);
 #ifndef SBR_LOW_POWER
-                    QMF_IM(X[l][k]) = QMF_IM(sbr->Xcodec[ch][l + sbr->tHFAdj][k]);
+                QMF_IM(X[l][k]) = QMF_IM(sbr->Xcodec[ch][l + sbr->tHFAdj][k]);
 #endif
-                }
-                for (k = xover_band; k < 64; k++)
-                {
-                    QMF_RE(X[l][k]) = QMF_RE(sbr->Xsbr[ch][l + sbr->tHFAdj][k]);
+            }
+            for (k = xover_band; k < 64; k++)
+            {
+                QMF_RE(X[l][k]) = QMF_RE(sbr->Xsbr[ch][l + sbr->tHFAdj][k]);
 #ifndef SBR_LOW_POWER
-                    QMF_IM(X[l][k]) = QMF_IM(sbr->Xsbr[ch][l + sbr->tHFAdj][k]);
+                QMF_IM(X[l][k]) = QMF_IM(sbr->Xsbr[ch][l + sbr->tHFAdj][k]);
 #endif
-                }
+            }
 #ifdef SBR_LOW_POWER
-                QMF_RE(X[l][xover_band - 1]) += QMF_RE(sbr->Xsbr[ch][l + sbr->tHFAdj][xover_band - 1]);
+            QMF_RE(X[l][xover_band - 1]) += QMF_RE(sbr->Xsbr[ch][l + sbr->tHFAdj][xover_band - 1]);
 #endif
-            }
         }
+    }
 
-        /* subband synthesis */
+    /* subband synthesis */
 #ifndef USE_SSE
-        sbr_qmf_synthesis_64(sbr, sbr->qmfs[ch], X, ch_out_buf);
+    sbr_qmf_synthesis_64(sbr, sbr->qmfs[ch], X, channel_buf);
 #else
-        sbr->qmfs[ch]->qmf_func(sbr, sbr->qmfs[ch], X, ch_out_buf);
+    sbr->qmfs[ch]->qmf_func(sbr, sbr->qmfs[ch], X, channel_buf);
 #endif
 
-        for (i = 0; i < sbr->tHFGen; i++)
-        {
-            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));
-        }
+    for (i = 0; i < sbr->tHFGen; i++)
+    {
+        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,
+void sbrDecodeCoupleFrame(sbr_info *sbr, real_t *left_chan, real_t *right_chan,
                           const uint8_t just_seeked, const uint8_t upsample_only)
 {
     uint8_t dont_process = 0;
@@ -293,8 +292,8 @@
         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);
+    sbr_process_channel(sbr, left_chan, 0, dont_process);
+    sbr_process_channel(sbr, right_chan, 1, dont_process);
 
     if (sbr->bs_header_flag)
         sbr->just_seeked = 0;
@@ -308,7 +307,7 @@
     sbr->frame++;
 }
 
-void sbrDecodeSingleFrame(sbr_info *sbr, real_t *left_in, real_t *left_out,
+void sbrDecodeSingleFrame(sbr_info *sbr, real_t *channel,
                           const uint8_t just_seeked, const uint8_t upsample_only)
 {
     uint8_t dont_process = 0;
@@ -330,7 +329,7 @@
         sbr->just_seeked = 0;
     }
 
-    sbr_process_channel(sbr, left_in, left_out, 0, dont_process);
+    sbr_process_channel(sbr, channel, 0, dont_process);
 
     if (sbr->bs_header_flag)
         sbr->just_seeked = 0;
--- 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.16 2004/01/13 14:24:10 menno Exp $
+** $Id: sbr_dec.h,v 1.17 2004/01/13 20:35:14 menno Exp $
 **/
 
 #ifndef __SBR_DEC_H__
@@ -212,10 +212,9 @@
 						);
 void sbrDecodeEnd(sbr_info *sbr);
 
-void sbrDecodeCoupleFrame(sbr_info *sbr, real_t *left_in, real_t *right_in,
-                          real_t *left_out, real_t *right_out,
+void sbrDecodeCoupleFrame(sbr_info *sbr, real_t *left_chan, real_t *right_chan,
                           const uint8_t just_seeked, const uint8_t upsample_only);
-void sbrDecodeSingleFrame(sbr_info *sbr, real_t *left_in, real_t *left_out,
+void sbrDecodeSingleFrame(sbr_info *sbr, real_t *channel,
                           const uint8_t just_seeked, const uint8_t upsample_only);
 
 
--- 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.38 2004/01/13 14:24:10 menno Exp $
+** $Id: specrec.c,v 1.39 2004/01/13 20:35:14 menno Exp $
 **/
 
 /*
@@ -682,7 +682,7 @@
 uint8_t reconstruct_single_channel(faacDecHandle hDecoder, ic_stream *ics,
                                    element *sce, int16_t *spec_data)
 {
-    uint8_t retval;
+    uint8_t retval, mul;
     ALIGN real_t spec_coef[1024];
 
 #ifdef PROFILE
@@ -777,10 +777,19 @@
             drc_decode(hDecoder->drc, spec_coef);
     }
 
+    mul = 1;
+#ifdef SBR_DEC
+    if ((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1))
+    {
+        /* SBR requires 2 times as much output data */
+        mul = 2;
+    }
+#endif
+
     if (hDecoder->time_out[sce->channel] == NULL)
     {
-        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));
+        hDecoder->time_out[sce->channel] = (real_t*)faad_malloc(mul*hDecoder->frameLength*sizeof(real_t));
+        memset(hDecoder->time_out[sce->channel], 0, mul*hDecoder->frameLength*sizeof(real_t));
     }
 
     if (hDecoder->fb_intermed[sce->channel] == NULL)
@@ -837,6 +846,28 @@
     }
 #endif
 
+#ifdef SBR_DEC
+    if ((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1))
+    {
+        uint8_t ele = hDecoder->fr_ch_ele;
+        uint8_t ch = sce->channel;
+
+        /* following case can happen when forceUpSampling == 1 */
+        if (hDecoder->sbr[ele] == NULL)
+        {
+            hDecoder->sbr[ele] = sbrDecodeInit(hDecoder->frameLength
+#ifdef DRM
+                , 0
+#endif
+                );
+            hDecoder->sbr[ele]->id_aac = sce->ele_id;
+        }
+
+        sbrDecodeSingleFrame(hDecoder->sbr[ele], hDecoder->time_out[ch],
+            hDecoder->postSeekResetFlag, hDecoder->forceUpSampling);
+    }
+#endif
+
     return 0;
 }
 
@@ -843,7 +874,7 @@
 uint8_t reconstruct_channel_pair(faacDecHandle hDecoder, ic_stream *ics1, ic_stream *ics2,
                                  element *cpe, int16_t *spec_data1, int16_t *spec_data2)
 {
-    uint8_t retval;
+    uint8_t retval, mul;
     ALIGN real_t spec_coef1[1024];
     ALIGN real_t spec_coef2[1024];
 
@@ -987,15 +1018,24 @@
             drc_decode(hDecoder->drc, spec_coef2);
     }
 
+    mul = 1;
+#ifdef SBR_DEC
+    if ((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1))
+    {
+        /* SBR requires 2 times as much output data */
+        mul = 2;
+    }
+#endif
+
     if (hDecoder->time_out[cpe->channel] == NULL)
     {
-        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));
+        hDecoder->time_out[cpe->channel] = (real_t*)faad_malloc(mul*hDecoder->frameLength*sizeof(real_t));
+        memset(hDecoder->time_out[cpe->channel], 0, mul*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*sizeof(real_t));
-        memset(hDecoder->time_out[cpe->paired_channel], 0, hDecoder->frameLength*sizeof(real_t));
+        hDecoder->time_out[cpe->paired_channel] = (real_t*)faad_malloc(mul*hDecoder->frameLength*sizeof(real_t));
+        memset(hDecoder->time_out[cpe->paired_channel], 0, mul*hDecoder->frameLength*sizeof(real_t));
     }
 
     if (hDecoder->fb_intermed[cpe->channel] == NULL)
@@ -1080,6 +1120,30 @@
             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->fb_intermed[cpe->paired_channel], hDecoder->frameLength, hDecoder->object_type);
+    }
+#endif
+
+#ifdef SBR_DEC
+    if ((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1))
+    {
+        uint8_t ele = hDecoder->fr_ch_ele;
+        uint8_t ch0 = cpe->channel;
+        uint8_t ch1 = cpe->paired_channel;
+
+        /* following case can happen when forceUpSampling == 1 */
+        if (hDecoder->sbr[ele] == NULL)
+        {
+            hDecoder->sbr[ele] = sbrDecodeInit(hDecoder->frameLength
+#ifdef DRM
+                , 0
+#endif
+                );
+            hDecoder->sbr[ele]->id_aac = cpe->ele_id;
+        }
+
+        sbrDecodeCoupleFrame(hDecoder->sbr[ele],
+            hDecoder->time_out[ch0], hDecoder->time_out[ch1],
+            hDecoder->postSeekResetFlag, hDecoder->forceUpSampling);
     }
 #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.26 2004/01/13 14:24:10 menno Exp $
+** $Id: structs.h,v 1.27 2004/01/13 20:35:14 menno Exp $
 **/
 
 #ifndef __STRUCTS_H__
@@ -399,8 +399,6 @@
 #ifdef SBR_DEC
     int8_t sbr_present_flag;
     int8_t forceUpSampling;
-
-    real_t *time_out2[MAX_CHANNELS];
 
     uint8_t sbr_used[32];