/* ** FAAD2 - Freeware Advanced Audio (AAC) Decoder including SBR 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$ **/ #include "common.h" #include "structs.h" #ifdef SBR_DEC #include #include #include "syntax.h" #include "bits.h" #include "sbr_syntax.h" #include "sbr_qmf.h" #include "sbr_hfgen.h" #include "sbr_hfadj.h" /* static function declarations */ static uint8_t sbr_save_prev_data(sbr_info *sbr, uint8_t ch); static void sbr_save_matrix(sbr_info *sbr, uint8_t ch); sbr_info *sbrDecodeInit(uint16_t framelength, uint8_t id_aac, uint32_t sample_rate, uint8_t downSampledSBR #ifdef DRM , uint8_t IsDRM #endif ) { sbr_info *sbr = faad_malloc(sizeof(sbr_info)); memset(sbr, 0, sizeof(sbr_info)); /* save id of the parent element */ sbr->id_aac = id_aac; sbr->sample_rate = sample_rate; sbr->bs_freq_scale = 2; sbr->bs_alter_scale = 1; sbr->bs_noise_bands = 2; sbr->bs_limiter_bands = 2; sbr->bs_limiter_gains = 2; sbr->bs_interpol_freq = 1; sbr->bs_smoothing_mode = 1; sbr->bs_start_freq = 5; sbr->bs_amp_res = 1; sbr->bs_samplerate_mode = 1; sbr->prevEnvIsShort[0] = -1; sbr->prevEnvIsShort[1] = -1; sbr->header_count = 0; sbr->Reset = 1; #ifdef DRM sbr->Is_DRM_SBR = IsDRM; #endif sbr->tHFGen = T_HFGEN; sbr->tHFAdj = T_HFADJ; sbr->bsco = 0; sbr->bsco_prev = 0; sbr->M_prev = 0; sbr->frame_len = framelength; /* force sbr reset */ sbr->bs_start_freq_prev = -1; if (framelength == 960) { sbr->numTimeSlotsRate = RATE * NO_TIME_SLOTS_960; sbr->numTimeSlots = NO_TIME_SLOTS_960; } else { sbr->numTimeSlotsRate = RATE * NO_TIME_SLOTS; sbr->numTimeSlots = NO_TIME_SLOTS; } sbr->GQ_ringbuf_index[0] = 0; sbr->GQ_ringbuf_index[1] = 0; if (id_aac == ID_CPE) { /* stereo */ uint8_t j; sbr->qmfa[0] = qmfa_init(32); sbr->qmfa[1] = qmfa_init(32); sbr->qmfs[0] = qmfs_init((downSampledSBR)?32:64); sbr->qmfs[1] = qmfs_init((downSampledSBR)?32:64); for (j = 0; j < 5; j++) { sbr->G_temp_prev[0][j] = faad_malloc(64*sizeof(real_t)); sbr->G_temp_prev[1][j] = faad_malloc(64*sizeof(real_t)); sbr->Q_temp_prev[0][j] = faad_malloc(64*sizeof(real_t)); sbr->Q_temp_prev[1][j] = faad_malloc(64*sizeof(real_t)); } memset(sbr->Xsbr[0], 0, (sbr->numTimeSlotsRate+sbr->tHFGen)*64 * sizeof(qmf_t)); memset(sbr->Xsbr[1], 0, (sbr->numTimeSlotsRate+sbr->tHFGen)*64 * sizeof(qmf_t)); } else { /* mono */ uint8_t j; sbr->qmfa[0] = qmfa_init(32); sbr->qmfs[0] = qmfs_init((downSampledSBR)?32:64); sbr->qmfs[1] = NULL; for (j = 0; j < 5; j++) { sbr->G_temp_prev[0][j] = faad_malloc(64*sizeof(real_t)); sbr->Q_temp_prev[0][j] = faad_malloc(64*sizeof(real_t)); } memset(sbr->Xsbr[0], 0, (sbr->numTimeSlotsRate+sbr->tHFGen)*64 * sizeof(qmf_t)); } return sbr; } void sbrDecodeEnd(sbr_info *sbr) { uint8_t j; if (sbr) { qmfa_end(sbr->qmfa[0]); qmfs_end(sbr->qmfs[0]); if (sbr->qmfs[1] != NULL) { qmfa_end(sbr->qmfa[1]); qmfs_end(sbr->qmfs[1]); } for (j = 0; j < 5; j++) { if (sbr->G_temp_prev[0][j]) faad_free(sbr->G_temp_prev[0][j]); if (sbr->Q_temp_prev[0][j]) faad_free(sbr->Q_temp_prev[0][j]); if (sbr->G_temp_prev[1][j]) faad_free(sbr->G_temp_prev[1][j]); if (sbr->Q_temp_prev[1][j]) faad_free(sbr->Q_temp_prev[1][j]); } #ifdef PS_DEC if (sbr->ps != NULL) ps_free(sbr->ps); #endif #ifdef DRM_PS if (sbr->drm_ps != NULL) drm_ps_free(sbr->drm_ps); #endif faad_free(sbr); } } static uint8_t sbr_save_prev_data(sbr_info *sbr, uint8_t ch) { uint8_t i; /* save data for next frame */ sbr->kx_prev = sbr->kx; sbr->M_prev = sbr->M; sbr->bsco_prev = sbr->bsco; sbr->L_E_prev[ch] = sbr->L_E[ch]; /* sbr->L_E[ch] can become 0 on files with bit errors */ if (sbr->L_E[ch] <= 0) return 19; sbr->f_prev[ch] = sbr->f[ch][sbr->L_E[ch] - 1]; for (i = 0; i < MAX_M; i++) { sbr->E_prev[ch][i] = sbr->E[ch][i][sbr->L_E[ch] - 1]; sbr->Q_prev[ch][i] = sbr->Q[ch][i][sbr->L_Q[ch] - 1]; } for (i = 0; i < MAX_M; i++) { sbr->bs_add_harmonic_prev[ch][i] = sbr->bs_add_harmonic[ch][i]; } sbr->bs_add_harmonic_flag_prev[ch] = sbr->bs_add_harmonic_flag[ch]; if (sbr->l_A[ch] == sbr->L_E[ch]) sbr->prevEnvIsShort[ch] = 0; else sbr->prevEnvIsShort[ch] = -1; return 0; } static void sbr_save_matrix(sbr_info *sbr, uint8_t ch) { uint8_t i; for (i = 0; i < sbr->tHFGen; i++) { memmove(sbr->Xsbr[ch][i], sbr->Xsbr[ch][i+sbr->numTimeSlotsRate], 64 * sizeof(qmf_t)); } for (i = sbr->tHFGen; i < MAX_NTSRHFG; i++) { memset(sbr->Xsbr[ch][i], 0, 64 * sizeof(qmf_t)); } } #ifdef SBR_LOW_POWER ALIGN real_t deg[64]; #endif static void sbr_process_channel(sbr_info *sbr, real_t *channel_buf, qmf_t X[MAX_NTSR][64], uint8_t ch, uint8_t dont_process, const uint8_t downSampledSBR) { int16_t k, l; (void)downSampledSBR; #ifdef DRM if (sbr->Is_DRM_SBR) { sbr->bsco = max((int32_t)sbr->maxAACLine*32/(int32_t)sbr->frame_len - (int32_t)sbr->kx, 0); } else { #endif sbr->bsco = 0; #ifdef DRM } #endif //#define PRE_QMF_PRINT #ifdef PRE_QMF_PRINT { int i; for (i = 0; i < 1024; i++) { printf("%d\n", channel_buf[i]); } } #endif /* subband analysis */ if (dont_process) sbr_qmf_analysis_32(sbr, sbr->qmfa[ch], channel_buf, sbr->Xsbr[ch], sbr->tHFGen, 32); else sbr_qmf_analysis_32(sbr, sbr->qmfa[ch], channel_buf, sbr->Xsbr[ch], sbr->tHFGen, sbr->kx); if (!dont_process) { #if 1 /* insert high frequencies here */ /* hf generation using patching */ hf_generation(sbr, sbr->Xsbr[ch], sbr->Xsbr[ch] #ifdef SBR_LOW_POWER ,deg #endif ,ch); #endif #ifdef SBR_LOW_POWER for (l = sbr->t_E[ch][0]; l < sbr->t_E[ch][sbr->L_E[ch]]; l++) { for (k = 0; k < sbr->kx; k++) { QMF_RE(sbr->Xsbr[ch][sbr->tHFAdj + l][k]) = 0; } } #endif #if 1 /* hf adjustment */ hf_adjustment(sbr, sbr->Xsbr[ch] #ifdef SBR_LOW_POWER ,deg #endif ,ch); #endif } if ((sbr->just_seeked != 0) || dont_process) { for (l = 0; l < sbr->numTimeSlotsRate; l++) { for (k = 0; k < 32; k++) { QMF_RE(X[l][k]) = QMF_RE(sbr->Xsbr[ch][l + sbr->tHFAdj][k]); #ifndef SBR_LOW_POWER QMF_IM(X[l][k]) = QMF_IM(sbr->Xsbr[ch][l + sbr->tHFAdj][k]); #endif } for (k = 32; k < 64; k++) { QMF_RE(X[l][k]) = 0; #ifndef SBR_LOW_POWER QMF_IM(X[l][k]) = 0; #endif } } } else { for (l = 0; l < sbr->numTimeSlotsRate; l++) { uint8_t kx_band, M_band, bsco_band; if (l < sbr->t_E[ch][0]) { kx_band = sbr->kx_prev; M_band = sbr->M_prev; bsco_band = sbr->bsco_prev; } else { kx_band = sbr->kx; M_band = sbr->M; bsco_band = sbr->bsco; } #ifndef SBR_LOW_POWER for (k = 0; k < kx_band + bsco_band; k++) { QMF_RE(X[l][k]) = QMF_RE(sbr->Xsbr[ch][l + sbr->tHFAdj][k]); QMF_IM(X[l][k]) = QMF_IM(sbr->Xsbr[ch][l + sbr->tHFAdj][k]); } for (k = kx_band + bsco_band; k < kx_band + M_band; k++) { QMF_RE(X[l][k]) = QMF_RE(sbr->Xsbr[ch][l + sbr->tHFAdj][k]); QMF_IM(X[l][k]) = QMF_IM(sbr->Xsbr[ch][l + sbr->tHFAdj][k]); } for (k = max(kx_band + bsco_band, kx_band + M_band); k < 64; k++) { QMF_RE(X[l][k]) = 0; QMF_IM(X[l][k]) = 0; } #else for (k = 0; k < kx_band + bsco_band; k++) { QMF_RE(X[l][k]) = QMF_RE(sbr->Xsbr[ch][l + sbr->tHFAdj][k]); } for (k = kx_band + bsco_band; k < min(kx_band + M_band, 63); k++) { QMF_RE(X[l][k]) = QMF_RE(sbr->Xsbr[ch][l + sbr->tHFAdj][k]); } for (k = max(kx_band + bsco_band, kx_band + M_band); k < 64; k++) { QMF_RE(X[l][k]) = 0; } QMF_RE(X[l][kx_band - 1 + bsco_band]) += QMF_RE(sbr->Xsbr[ch][l + sbr->tHFAdj][kx_band - 1 + bsco_band]); #endif } } } ALIGN qmf_t X[MAX_NTSR][64]; uint8_t sbrDecodeCoupleFrame(sbr_info *sbr, real_t *left_chan, real_t *right_chan, const uint8_t just_seeked, const uint8_t downSampledSBR) { uint8_t dont_process = 0; uint8_t ret = 0; if (sbr == NULL) return 20; /* case can occur due to bit errors */ if (sbr->id_aac != ID_CPE) return 21; if (sbr->ret || (sbr->header_count == 0)) { /* don't process just upsample */ dont_process = 1; /* Re-activate reset for next frame */ if (sbr->ret && sbr->Reset) sbr->bs_start_freq_prev = -1; } if (just_seeked) { sbr->just_seeked = 1; } else { sbr->just_seeked = 0; } sbr_process_channel(sbr, left_chan, X, 0, dont_process, downSampledSBR); /* subband synthesis */ if (downSampledSBR) { sbr_qmf_synthesis_32(sbr, sbr->qmfs[0], X, left_chan); } else { sbr_qmf_synthesis_64(sbr, sbr->qmfs[0], X, left_chan); } sbr_process_channel(sbr, right_chan, X, 1, dont_process, downSampledSBR); /* subband synthesis */ if (downSampledSBR) { sbr_qmf_synthesis_32(sbr, sbr->qmfs[1], X, right_chan); } else { sbr_qmf_synthesis_64(sbr, sbr->qmfs[1], X, right_chan); } if (sbr->bs_header_flag) sbr->just_seeked = 0; if (sbr->header_count != 0 && sbr->ret == 0) { ret = sbr_save_prev_data(sbr, 0); if (ret) return ret; ret = sbr_save_prev_data(sbr, 1); if (ret) return ret; } sbr_save_matrix(sbr, 0); sbr_save_matrix(sbr, 1); sbr->frame++; //#define POST_QMF_PRINT #ifdef POST_QMF_PRINT { int i; for (i = 0; i < 2048; i++) { printf("%d\n", left_chan[i]); } for (i = 0; i < 2048; i++) { printf("%d\n", right_chan[i]); } } #endif return 0; } ALIGN qmf_t X[MAX_NTSR][64]; uint8_t sbrDecodeSingleFrame(sbr_info *sbr, real_t *channel, const uint8_t just_seeked, const uint8_t downSampledSBR) { uint8_t dont_process = 0; uint8_t ret = 0; if (sbr == NULL) return 20; /* case can occur due to bit errors */ if (sbr->id_aac != ID_SCE && sbr->id_aac != ID_LFE) return 21; if (sbr->ret || (sbr->header_count == 0)) { /* don't process just upsample */ dont_process = 1; /* Re-activate reset for next frame */ if (sbr->ret && sbr->Reset) sbr->bs_start_freq_prev = -1; } if (just_seeked) { sbr->just_seeked = 1; } else { sbr->just_seeked = 0; } sbr_process_channel(sbr, channel, X, 0, dont_process, downSampledSBR); /* subband synthesis */ if (downSampledSBR) { sbr_qmf_synthesis_32(sbr, sbr->qmfs[0], X, channel); } else { sbr_qmf_synthesis_64(sbr, sbr->qmfs[0], X, channel); } if (sbr->bs_header_flag) sbr->just_seeked = 0; if (sbr->header_count != 0 && sbr->ret == 0) { ret = sbr_save_prev_data(sbr, 0); if (ret) return ret; } sbr_save_matrix(sbr, 0); sbr->frame++; //#define POST_QMF_PRINT #ifdef POST_QMF_PRINT { int i; for (i = 0; i < 2048; i++) { printf("%d\n", channel[i]); } } #endif return 0; } ALIGN qmf_t X_left[38][64];// = {{0}}; ALIGN qmf_t X_right[38][64];// = {{0}}; /* must set this to 0 */ #if (defined(PS_DEC) || defined(DRM_PS)) uint8_t sbrDecodeSingleFramePS(sbr_info *sbr, real_t *left_channel, real_t *right_channel, const uint8_t just_seeked, const uint8_t downSampledSBR) { uint8_t l, k; uint8_t dont_process = 0; uint8_t ret = 0; memset(X_left,0,sizeof(X_left)); memset(X_right,0,sizeof(X_right)); if (sbr == NULL) return 20; /* case can occur due to bit errors */ if (sbr->id_aac != ID_SCE && sbr->id_aac != ID_LFE) return 21; if (sbr->ret || (sbr->header_count == 0)) { /* don't process just upsample */ dont_process = 1; /* Re-activate reset for next frame */ if (sbr->ret && sbr->Reset) sbr->bs_start_freq_prev = -1; } if (just_seeked) { sbr->just_seeked = 1; } else { sbr->just_seeked = 0; } if (sbr->qmfs[1] == NULL) { sbr->qmfs[1] = qmfs_init((downSampledSBR)?32:64); } sbr_process_channel(sbr, left_channel, X_left, 0, dont_process, downSampledSBR); /* copy some extra data for PS */ for (l = 32; l < 38; l++) { for (k = 0; k < 5; k++) { QMF_RE(X_left[l][k]) = QMF_RE(sbr->Xsbr[0][sbr->tHFAdj+l][k]); QMF_IM(X_left[l][k]) = QMF_IM(sbr->Xsbr[0][sbr->tHFAdj+l][k]); } } /* perform parametric stereo */ #ifdef DRM_PS if (sbr->Is_DRM_SBR) { drm_ps_decode(sbr->drm_ps, (sbr->ret > 0), sbr->sample_rate, X_left, X_right); } else { #endif #ifdef PS_DEC ps_decode(sbr->ps, X_left, X_right); #endif #ifdef DRM_PS } #endif /* subband synthesis */ if (downSampledSBR) { sbr_qmf_synthesis_32(sbr, sbr->qmfs[0], X_left, left_channel); sbr_qmf_synthesis_32(sbr, sbr->qmfs[1], X_right, right_channel); } else { sbr_qmf_synthesis_64(sbr, sbr->qmfs[0], X_left, left_channel); sbr_qmf_synthesis_64(sbr, sbr->qmfs[1], X_right, right_channel); } if (sbr->bs_header_flag) sbr->just_seeked = 0; if (sbr->header_count != 0 && sbr->ret == 0) { ret = sbr_save_prev_data(sbr, 0); if (ret) return ret; } sbr_save_matrix(sbr, 0); sbr->frame++; return 0; } #endif #endif ef='#n384'>384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546
/*
** 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$
**/

