shithub: aacdec

Download patch

ref: dcebb7ecc54d95970cf9e6667c8dbe985a396751
parent: 394d1b79f128883302ab80c879f7c611e92f11fe
author: menno <menno>
date: Fri Jan 16 15:20:32 EST 2004

Stability fixes

--- 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.34 2004/01/14 20:32:30 menno Exp $
+** $Id: bits.c,v 1.35 2004/01/16 20:20:32 menno Exp $
 **/
 
 #include "common.h"
@@ -74,7 +74,13 @@
 void faad_endbits(bitfile *ld)
 {
     if (ld)
-        if (ld->buffer) faad_free(ld->buffer);
+    {
+        if (ld->buffer)
+        {
+            faad_free(ld->buffer);
+            ld->buffer = NULL;
+        }
+    }
 }
 
 uint32_t faad_get_processed_bits(bitfile *ld)
--- 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.33 2004/01/14 20:36:22 menno Exp $
+** $Id: bits.h,v 1.34 2004/01/16 20:20:32 menno Exp $
 **/
 
 #ifndef __BITS_H__
@@ -178,7 +178,7 @@
     r = (uint8_t)(ld->bufb >> 31);
     faad_flushbits_ex(ld, 1);
 #else
-    r = faad_getbits(ld, 1);
+    r = (uint8_t)faad_getbits(ld, 1);
 #endif
     return r;
 }
--- 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.91 2004/01/14 20:32:30 menno Exp $
+** $Id: decoder.c,v 1.92 2004/01/16 20:20:32 menno Exp $
 **/
 
 #include "common.h"
@@ -128,7 +128,7 @@
     }
 
 #ifdef SBR_DEC
-    for (i = 0; i < 32; i++)
+    for (i = 0; i < MAX_SYNTAX_ELEMENTS; i++)
     {
         hDecoder->sbr[i] = NULL;
     }
@@ -441,7 +441,7 @@
     }
 
 #ifdef SBR_DEC
-    for (i = 0; i < 32; i++)
+    for (i = 0; i < MAX_SYNTAX_ELEMENTS; i++)
     {
         if (hDecoder->sbr[i])
             sbrDecodeEnd(hDecoder->sbr[i]);
@@ -497,7 +497,7 @@
     if (hDecoder->sample_buffer) faad_free(hDecoder->sample_buffer);
 
 #ifdef SBR_DEC
-    for (i = 0; i < 32; i++)
+    for (i = 0; i < MAX_SYNTAX_ELEMENTS; i++)
     {
         if (hDecoder->sbr[i])
             sbrDecodeEnd(hDecoder->sbr[i]);
@@ -803,6 +803,13 @@
     if (hInfo->error > 0)
         goto error;
 
+    /* safety check */
+    if (channels == 0 || channels > MAX_CHANNELS)
+    {
+        /* invalid number of channels */
+        hInfo->error = 12;
+        goto error;
+    }
 
     /* no more bit reading after this */
     bitsconsumed = faad_get_processed_bits(&ld);
@@ -862,7 +869,8 @@
     }
 
     /* allocate the buffer for the final samples */
-    if (hDecoder->sample_buffer == NULL)
+    if ((hDecoder->sample_buffer == NULL) ||
+        (hDecoder->alloced_channels != output_channels))
     {
         static const uint8_t str[] = { sizeof(int16_t), sizeof(int32_t), sizeof(int32_t),
             sizeof(float32_t), sizeof(double), sizeof(int16_t), sizeof(int16_t),
@@ -873,7 +881,11 @@
         if ((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1))
             stride = 2 * stride;
 #endif
-        hDecoder->sample_buffer = faad_malloc(frame_len*channels*stride);
+        if (hDecoder->sample_buffer)
+            faad_free(hDecoder->sample_buffer);
+        hDecoder->sample_buffer = NULL;
+        hDecoder->sample_buffer = faad_malloc(frame_len*output_channels*stride);
+        hDecoder->alloced_channels = output_channels;
     }
 
     sample_buffer = hDecoder->sample_buffer;
@@ -881,10 +893,22 @@
 #ifdef SBR_DEC
     if ((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1))
     {
+        uint8_t ele;
+
         /* this data is different when SBR is used or when the data is upsampled */
         frame_len *= 2;
         hInfo->samples *= 2;
         hInfo->samplerate *= 2;
+
+        /* check if every element was provided with SBR data */
+        for (ele = 0; ele < hDecoder->fr_ch_ele; ele++)
+        {
+            if (hDecoder->sbr[ele] == NULL)
+            {
+                hInfo->error = 25;
+                goto error;
+            }
+        }
 
         /* sbr */
         if (hDecoder->sbr_present_flag == 1)
--- a/libfaad/error.c
+++ b/libfaad/error.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: error.c,v 1.19 2004/01/05 14:05:11 menno Exp $
+** $Id: error.c,v 1.20 2004/01/16 20:20:32 menno Exp $
 **/
 
 #include "common.h"
@@ -41,12 +41,19 @@
     "Error decoding huffman scalefactor (bitstream error)",
     "Error decoding huffman codeword (bitstream error)",
     "Non existent huffman codebook number found",
-    "Maximum number of channels exceeded",
+    "Invalid number of channels",
     "Maximum number of bitstream elements exceeded",
     "Input data buffer too small",
     "Array index out of range",
     "Maximum number of scalefactor bands exceeded",
     "Quantised value out of range",
-    "LTP lag out of range"
+    "LTP lag out of range",
+    "Invalid SBR parameter decoded",
+    "SBR called without being initialised",
+    "Unexpected channel configuration change",
+    "Error in program_config_element",
+    "First SBR frame is not the same as first AAC frame",
+    "Unexpected fill element with SBR data",
+    "Not all elements were provided with SBR data"
 };
 
--- a/libfaad/error.h
+++ b/libfaad/error.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: error.h,v 1.14 2004/01/05 14:05:11 menno Exp $
+** $Id: error.h,v 1.15 2004/01/16 20:20:32 menno Exp $
 **/
 
 #ifndef __ERROR_H__
@@ -32,7 +32,7 @@
 extern "C" {
 #endif
 
-#define NUM_ERROR_MESSAGES 19
+#define NUM_ERROR_MESSAGES 26
 extern int8_t *err_msg[];
 
 #ifdef __cplusplus
--- 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.14 2004/01/14 20:39:59 menno Exp $
+** $Id: huffman.c,v 1.15 2004/01/16 20:20:32 menno Exp $
 **/
 
 #include "common.h"
@@ -168,12 +168,8 @@
     {
         /* we know for sure it's more than hcbN[cb] bits long */
         faad_flushbits(ld, hcbN[cb]);
-#if 1
         offset += (uint16_t)faad_showbits(ld, extra_bits);
         faad_flushbits(ld, hcb_2_quad_table[cb][offset].bits - hcbN[cb]);
-#else
-        offset += (uint16_t)faad_getbits(ld, extra_bits);
-#endif
     } else {
         faad_flushbits(ld, hcb_2_quad_table[cb][offset].bits);
     }
@@ -215,12 +211,8 @@
     {
         /* we know for sure it's more than hcbN[cb] bits long */
         faad_flushbits(ld, hcbN[cb]);
-#if 1
         offset += (uint16_t)faad_showbits(ld, extra_bits);
         faad_flushbits(ld, hcb_2_pair_table[cb][offset].bits - hcbN[cb]);
-#else
-        offset += (uint16_t)faad_getbits(ld, extra_bits);
-#endif
     } else {
         faad_flushbits(ld, hcb_2_pair_table[cb][offset].bits);
     }
--- a/libfaad/is.c
+++ b/libfaad/is.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: is.c,v 1.19 2004/01/05 14:05:12 menno Exp $
+** $Id: is.c,v 1.21 2004/02/26 09:29:27 menno Exp $
 **/
 
 #include "common.h"
--- a/libfaad/rvlc.c
+++ b/libfaad/rvlc.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: rvlc.c,v 1.13 2004/01/05 14:05:12 menno Exp $
+** $Id: rvlc.c,v 1.17 2004/09/04 14:56:28 menno Exp $
 **/
 
 /* RVLC scalefactor decoding
--- 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.24 2004/01/14 20:32:30 menno Exp $
+** $Id: sbr_dec.c,v 1.25 2004/01/16 20:20:32 menno Exp $
 **/
 
 
@@ -42,7 +42,7 @@
 #include "sbr_hfadj.h"
 
 /* static function declarations */
-static void sbr_save_prev_data(sbr_info *sbr, uint8_t ch);
+static uint8_t sbr_save_prev_data(sbr_info *sbr, uint8_t ch);
 
 sbr_info *sbrDecodeInit(uint16_t framelength, uint8_t id_aac,
                         uint32_t sample_rate
@@ -120,7 +120,7 @@
     }
 }
 
-static void sbr_save_prev_data(sbr_info *sbr, uint8_t ch)
+static uint8_t sbr_save_prev_data(sbr_info *sbr, uint8_t ch)
 {
     uint8_t i;
 
@@ -130,21 +130,14 @@
     sbr->L_E_prev[ch] = sbr->L_E[ch];
 
     /* sbr->L_E[ch] can become 0 on files with bit errors */
-    if (sbr->L_E[ch] > 0)
+    if (sbr->L_E[ch] <= 0)
+        return 19;
+
+    sbr->f_prev[ch] = sbr->f[ch][sbr->L_E[ch] - 1];
+    for (i = 0; i < 64; i++)
     {
-        sbr->f_prev[ch] = sbr->f[ch][sbr->L_E[ch] - 1];
-        for (i = 0; i < 64; i++)
-        {
-            sbr->E_prev[ch][i] = sbr->E[ch][i][sbr->L_E[ch] - 1];
-            sbr->Q_prev[ch][i] = sbr->Q[ch][i][sbr->L_Q[ch] - 1];
-        }
-    } else {
-        sbr->f_prev[ch] = 0;
-        for (i = 0; i < 64; i++)
-        {
-            sbr->E_prev[ch][i] = 0;
-            sbr->Q_prev[ch][i] = 0;
-        }
+        sbr->E_prev[ch][i] = sbr->E[ch][i][sbr->L_E[ch] - 1];
+        sbr->Q_prev[ch][i] = sbr->Q[ch][i][sbr->L_Q[ch] - 1];
     }
 
     for (i = 0; i < 64; i++)
@@ -157,6 +150,8 @@
         sbr->prevEnvIsShort[ch] = 0;
     else
         sbr->prevEnvIsShort[ch] = -1;
+
+    return 0;
 }
 
 static void sbr_process_channel(sbr_info *sbr, real_t *channel_buf,
@@ -252,10 +247,6 @@
             else
                 xover_band = sbr->kx;
 
-            /* kx can be > 32 in cases of bit errors */
-            /* TODO: should be checked somewhere else */
-            xover_band = min(xover_band, 32);
-
             for (k = 0; k < xover_band; k++)
             {
                 QMF_RE(X[l][k]) = QMF_RE(sbr->Xcodec[ch][l + sbr->tHFAdj][k]);
@@ -290,17 +281,18 @@
     }
 }
 
-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 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;
+    uint8_t ret = 0;
 
     if (sbr == NULL)
-        return;
+        return 20;
 
     /* case can occur due to bit errors */
     if (sbr->id_aac != ID_CPE)
-        return;
+        return 21;
 
     if (sbr->ret || (sbr->header_count == 0))
     {
@@ -325,26 +317,31 @@
     if (sbr->bs_header_flag)
         sbr->just_seeked = 0;
 
-    if (sbr->header_count != 0)
+    if (sbr->header_count != 0 && sbr->ret == 0)
     {
-        sbr_save_prev_data(sbr, 0);
-        sbr_save_prev_data(sbr, 1);
+        ret = sbr_save_prev_data(sbr, 0);
+        if (ret) return ret;
+        ret = sbr_save_prev_data(sbr, 1);
+        if (ret) return ret;
     }
 
     sbr->frame++;
+
+    return 0;
 }
 
-void sbrDecodeSingleFrame(sbr_info *sbr, real_t *channel,
-                          const uint8_t just_seeked, const uint8_t upsample_only)
+uint8_t sbrDecodeSingleFrame(sbr_info *sbr, real_t *channel,
+                             const uint8_t just_seeked, const uint8_t upsample_only)
 {
     uint8_t dont_process = 0;
+    uint8_t ret = 0;
 
     if (sbr == NULL)
-        return;
+        return 20;
 
     /* case can occur due to bit errors */
     if (sbr->id_aac != ID_SCE && sbr->id_aac != ID_LFE)
-        return;
+        return 21;
 
     if (sbr->ret || (sbr->header_count == 0))
     {
@@ -368,12 +365,15 @@
     if (sbr->bs_header_flag)
         sbr->just_seeked = 0;
 
-    if (sbr->header_count != 0)
+    if (sbr->header_count != 0 && sbr->ret == 0)
     {
-        sbr_save_prev_data(sbr, 0);
+        ret = sbr_save_prev_data(sbr, 0);
+        if (ret) return ret;
     }
 
     sbr->frame++;
+
+    return 0;
 }
 
 #endif
--- 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.18 2004/01/14 20:32:30 menno Exp $
+** $Id: sbr_dec.h,v 1.19 2004/01/16 20:20:32 menno Exp $
 **/
 
 #ifndef __SBR_DEC_H__
@@ -213,10 +213,10 @@
 						);
 void sbrDecodeEnd(sbr_info *sbr);
 
-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 *channel,
-                          const uint8_t just_seeked, const uint8_t upsample_only);
+uint8_t sbrDecodeCoupleFrame(sbr_info *sbr, real_t *left_chan, real_t *right_chan,
+                             const uint8_t just_seeked, const uint8_t upsample_only);
+uint8_t sbrDecodeSingleFrame(sbr_info *sbr, real_t *channel,
+                             const uint8_t just_seeked, const uint8_t upsample_only);
 
 
 #ifdef __cplusplus
--- a/libfaad/sbr_fbt.c
+++ b/libfaad/sbr_fbt.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_fbt.c,v 1.9 2004/01/05 14:05:12 menno Exp $
+** $Id: sbr_fbt.c,v 1.10 2004/01/16 20:20:32 menno Exp $
 **/
 
 /* Calculate frequency band tables */
@@ -184,8 +184,8 @@
 
    version for bs_freq_scale = 0
 */
-void master_frequency_table_fs0(sbr_info *sbr, uint8_t k0, uint8_t k2,
-                                uint8_t bs_alter_scale)
+uint8_t master_frequency_table_fs0(sbr_info *sbr, uint8_t k0, uint8_t k2,
+                                   uint8_t bs_alter_scale)
 {
     int8_t incr;
     uint8_t k;
@@ -197,7 +197,7 @@
     if (k2 <= k0)
     {
         sbr->N_master = 0;
-        return;
+        return 0;
     }
 
     dk = bs_alter_scale ? 2 : 1;
@@ -213,6 +213,8 @@
     }
 #endif
     nrBands = min(nrBands, 63);
+    if (nrBands <= 0)
+        return 1;
 
     k2Achieved = k0 + nrBands * dk;
     k2Diff = k2 - k2Achieved;
@@ -247,6 +249,8 @@
     }
     printf("\n");
 #endif
+
+    return 0;
 }
 
 /*
@@ -255,22 +259,93 @@
 */
 static int32_t find_bands(uint8_t warp, uint8_t bands, uint8_t a0, uint8_t a1)
 {
+#ifdef FIXED_POINT
+    /* table with log2() values */
+    static const real_t log2Table[65] = {
+        COEF_CONST(0.0), COEF_CONST(0.0), COEF_CONST(1.0000000000), COEF_CONST(1.5849625007),
+        COEF_CONST(2.0000000000), COEF_CONST(2.3219280949), COEF_CONST(2.5849625007), COEF_CONST(2.8073549221),
+        COEF_CONST(3.0000000000), COEF_CONST(3.1699250014), COEF_CONST(3.3219280949), COEF_CONST(3.4594316186),
+        COEF_CONST(3.5849625007), COEF_CONST(3.7004397181), COEF_CONST(3.8073549221), COEF_CONST(3.9068905956),
+        COEF_CONST(4.0000000000), COEF_CONST(4.0874628413), COEF_CONST(4.1699250014), COEF_CONST(4.2479275134),
+        COEF_CONST(4.3219280949), COEF_CONST(4.3923174228), COEF_CONST(4.4594316186), COEF_CONST(4.5235619561),
+        COEF_CONST(4.5849625007), COEF_CONST(4.6438561898), COEF_CONST(4.7004397181), COEF_CONST(4.7548875022),
+        COEF_CONST(4.8073549221), COEF_CONST(4.8579809951), COEF_CONST(4.9068905956), COEF_CONST(4.9541963104),
+        COEF_CONST(5.0000000000), COEF_CONST(5.0443941194), COEF_CONST(5.0874628413), COEF_CONST(5.1292830169),
+        COEF_CONST(5.1699250014), COEF_CONST(5.2094533656), COEF_CONST(5.2479275134), COEF_CONST(5.2854022189),
+        COEF_CONST(5.3219280949), COEF_CONST(5.3575520046), COEF_CONST(5.3923174228), COEF_CONST(5.4262647547),
+        COEF_CONST(5.4594316186), COEF_CONST(5.4918530963), COEF_CONST(5.5235619561), COEF_CONST(5.5545888517),
+        COEF_CONST(5.5849625007), COEF_CONST(5.6147098441), COEF_CONST(5.6438561898), COEF_CONST(5.6724253420),
+        COEF_CONST(5.7004397181), COEF_CONST(5.7279204546), COEF_CONST(5.7548875022), COEF_CONST(5.7813597135),
+        COEF_CONST(5.8073549221), COEF_CONST(5.8328900142), COEF_CONST(5.8579809951), COEF_CONST(5.8826430494),
+        COEF_CONST(5.9068905956), COEF_CONST(5.9307373376), COEF_CONST(5.9541963104), COEF_CONST(5.9772799235),
+        COEF_CONST(6.0)
+    };
+    real_t r0 = log2Table[a0]; /* coef */
+    real_t r1 = log2Table[a1]; /* coef */
+    real_t r2 = (r1 - r0); /* coef */
+
+    if (warp)
+        r2 = MUL_C(r2, COEF_CONST(1.0/1.3));
+
+    /* convert r2 to real and then multiply and round */
+    r2 = (r2 >> (COEF_BITS-REAL_BITS)) * bands + (1<<(REAL_BITS-1));
+
+    return (r2 >> REAL_BITS);
+#else
     real_t div = (real_t)log(2.0);
     if (warp) div *= (real_t)1.3;
 
     return (int32_t)(bands * log((float)a1/(float)a0)/div + 0.5);
+#endif
 }
 
 static real_t find_initial_power(uint8_t bands, uint8_t a0, uint8_t a1)
 {
+#ifdef FIXED_POINT
+    /* table with log() values */
+    static const real_t logTable[65] = {
+        COEF_CONST(0.0), COEF_CONST(0.0), COEF_CONST(0.6931471806), COEF_CONST(1.0986122887),
+        COEF_CONST(1.3862943611), COEF_CONST(1.6094379124), COEF_CONST(1.7917594692), COEF_CONST(1.9459101491),
+        COEF_CONST(2.0794415417), COEF_CONST(2.1972245773), COEF_CONST(2.3025850930), COEF_CONST(2.3978952728),
+        COEF_CONST(2.4849066498), COEF_CONST(2.5649493575), COEF_CONST(2.6390573296), COEF_CONST(2.7080502011),
+        COEF_CONST(2.7725887222), COEF_CONST(2.8332133441), COEF_CONST(2.8903717579), COEF_CONST(2.9444389792),
+        COEF_CONST(2.9957322736), COEF_CONST(3.0445224377), COEF_CONST(3.0910424534), COEF_CONST(3.1354942159),
+        COEF_CONST(3.1780538303), COEF_CONST(3.2188758249), COEF_CONST(3.2580965380), COEF_CONST(3.2958368660),
+        COEF_CONST(3.3322045102), COEF_CONST(3.3672958300), COEF_CONST(3.4011973817), COEF_CONST(3.4339872045),
+        COEF_CONST(3.4657359028), COEF_CONST(3.4965075615), COEF_CONST(3.5263605246), COEF_CONST(3.5553480615),
+        COEF_CONST(3.5835189385), COEF_CONST(3.6109179126), COEF_CONST(3.6375861597), COEF_CONST(3.6635616461),
+        COEF_CONST(3.6888794541), COEF_CONST(3.7135720667), COEF_CONST(3.7376696183), COEF_CONST(3.7612001157),
+        COEF_CONST(3.7841896339), COEF_CONST(3.8066624898), COEF_CONST(3.8286413965), COEF_CONST(3.8501476017),
+        COEF_CONST(3.8712010109), COEF_CONST(3.8918202981), COEF_CONST(3.9120230054), COEF_CONST(3.9318256327),
+        COEF_CONST(3.9512437186), COEF_CONST(3.9702919136), COEF_CONST(3.9889840466), COEF_CONST(4.0073331852),
+        COEF_CONST(4.0253516907), COEF_CONST(4.0430512678), COEF_CONST(4.0604430105), COEF_CONST(4.0775374439),
+        COEF_CONST(4.0943445622), COEF_CONST(4.1108738642), COEF_CONST(4.1271343850), COEF_CONST(4.1431347264),
+        COEF_CONST(4.158883083)
+    };
+    /* standard Taylor polynomial coefficients for exp(x) around 0 */
+    /* a polynomial around x=1 is more precise, as most values are around 1.07,
+       but this is just fine already */
+    static const real_t c1 = COEF_CONST(1.0);
+    static const real_t c2 = COEF_CONST(1.0/2.0);
+    static const real_t c3 = COEF_CONST(1.0/6.0);
+    static const real_t c4 = COEF_CONST(1.0/24.0);
+
+    real_t r0 = logTable[a0]; /* coef */
+    real_t r1 = logTable[a1]; /* coef */
+    real_t r2 = (r1 - r0) / bands; /* coef */
+    real_t rexp = c1 + MUL_C((c1 + MUL_C((c2 + MUL_C((c3 + MUL_C(c4,r2)), r2)), r2)), r2);
+
+    return (rexp >> (COEF_BITS-REAL_BITS)); /* real */
+#else
     return (real_t)pow((real_t)a1/(real_t)a0, 1.0/(real_t)bands);
+#endif
 }
 
 /*
    version for bs_freq_scale > 0
 */
-void master_frequency_table(sbr_info *sbr, uint8_t k0, uint8_t k2,
-                            uint8_t bs_freq_scale, uint8_t bs_alter_scale)
+uint8_t master_frequency_table(sbr_info *sbr, uint8_t k0, uint8_t k2,
+                               uint8_t bs_freq_scale, uint8_t bs_alter_scale)
 {
     uint8_t k, bands, twoRegions;
     uint8_t k1;
@@ -285,12 +360,16 @@
     if (k2 <= k0)
     {
         sbr->N_master = 0;
-        return;
+        return 0;
     }
 
     bands = temp1[bs_freq_scale-1];
 
+#ifdef FIXED_POINT
+    if (REAL_CONST(k2) > MUL_R(REAL_CONST(k0),REAL_CONST(2.2449)))
+#else
     if ((float)k2/(float)k0 > 2.2449)
+#endif
     {
         twoRegions = 1;
         k1 = k0 << 1;
@@ -301,15 +380,26 @@
 
     nrBand0 = 2 * find_bands(0, bands, k0, k1);
     nrBand0 = min(nrBand0, 63);
+    if (nrBand0 <= 0)
+        return 1;
 
     q = find_initial_power(nrBand0, k0, k1);
     qk = REAL_CONST(k0);
+#ifdef FIXED_POINT
+    A_1 = (int32_t)((qk + REAL_CONST(0.5)) >> REAL_BITS);
+#else
     A_1 = (int32_t)(qk + .5);
+#endif
     for (k = 0; k <= nrBand0; k++)
     {
         int32_t A_0 = A_1;
+#ifdef FIXED_POINT
+        qk = MUL_R(qk,q);
+        A_1 = (int32_t)((qk + REAL_CONST(0.5)) >> REAL_BITS);
+#else
         qk *= q;
         A_1 = (int32_t)(qk + 0.5);
+#endif
         vDk0[k] = A_1 - A_0;
     }
 
@@ -320,6 +410,8 @@
     for (k = 1; k <= nrBand0; k++)
     {
         vk0[k] = vk0[k-1] + vDk0[k-1];
+        if (vDk0[k-1] == 0)
+            return 1;
     }
 
     if (!twoRegions)
@@ -329,7 +421,7 @@
 
         sbr->N_master = nrBand0;
         sbr->N_master = min(sbr->N_master, 64);
-        return;
+        return 0;
     }
 
     nrBand1 = 2 * find_bands(1 /* warped */, bands, k1, k2);
@@ -337,12 +429,21 @@
 
     q = find_initial_power(nrBand1, k1, k2);
     qk = REAL_CONST(k1);
+#ifdef FIXED_POINT
+    A_1 = (int32_t)((qk + REAL_CONST(0.5)) >> REAL_BITS);
+#else
     A_1 = (int32_t)(qk + .5);
+#endif
     for (k = 0; k <= nrBand1 - 1; k++)
     {
         int32_t A_0 = A_1;
+#ifdef FIXED_POINT
+        qk = MUL_R(qk,q);
+        A_1 = (int32_t)((qk + REAL_CONST(0.5)) >> REAL_BITS);
+#else
         qk *= q;
         A_1 = (int32_t)(qk + 0.5);
+#endif
         vDk1[k] = A_1 - A_0;
     }
 
@@ -363,6 +464,8 @@
     for (k = 1; k <= nrBand1; k++)
     {
         vk1[k] = vk1[k-1] + vDk1[k-1];
+        if (vDk1[k-1] == 0)
+            return 1;
     }
 
     sbr->N_master = nrBand0 + nrBand1;
@@ -384,6 +487,8 @@
     }
     printf("\n");
 #endif
+
+    return 0;
 }
 
 /* calculate the derived frequency border tables from f_master */
@@ -410,6 +515,10 @@
 
     sbr->M = sbr->f_table_res[HI_RES][sbr->N_high] - sbr->f_table_res[HI_RES][0];
     sbr->kx = sbr->f_table_res[HI_RES][0];
+    if (sbr->kx > 32)
+        return 1;
+    if (sbr->kx + sbr->M > 64)
+        return 1;
 
     minus = (sbr->N_high & 1) ? 1 : 0;
 
@@ -556,7 +665,11 @@
 #if 0
                 nOctaves = REAL_CONST(log((float)limTable[k]/(float)limTable[k-1])/log(2.0));
 #endif
+#ifdef FIXED_POINT
+                nOctaves = SBR_DIV(REAL_CONST(limTable[k]),REAL_CONST(limTable[k-1]));
+#else
                 nOctaves = (real_t)limTable[k]/(real_t)limTable[k-1];
+#endif
             else
                 nOctaves = 0;
 
--- a/libfaad/sbr_fbt.h
+++ b/libfaad/sbr_fbt.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_fbt.h,v 1.9 2004/01/05 14:05:12 menno Exp $
+** $Id: sbr_fbt.h,v 1.10 2004/01/16 20:20:32 menno Exp $
 **/
 
 #ifndef __SBR_FBT_H__
