summaryrefslogtreecommitdiffstats
path: root/libfaad2/ps_dec.c
diff options
context:
space:
mode:
authordiego <diego@b3059339-0415-0410-9bf9-f77b7e298cf2>2004-09-24 17:31:36 +0000
committerdiego <diego@b3059339-0415-0410-9bf9-f77b7e298cf2>2004-09-24 17:31:36 +0000
commite1ece5e2eb68c81b1645c9ff989c833c4d67dfd8 (patch)
tree8553b3a4ef8164d14ff1b4a3f67e57cfa1d8908a /libfaad2/ps_dec.c
parent2887bacbdb6bd320e4840fd230e92a59cc74b9ae (diff)
downloadmpv-e1ece5e2eb68c81b1645c9ff989c833c4d67dfd8.tar.bz2
mpv-e1ece5e2eb68c81b1645c9ff989c833c4d67dfd8.tar.xz
Update FAAD to a 2.1 beta CVS snapshot from 2004.07.12.
patch by adland <adland123 at yahoo dot com> git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@13454 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libfaad2/ps_dec.c')
-rw-r--r--libfaad2/ps_dec.c1986
1 files changed, 1986 insertions, 0 deletions
diff --git a/libfaad2/ps_dec.c b/libfaad2/ps_dec.c
new file mode 100644
index 0000000000..a7f09515e8
--- /dev/null
+++ b/libfaad2/ps_dec.c
@@ -0,0 +1,1986 @@
+/*
+** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR and PS decoding
+** Copyright (C) 2003-2004 M. Bakker, Ahead Software 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
+** 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.
+**
+** Commercial non-GPL licensing of this software is possible.
+** For more info contact Ahead Software through Mpeg4AAClicense@nero.com.
+**
+** Initially modified for use with MPlayer by Diego Biurrun on 2004/09/24
+** detailed CVS changelog at http://www.mplayerhq.hu/cgi-bin/cvsweb.cgi/main/
+**/
+
+#include "common.h"
+
+#ifdef PS_DEC
+
+#include <stdlib.h>
+#include "ps_dec.h"
+#include "ps_tables.h"
+
+/* constants */
+#define NEGATE_IPD_MASK (0x1000)
+#define DECAY_SLOPE FRAC_CONST(0.05)
+#define COEF_SQRT2 COEF_CONST(1.4142135623731)
+
+/* tables */
+/* filters are mirrored in coef 6, second half left out */
+static const real_t p8_13_20[7] =
+{
+ FRAC_CONST(0.00746082949812),
+ FRAC_CONST(0.02270420949825),
+ FRAC_CONST(0.04546865930473),
+ FRAC_CONST(0.07266113929591),
+ FRAC_CONST(0.09885108575264),
+ FRAC_CONST(0.11793710567217),
+ FRAC_CONST(0.125)
+};
+
+static const real_t p2_13_20[7] =
+{
+ FRAC_CONST(0.0),
+ FRAC_CONST(0.01899487526049),
+ FRAC_CONST(0.0),
+ FRAC_CONST(-0.07293139167538),
+ FRAC_CONST(0.0),
+ FRAC_CONST(0.30596630545168),
+ FRAC_CONST(0.5)
+};
+
+static const real_t p12_13_34[7] =
+{
+ FRAC_CONST(0.04081179924692),
+ FRAC_CONST(0.03812810994926),
+ FRAC_CONST(0.05144908135699),
+ FRAC_CONST(0.06399831151592),
+ FRAC_CONST(0.07428313801106),
+ FRAC_CONST(0.08100347892914),
+ FRAC_CONST(0.08333333333333)
+};
+
+static const real_t p8_13_34[7] =
+{
+ FRAC_CONST(0.01565675600122),
+ FRAC_CONST(0.03752716391991),
+ FRAC_CONST(0.05417891378782),
+ FRAC_CONST(0.08417044116767),
+ FRAC_CONST(0.10307344158036),
+ FRAC_CONST(0.12222452249753),
+ FRAC_CONST(0.125)
+};
+
+static const real_t p4_13_34[7] =
+{
+ FRAC_CONST(-0.05908211155639),
+ FRAC_CONST(-0.04871498374946),
+ FRAC_CONST(0.0),
+ FRAC_CONST(0.07778723915851),
+ FRAC_CONST(0.16486303567403),
+ FRAC_CONST(0.23279856662996),
+ FRAC_CONST(0.25)
+};
+
+#ifdef PARAM_32KHZ
+static const uint8_t delay_length_d[2][NO_ALLPASS_LINKS] = {
+ { 1, 2, 3 } /* d_24kHz */,
+ { 3, 4, 5 } /* d_48kHz */
+};
+#else
+static const uint8_t delay_length_d[NO_ALLPASS_LINKS] = {
+ 3, 4, 5 /* d_48kHz */
+};
+#endif
+static const real_t filter_a[NO_ALLPASS_LINKS] = { /* a(m) = exp(-d_48kHz(m)/7) */
+ FRAC_CONST(0.65143905753106),
+ FRAC_CONST(0.56471812200776),
+ FRAC_CONST(0.48954165955695)
+};
+
+static const uint8_t group_border20[10+12 + 1] =
+{
+ 6, 7, 0, 1, 2, 3, /* 6 subqmf subbands */
+ 9, 8, /* 2 subqmf subbands */
+ 10, 11, /* 2 subqmf subbands */
+ 3, 4, 5, 6, 7, 8, 9, 11, 14, 18, 23, 35, 64
+};
+
+static const uint8_t group_border34[32+18 + 1] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, /* 12 subqmf subbands */
+ 12, 13, 14, 15, 16, 17, 18, 19, /* 8 subqmf subbands */
+ 20, 21, 22, 23, /* 4 subqmf subbands */
+ 24, 25, 26, 27, /* 4 subqmf subbands */
+ 28, 29, 30, 31, /* 4 subqmf subbands */
+ 32-27, 33-27, 34-27, 35-27, 36-27, 37-27, 38-27, 40-27, 42-27, 44-27, 46-27, 48-27, 51-27, 54-27, 57-27, 60-27, 64-27, 68-27, 91-27
+};
+
+static const uint16_t map_group2bk20[10+12] =
+{
+ (NEGATE_IPD_MASK | 1), (NEGATE_IPD_MASK | 0),
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19
+};
+
+static const uint16_t map_group2bk34[32+18] =
+{
+ 0, 1, 2, 3, 4, 5, 6, 6, 7, (NEGATE_IPD_MASK | 2), (NEGATE_IPD_MASK | 1), (NEGATE_IPD_MASK | 0),
+ 10, 10, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 9,
+ 14, 11, 12, 13,
+ 14, 15, 16, 13,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33
+};
+
+/* type definitions */
+typedef struct
+{
+ uint8_t frame_len;
+ uint8_t resolution20[3];
+ uint8_t resolution34[5];
+
+ qmf_t *work;
+ qmf_t **buffer;
+ qmf_t **temp;
+} hyb_info;
+
+/* static function declarations */
+static void ps_data_decode(ps_info *ps);
+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);
+static void channel_filter8(hyb_info *hyb, uint8_t frame_len, const real_t *filter,
+ qmf_t *buffer, qmf_t **X_hybrid);
+static void hybrid_analysis(hyb_info *hyb, qmf_t X[32][64], qmf_t X_hybrid[32][32],
+ uint8_t use34);
+static void hybrid_synthesis(hyb_info *hyb, qmf_t X[32][64], qmf_t X_hybrid[32][32],
+ uint8_t use34);
+static int8_t delta_clip(int8_t i, int8_t min, int8_t max);
+static void delta_decode(uint8_t enable, int8_t *index, int8_t *index_prev,
+ uint8_t dt_flag, uint8_t nr_par, uint8_t stride,
+ 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);
+static void map20indexto34(int8_t *index, uint8_t bins);
+#ifdef PS_LOW_POWER
+static void map34indexto20(int8_t *index, uint8_t bins);
+#endif
+static void ps_data_decode(ps_info *ps);
+static void ps_decorrelate(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]);
+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]);
+
+/* */
+
+
+static hyb_info *hybrid_init()
+{
+ uint8_t i;
+
+ hyb_info *hyb = (hyb_info*)faad_malloc(sizeof(hyb_info));
+
+ hyb->resolution34[0] = 12;
+ hyb->resolution34[1] = 8;
+ hyb->resolution34[2] = 4;
+ hyb->resolution34[3] = 4;
+ hyb->resolution34[4] = 4;
+
+ hyb->resolution20[0] = 8;
+ hyb->resolution20[1] = 2;
+ hyb->resolution20[2] = 2;
+
+ hyb->frame_len = 32;
+
+ hyb->work = (qmf_t*)faad_malloc((hyb->frame_len+12) * sizeof(qmf_t));
+ memset(hyb->work, 0, (hyb->frame_len+12) * sizeof(qmf_t));
+
+ hyb->buffer = (qmf_t**)faad_malloc(5 * sizeof(qmf_t*));
+ for (i = 0; i < 5; i++)
+ {
+ hyb->buffer[i] = (qmf_t*)faad_malloc(hyb->frame_len * sizeof(qmf_t));
+ memset(hyb->buffer[i], 0, hyb->frame_len * sizeof(qmf_t));
+ }
+
+ hyb->temp = (qmf_t**)faad_malloc(hyb->frame_len * sizeof(qmf_t*));
+ for (i = 0; i < hyb->frame_len; i++)
+ {
+ hyb->temp[i] = (qmf_t*)faad_malloc(12 /*max*/ * sizeof(qmf_t));
+ }
+
+ return hyb;
+}
+
+static void hybrid_free(hyb_info *hyb)
+{
+ uint8_t i;
+
+ if (hyb->work)
+ faad_free(hyb->work);
+
+ for (i = 0; i < 5; i++)
+ {
+ if (hyb->buffer[i])
+ faad_free(hyb->buffer[i]);
+ }
+ if (hyb->buffer)
+ faad_free(hyb->buffer);
+
+ for (i = 0; i < hyb->frame_len; i++)
+ {
+ if (hyb->temp[i])
+ faad_free(hyb->temp[i]);
+ }
+ if (hyb->temp)
+ faad_free(hyb->temp);
+}
+
+/* real filter, size 2 */
+static void channel_filter2(hyb_info *hyb, uint8_t frame_len, const real_t *filter,
+ qmf_t *buffer, qmf_t **X_hybrid)
+{
+ uint8_t i;
+
+ for (i = 0; i < frame_len; i++)
+ {
+ real_t r0 = MUL_F(filter[0],(QMF_RE(buffer[0+i]) + QMF_RE(buffer[12+i])));
+ real_t r1 = MUL_F(filter[1],(QMF_RE(buffer[1+i]) + QMF_RE(buffer[11+i])));
+ real_t r2 = MUL_F(filter[2],(QMF_RE(buffer[2+i]) + QMF_RE(buffer[10+i])));
+ real_t r3 = MUL_F(filter[3],(QMF_RE(buffer[3+i]) + QMF_RE(buffer[9+i])));
+ real_t r4 = MUL_F(filter[4],(QMF_RE(buffer[4+i]) + QMF_RE(buffer[8+i])));
+ real_t r5 = MUL_F(filter[5],(QMF_RE(buffer[5+i]) + QMF_RE(buffer[7+i])));
+ real_t r6 = MUL_F(filter[6],QMF_RE(buffer[6+i]));
+ real_t i0 = MUL_F(filter[0],(QMF_IM(buffer[0+i]) + QMF_IM(buffer[12+i])));
+ real_t i1 = MUL_F(filter[1],(QMF_IM(buffer[1+i]) + QMF_IM(buffer[11+i])));
+ real_t i2 = MUL_F(filter[2],(QMF_IM(buffer[2+i]) + QMF_IM(buffer[10+i])));
+ real_t i3 = MUL_F(filter[3],(QMF_IM(buffer[3+i]) + QMF_IM(buffer[9+i])));
+ real_t i4 = MUL_F(filter[4],(QMF_IM(buffer[4+i]) + QMF_IM(buffer[8+i])));
+ real_t i5 = MUL_F(filter[5],(QMF_IM(buffer[5+i]) + QMF_IM(buffer[7+i])));
+ real_t i6 = MUL_F(filter[6],QMF_IM(buffer[6+i]));
+
+ /* q = 0 */
+ QMF_RE(X_hybrid[i][0]) = r0 + r1 + r2 + r3 + r4 + r5 + r6;
+ QMF_IM(X_hybrid[i][0]) = i0 + i1 + i2 + i3 + i4 + i5 + i6;
+
+ /* q = 1 */
+ QMF_RE(X_hybrid[i][1]) = r0 - r1 + r2 - r3 + r4 - r5 + r6;
+ QMF_IM(X_hybrid[i][1]) = i0 - i1 + i2 - i3 + i4 - i5 + i6;
+ }
+}
+
+/* complex filter, size 4 */
+static void channel_filter4(hyb_info *hyb, uint8_t frame_len, const real_t *filter,
+ qmf_t *buffer, qmf_t **X_hybrid)
+{
+ uint8_t i;
+ real_t input_re1[2], input_re2[2], input_im1[2], input_im2[2];
+
+ for (i = 0; i < frame_len; i++)
+ {
+ input_re1[0] = -MUL_F(filter[2], (QMF_RE(buffer[i+2]) + QMF_RE(buffer[i+10]))) +
+ MUL_F(filter[6], QMF_RE(buffer[i+6]));
+ input_re1[1] = MUL_F(FRAC_CONST(-0.70710678118655),
+ (MUL_F(filter[1], (QMF_RE(buffer[i+1]) + QMF_RE(buffer[i+11]))) +
+ MUL_F(filter[3], (QMF_RE(buffer[i+3]) + QMF_RE(buffer[i+9]))) -
+ MUL_F(filter[5], (QMF_RE(buffer[i+5]) + QMF_RE(buffer[i+7])))));
+
+ input_im1[0] = MUL_F(filter[0], (QMF_IM(buffer[i+0]) - QMF_IM(buffer[i+12]))) -
+ MUL_F(filter[4], (QMF_IM(buffer[i+4]) - QMF_IM(buffer[i+8])));
+ input_im1[1] = MUL_F(FRAC_CONST(0.70710678118655),
+ (MUL_F(filter[1], (QMF_IM(buffer[i+1]) - QMF_IM(buffer[i+11]))) -
+ MUL_F(filter[3], (QMF_IM(buffer[i+3]) - QMF_IM(buffer[i+9]))) -
+ MUL_F(filter[5], (QMF_IM(buffer[i+5]) - QMF_IM(buffer[i+7])))));
+
+ input_re2[0] = MUL_F(filter[0], (QMF_RE(buffer[i+0]) - QMF_RE(buffer[i+12]))) -
+ MUL_F(filter[4], (QMF_RE(buffer[i+4]) - QMF_RE(buffer[i+8])));
+ input_re2[1] = MUL_F(FRAC_CONST(0.70710678118655),
+ (MUL_F(filter[1], (QMF_RE(buffer[i+1]) - QMF_RE(buffer[i+11]))) -
+ MUL_F(filter[3], (QMF_RE(buffer[i+3]) - QMF_RE(buffer[i+9]))) -
+ MUL_F(filter[5], (QMF_RE(buffer[i+5]) - QMF_RE(buffer[i+7])))));
+
+ input_im2[0] = -MUL_F(filter[2], (QMF_IM(buffer[i+2]) + QMF_IM(buffer[i+10]))) +
+ MUL_F(filter[6], QMF_IM(buffer[i+6]));
+ input_im2[1] = MUL_F(FRAC_CONST(-0.70710678118655),
+ (MUL_F(filter[1], (QMF_IM(buffer[i+1]) + QMF_IM(buffer[i+11]))) +
+ MUL_F(filter[3], (QMF_IM(buffer[i+3]) + QMF_IM(buffer[i+9]))) -
+ MUL_F(filter[5], (QMF_IM(buffer[i+5]) + QMF_IM(buffer[i+7])))));
+
+ /* q == 0 */
+ QMF_RE(X_hybrid[i][0]) = input_re1[0] + input_re1[1] + input_im1[0] + input_im1[1];
+ QMF_IM(X_hybrid[i][0]) = -input_re2[0] - input_re2[1] + input_im2[0] + input_im2[1];
+
+ /* q == 1 */
+ QMF_RE(X_hybrid[i][1]) = input_re1[0] - input_re1[1] - input_im1[0] + input_im1[1];
+ QMF_IM(X_hybrid[i][1]) = input_re2[0] - input_re2[1] + input_im2[0] - input_im2[1];
+
+ /* q == 2 */
+ QMF_RE(X_hybrid[i][2]) = input_re1[0] - input_re1[1] + input_im1[0] - input_im1[1];
+ QMF_IM(X_hybrid[i][2]) = -input_re2[0] + input_re2[1] + input_im2[0] - input_im2[1];
+
+ /* q == 3 */
+ QMF_RE(X_hybrid[i][3]) = input_re1[0] + input_re1[1] - input_im1[0] - input_im1[1];
+ QMF_IM(X_hybrid[i][3]) = input_re2[0] + input_re2[1] + input_im2[0] + input_im2[1];
+ }
+}
+
+static void INLINE DCT3_4_unscaled(real_t *y, real_t *x)
+{
+ real_t f0, f1, f2, f3, f4, f5, f6, f7, f8;
+
+ f0 = MUL_F(x[2], FRAC_CONST(0.7071067811865476));
+ f1 = x[0] - f0;
+ f2 = x[0] + f0;
+ f3 = x[1] + x[3];
+ f4 = MUL_C(x[1], COEF_CONST(1.3065629648763766));
+ f5 = MUL_F(f3, FRAC_CONST(-0.9238795325112866));
+ f6 = MUL_F(x[3], FRAC_CONST(-0.5411961001461967));
+ f7 = f4 + f5;
+ f8 = f6 - f5;
+ y[3] = f2 - f8;
+ y[0] = f2 + f8;
+ y[2] = f1 - f7;
+ y[1] = f1 + f7;
+}
+
+/* complex filter, size 8 */
+static void channel_filter8(hyb_info *hyb, uint8_t frame_len, const real_t *filter,
+ qmf_t *buffer, qmf_t **X_hybrid)
+{
+ uint8_t i, n;
+ real_t input_re1[4], input_re2[4], input_im1[4], input_im2[4];
+ real_t x[4];
+
+ for (i = 0; i < frame_len; i++)
+ {
+ input_re1[0] = MUL_F(filter[6],QMF_RE(buffer[6+i]));
+ input_re1[1] = MUL_F(filter[5],(QMF_RE(buffer[5+i]) + QMF_RE(buffer[7+i])));
+ input_re1[2] = -MUL_F(filter[0],(QMF_RE(buffer[0+i]) + QMF_RE(buffer[12+i]))) + MUL_F(filter[4],(QMF_RE(buffer[4+i]) + QMF_RE(buffer[8+i])));
+ input_re1[3] = -MUL_F(filter[1],(QMF_RE(buffer[1+i]) + QMF_RE(buffer[11+i]))) + MUL_F(filter[3],(QMF_RE(buffer[3+i]) + QMF_RE(buffer[9+i])));
+
+ input_im1[0] = MUL_F(filter[5],(QMF_IM(buffer[7+i]) - QMF_IM(buffer[5+i])));
+ input_im1[1] = MUL_F(filter[0],(QMF_IM(buffer[12+i]) - QMF_IM(buffer[0+i]))) + MUL_F(filter[4],(QMF_IM(buffer[8+i]) - QMF_IM(buffer[4+i])));
+ input_im1[2] = MUL_F(filter[1],(QMF_IM(buffer[11+i]) - QMF_IM(buffer[1+i]))) + MUL_F(filter[3],(QMF_IM(buffer[9+i]) - QMF_IM(buffer[3+i])));
+ input_im1[3] = MUL_F(filter[2],(QMF_IM(buffer[10+i]) - QMF_IM(buffer[2+i])));
+
+ for (n = 0; n < 4; n++)
+ {
+ x[n] = input_re1[n] - input_im1[3-n];
+ }
+ DCT3_4_unscaled(x, x);
+ QMF_RE(X_hybrid[i][7]) = x[0];
+ QMF_RE(X_hybrid[i][5]) = x[2];
+ QMF_RE(X_hybrid[i][3]) = x[3];
+ QMF_RE(X_hybrid[i][1]) = x[1];
+
+ for (n = 0; n < 4; n++)
+ {
+ x[n] = input_re1[n] + input_im1[3-n];
+ }
+ DCT3_4_unscaled(x, x);
+ QMF_RE(X_hybrid[i][6]) = x[1];
+ QMF_RE(X_hybrid[i][4]) = x[3];
+ QMF_RE(X_hybrid[i][2]) = x[2];
+ QMF_RE(X_hybrid[i][0]) = x[0];
+
+ input_im2[0] = MUL_F(filter[6],QMF_IM(buffer[6+i]));
+ input_im2[1] = MUL_F(filter[5],(QMF_IM(buffer[5+i]) + QMF_IM(buffer[7+i])));
+ input_im2[2] = -MUL_F(filter[0],(QMF_IM(buffer[0+i]) + QMF_IM(buffer[12+i]))) + MUL_F(filter[4],(QMF_IM(buffer[4+i]) + QMF_IM(buffer[8+i])));
+ input_im2[3] = -MUL_F(filter[1],(QMF_IM(buffer[1+i]) + QMF_IM(buffer[11+i]))) + MUL_F(filter[3],(QMF_IM(buffer[3+i]) + QMF_IM(buffer[9+i])));
+
+ input_re2[0] = MUL_F(filter[5],(QMF_RE(buffer[7+i]) - QMF_RE(buffer[5+i])));
+ input_re2[1] = MUL_F(filter[0],(QMF_RE(buffer[12+i]) - QMF_RE(buffer[0+i]))) + MUL_F(filter[4],(QMF_RE(buffer[8+i]) - QMF_RE(buffer[4+i])));
+ input_re2[2] = MUL_F(filter[1],(QMF_RE(buffer[11+i]) - QMF_RE(buffer[1+i]))) + MUL_F(filter[3],(QMF_RE(buffer[9+i]) - QMF_RE(buffer[3+i])));
+ input_re2[3] = MUL_F(filter[2],(QMF_RE(buffer[10+i]) - QMF_RE(buffer[2+i])));
+
+ for (n = 0; n < 4; n++)
+ {
+ x[n] = input_im2[n] + input_re2[3-n];
+ }
+ DCT3_4_unscaled(x, x);
+ QMF_IM(X_hybrid[i][7]) = x[0];
+ QMF_IM(X_hybrid[i][5]) = x[2];
+ QMF_IM(X_hybrid[i][3]) = x[3];
+ QMF_IM(X_hybrid[i][1]) = x[1];
+
+ for (n = 0; n < 4; n++)
+ {
+ x[n] = input_im2[n] - input_re2[3-n];
+ }
+ DCT3_4_unscaled(x, x);
+ QMF_IM(X_hybrid[i][6]) = x[1];
+ QMF_IM(X_hybrid[i][4]) = x[3];
+ QMF_IM(X_hybrid[i][2]) = x[2];
+ QMF_IM(X_hybrid[i][0]) = x[0];
+ }
+}
+
+static void INLINE DCT3_6_unscaled(real_t *y, real_t *x)
+{
+ real_t f0, f1, f2, f3, f4, f5, f6, f7;
+
+ f0 = MUL_F(x[3], FRAC_CONST(0.70710678118655));
+ f1 = x[0] + f0;
+ f2 = x[0] - f0;
+ f3 = MUL_F((x[1] - x[5]), FRAC_CONST(0.70710678118655));
+ f4 = MUL_F(x[2], FRAC_CONST(0.86602540378444)) + MUL_F(x[4], FRAC_CONST(0.5));
+ f5 = f4 - x[4];
+ f6 = MUL_F(x[1], FRAC_CONST(0.96592582628907)) + MUL_F(x[5], FRAC_CONST(0.25881904510252));
+ f7 = f6 - f3;
+ y[0] = f1 + f6 + f4;
+ y[1] = f2 + f3 - x[4];
+ y[2] = f7 + f2 - f5;
+ y[3] = f1 - f7 - f5;
+ y[4] = f1 - f3 - x[4];
+ y[5] = f2 - f6 + f4;
+}
+
+/* complex filter, size 12 */
+static void channel_filter12(hyb_info *hyb, uint8_t frame_len, const real_t *filter,
+ qmf_t *buffer, qmf_t **X_hybrid)
+{
+ uint8_t i, n;
+ real_t input_re1[6], input_re2[6], input_im1[6], input_im2[6];
+ real_t out_re1[6], out_re2[6], out_im1[6], out_im2[6];
+
+ for (i = 0; i < frame_len; i++)
+ {
+ for (n = 0; n < 6; n++)
+ {
+ if (n == 0)
+ {
+ input_re1[0] = MUL_F(QMF_RE(buffer[6+i]), filter[6]);
+ input_re2[0] = MUL_F(QMF_IM(buffer[6+i]), filter[6]);
+ } else {
+ input_re1[6-n] = MUL_F((QMF_RE(buffer[n+i]) + QMF_RE(buffer[12-n+i])), filter[n]);
+ input_re2[6-n] = MUL_F((QMF_IM(buffer[n+i]) + QMF_IM(buffer[12-n+i])), filter[n]);
+ }
+ input_im2[n] = MUL_F((QMF_RE(buffer[n+i]) - QMF_RE(buffer[12-n+i])), filter[n]);
+ input_im1[n] = MUL_F((QMF_IM(buffer[n+i]) - QMF_IM(buffer[12-n+i])), filter[n]);
+ }
+
+ DCT3_6_unscaled(out_re1, input_re1);
+ DCT3_6_unscaled(out_re2, input_re2);
+
+ DCT3_6_unscaled(out_im1, input_im1);
+ DCT3_6_unscaled(out_im2, input_im2);
+
+ for (n = 0; n < 6; n += 2)
+ {
+ QMF_RE(X_hybrid[i][n]) = out_re1[n] - out_im1[n];
+ QMF_IM(X_hybrid[i][n]) = out_re2[n] + out_im2[n];
+ QMF_RE(X_hybrid[i][n+1]) = out_re1[n+1] + out_im1[n+1];
+ QMF_IM(X_hybrid[i][n+1]) = out_re2[n+1] - out_im2[n+1];
+
+ QMF_RE(X_hybrid[i][10-n]) = out_re1[n+1] - out_im1[n+1];
+ QMF_IM(X_hybrid[i][10-n]) = out_re2[n+1] + out_im2[n+1];
+ QMF_RE(X_hybrid[i][11-n]) = out_re1[n] + out_im1[n];
+ QMF_IM(X_hybrid[i][11-n]) = out_re2[n] - out_im2[n];
+ }
+ }
+}
+
+/* Hybrid analysis: further split up QMF subbands
+ * to improve frequency resolution
+ */
+static void hybrid_analysis(hyb_info *hyb, qmf_t X[32][64], qmf_t X_hybrid[32][32],
+ uint8_t use34)
+{
+ uint8_t k, n, band;
+ uint8_t offset = 0;
+ uint8_t qmf_bands = (use34) ? 5 : 3;
+ uint8_t *resolution = (use34) ? hyb->resolution34 : hyb->resolution20;
+
+ for (band = 0; band < qmf_bands; band++)
+ {
+ /* build working buffer */
+ memcpy(hyb->work, hyb->buffer[band], 12 * sizeof(qmf_t));
+
+ /* add new samples */
+ for (n = 0; n < hyb->frame_len; n++)
+ {
+ QMF_RE(hyb->work[12 + n]) = QMF_RE(X[n + 6 /*delay*/][band]);
+ QMF_IM(hyb->work[12 + n]) = QMF_IM(X[n + 6 /*delay*/][band]);
+ }
+
+ /* store samples */
+ memcpy(hyb->buffer[band], hyb->work + hyb->frame_len, 12 * sizeof(qmf_t));
+
+
+ switch(resolution[band])
+ {
+ case 2:
+ /* Type B real filter, Q[p] = 2 */
+ channel_filter2(hyb, hyb->frame_len, p2_13_20, hyb->work, hyb->temp);
+ break;
+ case 4:
+ /* Type A complex filter, Q[p] = 4 */
+ channel_filter4(hyb, hyb->frame_len, p4_13_34, hyb->work, hyb->temp);
+ break;
+ case 8:
+ /* Type A complex filter, Q[p] = 8 */
+ channel_filter8(hyb, hyb->frame_len, (use34) ? p8_13_34 : p8_13_20,
+ hyb->work, hyb->temp);
+ break;
+ case 12:
+ /* Type A complex filter, Q[p] = 12 */
+ channel_filter12(hyb, hyb->frame_len, p12_13_34, hyb->work, hyb->temp);
+ break;
+ }
+
+ for (n = 0; n < hyb->frame_len; n++)
+ {
+ for (k = 0; k < resolution[band]; k++)
+ {
+ QMF_RE(X_hybrid[n][offset + k]) = QMF_RE(hyb->temp[n][k]);
+ QMF_IM(X_hybrid[n][offset + k]) = QMF_IM(hyb->temp[n][k]);
+ }
+ }
+ offset += resolution[band];
+ }
+
+ /* group hybrid channels */
+ if (!use34)
+ {
+ for (n = 0; n < 32 /*30?*/; n++)
+ {
+ QMF_RE(X_hybrid[n][3]) += QMF_RE(X_hybrid[n][4]);
+ QMF_IM(X_hybrid[n][3]) += QMF_IM(X_hybrid[n][4]);
+ QMF_RE(X_hybrid[n][4]) = 0;
+ QMF_IM(X_hybrid[n][4]) = 0;
+
+ QMF_RE(X_hybrid[n][2]) += QMF_RE(X_hybrid[n][5]);
+ QMF_IM(X_hybrid[n][2]) += QMF_IM(X_hybrid[n][5]);
+ QMF_RE(X_hybrid[n][5]) = 0;
+ QMF_IM(X_hybrid[n][5]) = 0;
+ }
+ }
+}
+
+static void hybrid_synthesis(hyb_info *hyb, qmf_t X[32][64], qmf_t X_hybrid[32][32],
+ uint8_t use34)
+{
+ uint8_t k, n, band;
+ uint8_t offset = 0;
+ uint8_t qmf_bands = (use34) ? 5 : 3;
+ uint8_t *resolution = (use34) ? hyb->resolution34 : hyb->resolution20;
+
+ for(band = 0; band < qmf_bands; band++)
+ {
+ for (n = 0; n < hyb->frame_len; n++)
+ {
+ QMF_RE(X[n][band]) = 0;
+ QMF_IM(X[n][band]) = 0;
+
+ for (k = 0; k < resolution[band]; k++)
+ {
+ QMF_RE(X[n][band]) += QMF_RE(X_hybrid[n][offset + k]);
+ QMF_IM(X[n][band]) += QMF_IM(X_hybrid[n][offset + k]);
+ }
+ }
+ offset += resolution[band];
+ }
+}
+
+/* limits the value i to the range [min,max] */
+static int8_t delta_clip(int8_t i, int8_t min, int8_t max)
+{
+ if (i < min)
+ return min;
+ else if (i > max)
+ return max;
+ else
+ return i;
+}
+
+//int iid = 0;
+
+/* delta decode array */
+static void delta_decode(uint8_t enable, int8_t *index, int8_t *index_prev,
+ uint8_t dt_flag, uint8_t nr_par, uint8_t stride,
+ int8_t min_index, int8_t max_index)
+{
+ int8_t i;
+
+ if (enable == 1)
+ {
+ if (dt_flag == 0)
+ {
+ /* delta coded in frequency direction */
+ index[0] = 0 + index[0];
+ index[0] = delta_clip(index[0], min_index, max_index);
+
+ for (i = 1; i < nr_par; i++)
+ {
+ index[i] = index[i-1] + index[i];
+ index[i] = delta_clip(index[i], min_index, max_index);
+ }
+ } else {
+ /* delta coded in time direction */
+ for (i = 0; i < nr_par; i++)
+ {
+ //int8_t tmp2;
+ //int8_t tmp = index[i];
+
+ //printf("%d %d\n", index_prev[i*stride], index[i]);
+ //printf("%d\n", index[i]);
+
+ index[i] = index_prev[i*stride] + index[i];
+ //tmp2 = index[i];
+ index[i] = delta_clip(index[i], min_index, max_index);
+
+ //if (iid)
+ //{
+ // if (index[i] == 7)
+ // {
+ // printf("%d %d %d\n", index_prev[i*stride], tmp, tmp2);
+ // }
+ //}
+ }
+ }
+ } else {
+ /* set indices to zero */
+ for (i = 0; i < nr_par; i++)
+ {
+ index[i] = 0;
+ }
+ }
+
+ /* coarse */
+ if (stride == 2)
+ {
+ for (i = (nr_par<<1)-1; i > 0; i--)
+ {
+ index[i] = index[i>>1];
+ }
+ }
+}
+
+/* delta modulo decode array */
+/* 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 i;
+
+ if (enable == 1)
+ {
+ if (dt_flag == 0)
+ {
+ /* delta coded in frequency direction */
+ index[0] = 0 + index[0];
+ index[0] &= log2modulo;
+
+ for (i = 1; i < nr_par; i++)
+ {
+ index[i] = index[i-1] + index[i];
+ index[i] &= log2modulo;
+ }
+ } else {
+ /* delta coded in time direction */
+ for (i = 0; i < nr_par; i++)
+ {
+ index[i] = index_prev[i*stride] + index[i];
+ index[i] &= log2modulo;
+ }
+ }
+ } else {
+ /* set indices to zero */
+ for (i = 0; i < nr_par; i++)
+ {
+ index[i] = 0;
+ }
+ }
+
+ /* coarse */
+ if (stride == 2)
+ {
+ index[0] = 0;
+ for (i = (nr_par<<1)-1; i > 0; i--)
+ {
+ index[i] = index[i>>1];
+ }
+ }
+}
+
+#ifdef PS_LOW_POWER
+static void map34indexto20(int8_t *index, uint8_t bins)
+{
+ index[0] = (2*index[0]+index[1])/3;
+ index[1] = (index[1]+2*index[2])/3;
+ index[2] = (2*index[3]+index[4])/3;
+ index[3] = (index[4]+2*index[5])/3;
+ index[4] = (index[6]+index[7])/2;
+ index[5] = (index[8]+index[9])/2;
+ index[6] = index[10];
+ index[7] = index[11];
+ index[8] = (index[12]+index[13])/2;
+ index[9] = (index[14]+index[15])/2;
+ index[10] = index[16];
+
+ if (bins == 34)
+ {
+ index[11] = index[17];
+ index[12] = index[18];
+ index[13] = index[19];
+ index[14] = (index[20]+index[21])/2;
+ index[15] = (index[22]+index[23])/2;
+ index[16] = (index[24]+index[25])/2;
+ index[17] = (index[26]+index[27])/2;
+ index[18] = (index[28]+index[29]+index[30]+index[31])/4;
+ index[19] = (index[32]+index[33])/2;
+ }
+}
+#endif
+
+static void map20indexto34(int8_t *index, uint8_t bins)
+{
+ index[0] = index[0];
+ index[1] = (index[0] + index[1])/2;
+ index[2] = index[1];
+ index[3] = index[2];
+ index[4] = (index[2] + index[3])/2;
+ index[5] = index[3];
+ index[6] = index[4];
+ index[7] = index[4];
+ index[8] = index[5];
+ index[9] = index[5];
+ index[10] = index[6];
+ index[11] = index[7];
+ index[12] = index[8];
+ index[13] = index[8];
+ index[14] = index[9];
+ index[15] = index[9];
+ index[16] = index[10];
+
+ if (bins == 34)
+ {
+ index[17] = index[11];
+ index[18] = index[12];
+ index[19] = index[13];
+ index[20] = index[14];
+ index[21] = index[14];
+ index[22] = index[15];
+ index[23] = index[15];
+ index[24] = index[16];
+ index[25] = index[16];
+ index[26] = index[17];
+ index[27] = index[17];
+ index[28] = index[18];
+ index[29] = index[18];
+ index[30] = index[18];
+ index[31] = index[18];
+ index[32] = index[19];
+ index[33] = index[19];
+ }
+}
+
+/* parse the bitstream data decoded in ps_data() */
+static void ps_data_decode(ps_info *ps)
+{
+ uint8_t env, bin;
+
+ /* ps data not available, use data from previous frame */
+ if (ps->ps_data_available == 0)
+ {
+ ps->num_env = 0;
+ }
+
+ for (env = 0; env < ps->num_env; env++)
+ {
+ int8_t *iid_index_prev;
+ int8_t *icc_index_prev;
+ int8_t *ipd_index_prev;
+ int8_t *opd_index_prev;
+
+ int8_t num_iid_steps = (ps->iid_mode < 3) ? 7 : 15 /*fine quant*/;
+
+ if (env == 0)
+ {
+ /* take last envelope from previous frame */
+ iid_index_prev = ps->iid_index_prev;
+ icc_index_prev = ps->icc_index_prev;
+ ipd_index_prev = ps->ipd_index_prev;
+ opd_index_prev = ps->opd_index_prev;
+ } else {
+ /* take index values from previous envelope */
+ iid_index_prev = ps->iid_index[env - 1];
+ icc_index_prev = ps->icc_index[env - 1];
+ ipd_index_prev = ps->ipd_index[env - 1];
+ opd_index_prev = ps->opd_index[env - 1];
+ }
+
+// iid = 1;
+ /* delta decode iid parameters */
+ delta_decode(ps->enable_iid, ps->iid_index[env], iid_index_prev,
+ ps->iid_dt[env], ps->nr_iid_par,
+ (ps->iid_mode == 0 || ps->iid_mode == 3) ? 2 : 1,
+ -num_iid_steps, num_iid_steps);
+// iid = 0;
+
+ /* delta decode icc parameters */
+ delta_decode(ps->enable_icc, ps->icc_index[env], icc_index_prev,
+ ps->icc_dt[env], ps->nr_icc_par,
+ (ps->icc_mode == 0 || ps->icc_mode == 3) ? 2 : 1,
+ 0, 7);
+
+ /* 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);
+
+ /* 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);
+ }
+
+ /* handle error case */
+ if (ps->num_env == 0)
+ {
+ /* force to 1 */
+ ps->num_env = 1;
+
+ if (ps->enable_iid)
+ {
+ for (bin = 0; bin < 34; bin++)
+ ps->iid_index[0][bin] = ps->iid_index_prev[bin];
+ } else {
+ for (bin = 0; bin < 34; bin++)
+ ps->iid_index[0][bin] = 0;
+ }
+
+ if (ps->enable_icc)
+ {
+ for (bin = 0; bin < 34; bin++)
+ ps->icc_index[0][bin] = ps->icc_index_prev[bin];
+ } else {
+ for (bin = 0; bin < 34; bin++)
+ ps->icc_index[0][bin] = 0;
+ }
+
+ if (ps->enable_ipdopd)
+ {
+ for (bin = 0; bin < 17; bin++)
+ {
+ ps->ipd_index[0][bin] = ps->ipd_index_prev[bin];
+ ps->opd_index[0][bin] = ps->opd_index_prev[bin];
+ }
+ } else {
+ for (bin = 0; bin < 17; bin++)
+ {
+ ps->ipd_index[0][bin] = 0;
+ ps->opd_index[0][bin] = 0;
+ }
+ }
+ }
+
+ /* update previous indices */
+ for (bin = 0; bin < 34; bin++)
+ ps->iid_index_prev[bin] = ps->iid_index[ps->num_env-1][bin];
+ for (bin = 0; bin < 34; bin++)
+ ps->icc_index_prev[bin] = ps->icc_index[ps->num_env-1][bin];
+ for (bin = 0; bin < 17; bin++)
+ {
+ ps->ipd_index_prev[bin] = ps->ipd_index[ps->num_env-1][bin];
+ ps->opd_index_prev[bin] = ps->opd_index[ps->num_env-1][bin];
+ }
+
+ ps->ps_data_available = 0;
+
+ if (ps->frame_class == 0)
+ {
+ ps->border_position[0] = 0;
+ for (env = 1; env < ps->num_env; env++)
+ {
+ ps->border_position[env] = (env * 32 /* 30 for 960? */) / ps->num_env;
+ }
+ ps->border_position[ps->num_env] = 32 /* 30 for 960? */;
+ } else {
+ ps->border_position[0] = 0;
+
+ 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];
+ ps->icc_index[ps->num_env][bin] = ps->icc_index[ps->num_env-1][bin];
+ }
+ for (bin = 0; bin < 17; bin++)
+ {
+ 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];
+ }
+ }
+
+ for (env = 1; env < ps->num_env; env++)
+ {
+ int8_t thr = 32 /* 30 for 960? */ - (ps->num_env - env);
+
+ if (ps->border_position[env] > thr)
+ {
+ ps->border_position[env] = thr;
+ } else {
+ thr = ps->border_position[env-1]+1;
+ if (ps->border_position[env] < thr)
+ {
+ ps->border_position[env] = thr;
+ }
+ }
+ }
+ }
+
+ /* make sure that the indices of all parameters can be mapped
+ * to the same hybrid synthesis filterbank
+ */
+#ifdef PS_LOW_POWER
+ for (env = 0; env < ps->num_env; env++)
+ {
+ if (ps->iid_mode == 2 || ps->iid_mode == 5)
+ map34indexto20(ps->iid_index[env], 34);
+ if (ps->icc_mode == 2 || ps->icc_mode == 5)
+ map34indexto20(ps->icc_index[env], 34);
+
+ /* disable ipd/opd */
+ for (bin = 0; bin < 17; bin++)
+ {
+ ps->aaIpdIndex[env][bin] = 0;
+ ps->aaOpdIndex[env][bin] = 0;
+ }
+ }
+#else
+ if (ps->use34hybrid_bands)
+ {
+ for (env = 0; env < ps->num_env; env++)
+ {
+ if (ps->iid_mode != 2 && ps->iid_mode != 5)
+ map20indexto34(ps->iid_index[env], 34);
+ if (ps->icc_mode != 2 && ps->icc_mode != 5)
+ map20indexto34(ps->icc_index[env], 34);
+ if (ps->ipd_mode != 2 && ps->ipd_mode != 5)
+ {
+ map20indexto34(ps->ipd_index[env], 17);
+