#include "common.h"

#ifdef PS_DEC

#include "bits.h"
#include "ps_dec.h"

/* type definitaions */
typedef const int8_t (*ps_huff_tab)[2];

/* static data tables */
static const uint8_t nr_iid_par_tab[] = {
    10, 20, 34, 10, 20, 34, 0, 0
};
static const uint8_t nr_ipdopd_par_tab[] = {
    5, 11, 17, 5, 11, 17, 0, 0
};
static const uint8_t nr_icc_par_tab[] = {
    10, 20, 34, 10, 20, 34, 0, 0
};
static const uint8_t num_env_tab[][4] = {
    { 0, 1, 2, 4 },
    { 1, 2, 3, 4 }
};

/* binary lookup huffman tables */
static const int8_t f_huff_iid_def[][2] = {
    { /*0*/ -31, 1 },             /* index 0: 1 bits: x */
    { 2, 3 },                     /* index 1: 2 bits: 1x */
    { /*1*/ -30, /*-1*/ -32 },    /* index 2: 3 bits: 10x */
    { 4, 5 },                     /* index 3: 3 bits: 11x */
    { /*2*/ -29, /*-2*/ -33 },    /* index 4: 4 bits: 110x */
    { 6, 7 },                     /* index 5: 4 bits: 111x */
    { /*3*/ -28, /*-3*/ -34 },    /* index 6: 5 bits: 1110x */
    { 8, 9 },                     /* index 7: 5 bits: 1111x */
    { /*-4*/ -35, /*4*/ -27 },    /* index 8: 6 bits: 11110x */
    { /*5*/ -26, 10 },            /* index 9: 6 bits: 11111x */
    { /*-5*/ -36, 11 },           /* index 10: 7 bits: 111111x */
    { /*6*/ -25, 12 },            /* index 11: 8 bits: 1111111x */
    { /*-6*/ -37, 13 },           /* index 12: 9 bits: 11111111x */
    { /*-7*/ -38, 14 },           /* index 13: 10 bits: 111111111x */
    { /*7*/ -24, 15 },            /* index 14: 11 bits: 1111111111x */
    { 16, 17 },                   /* index 15: 12 bits: 11111111111x */
    { /*8*/ -23, /*-8*/ -39 },    /* index 16: 13 bits: 111111111110x */
    { 18, 19 },                   /* index 17: 13 bits: 111111111111x */
    { /*9*/ -22, /*10*/ -21 },    /* index 18: 14 bits: 1111111111110x */
    { 20, 21 },                   /* index 19: 14 bits: 1111111111111x */
    { /*-9*/ -40, /*11*/ -20 },   /* index 20: 15 bits: 11111111111110x */
    { 22, 23 },                   /* index 21: 15 bits: 11111111111111x */
    { /*-10*/ -41, 24 },          /* index 22: 16 bits: 111111111111110x */
    { 25, 26 },                   /* index 23: 16 bits: 111111111111111x */
    { /*-11*/ -42, /*-14*/ -45 }, /* index 24: 17 bits: 1111111111111101x */
    { /*-13*/ -44, /*-12*/ -43 }, /* index 25: 17 bits: 1111111111111110x */
    { /*12*/ -19, 27 },           /* index 26: 17 bits: 1111111111111111x */
    { /*13*/ -18, /*14*/ -17 }    /* index 27: 18 bits: 11111111111111111x */
};

static const int8_t t_huff_iid_def[][2] = {
    { /*0*/ -31, 1 },             /* index 0: 1 bits: x */
    { /*-1*/ -32, 2 },            /* index 1: 2 bits: 1x */
    { /*1*/ -30, 3 },             /* index 2: 3 bits: 11x */
    { /*-2*/ -33, 4 },            /* index 3: 4 bits: 111x */
    { /*2*/ -29, 5 },             /* index 4: 5 bits: 1111x */
    { /*-3*/ -34, 6 },            /* index 5: 6 bits: 11111x */
    { /*3*/ -28, 7 },             /* index 6: 7 bits: 111111x */
    { /*-4*/ -35, 8 },            /* index 7: 8 bits: 1111111x */
    { /*4*/ -27, 9 },             /* index 8: 9 bits: 11111111x */
    { /*-5*/ -36, 10 },           /* index 9: 10 bits: 111111111x */
    { /*5*/ -26, 11 },            /* index 10: 11 bits: 1111111111x */
    { /*-6*/ -37, 12 },           /* index 11: 12 bits: 11111111111x */
    { /*6*/ -25, 13 },            /* index 12: 13 bits: 111111111111x */
    { /*7*/ -24, 14 },            /* index 13: 14 bits: 1111111111111x */
    { /*-7*/ -38, 15 },           /* index 14: 15 bits: 11111111111111x */
    { 16, 17 },                   /* index 15: 16 bits: 111111111111111x */
    { /*8*/ -23, /*-8*/ -39 },    /* index 16: 17 bits: 1111111111111110x */
    { 18, 19 },                   /* index 17: 17 bits: 1111111111111111x */
    { 20, 21 },                   /* index 18: 18 bits: 11111111111111110x */
    { 22, 23 },                   /* index 19: 18 bits: 11111111111111111x */
    { /*9*/ -22, /*-14*/ -45 },   /* index 20: 19 bits: 111111111111111100x */
    { /*-13*/ -44, /*-12*/ -43 }, /* index 21: 19 bits: 111111111111111101x */
    { 24, 25 },                   /* index 22: 19 bits: 111111111111111110x */
    { 26, 27 },                   /* index 23: 19 bits: 111111111111111111x */
    { /*-11*/ -42, /*-10*/ -41 }, /* index 24: 20 bits: 1111111111111111100x */
    { /*-9*/ -40, /*10*/ -21 },   /* index 25: 20 bits: 1111111111111111101x */
    { /*11*/ -20, /*12*/ -19 },   /* index 26: 20 bits: 1111111111111111110x */
    { /*13*/ -18, /*14*/ -17 }    /* index 27: 20 bits: 1111111111111111111x */
};

static const int8_t f_huff_iid_fine[][2] = {
    { 1, /*0*/ -31 },             /* index 0: 1 bits: x */
    { 2, 3 },                     /* index 1: 2 bits: 0x */
    { 4, /*-1*/ -32 },            /* index 2: 3 bits: 00x */
    { /*1*/ -30, 5 },             /* index 3: 3 bits: 01x */
    { /*-2*/ -33, /*2*/ -29 },    /* index 4: 4 bits: 000x */
    { 6, 7 },                     /* index 5: 4 bits: 011x */
    { /*-3*/ -34, /*3*/ -28 },    /* index 6: 5 bits: 0110x */
    { 8, 9 },                     /* index 7: 5 bits: 0111x */
    { /*-4*/ -35, /*4*/ -27 },    /* index 8: 6 bits: 01110x */
    { 10, 11 },                   /* index 9: 6 bits: 01111x */
    { /*-5*/ -36, /*5*/ -26 },    /* index 10: 7 bits: 011110x */
    { 12, 13 },                   /* index 11: 7 bits: 011111x */
    { /*-6*/ -37, /*6*/ -25 },    /* index 12: 8 bits: 0111110x */
    { 14, 15 },                   /* index 13: 8 bits: 0111111x */
    { /*7*/ -24, 16 },            /* index 14: 9 bits: 01111110x */
    { 17, 18 },                   /* index 15: 9 bits: 01111111x */
    { 19, /*-8*/ -39 },           /* index 16: 10 bits: 011111101x */
    { /*8*/ -23, 20 },            /* index 17: 10 bits: 011111110x */
    { 21, /*-7*/ -38 },           /* index 18: 10 bits: 011111111x */
    { /*10*/ -21, 22 },           /* index 19: 11 bits: 0111111010x */
    { 23, /*-9*/ -40 },           /* index 20: 11 bits: 0111111101x */
    { /*9*/ -22, 24 },            /* index 21: 11 bits: 0111111110x */
    { /*-11*/ -42, /*11*/ -20 },  /* index 22: 12 bits: 01111110101x */
    { 25, 26 },                   /* index 23: 12 bits: 01111111010x */
    { 27, /*-10*/ -41 },          /* index 24: 12 bits: 01111111101x */
    { 28, /*-12*/ -43 },          /* index 25: 13 bits: 011111110100x */
    { /*12*/ -19, 29 },           /* index 26: 13 bits: 011111110101x */
    { 30, 31 },                   /* index 27: 13 bits: 011111111010x */
    { 32, /*-14*/ -45 },          /* index 28: 14 bits: 0111111101000x */
    { /*14*/ -17, 33 },           /* index 29: 14 bits: 0111111101011x */
    { 34, /*-13*/ -44 },          /* index 30: 14 bits: 0111111110100x */
    { /*13*/ -18, 35 },           /* index 31: 14 bits: 0111111110101x */
    { 36, 37 },                   /* index 32: 15 bits: 01111111010000x */
    { 38, /*-15*/ -46 },          /* index 33: 15 bits: 01111111010111x */
    { /*15*/ -16, 39 },           /* index 34: 15 bits: 01111111101000x */
    { 40, 41 },                   /* index 35: 15 bits: 01111111101011x */
    { 42, 43 },                   /* index 36: 16 bits: 011111110100000x */
    { /*-17*/ -48, /*17*/ -14 },  /* index 37: 16 bits: 011111110100001x */
    { 44, 45 },                   /* index 38: 16 bits: 011111110101110x */
    { 46, 47 },                   /* index 39: 16 bits: 011111111010001x */
    { 48, 49 },                   /* index 40: 16 bits: 011111111010110x */
    { /*-16*/ -47, /*16*/ -15 },  /* index 41: 16 bits: 011111111010111x */
    { /*-21*/ -52, /*21*/ -10 },  /* index 42: 17 bits: 0111111101000000x */
    { /*-19*/ -50, /*19*/ -12 },  /* index 43: 17 bits: 0111111101000001x */
    { /*-18*/ -49, /*18*/ -13 },  /* index 44: 17 bits: 0111111101011100x */
    { 50, 51 },                   /* index 45: 17 bits: 0111111101011101x */
    { 52, 53 },                   /* index 46: 17 bits: 0111111110100010x */
    { 54, 55 },                   /* index 47: 17 bits: 0111111110100011x */
    { 56, 57 },                   /* index 48: 17 bits: 0111111110101100x */
    { 58, 59 },                   /* index 49: 17 bits: 0111111110101101x */
    { /*-26*/ -57, /*-25*/ -56 }, /* index 50: 18 bits: 01111111010111010x */
    { /*-28*/ -59, /*-27*/ -58 }, /* index 51: 18 bits: 01111111010111011x */
    { /*-22*/ -53, /*22*/ -9 },   /* index 52: 18 bits: 01111111101000100x */
    { /*-24*/ -55, /*-23*/ -54 }, /* index 53: 18 bits: 01111111101000101x */
    { /*25*/ -6, /*26*/ -5 },     /* index 54: 18 bits: 01111111101000110x */
    { /*23*/ -8, /*24*/ -7 },     /* index 55: 18 bits: 01111111101000111x */
    { /*29*/ -2, /*30*/ -1 },     /* index 56: 18 bits: 01111111101011000x */
    { /*27*/ -4, /*28*/ -3 },     /* index 57: 18 bits: 01111111101011001x */
    { /*-30*/ -61, /*-29*/ -60 }, /* index 58: 18 bits: 01111111101011010x */
    { /*-20*/ -51, /*20*/ -11 }   /* index 59: 18 bits: 01111111101011011x */
};

static const int8_t t_huff_iid_fine[][2] = {
    { 1, /*0*/ -31 },             /* index 0: 1 bits: x */
    { /*1*/ -30, 2 },             /* index 1: 2 bits: 0x */
    { 3, /*-1*/ -32 },            /* index 2: 3 bits: 01x */
    { 4, 5 },                     /* index 3: 4 bits: 010x */
    { 6, 7 },                     /* index 4: 5 bits: 0100x */
    { /*-2*/ -33, /*2*/ -29 },    /* index 5: 5 bits: 0101x */
    { 8, /*-3*/ -34 },            /* index 6: 6 bits: 01000x */
    { /*3*/ -28, 9 },             /* index 7: 6 bits: 01001x */
    { /*-4*/ -35, /*4*/ -27 },    /* index 8: 7 bits: 010000x */
    { 10, 11 },                   /* index 9: 7 bits: 010011x */
    { /*5*/ -26, 12 },            /* index 10: 8 bits: 0100110x */
    { 13, 14 },                   /* index 11: 8 bits: 0100111x */
    { /*-6*/ -37, /*6*/ -25 },    /* index 12: 9 bits: 01001101x */
    { 15, 16 },                   /* index 13: 9 bits: 01001110x */
    { 17, /*-5*/ -36 },           /* index 14: 9 bits: 01001111x */
    { 18, /*-7*/ -38 },           /* index 15: 10 bits: 010011100x */
    { /*7*/ -24, 19 },            /* index 16: 10 bits: 010011101x */
    { 20, 21 },                   /* index 17: 10 bits: 010011110x */
    { /*9*/ -22, 22 },            /* index 18: 11 bits: 0100111000x */
    { 23, 24 },                   /* index 19: 11 bits: 0100111011x */
    { /*-8*/ -39, /*8*/ -23 },    /* index 20: 11 bits: 0100111100x */
    { 25, 26 },                   /* index 21: 11 bits: 0100111101x */
    { /*11*/ -20, 27 },           /* index 22: 12 bits: 01001110001x */
    { 28, 29 },                   /* index 23: 12 bits: 01001110110x */
    { /*-10*/ -41, /*10*/ -21 },  /* index 24: 12 bits: 01001110111x */
    { 30, 31 },                   /* index 25: 12 bits: 01001111010x */
    { 32, /*-9*/ -40 },           /* index 26: 12 bits: 01001111011x */
    { 33, /*-13*/ -44 },          /* index 27: 13 bits: 010011100011x */
    { /*13*/ -18, 34 },           /* index 28: 13 bits: 010011101100x */
    { 35, 36 },                   /* index 29: 13 bits: 010011101101x */
    { 37, /*-12*/ -43 },          /* index 30: 13 bits: 010011110100x */
    { /*12*/ -19, 38 },           /* index 31: 13 bits: 010011110101x */
    { 39, /*-11*/ -42 },          /* index 32: 13 bits: 010011110110x */
    { 40, 41 },                   /* index 33: 14 bits: 0100111000110x */
    { 42, 43 },                   /* index 34: 14 bits: 0100111011001x */
    { 44, 45 },                   /* index 35: 14 bits: 0100111011010x */
    { 46, /*-15*/ -46 },          /* index 36: 14 bits: 0100111011011x */
    { /*15*/ -16, 47 },           /* index 37: 14 bits: 0100111101000x */
    { /*-14*/ -45, /*14*/ -17 },  /* index 38: 14 bits: 0100111101011x */
    { 48, 49 },                   /* index 39: 14 bits: 0100111101100x */
    { /*-21*/ -52, /*-20*/ -51 }, /* index 40: 15 bits: 01001110001100x */
    { /*18*/ -13, /*19*/ -12 },   /* index 41: 15 bits: 01001110001101x */
    { /*-19*/ -50, /*-18*/ -49 }, /* index 42: 15 bits: 01001110110010x */
    { 50, 51 },                   /* index 43: 15 bits: 01001110110011x */
    { 52, 53 },                   /* index 44: 15 bits: 01001110110100x */
    { 54, 55 },                   /* index 45: 15 bits: 01001110110101x */
    { 56, /*-17*/ -48 },          /* index 46: 15 bits: 01001110110110x */
    { /*17*/ -14, 57 },           /* index 47: 15 bits: 01001111010001x */
    { 58, /*-16*/ -47 },          /* index 48: 15 bits: 01001111011000x */
    { /*16*/ -15, 59 },           /* index 49: 15 bits: 01001111011001x */
    { /*-26*/ -57, /*26*/ -5 },   /* index 50: 16 bits: 010011101100110x */
    { /*-28*/ -59, /*-27*/ -58 }, /* index 51: 16 bits: 010011101100111x */
    { /*29*/ -2, /*30*/ -1 },     /* index 52: 16 bits: 010011101101000x */
    { /*27*/ -4, /*28*/ -3 },     /* index 53: 16 bits: 010011101101001x */
    { /*-30*/ -61, /*-29*/ -60 }, /* index 54: 16 bits: 010011101101010x */
    { /*-25*/ -56, /*25*/ -6 },   /* index 55: 16 bits: 010011101101011x */
    { /*-24*/ -55, /*24*/ -7 },   /* index 56: 16 bits: 010011101101100x */
    { /*-23*/ -54, /*23*/ -8 },   /* index 57: 16 bits: 010011110100011x */
    { /*-22*/ -53, /*22*/ -9 },   /* index 58: 16 bits: 010011110110000x */
    { /*20*/ -11, /*21*/ -10 }    /* index 59: 16 bits: 010011110110011x */
};