@@ -36,10 +36,10 @@
                            uint32_t sample_rate);
 uint8_t qmf_stop_channel(uint8_t bs_stop_freq, uint32_t sample_rate,
                           uint8_t k0);
-void master_frequency_table_fs0(sbr_info *sbr, uint8_t k0, uint8_t k2,
-                                uint8_t bs_alter_scale);
-void master_frequency_table(sbr_info *sbr, uint8_t k0, uint8_t k2,
-                            uint8_t bs_freq_scale, uint8_t bs_alter_scale);
+uint8_t master_frequency_table_fs0(sbr_info *sbr, uint8_t k0, uint8_t k2,
+                                   uint8_t bs_alter_scale);
+uint8_t master_frequency_table(sbr_info *sbr, uint8_t k0, uint8_t k2,
+                               uint8_t bs_freq_scale, uint8_t bs_alter_scale);
 uint8_t derived_frequency_table(sbr_info *sbr, uint8_t bs_xover_band,
                                 uint8_t k2);
 void limiter_frequency_table(sbr_info *sbr);
--- a/libfaad/sbr_syntax.c
+++ b/libfaad/sbr_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: sbr_syntax.c,v 1.21 2004/01/13 14:24:10 menno Exp $
+** $Id: sbr_syntax.c,v 1.22 2004/01/16 20:20:32 menno Exp $
 **/
 
 #include "common.h"
@@ -105,7 +105,7 @@
 /* table 2 */
 uint8_t sbr_extension_data(bitfile *ld, sbr_info *sbr, uint16_t cnt)
 {
-    uint8_t result;
+    uint8_t result = 0;
     uint16_t num_align_bits = 0;
     uint16_t num_sbr_bits = (uint16_t)faad_get_processed_bits(ld);
 
@@ -149,27 +149,30 @@
             if (sbr->sample_rate >= 48000)
             {
                 if ((k2 - sbr->k0) > 32)
-                    return 1;
+                    result += 1;
             } else if (sbr->sample_rate <= 32000) {
                 if ((k2 - sbr->k0) > 48)
-                    return 1;
+                    result += 1;
             } else { /* (sbr->sample_rate == 44100) */
                 if ((k2 - sbr->k0) > 45)
-                    return 1;
+                    result += 1;
             }
 
             if (sbr->bs_freq_scale == 0)
             {
-                master_frequency_table_fs0(sbr, sbr->k0, k2, sbr->bs_alter_scale);
+                result += master_frequency_table_fs0(sbr, sbr->k0, k2,
+                    sbr->bs_alter_scale);
             } else {
-                master_frequency_table(sbr, sbr->k0, k2, sbr->bs_freq_scale,
+                result += master_frequency_table(sbr, sbr->k0, k2, sbr->bs_freq_scale,
                     sbr->bs_alter_scale);
             }
-            if ((result = derived_frequency_table(sbr, sbr->bs_xover_band, k2)) > 0)
-                return result;
+            result += derived_frequency_table(sbr, sbr->bs_xover_band, k2);
+
+            result = (result > 0) ? 1 : 0;
         }
 
-        result = sbr_data(ld, sbr);
+        if (result == 0)
+            result = sbr_data(ld, sbr);
     } else {
         result = 1;
     }
