Home | History | Annotate | Download | only in src
      1 /* -----------------------------------------------------------------------------
      2 Software License for The Fraunhofer FDK AAC Codec Library for Android
      3 
      4  Copyright  1995 - 2018 Fraunhofer-Gesellschaft zur Frderung der angewandten
      5 Forschung e.V. All rights reserved.
      6 
      7  1.    INTRODUCTION
      8 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software
      9 that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding
     10 scheme for digital audio. This FDK AAC Codec software is intended to be used on
     11 a wide variety of Android devices.
     12 
     13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient
     14 general perceptual audio codecs. AAC-ELD is considered the best-performing
     15 full-bandwidth communications codec by independent studies and is widely
     16 deployed. AAC has been standardized by ISO and IEC as part of the MPEG
     17 specifications.
     18 
     19 Patent licenses for necessary patent claims for the FDK AAC Codec (including
     20 those of Fraunhofer) may be obtained through Via Licensing
     21 (www.vialicensing.com) or through the respective patent owners individually for
     22 the purpose of encoding or decoding bit streams in products that are compliant
     23 with the ISO/IEC MPEG audio standards. Please note that most manufacturers of
     24 Android devices already license these patent claims through Via Licensing or
     25 directly from the patent owners, and therefore FDK AAC Codec software may
     26 already be covered under those patent licenses when it is used for those
     27 licensed purposes only.
     28 
     29 Commercially-licensed AAC software libraries, including floating-point versions
     30 with enhanced sound quality, are also available from Fraunhofer. Users are
     31 encouraged to check the Fraunhofer website for additional applications
     32 information and documentation.
     33 
     34 2.    COPYRIGHT LICENSE
     35 
     36 Redistribution and use in source and binary forms, with or without modification,
     37 are permitted without payment of copyright license fees provided that you
     38 satisfy the following conditions:
     39 
     40 You must retain the complete text of this software license in redistributions of
     41 the FDK AAC Codec or your modifications thereto in source code form.
     42 
     43 You must retain the complete text of this software license in the documentation
     44 and/or other materials provided with redistributions of the FDK AAC Codec or
     45 your modifications thereto in binary form. You must make available free of
     46 charge copies of the complete source code of the FDK AAC Codec and your
     47 modifications thereto to recipients of copies in binary form.
     48 
     49 The name of Fraunhofer may not be used to endorse or promote products derived
     50 from this library without prior written permission.
     51 
     52 You may not charge copyright license fees for anyone to use, copy or distribute
     53 the FDK AAC Codec software or your modifications thereto.
     54 
     55 Your modified versions of the FDK AAC Codec must carry prominent notices stating
     56 that you changed the software and the date of any change. For modified versions
     57 of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android"
     58 must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK
     59 AAC Codec Library for Android."
     60 
     61 3.    NO PATENT LICENSE
     62 
     63 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without
     64 limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE.
     65 Fraunhofer provides no warranty of patent non-infringement with respect to this
     66 software.
     67 
     68 You may use this FDK AAC Codec software or modifications thereto only for
     69 purposes that are authorized by appropriate patent licenses.
     70 
     71 4.    DISCLAIMER
     72 
     73 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright
     74 holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES,
     75 including but not limited to the implied warranties of merchantability and
     76 fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     77 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary,
     78 or consequential damages, including but not limited to procurement of substitute
     79 goods or services; loss of use, data, or profits, or business interruption,
     80 however caused and on any theory of liability, whether in contract, strict
     81 liability, or tort (including negligence), arising in any way out of the use of
     82 this software, even if advised of the possibility of such damage.
     83 
     84 5.    CONTACT INFORMATION
     85 
     86 Fraunhofer Institute for Integrated Circuits IIS
     87 Attention: Audio and Multimedia Departments - FDK AAC LL
     88 Am Wolfsmantel 33
     89 91058 Erlangen, Germany
     90 
     91 www.iis.fraunhofer.de/amm
     92 amm-info (at) iis.fraunhofer.de
     93 ----------------------------------------------------------------------------- */
     94 
     95 /**************************** AAC encoder library ******************************
     96 
     97    Author(s):   M.Werner
     98 
     99    Description: Psychoaccoustic configuration
    100 
    101 *******************************************************************************/
    102 
    103 #include "psy_configuration.h"
    104 #include "adj_thr.h"
    105 #include "aacEnc_rom.h"
    106 
    107 #include "genericStds.h"
    108 
    109 #include "FDK_trigFcts.h"
    110 
    111 typedef struct {
    112   LONG sampleRate;
    113   const SFB_PARAM_LONG *paramLong;
    114   const SFB_PARAM_SHORT *paramShort;
    115 } SFB_INFO_TAB;
    116 
    117 static const SFB_INFO_TAB sfbInfoTab[] = {
    118     {8000, &p_FDKaacEnc_8000_long_1024, &p_FDKaacEnc_8000_short_128},
    119     {11025, &p_FDKaacEnc_11025_long_1024, &p_FDKaacEnc_11025_short_128},
    120     {12000, &p_FDKaacEnc_12000_long_1024, &p_FDKaacEnc_12000_short_128},
    121     {16000, &p_FDKaacEnc_16000_long_1024, &p_FDKaacEnc_16000_short_128},
    122     {22050, &p_FDKaacEnc_22050_long_1024, &p_FDKaacEnc_22050_short_128},
    123     {24000, &p_FDKaacEnc_24000_long_1024, &p_FDKaacEnc_24000_short_128},
    124     {32000, &p_FDKaacEnc_32000_long_1024, &p_FDKaacEnc_32000_short_128},
    125     {44100, &p_FDKaacEnc_44100_long_1024, &p_FDKaacEnc_44100_short_128},
    126     {48000, &p_FDKaacEnc_48000_long_1024, &p_FDKaacEnc_48000_short_128},
    127     {64000, &p_FDKaacEnc_64000_long_1024, &p_FDKaacEnc_64000_short_128},
    128     {88200, &p_FDKaacEnc_88200_long_1024, &p_FDKaacEnc_88200_short_128},
    129     {96000, &p_FDKaacEnc_96000_long_1024, &p_FDKaacEnc_96000_short_128}
    130 
    131 };
    132 
    133 /* 22050 and 24000 Hz */
    134 static const SFB_PARAM_LONG p_22050_long_512 = {
    135     31, {4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  8,  8,  8,  12, 12,
    136          12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}};
    137 
    138 /* 32000 Hz */
    139 static const SFB_PARAM_LONG p_32000_long_512 = {
    140     37,
    141     {4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  8,  8,  8,  8, 8,
    142      12, 12, 12, 12, 16, 16, 16, 20, 24, 24, 28, 32, 32, 32, 32, 32, 32, 32}};
    143 
    144 /* 44100 Hz */
    145 static const SFB_PARAM_LONG p_44100_long_512 = {
    146     36, {4, 4, 4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  8,  8,  8,
    147          8, 8, 12, 12, 12, 12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32, 32, 52}};
    148 
    149 static const SFB_INFO_TAB sfbInfoTabLD512[] = {
    150     {8000, &p_22050_long_512, NULL},   {11025, &p_22050_long_512, NULL},
    151     {12000, &p_22050_long_512, NULL},  {16000, &p_22050_long_512, NULL},
    152     {22050, &p_22050_long_512, NULL},  {24000, &p_22050_long_512, NULL},
    153     {32000, &p_32000_long_512, NULL},  {44100, &p_44100_long_512, NULL},
    154     {48000, &p_44100_long_512, NULL},  {64000, &p_44100_long_512, NULL},
    155     {88200, &p_44100_long_512, NULL},  {96000, &p_44100_long_512, NULL},
    156     {128000, &p_44100_long_512, NULL}, {176400, &p_44100_long_512, NULL},
    157     {192000, &p_44100_long_512, NULL}, {256000, &p_44100_long_512, NULL},
    158     {352800, &p_44100_long_512, NULL}, {384000, &p_44100_long_512, NULL},
    159 };
    160 
    161 /* 22050 and 24000 Hz */
    162 static const SFB_PARAM_LONG p_22050_long_480 = {
    163     30, {4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  8,  8,  8,  12,
    164          12, 12, 16, 20, 24, 28, 32, 32, 32, 32, 32, 32, 32, 32, 32}};
    165 
    166 /* 32000 Hz */
    167 static const SFB_PARAM_LONG p_32000_long_480 = {
    168     37, {4, 4, 4, 4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  8,  8, 8,
    169          8, 8, 8, 12, 12, 12, 16, 16, 20, 24, 32, 32, 32, 32, 32, 32, 32, 32}};
    170 
    171 /* 44100 Hz */
    172 static const SFB_PARAM_LONG p_44100_long_480 = {
    173     35, {4, 4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  4,  8,  8,  8, 8,
    174          8, 12, 12, 12, 12, 12, 16, 16, 24, 28, 32, 32, 32, 32, 32, 32, 48}};
    175 
    176 static const SFB_INFO_TAB sfbInfoTabLD480[] = {
    177     {8000, &p_22050_long_480, NULL},   {11025, &p_22050_long_480, NULL},
    178     {12000, &p_22050_long_480, NULL},  {16000, &p_22050_long_480, NULL},
    179     {22050, &p_22050_long_480, NULL},  {24000, &p_22050_long_480, NULL},
    180     {32000, &p_32000_long_480, NULL},  {44100, &p_44100_long_480, NULL},
    181     {48000, &p_44100_long_480, NULL},  {64000, &p_44100_long_480, NULL},
    182     {88200, &p_44100_long_480, NULL},  {96000, &p_44100_long_480, NULL},
    183     {128000, &p_44100_long_480, NULL}, {176400, &p_44100_long_480, NULL},
    184     {192000, &p_44100_long_480, NULL}, {256000, &p_44100_long_480, NULL},
    185     {352800, &p_44100_long_480, NULL}, {384000, &p_44100_long_480, NULL},
    186 };
    187 
    188 /* Fixed point precision definitions */
    189 #define Q_BARCVAL (25)
    190 
    191 AAC_ENCODER_ERROR FDKaacEnc_initSfbTable(const LONG sampleRate,
    192                                          const INT blockType,
    193                                          const INT granuleLength,
    194                                          INT *const sfbOffset,
    195                                          INT *const sfbCnt) {
    196   INT i, specStartOffset = 0;
    197   INT granuleLengthWindow = granuleLength;
    198   const UCHAR *sfbWidth = NULL;
    199   const SFB_INFO_TAB *sfbInfo = NULL;
    200   int size;
    201 
    202   /*
    203     select table
    204   */
    205   switch (granuleLength) {
    206     case 1024:
    207     case 960:
    208       sfbInfo = sfbInfoTab;
    209       size = (INT)(sizeof(sfbInfoTab) / sizeof(SFB_INFO_TAB));
    210       break;
    211     case 512:
    212       sfbInfo = sfbInfoTabLD512;
    213       size = sizeof(sfbInfoTabLD512);
    214       break;
    215     case 480:
    216       sfbInfo = sfbInfoTabLD480;
    217       size = sizeof(sfbInfoTabLD480);
    218       break;
    219     default:
    220       return AAC_ENC_INVALID_FRAME_LENGTH;
    221   }
    222 
    223   for (i = 0; i < size; i++) {
    224     if (sfbInfo[i].sampleRate == sampleRate) {
    225       switch (blockType) {
    226         case LONG_WINDOW:
    227         case START_WINDOW:
    228         case STOP_WINDOW:
    229           sfbWidth = sfbInfo[i].paramLong->sfbWidth;
    230           *sfbCnt = sfbInfo[i].paramLong->sfbCnt;
    231           break;
    232         case SHORT_WINDOW:
    233           sfbWidth = sfbInfo[i].paramShort->sfbWidth;
    234           *sfbCnt = sfbInfo[i].paramShort->sfbCnt;
    235           granuleLengthWindow /= TRANS_FAC;
    236           break;
    237       }
    238       break;
    239     }
    240   }
    241   if (i == size) {
    242     return AAC_ENC_UNSUPPORTED_SAMPLINGRATE;
    243   }
    244 
    245   /*
    246     calc sfb offsets
    247   */
    248   for (i = 0; i < *sfbCnt; i++) {
    249     sfbOffset[i] = specStartOffset;
    250     specStartOffset += sfbWidth[i];
    251     if (specStartOffset >= granuleLengthWindow) {
    252       i++;
    253       break;
    254     }
    255   }
    256   *sfbCnt = fixMin(i, *sfbCnt);
    257   sfbOffset[*sfbCnt] = fixMin(specStartOffset, granuleLengthWindow);
    258   return AAC_ENC_OK;
    259 }
    260 
    261 /*****************************************************************************
    262 
    263     functionname: FDKaacEnc_BarcLineValue
    264     description:  Calculates barc value for one frequency line
    265     returns:      barc value of line
    266     input:        number of lines in transform, index of line to check, Fs
    267     output:
    268 
    269 *****************************************************************************/
    270 static FIXP_DBL FDKaacEnc_BarcLineValue(INT noOfLines, INT fftLine,
    271                                         LONG samplingFreq) {
    272   FIXP_DBL FOURBY3EM4 = (FIXP_DBL)0x45e7b273; /* 4.0/3 * 0.0001 in q43 */
    273   FIXP_DBL PZZZ76 = (FIXP_DBL)0x639d5e4a;     /* 0.00076 in q41 */
    274   FIXP_DBL ONE3P3 = (FIXP_DBL)0x35333333;     /* 13.3 in q26 */
    275   FIXP_DBL THREEP5 = (FIXP_DBL)0x1c000000;    /* 3.5 in q27 */
    276   FIXP_DBL INV480 = (FIXP_DBL)0x44444444;     // 1/480 in q39
    277 
    278   FIXP_DBL center_freq, x1, x2;
    279   FIXP_DBL bvalFFTLine, atan1, atan2;
    280 
    281   /* Theoritical maximum of center_freq (samp_freq*0.5) is 96khz * 0.5 = 48000
    282    */
    283   /* Theoritical maximum of x1 is 1.3333333e-4f * center_freq = 6.4, can keep in
    284    * q28  */
    285   /* Theoritical maximum of x2 is 0.00076f * center_freq = 36.48, can keep in
    286    * q25     */
    287 
    288   center_freq = fftLine * samplingFreq; /* q11 or q8 */
    289 
    290   switch (noOfLines) {
    291     case 1024:
    292       center_freq = center_freq << 2; /* q13 */
    293       break;
    294     case 128:
    295       center_freq = center_freq << 5; /* q13 */
    296       break;
    297     case 512:
    298       center_freq = (fftLine * samplingFreq) << 3;  // q13
    299       break;
    300     case 480:
    301       center_freq = fMult(center_freq, INV480) << 4;  // q13
    302       break;
    303     default:
    304       center_freq = (FIXP_DBL)0;
    305   }
    306 
    307   x1 = fMult(center_freq, FOURBY3EM4); /* q13 * q43 - (DFRACT_BITS-1) = q25 */
    308   x2 = fMult(center_freq, PZZZ76)
    309        << 2; /* q13 * q41 - (DFRACT_BITS-1) + 2 = q25 */
    310 
    311   atan1 = fixp_atan(x1);
    312   atan2 = fixp_atan(x2);
    313 
    314   /* q25 (q26 * q30 - (DFRACT_BITS-1)) + q25 (q27 * q30 * q30) */
    315   bvalFFTLine = fMult(ONE3P3, atan2) + fMult(THREEP5, fMult(atan1, atan1));
    316   return (bvalFFTLine);
    317 }
    318 
    319 /*
    320    do not consider energies below a certain input signal level,
    321    i.e. of -96dB or 1 bit at 16 bit PCM resolution,
    322    might need to be configurable to e.g. 24 bit PCM Input or a lower
    323    resolution for low bit rates
    324 */
    325 static void FDKaacEnc_InitMinPCMResolution(int numPb, int *pbOffset,
    326                                            FIXP_DBL *sfbPCMquantThreshold) {
    327 /* PCM_QUANT_NOISE = FDKpow(10.0f, - 20.f / 10.0f) * ABS_LOW * NORM_PCM_ENERGY *
    328  * FDKpow(2,PCM_QUANT_THR_SCALE) */
    329 #define PCM_QUANT_NOISE ((FIXP_DBL)0x00547062)
    330 
    331   for (int i = 0; i < numPb; i++) {
    332     sfbPCMquantThreshold[i] = (pbOffset[i + 1] - pbOffset[i]) * PCM_QUANT_NOISE;
    333   }
    334 }
    335 
    336 static FIXP_DBL getMaskFactor(const FIXP_DBL dbVal_fix, const INT dbVal_e,
    337                               const FIXP_DBL ten_fix, const INT ten_e) {
    338   INT q_msk;
    339   FIXP_DBL mask_factor;
    340 
    341   mask_factor = fPow(ten_fix, DFRACT_BITS - 1 - ten_e, -dbVal_fix,
    342                      DFRACT_BITS - 1 - dbVal_e, &q_msk);
    343   q_msk = fixMin(DFRACT_BITS - 1, fixMax(-(DFRACT_BITS - 1), q_msk));
    344 
    345   if ((q_msk > 0) && (mask_factor > (FIXP_DBL)MAXVAL_DBL >> q_msk)) {
    346     mask_factor = (FIXP_DBL)MAXVAL_DBL;
    347   } else {
    348     mask_factor = scaleValue(mask_factor, q_msk);
    349   }
    350 
    351   return (mask_factor);
    352 }
    353 
    354 static void FDKaacEnc_initSpreading(INT numPb, FIXP_DBL *pbBarcValue,
    355                                     FIXP_DBL *pbMaskLoFactor,
    356                                     FIXP_DBL *pbMaskHiFactor,
    357                                     FIXP_DBL *pbMaskLoFactorSprEn,
    358                                     FIXP_DBL *pbMaskHiFactorSprEn,
    359                                     const LONG bitrate, const INT blockType)
    360 
    361 {
    362   INT i;
    363   FIXP_DBL MASKLOWSPREN, MASKHIGHSPREN;
    364 
    365   FIXP_DBL MASKHIGH = (FIXP_DBL)0x30000000;               /* 1.5 in q29 */
    366   FIXP_DBL MASKLOW = (FIXP_DBL)0x60000000;                /* 3.0 in q29 */
    367   FIXP_DBL MASKLOWSPRENLONG = (FIXP_DBL)0x60000000;       /* 3.0 in q29 */
    368   FIXP_DBL MASKHIGHSPRENLONG = (FIXP_DBL)0x40000000;      /* 2.0 in q29 */
    369   FIXP_DBL MASKHIGHSPRENLONGLOWBR = (FIXP_DBL)0x30000000; /* 1.5 in q29 */
    370   FIXP_DBL MASKLOWSPRENSHORT = (FIXP_DBL)0x40000000;      /* 2.0 in q29 */
    371   FIXP_DBL MASKHIGHSPRENSHORT = (FIXP_DBL)0x30000000;     /* 1.5 in q29 */
    372   FIXP_DBL TEN = (FIXP_DBL)0x50000000;                    /* 10.0 in q27 */
    373 
    374   if (blockType != SHORT_WINDOW) {
    375     MASKLOWSPREN = MASKLOWSPRENLONG;
    376     MASKHIGHSPREN =
    377         (bitrate > 20000) ? MASKHIGHSPRENLONG : MASKHIGHSPRENLONGLOWBR;
    378   } else {
    379     MASKLOWSPREN = MASKLOWSPRENSHORT;
    380     MASKHIGHSPREN = MASKHIGHSPRENSHORT;
    381   }
    382 
    383   for (i = 0; i < numPb; i++) {
    384     if (i > 0) {
    385       pbMaskHiFactor[i] = getMaskFactor(
    386           fMult(MASKHIGH, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN, 27);
    387 
    388       pbMaskLoFactor[i - 1] = getMaskFactor(
    389           fMult(MASKLOW, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN, 27);
    390 
    391       pbMaskHiFactorSprEn[i] = getMaskFactor(
    392           fMult(MASKHIGHSPREN, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN,
    393           27);
    394 
    395       pbMaskLoFactorSprEn[i - 1] = getMaskFactor(
    396           fMult(MASKLOWSPREN, (pbBarcValue[i] - pbBarcValue[i - 1])), 23, TEN,
    397           27);
    398     } else {
    399       pbMaskHiFactor[i] = (FIXP_DBL)0;
    400       pbMaskLoFactor[numPb - 1] = (FIXP_DBL)0;
    401       pbMaskHiFactorSprEn[i] = (FIXP_DBL)0;
    402       pbMaskLoFactorSprEn[numPb - 1] = (FIXP_DBL)0;
    403     }
    404   }
    405 }
    406 
    407 static void FDKaacEnc_initBarcValues(INT numPb, INT *pbOffset, INT numLines,
    408                                      INT samplingFrequency, FIXP_DBL *pbBval) {
    409   INT i;
    410   FIXP_DBL MAX_BARC = (FIXP_DBL)0x30000000; /* 24.0 in q25 */
    411 
    412   for (i = 0; i < numPb; i++) {
    413     FIXP_DBL v1, v2, cur_bark;
    414     v1 = FDKaacEnc_BarcLineValue(numLines, pbOffset[i], samplingFrequency);
    415     v2 = FDKaacEnc_BarcLineValue(numLines, pbOffset[i + 1], samplingFrequency);
    416     cur_bark = (v1 >> 1) + (v2 >> 1);
    417     pbBval[i] = fixMin(cur_bark, MAX_BARC);
    418   }
    419 }
    420 
    421 static void FDKaacEnc_initMinSnr(const LONG bitrate, const LONG samplerate,
    422                                  const INT numLines, const INT *sfbOffset,
    423                                  const INT sfbActive, const INT blockType,
    424                                  FIXP_DBL *sfbMinSnrLdData) {
    425   INT sfb;
    426 
    427   /* Fix conversion variables */
    428   INT qbfac, qperwin, qdiv, qpeprt_const, qpeprt;
    429   INT qtmp, qsnr, sfbWidth;
    430 
    431   FIXP_DBL MAX_BARC = (FIXP_DBL)0x30000000;   /* 24.0 in q25 */
    432   FIXP_DBL MAX_BARCP1 = (FIXP_DBL)0x32000000; /* 25.0 in q25 */
    433   FIXP_DBL BITS2PEFAC = (FIXP_DBL)0x4b851eb8; /* 1.18 in q30 */
    434   FIXP_DBL PERS2P4 = (FIXP_DBL)0x624dd2f2;    /* 0.024 in q36 */
    435   FIXP_DBL ONEP5 = (FIXP_DBL)0x60000000;      /* 1.5 in q30 */
    436   FIXP_DBL MAX_SNR = (FIXP_DBL)0x33333333;    /* 0.8 in q30 */
    437   FIXP_DBL MIN_SNR = (FIXP_DBL)0x003126e9;    /* 0.003 in q30 */
    438 
    439   FIXP_DBL barcFactor, pePerWindow, pePart, barcWidth;
    440   FIXP_DBL pePart_const, tmp, snr, one_qsnr, one_point5;
    441 
    442   /* relative number of active barks */
    443   barcFactor = fDivNorm(fixMin(FDKaacEnc_BarcLineValue(
    444                                    numLines, sfbOffset[sfbActive], samplerate),
    445                                MAX_BARC),
    446                         MAX_BARCP1, &qbfac);
    447 
    448   qbfac = DFRACT_BITS - 1 - qbfac;
    449 
    450   pePerWindow = fDivNorm(bitrate, samplerate, &qperwin);
    451   qperwin = DFRACT_BITS - 1 - qperwin;
    452   pePerWindow = fMult(pePerWindow, BITS2PEFAC);
    453   qperwin = qperwin + 30 - (DFRACT_BITS - 1);
    454   pePerWindow = fMult(pePerWindow, PERS2P4);
    455   qperwin = qperwin + 36 - (DFRACT_BITS - 1);
    456 
    457   switch (numLines) {
    458     case 1024:
    459       qperwin = qperwin - 10;
    460       break;
    461     case 128:
    462       qperwin = qperwin - 7;
    463       break;
    464     case 512:
    465       qperwin = qperwin - 9;
    466       break;
    467     case 480:
    468       qperwin = qperwin - 9;
    469       pePerWindow = fMult(pePerWindow, FL2FXCONST_DBL(480.f / 512.f));
    470       break;
    471   }
    472 
    473   /* for short blocks it is assumed that more bits are available */
    474   if (blockType == SHORT_WINDOW) {
    475     pePerWindow = fMult(pePerWindow, ONEP5);
    476     qperwin = qperwin + 30 - (DFRACT_BITS - 1);
    477   }
    478   pePart_const = fDivNorm(pePerWindow, barcFactor, &qdiv);
    479   qpeprt_const = qperwin - qbfac + DFRACT_BITS - 1 - qdiv;
    480 
    481   for (sfb = 0; sfb < sfbActive; sfb++) {
    482     barcWidth =
    483         FDKaacEnc_BarcLineValue(numLines, sfbOffset[sfb + 1], samplerate) -
    484         FDKaacEnc_BarcLineValue(numLines, sfbOffset[sfb], samplerate);
    485 
    486     /* adapt to sfb bands */
    487     pePart = fMult(pePart_const, barcWidth);
    488     qpeprt = qpeprt_const + 25 - (DFRACT_BITS - 1);
    489 
    490     /* pe -> snr calculation */
    491     sfbWidth = (sfbOffset[sfb + 1] - sfbOffset[sfb]);
    492     pePart = fDivNorm(pePart, sfbWidth, &qdiv);
    493     qpeprt += DFRACT_BITS - 1 - qdiv;
    494 
    495     tmp = f2Pow(pePart, DFRACT_BITS - 1 - qpeprt, &qtmp);
    496     qtmp = DFRACT_BITS - 1 - qtmp;
    497 
    498     /* Subtract 1.5 */
    499     qsnr = fixMin(qtmp, 30);
    500     tmp = tmp >> (qtmp - qsnr);
    501 
    502     if ((30 + 1 - qsnr) > (DFRACT_BITS - 1))
    503       one_point5 = (FIXP_DBL)0;
    504     else
    505       one_point5 = (FIXP_DBL)(ONEP5 >> (30 + 1 - qsnr));
    506 
    507     snr = (tmp >> 1) - (one_point5);
    508     qsnr -= 1;
    509 
    510     /* max(snr, 1.0) */
    511     if (qsnr > 0)
    512       one_qsnr = (FIXP_DBL)(1 << qsnr);
    513     else
    514       one_qsnr = (FIXP_DBL)0;
    515 
    516     snr = fixMax(one_qsnr, snr);
    517 
    518     /* 1/snr */
    519     snr = fDivNorm(one_qsnr, snr, &qsnr);
    520     qsnr = DFRACT_BITS - 1 - qsnr;
    521     snr = (qsnr > 30) ? (snr >> (qsnr - 30)) : snr;
    522 
    523     /* upper limit is -1 dB */
    524     snr = (snr > MAX_SNR) ? MAX_SNR : snr;
    525 
    526     /* lower limit is -25 dB */
    527     snr = (snr < MIN_SNR) ? MIN_SNR : snr;
    528     snr = snr << 1;
    529 
    530     sfbMinSnrLdData[sfb] = CalcLdData(snr);
    531   }
    532 }
    533 
    534 AAC_ENCODER_ERROR FDKaacEnc_InitPsyConfiguration(INT bitrate, INT samplerate,
    535                                                  INT bandwidth, INT blocktype,
    536                                                  INT granuleLength, INT useIS,
    537                                                  INT useMS,
    538                                                  PSY_CONFIGURATION *psyConf,
    539                                                  FB_TYPE filterbank) {
    540   AAC_ENCODER_ERROR ErrorStatus;
    541   INT sfb;
    542   FIXP_DBL sfbBarcVal[MAX_SFB];
    543   const INT frameLengthLong = granuleLength;
    544   const INT frameLengthShort = granuleLength / TRANS_FAC;
    545   INT downscaleFactor = 1;
    546 
    547   switch (granuleLength) {
    548     case 256:
    549     case 240:
    550       downscaleFactor = 2;
    551       break;
    552     case 128:
    553     case 120:
    554       downscaleFactor = 4;
    555       break;
    556     default:
    557       downscaleFactor = 1;
    558       break;
    559   }
    560 
    561   FDKmemclear(psyConf, sizeof(PSY_CONFIGURATION));
    562   psyConf->granuleLength = granuleLength;
    563   psyConf->filterbank = filterbank;
    564 
    565   psyConf->allowIS = (useIS) && ((bitrate / bandwidth) < 5);
    566   psyConf->allowMS = useMS;
    567 
    568   /* init sfb table */
    569   ErrorStatus = FDKaacEnc_initSfbTable(samplerate * downscaleFactor, blocktype,
    570                                        granuleLength * downscaleFactor,
    571                                        psyConf->sfbOffset, &psyConf->sfbCnt);
    572 
    573   if (ErrorStatus != AAC_ENC_OK) return ErrorStatus;
    574 
    575   /* calculate barc values for each pb */
    576   FDKaacEnc_initBarcValues(psyConf->sfbCnt, psyConf->sfbOffset,
    577                            psyConf->sfbOffset[psyConf->sfbCnt], samplerate,
    578                            sfbBarcVal);
    579 
    580   FDKaacEnc_InitMinPCMResolution(psyConf->sfbCnt, psyConf->sfbOffset,
    581                                  psyConf->sfbPcmQuantThreshold);
    582 
    583   /* calculate spreading function */
    584   FDKaacEnc_initSpreading(psyConf->sfbCnt, sfbBarcVal,
    585                           psyConf->sfbMaskLowFactor, psyConf->sfbMaskHighFactor,
    586                           psyConf->sfbMaskLowFactorSprEn,
    587                           psyConf->sfbMaskHighFactorSprEn, bitrate, blocktype);
    588 
    589   /* init ratio */
    590 
    591   psyConf->maxAllowedIncreaseFactor = 2; /* integer */
    592   psyConf->minRemainingThresholdFactor = (FIXP_SGL)0x0148;
    593   /* FL2FXCONST_SGL(0.01f); */ /* fract   */
    594 
    595   psyConf->clipEnergy =
    596       (FIXP_DBL)0x773593ff; /* FL2FXCONST_DBL(1.0e9*NORM_PCM_ENERGY); */
    597 
    598   if (blocktype != SHORT_WINDOW) {
    599     psyConf->lowpassLine =
    600         (INT)((2 * bandwidth * frameLengthLong) / samplerate);
    601     psyConf->lowpassLineLFE = LFE_LOWPASS_LINE;
    602   } else {
    603     psyConf->lowpassLine =
    604         (INT)((2 * bandwidth * frameLengthShort) / samplerate);
    605     psyConf->lowpassLineLFE = 0; /* LFE only in lonf blocks */
    606     /* psyConf->clipEnergy /= (TRANS_FAC * TRANS_FAC); */
    607     psyConf->clipEnergy >>= 6;
    608   }
    609 
    610   for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) {
    611     if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLine) break;
    612   }
    613   psyConf->sfbActive = fMax(sfb, 1);
    614 
    615   for (sfb = 0; sfb < psyConf->sfbCnt; sfb++) {
    616     if (psyConf->sfbOffset[sfb] >= psyConf->lowpassLineLFE) break;
    617   }
    618   psyConf->sfbActiveLFE = sfb;
    619   psyConf->sfbActive = fMax(psyConf->sfbActive, psyConf->sfbActiveLFE);
    620 
    621   /* calculate minSnr */
    622   FDKaacEnc_initMinSnr(bitrate, samplerate * downscaleFactor,
    623                        psyConf->sfbOffset[psyConf->sfbCnt], psyConf->sfbOffset,
    624                        psyConf->sfbActive, blocktype, psyConf->sfbMinSnrLdData);
    625 
    626   return AAC_ENC_OK;
    627 }
    628