static const int8_t f_huff_icc[][2] = {
    { /*0*/ -31, 1 },            /* index 0: 1 bits: x */
    { /*1*/ -30, 2 },            /* index 1: 2 bits: 1x */
    { /*-1*/ -32, 3 },           /* index 2: 3 bits: 11x */
    { /*2*/ -29, 4 },            /* index 3: 4 bits: 111x */
    { /*-2*/ -33, 5 },           /* index 4: 5 bits: 1111x */
    { /*3*/ -28, 6 },            /* index 5: 6 bits: 11111x */
    { /*-3*/ -34, 7 },           /* index 6: 7 bits: 111111x */
    { /*4*/ -27, 8 },            /* index 7: 8 bits: 1111111x */
    { /*5*/ -26, 9 },            /* index 8: 9 bits: 11111111x */
    { /*-4*/ -35, 10 },          /* index 9: 10 bits: 111111111x */
    { /*6*/ -25, 11 },           /* index 10: 11 bits: 1111111111x */
    { /*-5*/ -36, 12 },          /* index 11: 12 bits: 11111111111x */
    { /*7*/ -24, 13 },           /* index 12: 13 bits: 111111111111x */
    { /*-6*/ -37, /*-7*/ -38 }   /* index 13: 14 bits: 1111111111111x */
};