@@ -633,6 +636,9 @@
         sbr->L_E[ch] = min(bs_num_env, 5);
     else
         sbr->L_E[ch] = min(bs_num_env, 4);
+
+    if (sbr->L_E[ch] <= 0)
+        return 1;
 
     if (sbr->L_E[ch] > 1)
         sbr->L_Q[ch] = 2;
--- 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.40 2004/01/14 20:32:30 menno Exp $
+** $Id: specrec.c,v 1.41 2004/01/16 20:20:32 menno Exp $
 **/
 
 /*
@@ -588,7 +588,8 @@
         {
             top = ics->sect_sfb_offset[g][sfb+1];
 
-            /* this could be scalefactor for IS or PNS, those could be negative or bigger then 255??? */
+            /* this could be scalefactor for IS or PNS, those can be negative or bigger then 255 */
+            /* just ignore them */
             if (ics->scale_factors[g][sfb] < 0 || ics->scale_factors[g][sfb] > 255)
             {
                 exp = 0;
@@ -790,12 +791,12 @@
     {
         mul = 1;
 #ifdef SBR_DEC
-        hDecoder->sbr_alloced = 0;
+        hDecoder->sbr_alloced[hDecoder->fr_ch_ele] = 0;
         if ((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1))
         {
             /* SBR requires 2 times as much output data */
             mul = 2;
-            hDecoder->sbr_alloced = 1;
+            hDecoder->sbr_alloced[hDecoder->fr_ch_ele] = 1;
         }
 #endif
         hDecoder->time_out[sce->channel] = (real_t*)faad_malloc(mul*hDecoder->frameLength*sizeof(real_t));
@@ -858,7 +859,7 @@
 
 #ifdef SBR_DEC
     if (((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1))
-        && hDecoder->sbr_alloced)
+        && hDecoder->sbr_alloced[hDecoder->fr_ch_ele])
     {
         uint8_t ele = hDecoder->fr_ch_ele;
         uint8_t ch = sce->channel;
@@ -874,11 +875,14 @@
                 );
         }
 
-        sbrDecodeSingleFrame(hDecoder->sbr[ele], hDecoder->time_out[ch],
+        retval = sbrDecodeSingleFrame(hDecoder->sbr[ele], hDecoder->time_out[ch],
             hDecoder->postSeekResetFlag, hDecoder->forceUpSampling);
-    } else {
-        hDecoder->sbr_present_flag = 0;
-        hDecoder->forceUpSampling = 0;
+        if (retval > 0)
+            return retval;
+    } else if (((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1))
+        && !hDecoder->sbr_alloced[hDecoder->fr_ch_ele])
+    {
+        return 23;
     }
 #endif
 
