📄 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_32KHZstatic const uint8_t delay_length_d[2][NO_ALLPASS_LINKS] = { { 1, 2, 3 } /* d_24kHz */, { 3, 4, 5 } /* d_48kHz */};#elsestatic const uint8_t delay_length_d[NO_ALLPASS_LINKS] = { 3, 4, 5 /* d_48kHz */};#endifstatic 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_POWERstatic void map34indexto20(int8_t *index, uint8_t bins);#endifstatic 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; y[3] = f2 - f8; y[0] = f2 + f8; y[2] = f1 - f7; y[1] = f1 + f7;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -