📄 ps_dec.c
字号:
/*
** 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.
**
** $Id: ps_dec.c,v 1.10 2004/09/04 14:56:28 menno Exp $
**/
#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);
faad_free(hyb);
}
/* 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;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -