shithub: aacdec

Download patch

ref: b9c91dbb598721be05a21034877deac322c5c80a
parent: c5c3fc3f9ffcd7d06e3a565ba31162193cb9d065
author: menno <menno>
date: Fri Aug 30 08:10:57 EDT 2002

Bugfix in filterbank and dequantisation

--- a/libfaad/decoder.c
+++ b/libfaad/decoder.c
@@ -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: decoder.c,v 1.24 2002/08/27 18:16:12 menno Exp $
+** $Id: decoder.c,v 1.25 2002/08/30 12:10:57 menno Exp $
 **/
 
 #include <stdlib.h>
@@ -86,7 +86,11 @@
     hDecoder->drc = drc_init(REAL_CONST(1.0), REAL_CONST(1.0));
 
     /* build table for inverse quantization */
-    build_tables(hDecoder->iq_table);
+#if IQ_TABLE_SIZE && POW_TABLE_SIZE
+    build_tables(hDecoder->iq_table, hDecoder->pow2_table);
+#elif !POW_TABLE_SIZE
+    build_tables(hDecoder->iq_table, NULL);
+#endif
 
     return hDecoder;
 }
@@ -445,6 +449,11 @@
     real_t **lt_pred_stat  =  hDecoder->lt_pred_stat;
 #endif
     real_t *iq_table       =  hDecoder->iq_table;
+#if POW_TABLE_SIZE
+    real_t *pow2_table     =  hDecoder->pow2_table;
+#else
+    real_t *pow2_table     =  NULL;
+#endif 
     uint8_t *window_shape_prev = hDecoder->window_shape_prev;
     real_t **time_out      =  hDecoder->time_out;
     fb_info *fb            =  hDecoder->fb;
@@ -628,9 +637,18 @@
                 ics = &(syntax_elements[i]->ics2);
         }
 
+#ifdef FIXED_POINT
         /* inverse quantization and application of scalefactors */
         iquant_and_apply_scalefactors(ics, spec_coef[ch], spec_data[ch],
             iq_table, frame_len);
+#else
+        /* inverse quantization */
+        inverse_quantization(spec_coef[ch], spec_data[ch], iq_table,
+            frame_len);
+
+        /* apply scalefactors */
+        apply_scalefactors(ics, spec_coef[ch], pow2_table, frame_len);
+#endif
 
         /* deinterleave short block grouping */
         if (ics->window_sequence == EIGHT_SHORT_SEQUENCE)
--- a/libfaad/decoder.h
+++ b/libfaad/decoder.h
@@ -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: decoder.h,v 1.12 2002/08/27 10:24:55 menno Exp $
+** $Id: decoder.h,v 1.13 2002/08/30 12:10:57 menno Exp $
 **/
 
 #ifndef __DECODER_H__
@@ -104,6 +104,9 @@
     real_t mnt_table[128];
 
     real_t iq_table[IQ_TABLE_SIZE];
+#if POW_TABLE_SIZE   
+    real_t pow2_table[POW_TABLE_SIZE];
+#endif 
 
     /* Configuration data */
     faacDecConfiguration config;
--- a/libfaad/filtbank.c
+++ b/libfaad/filtbank.c
@@ -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: filtbank.c,v 1.17 2002/08/27 18:16:12 menno Exp $
+** $Id: filtbank.c,v 1.18 2002/08/30 12:10:57 menno Exp $
 **/
 
 #include "common.h"
@@ -211,7 +211,7 @@
 
     case LONG_START_SEQUENCE:
         imdct(fb, freq_in, transf_buf, 2*nlong);
-        for (i = 0; i < 0; i++)
+        for (i = 0; i < nlong; i++)
             time_out[i] = time_out[nlong+i] + MUL_R_C(transf_buf[i],window_long_prev[i]);
         for (i = 0; i < nflat_ls; i++)
             time_out[nlong+i] = transf_buf[nlong+i];
--- a/libfaad/specrec.c
+++ b/libfaad/specrec.c
@@ -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: specrec.c,v 1.12 2002/08/27 10:24:57 menno Exp $
+** $Id: specrec.c,v 1.13 2002/08/30 12:10:57 menno Exp $
 **/
 
 /*
@@ -241,7 +241,7 @@
     }
 }
 
-void build_tables(real_t *iq_table)
+void build_tables(real_t *iq_table, real_t *pow2_table)
 {
     uint16_t i;
 
@@ -250,8 +250,18 @@
     {
         iq_table[i] = REAL_CONST(pow(i, 4.0/3.0));
     }
+
+#ifndef FIXED_POINT
+    /* build pow(2, 0.25*x) table for scalefactors */
+    for(i = 0; i < POW_TABLE_SIZE; i++)
+    {
+        pow2_table[i] = (real_t)pow(2.0, 0.25 * (i-100));
+    }
+#endif
 }
 
