diff options
Diffstat (limited to 'src/libfaad/ps_dec.c')
-rw-r--r-- | src/libfaad/ps_dec.c | 159 |
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); |