static const int8_t t_huff_icc[][2] = {
    { /*0*/ -31, 1 },            /* index 0: 1 bits: x */
    { /*1*/ -30, 2 },            /* index 1: 2 bits: 1x */
    { /*-1*/ -32, 3 },           /* index 2: 3 bits: 11x */
    { /*2*/ -29, 4 },            /* index 3: 4 bits: 111x */
    { /*-2*/ -33, 5 },           /* index 4: 5 bits: 1111x */
    { /*3*/ -28, 6 },            /* index 5: 6 bits: 11111x */
    { /*-3*/ -34, 7 },           /* index 6: 7 bits: 111111x */
    { /*4*/ -27, 8 },            /* index 7: 8 bits: 1111111x */
    { /*-4*/ -35, 9 },           /* index 8: 9 bits: 11111111x */
    { /*5*/ -26, 10 },           /* index 9: 10 bits: 111111111x */
    { /*-5*/ -36, 11 },          /* index 10: 11 bits: 1111111111x */
    { /*6*/ -25, 12 },           /* index 11: 12 bits: 11111111111x */
    { /*-6*/ -37, 13 },          /* index 12: 13 bits: 111111111111x */
    { /*-7*/ -38, /*7*/ -24 }    /* index 13: 14 bits: 1111111111111x */
};

static const int8_t f_huff_ipd[][2] = {
    { 1, /*0*/ -31 },         /* index 0: 1 bits: x */
    { 2, 3 },                 /* index 1: 2 bits: 0x */
    { /*1*/ -30, 4 },         /* index 2: 3 bits: 00x */
    { 5, 6 },                 /* index 3: 3 bits: 01x */
    { /*4*/ -27, /*5*/ -26 }, /* index 4: 4 bits: 001x */
    { /*3*/ -28, /*6*/ -25 }, /* index 5: 4 bits: 010x */
    { /*2*/ -29, /*7*/ -24 }  /* index 6: 4 bits: 011x */
};

static const int8_t t_huff_ipd[][2] = {
    { 1, /*0*/ -31 },         /* index 0: 1 bits: x */
    { 2, 3 },                 /* index 1: 2 bits: 0x */
    { 4, 5 },                 /* index 2: 3 bits: 00x */
    { /*1*/ -30, /*7*/ -24 }, /* index 3: 3 bits: 01x */
    { /*5*/ -26, 6 },         /* index 4: 4 bits: 000x */
    { /*2*/ -29, /*6*/ -25 }, /* index 5: 4 bits: 001x */
    { /*4*/ -27, /*3*/ -28 }  /* index 6: 5 bits: 0001x */
};

static const int8_t f_huff_opd[][2] = {
    { 1, /*0*/ -31 },         /* index 0: 1 bits: x */
    { 2, 3 },                 /* index 1: 2 bits: 0x */
    { /*7*/ -24, /*1*/ -30 }, /* index 2: 3 bits: 00x */
    { 4, 5 },                 /* index 3: 3 bits: 01x */
    { /*3*/ -28, /*6*/ -25 }, /* index 4: 4 bits: 010x */
    { /*2*/ -29, 6 },         /* index 5: 4 bits: 011x */
    { /*5*/ -26, /*4*/ -27 }  /* index 6: 5 bits: 0111x */
};

static const int8_t t_huff_opd[][2] = {
    { 1, /*0*/ -31 },         /* index 0: 1 bits: x */
    { 2, 3 },                 /* index 1: 2 bits: 0x */
    { 4, 5 },                 /* index 2: 3 bits: 00x */
    { /*1*/ -30, /*7*/ -24 }, /* index 3: 3 bits: 01x */
    { /*5*/ -26, 6 },         /* index 4: 4 bits: 000x */
    { /*2*/ -29, /*6*/ -25 }, /* index 5: 4 bits: 001x */
    { /*4*/ -27, /*3*/ -28 }  /* index 6: 5 bits: 0001x */
};

/* static function declarations */
static uint16_t ps_extension(ps_info *ps, bitfile *ld,
                             const uint8_t ps_extension_id,
                             const uint16_t num_bits_left);
static void huff_data(bitfile *ld, const uint8_t dt, const uint8_t nr_par,
                      ps_huff_tab t_huff, ps_huff_tab f_huff, int8_t *par);
static INLINE int8_t ps_huff_dec(bitfile *ld, ps_huff_tab t_huff);