+#ifdef FIXED_POINT
+
 static real_t newpow2_table[4] = {
     COEF_CONST(1.0),
     COEF_CONST(1.1892071), /* pow(2,.25) */
@@ -316,3 +326,93 @@
         x_quant += nshort * ics->window_group_length[g];
     }
 }
+
+#else
+
+static INLINE real_t iquant(int16_t q, real_t *iq_table)
+{
+    if (q > 0)
+    {
+        if (q < IQ_TABLE_SIZE)
+            return iq_table[q];
+        else
+            return iq_table[q>>3] * 16;
+    } else if (q < 0) {
+        q = -q;
+        if (q < IQ_TABLE_SIZE)
+            return -iq_table[q];
+        else
+          return -iq_table[q>>3] * 16;
+    } else {
+        return 0;
+    }
+}
+
+void inverse_quantization(real_t *x_invquant, int16_t *x_quant, real_t *iq_table,
+                          uint16_t frame_len)
+{
+    int8_t i;
+    int16_t *in_ptr = x_quant;
+    real_t *out_ptr = x_invquant;
+
+    for(i = frame_len/8-1; i >= 0; --i)
+    {
+        *out_ptr++ = iquant(*in_ptr++, iq_table);
+        *out_ptr++ = iquant(*in_ptr++, iq_table);
+        *out_ptr++ = iquant(*in_ptr++, iq_table);
+        *out_ptr++ = iquant(*in_ptr++, iq_table);
+        *out_ptr++ = iquant(*in_ptr++, iq_table);
+        *out_ptr++ = iquant(*in_ptr++, iq_table);
+        *out_ptr++ = iquant(*in_ptr++, iq_table);
+        *out_ptr++ = iquant(*in_ptr++, iq_table);
+    }
+}
+
+static INLINE real_t get_scale_factor_gain(uint16_t scale_factor, real_t *pow2_table)
+{
+    if (scale_factor < POW_TABLE_SIZE)
+        return pow2_table[scale_factor];
+    else
+        return REAL_CONST(exp(LN2 * 0.25 * (scale_factor - 100)));
+}
+
+void apply_scalefactors(ic_stream *ics, real_t *x_invquant, real_t *pow2_table,
+                        uint16_t frame_len)
+{
+    uint8_t g, sfb;
+    uint16_t top;
+    real_t *fp, scale;
+    uint8_t groups = 0;
+    uint16_t nshort = frame_len/8;
+
+    for (g = 0; g < ics->num_window_groups; g++)
+    {
+        uint16_t k = 0;
+
+        /* using this 128*groups doesn't hurt long blocks, because
+           long blocks only have 1 group, so that means 'groups' is
+           always 0 for long blocks
+        */
+        fp = x_invquant + (groups*nshort);
+
+        for (sfb = 0; sfb < ics->max_sfb; sfb++)
+        {
+            top = ics->sect_sfb_offset[g][sfb+1];
+
+            scale = get_scale_factor_gain(ics->scale_factors[g][sfb], pow2_table);
+
+            /* minimum size of a sf band is 4 and always a multiple of 4 */
+            for ( ; k < top; k+=4)
+            {
+                fp[0] *= scale;
+                fp[1] *= scale;
+                fp[2] *= scale;
+                fp[3] *= scale;
+                fp += 4;
+            }
+        }
+        groups += ics->window_group_length[g];
+    }
+}
+
+#endif
--- a/libfaad/specrec.h
+++ b/libfaad/specrec.h
@@ -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: specrec.h,v 1.6 2002/08/26 18:41:47 menno Exp $
+** $Id: specrec.h,v 1.7 2002/08/30 12:10:57 menno Exp $
 **/
 
 #ifndef __SPECREC_H__
@@ -29,16 +29,28 @@
 #include "syntax.h"
 
 /* !!!DON'T CHANGE IQ_TABLE_SIZE!!! */
-#define IQ_TABLE_SIZE   1026
+#define IQ_TABLE_SIZE  1026
 
+#ifdef FIXED_POINT
+#define POW_TABLE_SIZE 0
+#else
+#define POW_TABLE_SIZE 200
+#endif
 
 uint8_t window_grouping_info(ic_stream *ics, uint8_t fs_index,
                              uint8_t object_type, uint16_t frame_len);
 void quant_to_spec(ic_stream *ics, real_t *spec_data, uint16_t frame_len);
-void build_tables(real_t *iq_table);
+void build_tables(real_t *iq_table, real_t *pow2_table);
+#ifdef FIXED_POINT
 void iquant_and_apply_scalefactors(ic_stream *ics, real_t *x_invquant,
                                    int16_t *x_quant, real_t *iq_table,
                                    uint16_t frame_len);
+#else
+void inverse_quantization(real_t *x_invquant, int16_t *x_quant, real_t *iq_table,
+                          uint16_t frame_len);
+void apply_scalefactors(ic_stream *ics, real_t *x_invquant, real_t *pow2_table,
+                        uint16_t frame_len);
+#endif
 
 #ifdef __cplusplus
 }