@@ -976,7 +980,7 @@
     if (is_ltp_ot(hDecoder->object_type))
     {
         ltp_info *ltp1 = &(ics1->ltp);
-        ltp_info *ltp2 = (cpe->common_window) ? &(ics2->ltp2) : &(ics2->ltp) ;
+        ltp_info *ltp2 = (cpe->common_window) ? &(ics2->ltp2) : &(ics2->ltp);
 #ifdef LD_DEC
         if (hDecoder->object_type == LD)
         {
@@ -1036,12 +1040,12 @@
     {
         mul = 1;
 #ifdef SBR_DEC
-        hDecoder->sbr_alloced = 0;
+        hDecoder->sbr_alloced[hDecoder->fr_ch_ele] = 0;
         if ((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1))
         {
             /* SBR requires 2 times as much output data */
             mul = 2;
-            hDecoder->sbr_alloced = 1;
+            hDecoder->sbr_alloced[hDecoder->fr_ch_ele] = 1;
         }
 #endif
         hDecoder->time_out[cpe->channel] = (real_t*)faad_malloc(mul*hDecoder->frameLength*sizeof(real_t));
@@ -1140,7 +1144,7 @@
 
 #ifdef SBR_DEC
     if (((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1))
-        && hDecoder->sbr_alloced)
+        && hDecoder->sbr_alloced[hDecoder->fr_ch_ele])
     {
         uint8_t ele = hDecoder->fr_ch_ele;
         uint8_t ch0 = cpe->channel;
@@ -1157,12 +1161,15 @@
                 );
         }
 
-        sbrDecodeCoupleFrame(hDecoder->sbr[ele],
+        retval = sbrDecodeCoupleFrame(hDecoder->sbr[ele],
             hDecoder->time_out[ch0], hDecoder->time_out[ch1],
             hDecoder->postSeekResetFlag, hDecoder->forceUpSampling);
-    } else {
-        hDecoder->sbr_present_flag = 0;
-        hDecoder->forceUpSampling = 0;
+        if (retval > 0)
+            return retval;
+    } else if (((hDecoder->sbr_present_flag == 1) || (hDecoder->forceUpSampling == 1))
+        && !hDecoder->sbr_alloced[hDecoder->fr_ch_ele])
+    {
+        return 23;
     }
 #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.28 2004/01/14 20:32:30 menno Exp $
+** $Id: structs.h,v 1.29 2004/01/16 20:20:32 menno Exp $
 **/
 
 #ifndef __STRUCTS_H__
@@ -385,6 +385,7 @@
     uint8_t fr_ch_ele;
 
     void *sample_buffer;
+    uint8_t alloced_channels;
 
     uint8_t window_shape_prev[MAX_CHANNELS];
 #ifdef LTP_DEC
@@ -399,9 +400,9 @@
 #ifdef SBR_DEC
     int8_t sbr_present_flag;
     int8_t forceUpSampling;
-    uint8_t sbr_alloced;
+    uint8_t sbr_alloced[MAX_SYNTAX_ELEMENTS];
 
-    sbr_info *sbr[32];
+    sbr_info *sbr[MAX_SYNTAX_ELEMENTS];
 #ifdef DRM
     int8_t lcstereo_flag;
 #endif
--- 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.67 2004/01/14 20:32:30 menno Exp $
+** $Id: syntax.c,v 1.68 2004/01/16 20:20:32 menno Exp $
 **/
 
 /*
@@ -118,7 +118,8 @@
     mp4ASC->extensionFlag = faad_get1bit(ld DEBUGVAR(1,141,"GASpecificConfig(): ExtensionFlag"));
     if (mp4ASC->channelsConfiguration == 0)
     {
-        program_config_element(&pce, ld);
+        if (program_config_element(&pce, ld))
+            return -3;
         //mp4ASC->channelsConfiguration = pce.channels;
 
         if (pce_out != NULL)
@@ -158,7 +159,7 @@
    PCEs transmitted in raw data blocks cannot be used to convey decoder
    configuration information.
 */
-uint8_t program_config_element(program_config *pce, bitfile *ld)
+static uint8_t program_config_element(program_config *pce, bitfile *ld)
 {
     uint8_t i;
 
@@ -303,6 +304,9 @@
     }
     pce->comment_field_data[i] = 0;
 
+    if (pce->channels > MAX_CHANNELS)
+        return 22;
+
     return 0;
 }
 
@@ -431,15 +435,21 @@
                 data_stream_element(hDecoder, ld);
                 break;
             case ID_PCE:
-                if ((hInfo->error = program_config_element(pce, ld)) > 0)
-                    return;
-                hDecoder->pce_set = 1;
+                /* 14496-4: 5.6.4.1.2.1.3: */
+                /* program_configuration_element()'s in access units shall be ignored */
+                program_config_element(pce, ld);
+                //if ((hInfo->error = program_config_element(pce, ld)) > 0)
+                //    return;
+                //hDecoder->pce_set = 1;
                 break;
             case ID_FIL:
                 /* one sbr_info describes a channel_element not a channel! */
+                /* if we encounter SBR data here: error */
+                /* SBR data will be read directly in the SCE/LFE/CPE element */
                 if ((hInfo->error = fill_element(hDecoder, ld, drc
 #ifdef SBR_DEC
-                    , (ch_ele == 0) ? 0 : (ch_ele-1)
+                    //, (ch_ele == 0) ? INVALID_SBR_ELEMENT : (ch_ele-1)
+                    , INVALID_SBR_ELEMENT
 #endif
                     )) > 0)
                     return;
@@ -968,6 +978,9 @@
         if ((bs_extension_type == EXT_SBR_DATA) ||
             (bs_extension_type == EXT_SBR_DATA_CRC))
         {
+            if (sbr_ele == INVALID_SBR_ELEMENT)
+                return 24;
+
             if (!hDecoder->sbr[sbr_ele])
             {
                 hDecoder->sbr[sbr_ele] = sbrDecodeInit(hDecoder->frameLength,
--- a/libfaad/syntax.h
+++ b/libfaad/syntax.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: syntax.h,v 1.45 2004/01/05 14:05:12 menno Exp $
+** $Id: syntax.h,v 1.46 2004/01/16 20:20:32 menno Exp $
 **/
 
 #ifndef __SYNTAX_H__
@@ -33,7 +33,6 @@
 #endif
 
 #include "decoder.h"
-#include "drc.h"
 #include "bits.h"
 
 #define MAIN       1
@@ -103,6 +102,8 @@
 #define NOISE_HCB      13
 #define INTENSITY_HCB2 14
 #define INTENSITY_HCB  15
+
+#define INVALID_SBR_ELEMENT 255
 
 int8_t GASpecificConfig(bitfile *ld, mp4AudioSpecificConfig *mp4ASC,
                         program_config *pce);