summaryrefslogtreecommitdiff
path: root/src/libfaad/ps_dec.c
diff options
context:
space:
mode:
authorDarren Salt <linux@youmustbejoking.demon.co.uk>2008-08-13 14:28:30 +0100
committerDarren Salt <linux@youmustbejoking.demon.co.uk>2008-08-13 14:28:30 +0100
commite8cc3903fc5be11c0e326fc23650599dbb1d07a0 (patch)
tree45c2bff1062583269fc745a54dcc1df048cbd62a /src/libfaad/ps_dec.c
parent3a6da3fcaef64afe71e1e1a0d41baca0872e98f8 (diff)
downloadxine-lib-e8cc3903fc5be11c0e326fc23650599dbb1d07a0.tar.gz
xine-lib-e8cc3903fc5be11c0e326fc23650599dbb1d07a0.tar.bz2
Update to libfaad 2.6.1, fixing a crash with a corrupted AAC file.
Source is the version in the 1.2 branch.
Diffstat (limited to 'src/libfaad/ps_dec.c')
-rw-r--r--src/libfaad/ps_dec.c159
1 files changed, 95 insertions, 64 deletions
diff --git a/src/libfaad/ps_dec.c b/src/libfaad/ps_dec.c
index 3b957bfda..aebfe0a48 100644
--- a/src/libfaad/ps_dec.c
+++ b/src/libfaad/ps_dec.c
@@ -1,28 +1,31 @@
/*
-** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR and PS decoding
-** Copyright (C) 2003-2004 M. Bakker, Ahead Software AG, http://www.nero.com
-**
+** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR decoding
+** Copyright (C) 2003-2005 M. Bakker, Nero AG, http://www.nero.com
+**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
-**
+**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
-**
+**
** You should have received a copy of the GNU General Public License
-** along with this program; if not, write to the Free Software
+** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
**
** Any non-GPL usage of this software or parts of this software is strictly
** forbidden.
**
+** The "appropriate copyright message" mentioned in section 2c of the GPLv2
+** must read: "Code from FAAD2 is copyright (c) Nero AG, www.nero.com"
+**
** Commercial non-GPL licensing of this software is possible.
-** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
+** For more info contact Nero AG through Mpeg4AAClicense@nero.com.
**
-** $Id: ps_dec.c,v 1.3 2006/09/26 17:55:59 dgp85 Exp $
+** $Id: ps_dec.c,v 1.14 2007/11/01 12:33:33 menno Exp $
**/
#include "common.h"
@@ -159,7 +162,7 @@ typedef struct
/* static function declarations */
static void ps_data_decode(ps_info *ps);
-static hyb_info *hybrid_init(void);
+static hyb_info *hybrid_init();
static void channel_filter2(hyb_info *hyb, uint8_t frame_len, const real_t *filter,
qmf_t *buffer, qmf_t **X_hybrid);
static void INLINE DCT3_4_unscaled(real_t *y, real_t *x);
@@ -175,7 +178,7 @@ static void delta_decode(uint8_t enable, int8_t *index, int8_t *index_prev,
int8_t min_index, int8_t max_index);
static void delta_modulo_decode(uint8_t enable, int8_t *index, int8_t *index_prev,
uint8_t dt_flag, uint8_t nr_par, uint8_t stride,
- int8_t log2modulo);
+ int8_t and_modulo);
static void map20indexto34(int8_t *index, uint8_t bins);
#ifdef PS_LOW_POWER
static void map34indexto20(int8_t *index, uint8_t bins);
@@ -189,7 +192,7 @@ static void ps_mix_phase(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64
/* */
-static hyb_info *hybrid_init(void)
+static hyb_info *hybrid_init()
{
uint8_t i;
@@ -230,16 +233,24 @@ static void hybrid_free(hyb_info *hyb)
{
uint8_t i;
- faad_free(hyb->work);
+ if (hyb->work)
+ faad_free(hyb->work);
for (i = 0; i < 5; i++)
- faad_free(hyb->buffer[i]);
- faad_free(hyb->buffer);
+ {
+ if (hyb->buffer[i])
+ faad_free(hyb->buffer[i]);
+ }
+ if (hyb->buffer)
+ faad_free(hyb->buffer);
for (i = 0; i < hyb->frame_len; i++)
- faad_free(hyb->temp[i]);
-
- faad_free(hyb->temp);
+ {
+ if (hyb->temp[i])
+ faad_free(hyb->temp[i]);
+ }
+ if (hyb->temp)
+ faad_free(hyb->temp);
}
/* real filter, size 2 */
@@ -666,7 +677,7 @@ static void delta_decode(uint8_t enable, int8_t *index, int8_t *index_prev,
/* in: log2 value of the modulo value to allow using AND instead of MOD */
static void delta_modulo_decode(uint8_t enable, int8_t *index, int8_t *index_prev,
uint8_t dt_flag, uint8_t nr_par, uint8_t stride,
- int8_t log2modulo)
+ int8_t and_modulo)
{
int8_t i;
@@ -676,19 +687,19 @@ static void delta_modulo_decode(uint8_t enable, int8_t *index, int8_t *index_pre
{
/* delta coded in frequency direction */
index[0] = 0 + index[0];
- index[0] &= log2modulo;
+ index[0] &= and_modulo;
for (i = 1; i < nr_par; i++)
{
index[i] = index[i-1] + index[i];
- index[i] &= log2modulo;
+ index[i] &= and_modulo;
}
} else {
/* delta coded in time direction */
for (i = 0; i < nr_par; i++)
{
index[i] = index_prev[i*stride] + index[i];
- index[i] &= log2modulo;
+ index[i] &= and_modulo;
}
}
} else {
@@ -833,11 +844,11 @@ static void ps_data_decode(ps_info *ps)
/* delta modulo decode ipd parameters */
delta_modulo_decode(ps->enable_ipdopd, ps->ipd_index[env], ipd_index_prev,
- ps->ipd_dt[env], ps->nr_ipdopd_par, 1, /*log2(8)*/ 3);
+ ps->ipd_dt[env], ps->nr_ipdopd_par, 1, 7);
/* delta modulo decode opd parameters */
delta_modulo_decode(ps->enable_ipdopd, ps->opd_index[env], opd_index_prev,
- ps->opd_dt[env], ps->nr_ipdopd_par, 1, /*log2(8)*/ 3);
+ ps->opd_dt[env], ps->nr_ipdopd_par, 1, 7);
}
/* handle error case */
@@ -906,8 +917,6 @@ static void ps_data_decode(ps_info *ps)
if (ps->border_position[ps->num_env] < 32 /* 30 for 960? */)
{
- ps->num_env++;
- ps->border_position[ps->num_env] = 32 /* 30 for 960? */;
for (bin = 0; bin < 34; bin++)
{
ps->iid_index[ps->num_env][bin] = ps->iid_index[ps->num_env-1][bin];
@@ -918,6 +927,8 @@ static void ps_data_decode(ps_info *ps)
ps->ipd_index[ps->num_env][bin] = ps->ipd_index[ps->num_env-1][bin];
ps->opd_index[ps->num_env][bin] = ps->opd_index[ps->num_env-1][bin];
}
+ ps->num_env++;
+ ps->border_position[ps->num_env] = 32 /* 30 for 960? */;
}
for (env = 1; env < ps->num_env; env++)
@@ -1410,6 +1421,26 @@ static const real_t ipdopd_sin_tab[] = {
FRAC_CONST(-0.000000000000000)
};
+static real_t magnitude_c(complex_t c)
+{
+#ifdef FIXED_POINT
+#define ps_abs(A) (((A) > 0) ? (A) : (-(A)))
+#define ALPHA FRAC_CONST(0.948059448969)
+#define BETA FRAC_CONST(0.392699081699)
+
+ real_t abs_inphase = ps_abs(RE(c));
+ real_t abs_quadrature = ps_abs(IM(c));
+
+ if (abs_inphase > abs_quadrature) {
+ return MUL_F(abs_inphase, ALPHA) + MUL_F(abs_quadrature, BETA);
+ } else {
+ return MUL_F(abs_quadrature, ALPHA) + MUL_F(abs_inphase, BETA);
+ }
+#else
+ return sqrt(RE(c)*RE(c) + IM(c)*IM(c));
+#endif
+}
+
static void ps_mix_phase(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64],
qmf_t X_hybrid_left[32][32], qmf_t X_hybrid_right[32][32])
{
@@ -1580,8 +1611,7 @@ static void ps_mix_phase(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64
if ((ps->enable_ipdopd) && (bk < nr_ipdopd_par))
{
int8_t i;
- real_t xxyy, ppqq;
- real_t yq, xp, xq, py, tmp;
+ real_t xy, pq, xypq;
/* ringbuffer index */
i = ps->phase_hist;
@@ -1614,7 +1644,7 @@ static void ps_mix_phase(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64
/* ringbuffer index */
if (i == 0)
- {
+ {
i = 2;
}
i--;
@@ -1644,53 +1674,54 @@ static void ps_mix_phase(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64
RE(phaseRight) = (float)cos(opd);
IM(phaseRight) = (float)sin(opd);
#else
+
// x = IM(tempLeft)
// y = RE(tempLeft)
// p = IM(tempRight)
// q = RE(tempRight)
- // cos(atan2(x,y)) = 1/sqrt(1 + (x*x)/(y*y))
- // sin(atan2(x,y)) = x/(y*sqrt(1 + (x*x)/(y*y)))
- // cos(atan2(x,y)-atan2(p,q)) = (y*q+x*p)/(y*q * sqrt(1 + (x*x)/(y*y)) * sqrt(1 + (p*p)/(q*q)));
- // sin(atan2(x,y)-atan2(p,q)) = (x*q-p*y)/(y*q * sqrt(1 + (x*x)/(y*y)) * sqrt(1 + (p*p)/(q*q)));
+ // cos(atan2(x,y)) = y/sqrt((x*x) + (y*y))
+ // sin(atan2(x,y)) = x/sqrt((x*x) + (y*y))
+ // cos(atan2(x,y)-atan2(p,q)) = (y*q + x*p) / ( sqrt((x*x) + (y*y)) * sqrt((p*p) + (q*q)) );
+ // sin(atan2(x,y)-atan2(p,q)) = (x*q - y*p) / ( sqrt((x*x) + (y*y)) * sqrt((p*p) + (q*q)) );
- /* (x*x)/(y*y) (REAL > 0) */
- xxyy = DIV_R(MUL_C(IM(tempLeft),IM(tempLeft)), MUL_C(RE(tempLeft),RE(tempLeft)));
- ppqq = DIV_R(MUL_C(IM(tempRight),IM(tempRight)), MUL_C(RE(tempRight),RE(tempRight)));
+ xy = magnitude_c(tempRight);
+ pq = magnitude_c(tempLeft);
- /* 1 + (x*x)/(y*y) (REAL > 1) */
- xxyy += REAL_CONST(1);
- ppqq += REAL_CONST(1);
-
- /* 1 / sqrt(1 + (x*x)/(y*y)) (FRAC <= 1) */
- xxyy = DIV_R(FRAC_CONST(1), ps_sqrt(xxyy));
- ppqq = DIV_R(FRAC_CONST(1), ps_sqrt(ppqq));
+ if (xy != 0)
+ {
+ RE(phaseLeft) = DIV_R(RE(tempRight), xy);
+ IM(phaseLeft) = DIV_R(IM(tempRight), xy);
+ } else {
+ RE(phaseLeft) = 0;
+ IM(phaseLeft) = 0;
+ }
- /* COEF */
- yq = MUL_C(RE(tempLeft), RE(tempRight));
- xp = MUL_C(IM(tempLeft), IM(tempRight));
- xq = MUL_C(IM(tempLeft), RE(tempRight));
- py = MUL_C(RE(tempLeft), IM(tempRight));
+ xypq = MUL_R(xy, pq);
- RE(phaseLeft) = xxyy;
- IM(phaseLeft) = MUL_R(xxyy, (DIV_R(IM(tempLeft), RE(tempLeft))));
+ if (xypq != 0)
+ {
+ real_t tmp1 = MUL_R(RE(tempRight), RE(tempLeft)) + MUL_R(IM(tempRight), IM(tempLeft));
+ real_t tmp2 = MUL_R(IM(tempRight), RE(tempLeft)) - MUL_R(RE(tempRight), IM(tempLeft));
- tmp = DIV_C(MUL_F(xxyy, ppqq), yq);
+ RE(phaseRight) = DIV_R(tmp1, xypq);
+ IM(phaseRight) = DIV_R(tmp2, xypq);
+ } else {
+ RE(phaseRight) = 0;
+ IM(phaseRight) = 0;
+ }
- /* MUL_C(FRAC,COEF) = FRAC */
- RE(phaseRight) = MUL_C(tmp, (yq+xp));
- IM(phaseRight) = MUL_C(tmp, (xq-py));
#endif
- /* MUL_F(COEF, FRAC) = COEF */
- IM(h11) = MUL_F(RE(h11), IM(phaseLeft));
- IM(h12) = MUL_F(RE(h12), IM(phaseRight));
- IM(h21) = MUL_F(RE(h21), IM(phaseLeft));
- IM(h22) = MUL_F(RE(h22), IM(phaseRight));
+ /* MUL_F(COEF, REAL) = COEF */
+ IM(h11) = MUL_R(RE(h11), IM(phaseLeft));
+ IM(h12) = MUL_R(RE(h12), IM(phaseRight));
+ IM(h21) = MUL_R(RE(h21), IM(phaseLeft));
+ IM(h22) = MUL_R(RE(h22), IM(phaseRight));
- RE(h11) = MUL_F(RE(h11), RE(phaseLeft));
- RE(h12) = MUL_F(RE(h12), RE(phaseRight));
- RE(h21) = MUL_F(RE(h21), RE(phaseLeft));
- RE(h22) = MUL_F(RE(h22), RE(phaseRight));
+ RE(h11) = MUL_R(RE(h11), RE(phaseLeft));
+ RE(h12) = MUL_R(RE(h12), RE(phaseRight));
+ RE(h21) = MUL_R(RE(h21), RE(phaseLeft));
+ RE(h22) = MUL_R(RE(h22), RE(phaseRight));
}
/* length of the envelope n_e+1 - n_e (in time samples) */
@@ -1927,8 +1958,8 @@ ps_info *ps_init(uint8_t sr_index)
/* main Parametric Stereo decoding function */
uint8_t ps_decode(ps_info *ps, qmf_t X_left[38][64], qmf_t X_right[38][64])
{
- qmf_t X_hybrid_left[32][32] = {{{0}}};
- qmf_t X_hybrid_right[32][32] = {{{0}}};
+ qmf_t X_hybrid_left[32][32] = {{0}};
+ qmf_t X_hybrid_right[32][32] = {{0}};
/* delta decoding of the bitstream data */
ps_data_decode(ps);