uint16_t ps_data(ps_info *ps, bitfile *ld, uint8_t *header)
{
    uint8_t tmp, n;
    uint16_t bits = (uint16_t)faad_get_processed_bits(ld);

    *header = 0;

    /* check for new PS header */
    if (faad_get1bit(ld
        DEBUGVAR(1,1000,"ps_data(): enable_ps_header")))
    {
        *header = 1;

        ps->header_read = 1;

        ps->use34hybrid_bands = 0;

        /* Inter-channel Intensity Difference (IID) parameters enabled */
        ps->enable_iid = (uint8_t)faad_get1bit(ld
            DEBUGVAR(1,1001,"ps_data(): enable_iid"));

        if (ps->enable_iid)
        {
            ps->iid_mode = (uint8_t)faad_getbits(ld, 3
                DEBUGVAR(1,1002,"ps_data(): iid_mode"));

            ps->nr_iid_par = nr_iid_par_tab[ps->iid_mode];
            ps->nr_ipdopd_par = nr_ipdopd_par_tab[ps->iid_mode];

            if (ps->iid_mode == 2 || ps->iid_mode == 5)
                ps->use34hybrid_bands = 1;

            /* IPD freq res equal to IID freq res */
            ps->ipd_mode = ps->iid_mode;
        }

        /* Inter-channel Coherence (ICC) parameters enabled */
        ps->enable_icc = (uint8_t)faad_get1bit(ld
            DEBUGVAR(1,1003,"ps_data(): enable_icc"));

        if (ps->enable_icc)
        {
            ps->icc_mode = (uint8_t)faad_getbits(ld, 3
                DEBUGVAR(1,1004,"ps_data(): icc_mode"));

            ps->nr_icc_par = nr_icc_par_tab[ps->icc_mode];

            if (ps->icc_mode == 2 || ps->icc_mode == 5)
                ps->use34hybrid_bands = 1;
        }

        /* PS extension layer enabled */
        ps->enable_ext = (uint8_t)faad_get1bit(ld
            DEBUGVAR(1,1005,"ps_data(): enable_ext"));
    }

    /* we are here, but no header has been read yet */
    if (ps->header_read == 0)
        return 1;

    ps->frame_class = (uint8_t)faad_get1bit(ld
        DEBUGVAR(1,1006,"ps_data(): frame_class"));
    tmp = (uint8_t)faad_getbits(ld, 2
        DEBUGVAR(1,1007,"ps_data(): num_env_idx"));

    ps->num_env = num_env_tab[ps->frame_class][tmp];

    if (ps->frame_class)
    {
        for (n = 1; n < ps->num_env+1; n++)
        {
            ps->border_position[n] = (uint8_t)faad_getbits(ld, 5
                DEBUGVAR(1,1008,"ps_data(): border_position"));
        }
    }

    if (ps->enable_iid)
    {
        for (n = 0; n < ps->num_env; n++)
        {
            ps->iid_dt[n] = (uint8_t)faad_get1bit(ld
                DEBUGVAR(1,1009,"ps_data(): iid_dt"));

            /* iid_data */
            if (ps->iid_mode < 3)
            {
                huff_data(ld, ps->iid_dt[n], ps->nr_iid_par, t_huff_iid_def,
                    f_huff_iid_def, ps->iid_index[n]);
            } else {
                huff_data(ld, ps->iid_dt[n], ps->nr_iid_par, t_huff_iid_fine,
                    f_huff_iid_fine, ps->iid_index[n]);
            }
        }
    }

    if (ps->enable_icc)
    {
        for (n = 0; n < ps->num_env; n++)
        {
            ps->icc_dt[n] = (uint8_t)faad_get1bit(ld
                DEBUGVAR(1,1010,"ps_data(): icc_dt"));

            /* icc_data */
            huff_data(ld, ps->icc_dt[n], ps->nr_icc_par, t_huff_icc,
                f_huff_icc, ps->icc_index[n]);
        }
    }

    if (ps->enable_ext)
    {
        uint16_t num_bits_left;
        uint16_t cnt = (uint16_t)faad_getbits(ld, 4
            DEBUGVAR(1,1011,"ps_data(): ps_extension_size"));
        if (cnt == 15)
        {
            cnt += (uint16_t)faad_getbits(ld, 8
                DEBUGVAR(1,1012,"ps_data(): esc_count"));
        }

        num_bits_left = 8 * cnt;
        while (num_bits_left > 7)
        {
            uint8_t ps_extension_id = (uint8_t)faad_getbits(ld, 2
                DEBUGVAR(1,1013,"ps_data(): ps_extension_size"));

            num_bits_left -= 2;
            num_bits_left -= ps_extension(ps, ld, ps_extension_id, num_bits_left);
        }

        faad_getbits(ld, num_bits_left
            DEBUGVAR(1,1014,"ps_data(): fill_bits"));
    }

    bits = (uint16_t)faad_get_processed_bits(ld) - bits;

    ps->ps_data_available = 1;

    return bits;
}

static uint16_t ps_extension(ps_info *ps, bitfile *ld,
                             const uint8_t ps_extension_id,
                             const uint16_t num_bits_left)
{
    uint8_t n;
    uint16_t bits = (uint16_t)faad_get_processed_bits(ld);

    (void)num_bits_left;
    if (ps_extension_id == 0)
    {
        ps->enable_ipdopd = (uint8_t)faad_get1bit(ld
            DEBUGVAR(1,1015,"ps_extension(): enable_ipdopd"));

        if (ps->enable_ipdopd)
        {
            for (n = 0; n < ps->num_env; n++)
            {
                ps->ipd_dt[n] = (uint8_t)faad_get1bit(ld
                    DEBUGVAR(1,1016,"ps_extension(): ipd_dt"));

                /* ipd_data */
                huff_data(ld, ps->ipd_dt[n], ps->nr_ipdopd_par, t_huff_ipd,
                    f_huff_ipd, ps->ipd_index[n]);

                ps->opd_dt[n] = (uint8_t)faad_get1bit(ld
                    DEBUGVAR(1,1017,"ps_extension(): opd_dt"));

                /* opd_data */
                huff_data(ld, ps->opd_dt[n], ps->nr_ipdopd_par, t_huff_opd,
                    f_huff_opd, ps->opd_index[n]);
            }
        }
        faad_get1bit(ld
            DEBUGVAR(1,1018,"ps_extension(): reserved_ps"));
    }

    /* return number of bits read */
    bits = (uint16_t)faad_get_processed_bits(ld) - bits;

    return bits;
}

/* read huffman data coded in either the frequency or the time direction */
static void huff_data(bitfile *ld, const uint8_t dt, const uint8_t nr_par,
                      ps_huff_tab t_huff, ps_huff_tab f_huff, int8_t *par)
{
    uint8_t n;

    if (dt)
    {
        /* coded in time direction */
        for (n = 0; n < nr_par; n++)
        {
            par[n] = ps_huff_dec(ld, t_huff);
        }
    } else {
        /* coded in frequency direction */
        par[0] = ps_huff_dec(ld, f_huff);

        for (n = 1; n < nr_par; n++)
        {
            par[n] = ps_huff_dec(ld, f_huff);
        }
    }
}

/* binary search huffman decoding */
static INLINE int8_t ps_huff_dec(bitfile *ld, ps_huff_tab t_huff)
{
    uint8_t bit;
    int16_t index = 0;

    while (index >= 0)
    {
        bit = (uint8_t)faad_get1bit(ld);
        index = t_huff[index][bit];
    }

    return index + 31;
}

#endif