Home | History | Annotate | Download | only in src
      1 /* -----------------------------------------------------------------------------
      2 Software License for The Fraunhofer FDK AAC Codec Library for Android
      3 
      4  Copyright  1995 - 2019 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: Threshold compensation
    100 
    101 *******************************************************************************/
    102 
    103 #include "adj_thr.h"
    104 #include "sf_estim.h"
    105 #include "aacEnc_ram.h"
    106 
    107 #define NUM_NRG_LEVS (8)
    108 #define INV_INT_TAB_SIZE (8)
    109 static const FIXP_DBL invInt[INV_INT_TAB_SIZE] = {
    110     0x7fffffff, 0x7fffffff, 0x40000000, 0x2aaaaaaa,
    111     0x20000000, 0x19999999, 0x15555555, 0x12492492};
    112 
    113 #define INV_SQRT4_TAB_SIZE (8)
    114 static const FIXP_DBL invSqrt4[INV_SQRT4_TAB_SIZE] = {
    115     0x7fffffff, 0x7fffffff, 0x6ba27e65, 0x61424bb5,
    116     0x5a827999, 0x55994845, 0x51c8e33c, 0x4eb160d1};
    117 
    118 /*static const INT      invRedExp = 4;*/
    119 static const FIXP_DBL SnrLdMin1 =
    120     (FIXP_DBL)0xfcad0ddf; /*FL2FXCONST_DBL(FDKlog(0.316)/FDKlog(2.0)/LD_DATA_SCALING);*/
    121 static const FIXP_DBL SnrLdMin2 =
    122     (FIXP_DBL)0x0351e1a2; /*FL2FXCONST_DBL(FDKlog(3.16)
    123                              /FDKlog(2.0)/LD_DATA_SCALING);*/
    124 static const FIXP_DBL SnrLdFac =
    125     (FIXP_DBL)0xff5b2c3e; /*FL2FXCONST_DBL(FDKlog(0.8)
    126                              /FDKlog(2.0)/LD_DATA_SCALING);*/
    127 
    128 static const FIXP_DBL SnrLdMin3 =
    129     (FIXP_DBL)0xfe000000; /*FL2FXCONST_DBL(FDKlog(0.5)
    130                              /FDKlog(2.0)/LD_DATA_SCALING);*/
    131 static const FIXP_DBL SnrLdMin4 =
    132     (FIXP_DBL)0x02000000; /*FL2FXCONST_DBL(FDKlog(2.0)
    133                              /FDKlog(2.0)/LD_DATA_SCALING);*/
    134 static const FIXP_DBL SnrLdMin5 =
    135     (FIXP_DBL)0xfc000000; /*FL2FXCONST_DBL(FDKlog(0.25)
    136                              /FDKlog(2.0)/LD_DATA_SCALING);*/
    137 
    138 /*
    139 The bits2Pe factors are choosen for the case that some times
    140 the crash recovery strategy will be activated once.
    141 */
    142 #define AFTERBURNER_STATI 2
    143 #define MAX_ALLOWED_EL_CHANNELS 2
    144 
    145 typedef struct {
    146   INT bitrate;
    147   FIXP_DBL bits2PeFactor[AFTERBURNER_STATI][MAX_ALLOWED_EL_CHANNELS];
    148 } BIT_PE_SFAC;
    149 
    150 typedef struct {
    151   INT sampleRate;
    152   const BIT_PE_SFAC *pPeTab;
    153   INT nEntries;
    154 
    155 } BITS2PE_CFG_TAB;
    156 
    157 #define FL2B2PE(value) FL2FXCONST_DBL((value) / (1 << 2))
    158 
    159 static const BIT_PE_SFAC S_Bits2PeTab16000[] = {
    160     /* bitrate|   afterburner off              |   afterburner on | |   nCh=1
    161        |   nCh=2       |   nCh=1       |   nCh=2        */
    162     {10000,
    163      {{FL2B2PE(1.60f), FL2B2PE(0.00f)}, {FL2B2PE(1.40f), FL2B2PE(0.00f)}}},
    164     {24000,
    165      {{FL2B2PE(1.80f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}},
    166     {32000,
    167      {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
    168     {48000,
    169      {{FL2B2PE(1.60f), FL2B2PE(1.80f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}},
    170     {64000,
    171      {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(1.20f), FL2B2PE(1.60f)}}},
    172     {96000,
    173      {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.60f)}}},
    174     {128000,
    175      {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.80f)}}},
    176     {148000,
    177      {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.40f)}}}};
    178 
    179 static const BIT_PE_SFAC S_Bits2PeTab22050[] = {
    180     /* bitrate|   afterburner off              |   afterburner on | |   nCh=1
    181        |   nCh=2       |   nCh=1       |   nCh=2        */
    182     {16000,
    183      {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.20f), FL2B2PE(0.80f)}}},
    184     {24000,
    185      {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.40f), FL2B2PE(1.00f)}}},
    186     {32000,
    187      {{FL2B2PE(1.40f), FL2B2PE(1.40f)}, {FL2B2PE(1.40f), FL2B2PE(1.20f)}}},
    188     {48000,
    189      {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(1.20f), FL2B2PE(1.40f)}}},
    190     {64000,
    191      {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
    192     {96000,
    193      {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}},
    194     {128000,
    195      {{FL2B2PE(1.80f), FL2B2PE(1.80f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}},
    196     {148000,
    197      {{FL2B2PE(1.40f), FL2B2PE(1.80f)}, {FL2B2PE(1.40f), FL2B2PE(1.60f)}}}};
    198 
    199 static const BIT_PE_SFAC S_Bits2PeTab24000[] = {
    200     /* bitrate|   afterburner off              |   afterburner on | |   nCh=1
    201        |   nCh=2       |   nCh=1      |   nCh=2         */
    202     {16000,
    203      {{FL2B2PE(1.40f), FL2B2PE(1.40f)}, {FL2B2PE(1.20f), FL2B2PE(0.80f)}}},
    204     {24000,
    205      {{FL2B2PE(1.60f), FL2B2PE(1.20f)}, {FL2B2PE(1.40f), FL2B2PE(1.00f)}}},
    206     {32000,
    207      {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.40f), FL2B2PE(0.80f)}}},
    208     {48000,
    209      {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.40f), FL2B2PE(1.40f)}}},
    210     {64000,
    211      {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
    212     {96000,
    213      {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}},
    214     {128000,
    215      {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.80f)}}},
    216     {148000,
    217      {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.40f), FL2B2PE(1.80f)}}}};
    218 
    219 static const BIT_PE_SFAC S_Bits2PeTab32000[] = {
    220     /* bitrate|   afterburner off              |   afterburner on | |   nCh=1
    221        |   nCh=2       |   nCh=1       |   nCh=2        */
    222     {16000,
    223      {{FL2B2PE(1.20f), FL2B2PE(1.40f)}, {FL2B2PE(0.80f), FL2B2PE(0.80f)}}},
    224     {24000,
    225      {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.60f)}}},
    226     {32000,
    227      {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.80f)}}},
    228     {48000,
    229      {{FL2B2PE(1.40f), FL2B2PE(1.40f)}, {FL2B2PE(1.20f), FL2B2PE(1.20f)}}},
    230     {64000,
    231      {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}},
    232     {96000,
    233      {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
    234     {128000,
    235      {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}},
    236     {148000,
    237      {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}},
    238     {160000,
    239      {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.80f), FL2B2PE(1.60f)}}},
    240     {200000,
    241      {{FL2B2PE(1.40f), FL2B2PE(1.60f)}, {FL2B2PE(1.40f), FL2B2PE(1.60f)}}},
    242     {320000,
    243      {{FL2B2PE(3.20f), FL2B2PE(1.80f)}, {FL2B2PE(3.20f), FL2B2PE(1.80f)}}}};
    244 
    245 static const BIT_PE_SFAC S_Bits2PeTab44100[] = {
    246     /* bitrate|   afterburner off              |   afterburner on | |   nCh=1
    247        |   nCh=2       |   nCh=1       |   nCh=2        */
    248     {16000,
    249      {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(0.80f), FL2B2PE(1.00f)}}},
    250     {24000,
    251      {{FL2B2PE(1.00f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.80f)}}},
    252     {32000,
    253      {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(0.80f), FL2B2PE(0.60f)}}},
    254     {48000,
    255      {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(1.20f), FL2B2PE(0.80f)}}},
    256     {64000,
    257      {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.20f), FL2B2PE(1.00f)}}},
    258     {96000,
    259      {{FL2B2PE(1.60f), FL2B2PE(1.20f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}},
    260     {128000,
    261      {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
    262     {148000,
    263      {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}},
    264     {160000,
    265      {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}},
    266     {200000,
    267      {{FL2B2PE(1.80f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.60f)}}},
    268     {320000,
    269      {{FL2B2PE(3.20f), FL2B2PE(1.60f)}, {FL2B2PE(3.20f), FL2B2PE(1.60f)}}}};
    270 
    271 static const BIT_PE_SFAC S_Bits2PeTab48000[] = {
    272     /* bitrate|   afterburner off              |   afterburner on | |   nCh=1
    273        |   nCh=2       |   nCh=1       |   nCh=2        */
    274     {16000,
    275      {{FL2B2PE(1.40f), FL2B2PE(0.00f)}, {FL2B2PE(0.80f), FL2B2PE(0.00f)}}},
    276     {24000,
    277      {{FL2B2PE(1.40f), FL2B2PE(1.20f)}, {FL2B2PE(1.00f), FL2B2PE(0.80f)}}},
    278     {32000,
    279      {{FL2B2PE(1.00f), FL2B2PE(1.20f)}, {FL2B2PE(0.60f), FL2B2PE(0.80f)}}},
    280     {48000,
    281      {{FL2B2PE(1.20f), FL2B2PE(1.00f)}, {FL2B2PE(0.80f), FL2B2PE(0.80f)}}},
    282     {64000,
    283      {{FL2B2PE(1.20f), FL2B2PE(1.20f)}, {FL2B2PE(1.20f), FL2B2PE(1.00f)}}},
    284     {96000,
    285      {{FL2B2PE(1.60f), FL2B2PE(1.40f)}, {FL2B2PE(1.60f), FL2B2PE(1.20f)}}},
    286     {128000,
    287      {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
    288     {148000,
    289      {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
    290     {160000,
    291      {{FL2B2PE(1.60f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
    292     {200000,
    293      {{FL2B2PE(1.20f), FL2B2PE(1.60f)}, {FL2B2PE(1.60f), FL2B2PE(1.40f)}}},
    294     {320000,
    295      {{FL2B2PE(3.20f), FL2B2PE(1.60f)}, {FL2B2PE(3.20f), FL2B2PE(1.60f)}}}};
    296 
    297 static const BITS2PE_CFG_TAB bits2PeConfigTab[] = {
    298     {16000, S_Bits2PeTab16000, sizeof(S_Bits2PeTab16000) / sizeof(BIT_PE_SFAC)},
    299     {22050, S_Bits2PeTab22050, sizeof(S_Bits2PeTab22050) / sizeof(BIT_PE_SFAC)},
    300     {24000, S_Bits2PeTab24000, sizeof(S_Bits2PeTab24000) / sizeof(BIT_PE_SFAC)},
    301     {32000, S_Bits2PeTab32000, sizeof(S_Bits2PeTab32000) / sizeof(BIT_PE_SFAC)},
    302     {44100, S_Bits2PeTab44100, sizeof(S_Bits2PeTab44100) / sizeof(BIT_PE_SFAC)},
    303     {48000, S_Bits2PeTab48000,
    304      sizeof(S_Bits2PeTab48000) / sizeof(BIT_PE_SFAC)}};
    305 
    306 /* values for avoid hole flag */
    307 enum _avoid_hole_state { NO_AH = 0, AH_INACTIVE = 1, AH_ACTIVE = 2 };
    308 
    309 /*  Q format definitions */
    310 #define Q_BITFAC \
    311   (24) /* Q scaling used in FDKaacEnc_bitresCalcBitFac() calculation */
    312 #define Q_AVGBITS (17) /* scale bit values */
    313 
    314 /*****************************************************************************
    315     functionname: FDKaacEnc_InitBits2PeFactor
    316     description:  retrieve bits2PeFactor from table
    317 *****************************************************************************/
    318 static void FDKaacEnc_InitBits2PeFactor(
    319     FIXP_DBL *bits2PeFactor_m, INT *bits2PeFactor_e, const INT bitRate,
    320     const INT nChannels, const INT sampleRate, const INT advancedBitsToPe,
    321     const INT dZoneQuantEnable, const INT invQuant) {
    322   /**** 1) Set default bits2pe factor ****/
    323   FIXP_DBL bit2PE_m = FL2FXCONST_DBL(1.18f / (1 << (1)));
    324   INT bit2PE_e = 1;
    325 
    326   /**** 2) For AAC-(E)LD, make use of advanced bits to pe factor table ****/
    327   if (advancedBitsToPe && nChannels <= (2)) {
    328     int i;
    329     const BIT_PE_SFAC *peTab = NULL;
    330     INT size = 0;
    331 
    332     /*** 2.1) Get correct table entry ***/
    333     for (i = 0; i < (INT)(sizeof(bits2PeConfigTab) / sizeof(BITS2PE_CFG_TAB));
    334          i++) {
    335       if (sampleRate >= bits2PeConfigTab[i].sampleRate) {
    336         peTab = bits2PeConfigTab[i].pPeTab;
    337         size = bits2PeConfigTab[i].nEntries;
    338       }
    339     }
    340 
    341     if ((peTab != NULL) && (size != 0)) {
    342       INT startB = -1; /* bitrate entry in table that is the next-lower to
    343                           actual bitrate  */
    344       INT stopB = -1;  /* bitrate entry in table that is the next-higher to
    345                           actual bitrate */
    346       FIXP_DBL startPF =
    347           FL2FXCONST_DBL(0.0f); /* bits2PE factor entry in table that is the
    348                                    next-lower to actual bits2PE factor  */
    349       FIXP_DBL stopPF = FL2FXCONST_DBL(0.0f); /* bits2PE factor entry in table
    350                                                  that is the next-higher to
    351                                                  actual bits2PE factor */
    352       FIXP_DBL slope = FL2FXCONST_DBL(
    353           0.0f); /* the slope from the start bits2Pe entry to the next one */
    354       const int qualityIdx = (invQuant == 0) ? 0 : 1;
    355 
    356       if (bitRate >= peTab[size - 1].bitrate) {
    357         /* Chosen bitrate is higher than the highest bitrate in table.
    358            The slope for extrapolating the bits2PE factor must be zero.
    359            Values are set accordingly.                                       */
    360         startB = peTab[size - 1].bitrate;
    361         stopB =
    362             bitRate +
    363             1; /* Can be an arbitrary value greater than startB and bitrate. */
    364         startPF = peTab[size - 1].bits2PeFactor[qualityIdx][nChannels - 1];
    365         stopPF = peTab[size - 1].bits2PeFactor[qualityIdx][nChannels - 1];
    366       } else {
    367         for (i = 0; i < size - 1; i++) {
    368           if ((peTab[i].bitrate <= bitRate) &&
    369               (peTab[i + 1].bitrate > bitRate)) {
    370             startB = peTab[i].bitrate;
    371             stopB = peTab[i + 1].bitrate;
    372             startPF = peTab[i].bits2PeFactor[qualityIdx][nChannels - 1];
    373             stopPF = peTab[i + 1].bits2PeFactor[qualityIdx][nChannels - 1];
    374             break;
    375           }
    376         }
    377       }
    378 
    379       /*** 2.2) Configuration available? ***/
    380       if (startB != -1) {
    381         /** 2.2.1) linear interpolate to actual PEfactor **/
    382         FIXP_DBL bit2PE = 0;
    383 
    384         const FIXP_DBL maxBit2PE = FL2FXCONST_DBL(3.f / 4.f);
    385 
    386         /* bit2PE = ((stopPF-startPF)/(stopB-startB))*(bitRate-startB)+startPF;
    387          */
    388         slope = fDivNorm(bitRate - startB, stopB - startB);
    389         bit2PE = fMult(slope, stopPF - startPF) + startPF;
    390 
    391         bit2PE = fMin(maxBit2PE, bit2PE);
    392 
    393         /** 2.2.2) sanity check if bits2pe value is high enough **/
    394         if (bit2PE >= (FL2FXCONST_DBL(0.35f) >> 2)) {
    395           bit2PE_m = bit2PE;
    396           bit2PE_e = 2; /*  table is fixed scaled */
    397         }
    398       } /* br */
    399     }   /* sr */
    400   }     /* advancedBitsToPe */
    401 
    402   if (dZoneQuantEnable) {
    403     if (bit2PE_m >= (FL2FXCONST_DBL(0.6f)) >> bit2PE_e) {
    404       /* Additional headroom for addition */
    405       bit2PE_m >>= 1;
    406       bit2PE_e += 1;
    407     }
    408 
    409     /* the quantTendencyCompensator compensates a lower bit consumption due to
    410      * increasing the tendency to quantize low spectral values to the lower
    411      * quantizer border for bitrates below a certain bitrate threshold --> see
    412      * also function calcSfbDistLD in quantize.c */
    413     if ((bitRate / nChannels > 32000) && (bitRate / nChannels <= 40000)) {
    414       bit2PE_m += (FL2FXCONST_DBL(0.4f)) >> bit2PE_e;
    415     } else if (bitRate / nChannels > 20000) {
    416       bit2PE_m += (FL2FXCONST_DBL(0.3f)) >> bit2PE_e;
    417     } else if (bitRate / nChannels >= 16000) {
    418       bit2PE_m += (FL2FXCONST_DBL(0.3f)) >> bit2PE_e;
    419     } else {
    420       bit2PE_m += (FL2FXCONST_DBL(0.0f)) >> bit2PE_e;
    421     }
    422   }
    423 
    424   /***** 3.) Return bits2pe factor *****/
    425   *bits2PeFactor_m = bit2PE_m;
    426   *bits2PeFactor_e = bit2PE_e;
    427 }
    428 
    429 /*****************************************************************************
    430 functionname: FDKaacEnc_bits2pe2
    431 description:  convert from bits to pe
    432 *****************************************************************************/
    433 FDK_INLINE INT FDKaacEnc_bits2pe2(const INT bits, const FIXP_DBL factor_m,
    434                                   const INT factor_e) {
    435   return (INT)(fMult(factor_m, (FIXP_DBL)(bits << Q_AVGBITS)) >>
    436                (Q_AVGBITS - factor_e));
    437 }
    438 
    439 /*****************************************************************************
    440 functionname: FDKaacEnc_calcThreshExp
    441 description:  loudness calculation (threshold to the power of redExp)
    442 *****************************************************************************/
    443 static void FDKaacEnc_calcThreshExp(
    444     FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB],
    445     const QC_OUT_CHANNEL *const qcOutChannel[(2)],
    446     const PSY_OUT_CHANNEL *const psyOutChannel[(2)], const INT nChannels) {
    447   INT ch, sfb, sfbGrp;
    448   FIXP_DBL thrExpLdData;
    449 
    450   for (ch = 0; ch < nChannels; ch++) {
    451     for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
    452          sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
    453       for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
    454         thrExpLdData = psyOutChannel[ch]->sfbThresholdLdData[sfbGrp + sfb] >> 2;
    455         thrExp[ch][sfbGrp + sfb] = CalcInvLdData(thrExpLdData);
    456       }
    457     }
    458   }
    459 }
    460 
    461 /*****************************************************************************
    462     functionname: FDKaacEnc_adaptMinSnr
    463     description:  reduce minSnr requirements for bands with relative low
    464 energies
    465 *****************************************************************************/
    466 static void FDKaacEnc_adaptMinSnr(
    467     QC_OUT_CHANNEL *const qcOutChannel[(2)],
    468     const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
    469     const MINSNR_ADAPT_PARAM *const msaParam, const INT nChannels) {
    470   INT ch, sfb, sfbGrp, nSfb;
    471   FIXP_DBL avgEnLD64, dbRatio, minSnrRed;
    472   FIXP_DBL minSnrLimitLD64 =
    473       FL2FXCONST_DBL(-0.00503012648262f); /* ld64(0.8f) */
    474   FIXP_DBL nSfbLD64;
    475   FIXP_DBL accu;
    476 
    477   FIXP_DBL msaParam_maxRed = msaParam->maxRed;
    478   FIXP_DBL msaParam_startRatio = msaParam->startRatio;
    479   FIXP_DBL msaParam_redRatioFac =
    480       fMult(msaParam->redRatioFac, FL2FXCONST_DBL(0.3010299956f));
    481   FIXP_DBL msaParam_redOffs = msaParam->redOffs;
    482 
    483   for (ch = 0; ch < nChannels; ch++) {
    484     /* calc average energy per scalefactor band */
    485     nSfb = 0;
    486     accu = FL2FXCONST_DBL(0.0f);
    487 
    488     DWORD_ALIGNED(psyOutChannel[ch]->sfbEnergy);
    489 
    490     for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
    491          sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
    492       int maxSfbPerGroup = psyOutChannel[ch]->maxSfbPerGroup;
    493       nSfb += maxSfbPerGroup;
    494       for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
    495         accu += psyOutChannel[ch]->sfbEnergy[sfbGrp + sfb] >> 6;
    496       }
    497     }
    498 
    499     if ((accu == FL2FXCONST_DBL(0.0f)) || (nSfb == 0)) {
    500       avgEnLD64 = FL2FXCONST_DBL(-1.0f);
    501     } else {
    502       nSfbLD64 = CalcLdInt(nSfb);
    503       avgEnLD64 = CalcLdData(accu);
    504       avgEnLD64 = avgEnLD64 + FL2FXCONST_DBL(0.09375f) -
    505                   nSfbLD64; /* 0.09375f: compensate shift with 6 */
    506     }
    507 
    508     /* reduce minSnr requirement by minSnr^minSnrRed dependent on avgEn/sfbEn */
    509     int maxSfbPerGroup = psyOutChannel[ch]->maxSfbPerGroup;
    510     int sfbCnt = psyOutChannel[ch]->sfbCnt;
    511     int sfbPerGroup = psyOutChannel[ch]->sfbPerGroup;
    512 
    513     for (sfbGrp = 0; sfbGrp < sfbCnt; sfbGrp += sfbPerGroup) {
    514       FIXP_DBL *RESTRICT psfbEnergyLdData =
    515           &qcOutChannel[ch]->sfbEnergyLdData[sfbGrp];
    516       FIXP_DBL *RESTRICT psfbMinSnrLdData =
    517           &qcOutChannel[ch]->sfbMinSnrLdData[sfbGrp];
    518       for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
    519         FIXP_DBL sfbEnergyLdData = *psfbEnergyLdData++;
    520         FIXP_DBL sfbMinSnrLdData = *psfbMinSnrLdData;
    521         dbRatio = avgEnLD64 - sfbEnergyLdData;
    522         int update = (msaParam_startRatio < dbRatio) ? 1 : 0;
    523         minSnrRed = msaParam_redOffs + fMult(msaParam_redRatioFac,
    524                                              dbRatio); /* scaled by 1.0f/64.0f*/
    525         minSnrRed =
    526             fixMax(minSnrRed, msaParam_maxRed); /* scaled by 1.0f/64.0f*/
    527         minSnrRed = (fMult(sfbMinSnrLdData, minSnrRed)) << 6;
    528         minSnrRed = fixMin(minSnrLimitLD64, minSnrRed);
    529         *psfbMinSnrLdData++ = update ? minSnrRed : sfbMinSnrLdData;
    530       }
    531     }
    532   }
    533 }
    534 
    535 /*****************************************************************************
    536 functionname: FDKaacEnc_initAvoidHoleFlag
    537 description:  determine bands where avoid hole is not necessary resp. possible
    538 *****************************************************************************/
    539 static void FDKaacEnc_initAvoidHoleFlag(
    540     QC_OUT_CHANNEL *const qcOutChannel[(2)],
    541     const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
    542     UCHAR ahFlag[(2)][MAX_GROUPED_SFB], const struct TOOLSINFO *const toolsInfo,
    543     const INT nChannels, const AH_PARAM *const ahParam) {
    544   INT ch, sfb, sfbGrp;
    545   FIXP_DBL sfbEn, sfbEnm1;
    546   FIXP_DBL sfbEnLdData;
    547   FIXP_DBL avgEnLdData;
    548 
    549   /* decrease spread energy by 3dB for long blocks, resp. 2dB for shorts
    550      (avoid more holes in long blocks) */
    551   for (ch = 0; ch < nChannels; ch++) {
    552     QC_OUT_CHANNEL *const qcOutChan = qcOutChannel[ch];
    553 
    554     if (psyOutChannel[ch]->lastWindowSequence != SHORT_WINDOW) {
    555       for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
    556            sfbGrp += psyOutChannel[ch]->sfbPerGroup)
    557         for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++)
    558           qcOutChan->sfbSpreadEnergy[sfbGrp + sfb] >>= 1;
    559     } else {
    560       for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
    561            sfbGrp += psyOutChannel[ch]->sfbPerGroup)
    562         for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++)
    563           qcOutChan->sfbSpreadEnergy[sfbGrp + sfb] = fMult(
    564               FL2FXCONST_DBL(0.63f), qcOutChan->sfbSpreadEnergy[sfbGrp + sfb]);
    565     }
    566   }
    567 
    568   /* increase minSnr for local peaks, decrease it for valleys */
    569   if (ahParam->modifyMinSnr) {
    570     for (ch = 0; ch < nChannels; ch++) {
    571       QC_OUT_CHANNEL *const qcOutChan = qcOutChannel[ch];
    572       for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
    573            sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
    574         for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
    575           FIXP_DBL sfbEnp1, avgEn;
    576           if (sfb > 0)
    577             sfbEnm1 = qcOutChan->sfbEnergy[sfbGrp + sfb - 1];
    578           else
    579             sfbEnm1 = qcOutChan->sfbEnergy[sfbGrp + sfb];
    580 
    581           if (sfb < psyOutChannel[ch]->maxSfbPerGroup - 1)
    582             sfbEnp1 = qcOutChan->sfbEnergy[sfbGrp + sfb + 1];
    583           else
    584             sfbEnp1 = qcOutChan->sfbEnergy[sfbGrp + sfb];
    585 
    586           avgEn = (sfbEnm1 >> 1) + (sfbEnp1 >> 1);
    587           avgEnLdData = CalcLdData(avgEn);
    588           sfbEn = qcOutChan->sfbEnergy[sfbGrp + sfb];
    589           sfbEnLdData = qcOutChan->sfbEnergyLdData[sfbGrp + sfb];
    590           /* peak ? */
    591           if (sfbEn > avgEn) {
    592             FIXP_DBL tmpMinSnrLdData;
    593             if (psyOutChannel[ch]->lastWindowSequence == LONG_WINDOW)
    594               tmpMinSnrLdData = SnrLdFac + fixMax(avgEnLdData - sfbEnLdData,
    595                                                   SnrLdMin1 - SnrLdFac);
    596             else
    597               tmpMinSnrLdData = SnrLdFac + fixMax(avgEnLdData - sfbEnLdData,
    598                                                   SnrLdMin3 - SnrLdFac);
    599 
    600             qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] = fixMin(
    601                 qcOutChan->sfbMinSnrLdData[sfbGrp + sfb], tmpMinSnrLdData);
    602           }
    603           /* valley ? */
    604           if (((sfbEnLdData + (FIXP_DBL)SnrLdMin4) < (FIXP_DBL)avgEnLdData) &&
    605               (sfbEn > FL2FXCONST_DBL(0.0))) {
    606             FIXP_DBL tmpMinSnrLdData = avgEnLdData - sfbEnLdData -
    607                                        (FIXP_DBL)SnrLdMin4 +
    608                                        qcOutChan->sfbMinSnrLdData[sfbGrp + sfb];
    609             tmpMinSnrLdData = fixMin((FIXP_DBL)SnrLdFac, tmpMinSnrLdData);
    610             qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] =
    611                 fixMin(tmpMinSnrLdData,
    612                        (FIXP_DBL)(qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] +
    613                                   SnrLdMin2));
    614           }
    615         }
    616       }
    617     }
    618   }
    619 
    620   /* stereo: adapt the minimum requirements sfbMinSnr of mid and
    621      side channels to avoid spending unnoticable bits */
    622   if (nChannels == 2) {
    623     QC_OUT_CHANNEL *qcOutChanM = qcOutChannel[0];
    624     QC_OUT_CHANNEL *qcOutChanS = qcOutChannel[1];
    625     const PSY_OUT_CHANNEL *const psyOutChanM = psyOutChannel[0];
    626     for (sfbGrp = 0; sfbGrp < psyOutChanM->sfbCnt;
    627          sfbGrp += psyOutChanM->sfbPerGroup) {
    628       for (sfb = 0; sfb < psyOutChanM->maxSfbPerGroup; sfb++) {
    629         if (toolsInfo->msMask[sfbGrp + sfb]) {
    630           FIXP_DBL maxSfbEnLd =
    631               fixMax(qcOutChanM->sfbEnergyLdData[sfbGrp + sfb],
    632                      qcOutChanS->sfbEnergyLdData[sfbGrp + sfb]);
    633           FIXP_DBL maxThrLd, sfbMinSnrTmpLd;
    634 
    635           if (((SnrLdMin5 >> 1) + (maxSfbEnLd >> 1) +
    636                (qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] >> 1)) <=
    637               FL2FXCONST_DBL(-0.5f))
    638             maxThrLd = FL2FXCONST_DBL(-1.0f);
    639           else
    640             maxThrLd = SnrLdMin5 + maxSfbEnLd +
    641                        qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb];
    642 
    643           if (qcOutChanM->sfbEnergy[sfbGrp + sfb] > FL2FXCONST_DBL(0.0f))
    644             sfbMinSnrTmpLd =
    645                 maxThrLd - qcOutChanM->sfbEnergyLdData[sfbGrp + sfb];
    646           else
    647             sfbMinSnrTmpLd = FL2FXCONST_DBL(0.0f);
    648 
    649           qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] =
    650               fixMax(qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb], sfbMinSnrTmpLd);
    651 
    652           if (qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] <= FL2FXCONST_DBL(0.0f))
    653             qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb] = fixMin(
    654                 qcOutChanM->sfbMinSnrLdData[sfbGrp + sfb], (FIXP_DBL)SnrLdFac);
    655 
    656           if (qcOutChanS->sfbEnergy[sfbGrp + sfb] > FL2FXCONST_DBL(0.0f))
    657             sfbMinSnrTmpLd =
    658                 maxThrLd - qcOutChanS->sfbEnergyLdData[sfbGrp + sfb];
    659           else
    660             sfbMinSnrTmpLd = FL2FXCONST_DBL(0.0f);
    661 
    662           qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb] =
    663               fixMax(qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb], sfbMinSnrTmpLd);
    664 
    665           if (qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb] <= FL2FXCONST_DBL(0.0f))
    666             qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb] = fixMin(
    667                 qcOutChanS->sfbMinSnrLdData[sfbGrp + sfb], (FIXP_DBL)SnrLdFac);
    668 
    669           if (qcOutChanM->sfbEnergy[sfbGrp + sfb] >
    670               qcOutChanM->sfbSpreadEnergy[sfbGrp + sfb])
    671             qcOutChanS->sfbSpreadEnergy[sfbGrp + sfb] = fMult(
    672                 qcOutChanS->sfbEnergy[sfbGrp + sfb], FL2FXCONST_DBL(0.9f));
    673 
    674           if (qcOutChanS->sfbEnergy[sfbGrp + sfb] >
    675               qcOutChanS->sfbSpreadEnergy[sfbGrp + sfb])
    676             qcOutChanM->sfbSpreadEnergy[sfbGrp + sfb] = fMult(
    677                 qcOutChanM->sfbEnergy[sfbGrp + sfb], FL2FXCONST_DBL(0.9f));
    678 
    679         } /* if (toolsInfo->msMask[sfbGrp+sfb]) */
    680       }   /* sfb */
    681     }     /* sfbGrp */
    682   }       /* nChannels==2 */
    683 
    684   /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
    685   for (ch = 0; ch < nChannels; ch++) {
    686     QC_OUT_CHANNEL *qcOutChan = qcOutChannel[ch];
    687     const PSY_OUT_CHANNEL *const psyOutChan = psyOutChannel[ch];
    688     for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
    689          sfbGrp += psyOutChan->sfbPerGroup) {
    690       for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
    691         if ((qcOutChan->sfbSpreadEnergy[sfbGrp + sfb] >
    692              qcOutChan->sfbEnergy[sfbGrp + sfb]) ||
    693             (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] > FL2FXCONST_DBL(0.0f))) {
    694           ahFlag[ch][sfbGrp + sfb] = NO_AH;
    695         } else {
    696           ahFlag[ch][sfbGrp + sfb] = AH_INACTIVE;
    697         }
    698       }
    699     }
    700   }
    701 }
    702 
    703 /**
    704  * \brief  Calculate constants that do not change during successive pe
    705  * calculations.
    706  *
    707  * \param peData                Pointer to structure containing PE data of
    708  * current element.
    709  * \param psyOutChannel         Pointer to PSY_OUT_CHANNEL struct holding
    710  * nChannels elements.
    711  * \param qcOutChannel          Pointer to QC_OUT_CHANNEL struct holding
    712  * nChannels elements.
    713  * \param nChannels             Number of channels in element.
    714  * \param peOffset              Fixed PE offset defined while
    715  * FDKaacEnc_AdjThrInit() depending on bitrate.
    716  *
    717  * \return  void
    718  */
    719 static void FDKaacEnc_preparePe(PE_DATA *const peData,
    720                                 const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
    721                                 const QC_OUT_CHANNEL *const qcOutChannel[(2)],
    722                                 const INT nChannels, const INT peOffset) {
    723   INT ch;
    724 
    725   for (ch = 0; ch < nChannels; ch++) {
    726     const PSY_OUT_CHANNEL *const psyOutChan = psyOutChannel[ch];
    727     FDKaacEnc_prepareSfbPe(
    728         &peData->peChannelData[ch], psyOutChan->sfbEnergyLdData,
    729         psyOutChan->sfbThresholdLdData, qcOutChannel[ch]->sfbFormFactorLdData,
    730         psyOutChan->sfbOffsets, psyOutChan->sfbCnt, psyOutChan->sfbPerGroup,
    731         psyOutChan->maxSfbPerGroup);
    732   }
    733   peData->offset = peOffset;
    734 }
    735 
    736 /**
    737  * \brief  Calculate weighting factor for threshold adjustment.
    738  *
    739  * Calculate weighting factor to be applied at energies and thresholds in ld64
    740  * format.
    741  *
    742  * \param peData,               Pointer to PE data in current element.
    743  * \param psyOutChannel         Pointer to PSY_OUT_CHANNEL struct holding
    744  * nChannels elements.
    745  * \param qcOutChannel          Pointer to QC_OUT_CHANNEL struct holding
    746  * nChannels elements.
    747  * \param toolsInfo             Pointer to tools info struct of current element.
    748  * \param adjThrStateElement    Pointer to ATS_ELEMENT holding enFacPatch
    749  * states.
    750  * \param nChannels             Number of channels in element.
    751  * \param usePatchTool          Apply the weighting tool 0 (no) else (yes).
    752  *
    753  * \return  void
    754  */
    755 static void FDKaacEnc_calcWeighting(
    756     const PE_DATA *const peData,
    757     const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
    758     QC_OUT_CHANNEL *const qcOutChannel[(2)],
    759     const struct TOOLSINFO *const toolsInfo,
    760     ATS_ELEMENT *const adjThrStateElement, const INT nChannels,
    761     const INT usePatchTool) {
    762   int ch, noShortWindowInFrame = TRUE;
    763   INT exePatchM = 0;
    764 
    765   for (ch = 0; ch < nChannels; ch++) {
    766     if (psyOutChannel[ch]->lastWindowSequence == SHORT_WINDOW) {
    767       noShortWindowInFrame = FALSE;
    768     }
    769     FDKmemclear(qcOutChannel[ch]->sfbEnFacLd,
    770                 MAX_GROUPED_SFB * sizeof(FIXP_DBL));
    771   }
    772 
    773   if (usePatchTool == 0) {
    774     return; /* tool is disabled */
    775   }
    776 
    777   for (ch = 0; ch < nChannels; ch++) {
    778     const PSY_OUT_CHANNEL *const psyOutChan = psyOutChannel[ch];
    779 
    780     if (noShortWindowInFrame) { /* retain energy ratio between blocks of
    781                                    different length */
    782 
    783       FIXP_DBL nrgSum14, nrgSum12, nrgSum34, nrgTotal;
    784       FIXP_DBL nrgFacLd_14, nrgFacLd_12, nrgFacLd_34;
    785       INT usePatch, exePatch;
    786       int sfb, sfbGrp, nLinesSum = 0;
    787 
    788       nrgSum14 = nrgSum12 = nrgSum34 = nrgTotal = FL2FXCONST_DBL(0.f);
    789 
    790       /* calculate flatness of audible spectrum, i.e. spectrum above masking
    791        * threshold. */
    792       for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
    793            sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
    794         for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
    795           FIXP_DBL nrgFac12 = CalcInvLdData(
    796               psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 1); /* nrg^(1/2) */
    797           FIXP_DBL nrgFac14 = CalcInvLdData(
    798               psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 2); /* nrg^(1/4) */
    799 
    800           /* maximal number of bands is 64, results scaling factor 6 */
    801           nLinesSum += peData->peChannelData[ch]
    802                            .sfbNLines[sfbGrp + sfb]; /* relevant lines */
    803           nrgTotal +=
    804               (psyOutChan->sfbEnergy[sfbGrp + sfb] >> 6); /* sum up nrg */
    805           nrgSum12 += (nrgFac12 >> 6);                    /* sum up nrg^(2/4) */
    806           nrgSum14 += (nrgFac14 >> 6);                    /* sum up nrg^(1/4) */
    807           nrgSum34 += (fMult(nrgFac14, nrgFac12) >> 6);   /* sum up nrg^(3/4) */
    808         }
    809       }
    810 
    811       nrgTotal = CalcLdData(nrgTotal); /* get ld64 of total nrg */
    812 
    813       nrgFacLd_14 =
    814           CalcLdData(nrgSum14) - nrgTotal; /* ld64(nrgSum14/nrgTotal) */
    815       nrgFacLd_12 =
    816           CalcLdData(nrgSum12) - nrgTotal; /* ld64(nrgSum12/nrgTotal) */
    817       nrgFacLd_34 =
    818           CalcLdData(nrgSum34) - nrgTotal; /* ld64(nrgSum34/nrgTotal) */
    819 
    820       /* Note: nLinesSum cannot be larger than the number of total lines, thats
    821        * taken care of in line_pe.cpp FDKaacEnc_prepareSfbPe() */
    822       adjThrStateElement->chaosMeasureEnFac[ch] =
    823           fMax(FL2FXCONST_DBL(0.1875f),
    824                fDivNorm(nLinesSum, psyOutChan->sfbOffsets[psyOutChan->sfbCnt]));
    825 
    826       usePatch = (adjThrStateElement->chaosMeasureEnFac[ch] >
    827                   FL2FXCONST_DBL(0.78125f));
    828       exePatch = ((usePatch) && (adjThrStateElement->lastEnFacPatch[ch]));
    829 
    830       for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
    831            sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
    832         for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
    833           INT sfbExePatch;
    834           /* for MS coupled SFBs, also execute patch in side channel if done in
    835            * mid channel */
    836           if ((ch == 1) && (toolsInfo->msMask[sfbGrp + sfb])) {
    837             sfbExePatch = exePatchM;
    838           } else {
    839             sfbExePatch = exePatch;
    840           }
    841 
    842           if ((sfbExePatch) &&
    843               (psyOutChan->sfbEnergy[sfbGrp + sfb] > FL2FXCONST_DBL(0.f))) {
    844             /* execute patch based on spectral flatness calculated above */
    845             if (adjThrStateElement->chaosMeasureEnFac[ch] >
    846                 FL2FXCONST_DBL(0.8125f)) {
    847               qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] =
    848                   ((nrgFacLd_14 +
    849                     (psyOutChan->sfbEnergyLdData[sfbGrp + sfb] +
    850                      (psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 1))) >>
    851                    1); /* sfbEnergy^(3/4) */
    852             } else if (adjThrStateElement->chaosMeasureEnFac[ch] >
    853                        FL2FXCONST_DBL(0.796875f)) {
    854               qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] =
    855                   ((nrgFacLd_12 + psyOutChan->sfbEnergyLdData[sfbGrp + sfb]) >>
    856                    1); /* sfbEnergy^(2/4) */
    857             } else {
    858               qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] =
    859                   ((nrgFacLd_34 +
    860                     (psyOutChan->sfbEnergyLdData[sfbGrp + sfb] >> 1)) >>
    861                    1); /* sfbEnergy^(1/4) */
    862             }
    863             qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb] =
    864                 fixMin(qcOutChannel[ch]->sfbEnFacLd[sfbGrp + sfb], (FIXP_DBL)0);
    865           }
    866         }
    867       } /* sfb loop */
    868 
    869       adjThrStateElement->lastEnFacPatch[ch] = usePatch;
    870       exePatchM = exePatch;
    871     } else {
    872       /* !noShortWindowInFrame */
    873       adjThrStateElement->chaosMeasureEnFac[ch] = FL2FXCONST_DBL(0.75f);
    874       adjThrStateElement->lastEnFacPatch[ch] =
    875           TRUE; /* allow use of sfbEnFac patch in upcoming frame */
    876     }
    877 
    878   } /* ch loop */
    879 }
    880 
    881 /*****************************************************************************
    882 functionname: FDKaacEnc_calcPe
    883 description:  calculate pe for both channels
    884 *****************************************************************************/
    885 static void FDKaacEnc_calcPe(const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
    886                              const QC_OUT_CHANNEL *const qcOutChannel[(2)],
    887                              PE_DATA *const peData, const INT nChannels) {
    888   INT ch;
    889 
    890   peData->pe = peData->offset;
    891   peData->constPart = 0;
    892   peData->nActiveLines = 0;
    893   for (ch = 0; ch < nChannels; ch++) {
    894     PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch];
    895 
    896     FDKaacEnc_calcSfbPe(
    897         peChanData, qcOutChannel[ch]->sfbWeightedEnergyLdData,
    898         qcOutChannel[ch]->sfbThresholdLdData, psyOutChannel[ch]->sfbCnt,
    899         psyOutChannel[ch]->sfbPerGroup, psyOutChannel[ch]->maxSfbPerGroup,
    900         psyOutChannel[ch]->isBook, psyOutChannel[ch]->isScale);
    901 
    902     peData->pe += peChanData->pe;
    903     peData->constPart += peChanData->constPart;
    904     peData->nActiveLines += peChanData->nActiveLines;
    905   }
    906 }
    907 
    908 void FDKaacEnc_peCalculation(PE_DATA *const peData,
    909                              const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
    910                              QC_OUT_CHANNEL *const qcOutChannel[(2)],
    911                              const struct TOOLSINFO *const toolsInfo,
    912                              ATS_ELEMENT *const adjThrStateElement,
    913                              const INT nChannels) {
    914   /* constants that will not change during successive pe calculations */
    915   FDKaacEnc_preparePe(peData, psyOutChannel, qcOutChannel, nChannels,
    916                       adjThrStateElement->peOffset);
    917 
    918   /* calculate weighting factor for threshold adjustment */
    919   FDKaacEnc_calcWeighting(peData, psyOutChannel, qcOutChannel, toolsInfo,
    920                           adjThrStateElement, nChannels, 1);
    921   {
    922     /* no weighting of threholds and energies for mlout */
    923     /* weight energies and thresholds */
    924     int ch;
    925     for (ch = 0; ch < nChannels; ch++) {
    926       int sfb, sfbGrp;
    927       QC_OUT_CHANNEL *pQcOutCh = qcOutChannel[ch];
    928 
    929       for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
    930            sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
    931         for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
    932           pQcOutCh->sfbWeightedEnergyLdData[sfb + sfbGrp] =
    933               pQcOutCh->sfbEnergyLdData[sfb + sfbGrp] -
    934               pQcOutCh->sfbEnFacLd[sfb + sfbGrp];
    935           pQcOutCh->sfbThresholdLdData[sfb + sfbGrp] -=
    936               pQcOutCh->sfbEnFacLd[sfb + sfbGrp];
    937         }
    938       }
    939     }
    940   }
    941 
    942   /* pe without reduction */
    943   FDKaacEnc_calcPe(psyOutChannel, qcOutChannel, peData, nChannels);
    944 }
    945 
    946 /*****************************************************************************
    947 functionname: FDKaacEnc_FDKaacEnc_calcPeNoAH
    948 description:  sum the pe data only for bands where avoid hole is inactive
    949 *****************************************************************************/
    950 #define CONSTPART_HEADROOM 4
    951 static void FDKaacEnc_FDKaacEnc_calcPeNoAH(
    952     INT *const pe, INT *const constPart, INT *const nActiveLines,
    953     const PE_DATA *const peData, const UCHAR ahFlag[(2)][MAX_GROUPED_SFB],
    954     const PSY_OUT_CHANNEL *const psyOutChannel[(2)], const INT nChannels) {
    955   INT ch, sfb, sfbGrp;
    956 
    957   INT pe_tmp = peData->offset;
    958   INT constPart_tmp = 0;
    959   INT nActiveLines_tmp = 0;
    960   for (ch = 0; ch < nChannels; ch++) {
    961     const PE_CHANNEL_DATA *const peChanData = &peData->peChannelData[ch];
    962     for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
    963          sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
    964       for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
    965         if (ahFlag[ch][sfbGrp + sfb] < AH_ACTIVE) {
    966           pe_tmp += peChanData->sfbPe[sfbGrp + sfb];
    967           constPart_tmp +=
    968               peChanData->sfbConstPart[sfbGrp + sfb] >> CONSTPART_HEADROOM;
    969           nActiveLines_tmp += peChanData->sfbNActiveLines[sfbGrp + sfb];
    970         }
    971       }
    972     }
    973   }
    974   /* correct scaled pe and constPart values */
    975   *pe = pe_tmp >> PE_CONSTPART_SHIFT;
    976   *constPart = constPart_tmp >> (PE_CONSTPART_SHIFT - CONSTPART_HEADROOM);
    977 
    978   *nActiveLines = nActiveLines_tmp;
    979 }
    980 
    981 /*****************************************************************************
    982 functionname: FDKaacEnc_reduceThresholdsCBR
    983 description:  apply reduction formula
    984 *****************************************************************************/
    985 static const FIXP_DBL limitThrReducedLdData =
    986     (FIXP_DBL)0x00008000; /*FL2FXCONST_DBL(FDKpow(2.0,-LD_DATA_SCALING/4.0));*/
    987 
    988 static void FDKaacEnc_reduceThresholdsCBR(
    989     QC_OUT_CHANNEL *const qcOutChannel[(2)],
    990     const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
    991     UCHAR ahFlag[(2)][MAX_GROUPED_SFB],
    992     const FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB], const INT nChannels,
    993     const FIXP_DBL redVal_m, const SCHAR redVal_e) {
    994   INT ch, sfb, sfbGrp;
    995   FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData;
    996   FIXP_DBL sfbThrExp;
    997 
    998   for (ch = 0; ch < nChannels; ch++) {
    999     QC_OUT_CHANNEL *qcOutChan = qcOutChannel[ch];
   1000     for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
   1001          sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
   1002       for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
   1003         sfbEnLdData = qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb];
   1004         sfbThrLdData = qcOutChan->sfbThresholdLdData[sfbGrp + sfb];
   1005         sfbThrExp = thrExp[ch][sfbGrp + sfb];
   1006         if ((sfbEnLdData > sfbThrLdData) &&
   1007             (ahFlag[ch][sfbGrp + sfb] != AH_ACTIVE)) {
   1008           /* threshold reduction formula:
   1009            float tmp = thrExp[ch][sfb]+redVal;
   1010            tmp *= tmp;
   1011            sfbThrReduced = tmp*tmp;
   1012           */
   1013           int minScale = fixMin(CountLeadingBits(sfbThrExp),
   1014                                 CountLeadingBits(redVal_m) - redVal_e) -
   1015                          1;
   1016 
   1017           /* 4*log( sfbThrExp + redVal ) */
   1018           sfbThrReducedLdData =
   1019               CalcLdData(fAbs(scaleValue(sfbThrExp, minScale) +
   1020                               scaleValue(redVal_m, redVal_e + minScale))) -
   1021               (FIXP_DBL)(minScale << (DFRACT_BITS - 1 - LD_DATA_SHIFT));
   1022           sfbThrReducedLdData <<= 2;
   1023 
   1024           /* avoid holes */
   1025           if ((sfbThrReducedLdData >
   1026                (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData)) &&
   1027               (ahFlag[ch][sfbGrp + sfb] != NO_AH)) {
   1028             if (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] >
   1029                 (FL2FXCONST_DBL(-1.0f) - sfbEnLdData)) {
   1030               sfbThrReducedLdData = fixMax(
   1031                   (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData),
   1032                   sfbThrLdData);
   1033             } else
   1034               sfbThrReducedLdData = sfbThrLdData;
   1035             ahFlag[ch][sfbGrp + sfb] = AH_ACTIVE;
   1036           }
   1037 
   1038           /* minimum of 29 dB Ratio for Thresholds */
   1039           if ((sfbEnLdData + (FIXP_DBL)MAXVAL_DBL) >
   1040               FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING)) {
   1041             sfbThrReducedLdData = fixMax(
   1042                 sfbThrReducedLdData,
   1043                 (sfbEnLdData - FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING)));
   1044           }
   1045 
   1046           qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData;
   1047         }
   1048       }
   1049     }
   1050   }
   1051 }
   1052 
   1053 /* similar to prepareSfbPe1() */
   1054 static FIXP_DBL FDKaacEnc_calcChaosMeasure(
   1055     const PSY_OUT_CHANNEL *const psyOutChannel,
   1056     const FIXP_DBL *const sfbFormFactorLdData) {
   1057 #define SCALE_FORM_FAC \
   1058   (4) /* (SCALE_FORM_FAC+FORM_FAC_SHIFT) >= ld(FRAME_LENGTH)*/
   1059 #define SCALE_NRGS (8)
   1060 #define SCALE_NLINES (16)
   1061 #define SCALE_NRGS_SQRT4 (2)  /* 0.25 * SCALE_NRGS */
   1062 #define SCALE_NLINES_P34 (12) /* 0.75 * SCALE_NLINES */
   1063 
   1064   INT sfbGrp, sfb;
   1065   FIXP_DBL chaosMeasure;
   1066   INT frameNLines = 0;
   1067   FIXP_DBL frameFormFactor = FL2FXCONST_DBL(0.f);
   1068   FIXP_DBL frameEnergy = FL2FXCONST_DBL(0.f);
   1069 
   1070   for (sfbGrp = 0; sfbGrp < psyOutChannel->sfbCnt;
   1071        sfbGrp += psyOutChannel->sfbPerGroup) {
   1072     for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) {
   1073       if (psyOutChannel->sfbEnergyLdData[sfbGrp + sfb] >
   1074           psyOutChannel->sfbThresholdLdData[sfbGrp + sfb]) {
   1075         frameFormFactor += (CalcInvLdData(sfbFormFactorLdData[sfbGrp + sfb]) >>
   1076                             SCALE_FORM_FAC);
   1077         frameNLines += (psyOutChannel->sfbOffsets[sfbGrp + sfb + 1] -
   1078                         psyOutChannel->sfbOffsets[sfbGrp + sfb]);
   1079         frameEnergy += (psyOutChannel->sfbEnergy[sfbGrp + sfb] >> SCALE_NRGS);
   1080       }
   1081     }
   1082   }
   1083 
   1084   if (frameNLines > 0) {
   1085     /*  frameNActiveLines = frameFormFactor*2^FORM_FAC_SHIFT * ((frameEnergy
   1086        *2^SCALE_NRGS)/frameNLines)^-0.25 chaosMeasure      = frameNActiveLines /
   1087        frameNLines */
   1088     chaosMeasure = CalcInvLdData(
   1089         (((CalcLdData(frameFormFactor) >> 1) -
   1090           (CalcLdData(frameEnergy) >> (2 + 1))) -
   1091          (fMultDiv2(FL2FXCONST_DBL(0.75f),
   1092                     CalcLdData((FIXP_DBL)frameNLines
   1093                                << (DFRACT_BITS - 1 - SCALE_NLINES))) -
   1094           (((FIXP_DBL)(-((-SCALE_FORM_FAC + SCALE_NRGS_SQRT4 - FORM_FAC_SHIFT +
   1095                           SCALE_NLINES_P34)
   1096                          << (DFRACT_BITS - 1 - LD_DATA_SHIFT)))) >>
   1097            1)))
   1098         << 1);
   1099   } else {
   1100     /* assuming total chaos, if no sfb is above thresholds */
   1101     chaosMeasure = FL2FXCONST_DBL(1.f);
   1102   }
   1103 
   1104   return chaosMeasure;
   1105 }
   1106 
   1107 /* apply reduction formula for VBR-mode */
   1108 static void FDKaacEnc_reduceThresholdsVBR(
   1109     QC_OUT_CHANNEL *const qcOutChannel[(2)],
   1110     const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
   1111     UCHAR ahFlag[(2)][MAX_GROUPED_SFB],
   1112     const FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB], const INT nChannels,
   1113     const FIXP_DBL vbrQualFactor, FIXP_DBL *const chaosMeasureOld) {
   1114   INT ch, sfbGrp, sfb;
   1115   FIXP_DBL chGroupEnergy[TRANS_FAC][2]; /*energy for each group and channel*/
   1116   FIXP_DBL chChaosMeasure[2];
   1117   FIXP_DBL frameEnergy = FL2FXCONST_DBL(1e-10f);
   1118   FIXP_DBL chaosMeasure = FL2FXCONST_DBL(0.f);
   1119   FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrExp;
   1120   FIXP_DBL sfbThrReducedLdData;
   1121   FIXP_DBL chaosMeasureAvg;
   1122   INT groupCnt;               /* loop counter */
   1123   FIXP_DBL redVal[TRANS_FAC]; /* reduction values; in short-block case one
   1124                                  redVal for each group */
   1125   QC_OUT_CHANNEL *qcOutChan = NULL;
   1126   const PSY_OUT_CHANNEL *psyOutChan = NULL;
   1127 
   1128 #define SCALE_GROUP_ENERGY (8)
   1129 
   1130 #define CONST_CHAOS_MEAS_AVG_FAC_0 (FL2FXCONST_DBL(0.25f))
   1131 #define CONST_CHAOS_MEAS_AVG_FAC_1 (FL2FXCONST_DBL(1.f - 0.25f))
   1132 
   1133 #define MIN_LDTHRESH (FL2FXCONST_DBL(-0.515625f))
   1134 
   1135   for (ch = 0; ch < nChannels; ch++) {
   1136     psyOutChan = psyOutChannel[ch];
   1137 
   1138     /* adding up energy for each channel and each group separately */
   1139     FIXP_DBL chEnergy = FL2FXCONST_DBL(0.f);
   1140     groupCnt = 0;
   1141 
   1142     for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
   1143          sfbGrp += psyOutChan->sfbPerGroup, groupCnt++) {
   1144       chGroupEnergy[groupCnt][ch] = FL2FXCONST_DBL(0.f);
   1145       for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
   1146         chGroupEnergy[groupCnt][ch] +=
   1147             (psyOutChan->sfbEnergy[sfbGrp + sfb] >> SCALE_GROUP_ENERGY);
   1148       }
   1149       chEnergy += chGroupEnergy[groupCnt][ch];
   1150     }
   1151     frameEnergy += chEnergy;
   1152 
   1153     /* chaosMeasure */
   1154     if (psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) {
   1155       chChaosMeasure[ch] = FL2FXCONST_DBL(
   1156           0.5f); /* assume a constant chaos measure of 0.5f for short blocks */
   1157     } else {
   1158       chChaosMeasure[ch] = FDKaacEnc_calcChaosMeasure(
   1159           psyOutChannel[ch], qcOutChannel[ch]->sfbFormFactorLdData);
   1160     }
   1161     chaosMeasure += fMult(chChaosMeasure[ch], chEnergy);
   1162   }
   1163 
   1164   if (frameEnergy > chaosMeasure) {
   1165     INT scale = CntLeadingZeros(frameEnergy) - 1;
   1166     FIXP_DBL num = chaosMeasure << scale;
   1167     FIXP_DBL denum = frameEnergy << scale;
   1168     chaosMeasure = schur_div(num, denum, 16);
   1169   } else {
   1170     chaosMeasure = FL2FXCONST_DBL(1.f);
   1171   }
   1172 
   1173   chaosMeasureAvg = fMult(CONST_CHAOS_MEAS_AVG_FAC_0, chaosMeasure) +
   1174                     fMult(CONST_CHAOS_MEAS_AVG_FAC_1,
   1175                           *chaosMeasureOld); /* averaging chaos measure */
   1176   *chaosMeasureOld = chaosMeasure = (fixMin(
   1177       chaosMeasure, chaosMeasureAvg)); /* use min-value, safe for next frame */
   1178 
   1179   /* characteristic curve
   1180      chaosMeasure = 0.2f + 0.7f/0.3f * (chaosMeasure - 0.2f);
   1181      chaosMeasure = fixMin(1.0f, fixMax(0.1f, chaosMeasure));
   1182      constants scaled by 4.f
   1183   */
   1184   chaosMeasure = ((FL2FXCONST_DBL(0.2f) >> 2) +
   1185                   fMult(FL2FXCONST_DBL(0.7f / (4.f * 0.3f)),
   1186                         (chaosMeasure - FL2FXCONST_DBL(0.2f))));
   1187   chaosMeasure =
   1188       (fixMin((FIXP_DBL)(FL2FXCONST_DBL(1.0f) >> 2),
   1189               fixMax((FIXP_DBL)(FL2FXCONST_DBL(0.1f) >> 2), chaosMeasure)))
   1190       << 2;
   1191 
   1192   /* calculation of reduction value */
   1193   if (psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) { /* short-blocks */
   1194     FDK_ASSERT(TRANS_FAC == 8);
   1195 #define WIN_TYPE_SCALE (3)
   1196 
   1197     groupCnt = 0;
   1198     for (sfbGrp = 0; sfbGrp < psyOutChannel[0]->sfbCnt;
   1199          sfbGrp += psyOutChannel[0]->sfbPerGroup, groupCnt++) {
   1200       FIXP_DBL groupEnergy = FL2FXCONST_DBL(0.f);
   1201 
   1202       for (ch = 0; ch < nChannels; ch++) {
   1203         groupEnergy +=
   1204             chGroupEnergy[groupCnt]
   1205                          [ch]; /* adding up the channels groupEnergy */
   1206       }
   1207 
   1208       FDK_ASSERT(psyOutChannel[0]->groupLen[groupCnt] <= INV_INT_TAB_SIZE);
   1209       groupEnergy = fMult(
   1210           groupEnergy,
   1211           invInt[psyOutChannel[0]->groupLen[groupCnt]]); /* correction of
   1212                                                             group energy */
   1213       groupEnergy = fixMin(groupEnergy,
   1214                            frameEnergy >> WIN_TYPE_SCALE); /* do not allow an
   1215                                                               higher redVal as
   1216                                                               calculated
   1217                                                               framewise */
   1218 
   1219       groupEnergy >>=
   1220           2; /* 2*WIN_TYPE_SCALE = 6 => 6+2 = 8 ==> 8/4 = int number */
   1221 
   1222       redVal[groupCnt] =
   1223           fMult(fMult(vbrQualFactor, chaosMeasure),
   1224                 CalcInvLdData(CalcLdData(groupEnergy) >> 2))
   1225           << (int)((2 + (2 * WIN_TYPE_SCALE) + SCALE_GROUP_ENERGY) >> 2);
   1226     }
   1227   } else { /* long-block */
   1228 
   1229     redVal[0] = fMult(fMult(vbrQualFactor, chaosMeasure),
   1230                       CalcInvLdData(CalcLdData(frameEnergy) >> 2))
   1231                 << (int)(SCALE_GROUP_ENERGY >> 2);
   1232   }
   1233 
   1234   for (ch = 0; ch < nChannels; ch++) {
   1235     qcOutChan = qcOutChannel[ch];
   1236     psyOutChan = psyOutChannel[ch];
   1237 
   1238     for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
   1239          sfbGrp += psyOutChan->sfbPerGroup) {
   1240       for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
   1241         sfbEnLdData = (qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb]);
   1242         sfbThrLdData = (qcOutChan->sfbThresholdLdData[sfbGrp + sfb]);
   1243         sfbThrExp = thrExp[ch][sfbGrp + sfb];
   1244 
   1245         if ((sfbThrLdData >= MIN_LDTHRESH) && (sfbEnLdData > sfbThrLdData) &&
   1246             (ahFlag[ch][sfbGrp + sfb] != AH_ACTIVE)) {
   1247           /* Short-Window */
   1248           if (psyOutChannel[ch]->lastWindowSequence == SHORT_WINDOW) {
   1249             const int groupNumber = (int)sfb / psyOutChan->sfbPerGroup;
   1250 
   1251             FDK_ASSERT(INV_SQRT4_TAB_SIZE > psyOutChan->groupLen[groupNumber]);
   1252 
   1253             sfbThrExp =
   1254                 fMult(sfbThrExp,
   1255                       fMult(FL2FXCONST_DBL(2.82f / 4.f),
   1256                             invSqrt4[psyOutChan->groupLen[groupNumber]]))
   1257                 << 2;
   1258 
   1259             if (sfbThrExp <= (limitThrReducedLdData - redVal[groupNumber])) {
   1260               sfbThrReducedLdData = FL2FXCONST_DBL(-1.0f);
   1261             } else {
   1262               if ((FIXP_DBL)redVal[groupNumber] >=
   1263                   FL2FXCONST_DBL(1.0f) - sfbThrExp)
   1264                 sfbThrReducedLdData = FL2FXCONST_DBL(0.0f);
   1265               else {
   1266                 /* threshold reduction formula */
   1267                 sfbThrReducedLdData =
   1268                     CalcLdData(sfbThrExp + redVal[groupNumber]);
   1269                 sfbThrReducedLdData <<= 2;
   1270               }
   1271             }
   1272             sfbThrReducedLdData +=
   1273                 (CalcLdInt(psyOutChan->groupLen[groupNumber]) -
   1274                  ((FIXP_DBL)6 << (DFRACT_BITS - 1 - LD_DATA_SHIFT)));
   1275           }
   1276 
   1277           /* Long-Window */
   1278           else {
   1279             if ((FIXP_DBL)redVal[0] >= FL2FXCONST_DBL(1.0f) - sfbThrExp) {
   1280               sfbThrReducedLdData = FL2FXCONST_DBL(0.0f);
   1281             } else {
   1282               /* threshold reduction formula */
   1283               sfbThrReducedLdData = CalcLdData(sfbThrExp + redVal[0]);
   1284               sfbThrReducedLdData <<= 2;
   1285             }
   1286           }
   1287 
   1288           /* avoid holes */
   1289           if (((sfbThrReducedLdData - sfbEnLdData) >
   1290                qcOutChan->sfbMinSnrLdData[sfbGrp + sfb]) &&
   1291               (ahFlag[ch][sfbGrp + sfb] != NO_AH)) {
   1292             if (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] >
   1293                 (FL2FXCONST_DBL(-1.0f) - sfbEnLdData)) {
   1294               sfbThrReducedLdData = fixMax(
   1295                   (qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData),
   1296                   sfbThrLdData);
   1297             } else
   1298               sfbThrReducedLdData = sfbThrLdData;
   1299             ahFlag[ch][sfbGrp + sfb] = AH_ACTIVE;
   1300           }
   1301 
   1302           if (sfbThrReducedLdData < FL2FXCONST_DBL(-0.5f))
   1303             sfbThrReducedLdData = FL2FXCONST_DBL(-1.f);
   1304 
   1305           /* minimum of 29 dB Ratio for Thresholds */
   1306           if ((sfbEnLdData + FL2FXCONST_DBL(1.0f)) >
   1307               FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING)) {
   1308             sfbThrReducedLdData = fixMax(
   1309                 sfbThrReducedLdData,
   1310                 sfbEnLdData - FL2FXCONST_DBL(9.6336206 / LD_DATA_SCALING));
   1311           }
   1312 
   1313           sfbThrReducedLdData = fixMax(MIN_LDTHRESH, sfbThrReducedLdData);
   1314 
   1315           qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData;
   1316         }
   1317       }
   1318     }
   1319   }
   1320 }
   1321 
   1322 /*****************************************************************************
   1323 functionname: FDKaacEnc_correctThresh
   1324 description:  if pe difference deltaPe between desired pe and real pe is small
   1325 enough, the difference can be distributed among the scale factor bands. New
   1326 thresholds can be derived from this pe-difference
   1327 *****************************************************************************/
   1328 static void FDKaacEnc_correctThresh(
   1329     const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))],
   1330     const PSY_OUT_ELEMENT *const psyOutElement[((8))],
   1331     UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB],
   1332     const FIXP_DBL thrExp[((8))][(2)][MAX_GROUPED_SFB], const FIXP_DBL redVal_m,
   1333     const SCHAR redVal_e, const INT deltaPe, const INT processElements,
   1334     const INT elementOffset) {
   1335   INT ch, sfb, sfbGrp;
   1336   QC_OUT_CHANNEL *qcOutChan;
   1337   PSY_OUT_CHANNEL *psyOutChan;
   1338   PE_CHANNEL_DATA *peChanData;
   1339   FIXP_DBL thrFactorLdData;
   1340   FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData;
   1341   FIXP_DBL *sfbPeFactorsLdData[((8))][(2)];
   1342   FIXP_DBL(*sfbNActiveLinesLdData)[(2)][MAX_GROUPED_SFB];
   1343 
   1344   INT normFactorInt;
   1345   FIXP_DBL normFactorLdData;
   1346 
   1347   INT nElements = elementOffset + processElements;
   1348   INT elementId;
   1349 
   1350   /* scratch is empty; use temporal memory from quantSpec in QC_OUT_CHANNEL */
   1351   for (elementId = elementOffset; elementId < nElements; elementId++) {
   1352     for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
   1353       /* The reinterpret_cast is used to suppress a compiler warning. We know
   1354        * that qcElement[elementId]->qcOutChannel[ch]->quantSpec is sufficiently
   1355        * aligned, so the cast is safe */
   1356       sfbPeFactorsLdData[elementId][ch] =
   1357           reinterpret_cast<FIXP_DBL *>(reinterpret_cast<void *>(
   1358               qcElement[elementId]->qcOutChannel[ch]->quantSpec));
   1359     }
   1360   }
   1361   /* The reinterpret_cast is used to suppress a compiler warning. We know that
   1362    * qcElement[0]->dynMem_SfbNActiveLinesLdData is sufficiently aligned, so the
   1363    * cast is safe */
   1364   sfbNActiveLinesLdData = reinterpret_cast<FIXP_DBL(*)[(2)][MAX_GROUPED_SFB]>(
   1365       reinterpret_cast<void *>(qcElement[0]->dynMem_SfbNActiveLinesLdData));
   1366 
   1367   /* for each sfb calc relative factors for pe changes */
   1368   normFactorInt = 0;
   1369 
   1370   for (elementId = elementOffset; elementId < nElements; elementId++) {
   1371     if (cm->elInfo[elementId].elType != ID_DSE) {
   1372       for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
   1373         psyOutChan = psyOutElement[elementId]->psyOutChannel[ch];
   1374         peChanData = &qcElement[elementId]->peData.peChannelData[ch];
   1375 
   1376         for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
   1377              sfbGrp += psyOutChan->sfbPerGroup) {
   1378           for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
   1379             if (peChanData->sfbNActiveLines[sfbGrp + sfb] == 0) {
   1380               sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] =
   1381                   FL2FXCONST_DBL(-1.0f);
   1382             } else {
   1383               /* Both CalcLdInt and CalcLdData can be used!
   1384                * No offset has to be subtracted, because sfbNActiveLinesLdData
   1385                * is shorted while thrFactor calculation */
   1386               sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] =
   1387                   CalcLdInt(peChanData->sfbNActiveLines[sfbGrp + sfb]);
   1388             }
   1389             if (((ahFlag[elementId][ch][sfbGrp + sfb] < AH_ACTIVE) ||
   1390                  (deltaPe > 0)) &&
   1391                 peChanData->sfbNActiveLines[sfbGrp + sfb] != 0) {
   1392               if (thrExp[elementId][ch][sfbGrp + sfb] > -redVal_m) {
   1393                 /* sfbPeFactors[ch][sfbGrp+sfb] =
   1394                    peChanData->sfbNActiveLines[sfbGrp+sfb] /
   1395                                   (thrExp[elementId][ch][sfbGrp+sfb] +
   1396                    redVal[elementId]); */
   1397 
   1398                 int minScale =
   1399                     fixMin(
   1400                         CountLeadingBits(thrExp[elementId][ch][sfbGrp + sfb]),
   1401                         CountLeadingBits(redVal_m) - redVal_e) -
   1402                     1;
   1403 
   1404                 /* sumld = ld64( sfbThrExp + redVal ) */
   1405                 FIXP_DBL sumLd =
   1406                     CalcLdData(scaleValue(thrExp[elementId][ch][sfbGrp + sfb],
   1407                                           minScale) +
   1408                                scaleValue(redVal_m, redVal_e + minScale)) -
   1409                     (FIXP_DBL)(minScale << (DFRACT_BITS - 1 - LD_DATA_SHIFT));
   1410 
   1411                 if (sumLd < FL2FXCONST_DBL(0.f)) {
   1412                   sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
   1413                       sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] -
   1414                       sumLd;
   1415                 } else {
   1416                   if (sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] >
   1417                       (FL2FXCONST_DBL(-1.f) + sumLd)) {
   1418                     sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
   1419                         sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] -
   1420                         sumLd;
   1421                   } else {
   1422                     sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
   1423                         sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb];
   1424                   }
   1425                 }
   1426 
   1427                 normFactorInt += (INT)CalcInvLdData(
   1428                     sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb]);
   1429               } else
   1430                 sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
   1431                     FL2FXCONST_DBL(1.0f);
   1432             } else
   1433               sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] =
   1434                   FL2FXCONST_DBL(-1.0f);
   1435           }
   1436         }
   1437       }
   1438     }
   1439   }
   1440 
   1441   /* normFactorLdData = ld64(deltaPe/normFactorInt) */
   1442   normFactorLdData =
   1443       CalcLdData((FIXP_DBL)((deltaPe < 0) ? (-deltaPe) : (deltaPe))) -
   1444       CalcLdData((FIXP_DBL)normFactorInt);
   1445 
   1446   /* distribute the pe difference to the scalefactors
   1447      and calculate the according thresholds */
   1448   for (elementId = elementOffset; elementId < nElements; elementId++) {
   1449     if (cm->elInfo[elementId].elType != ID_DSE) {
   1450       for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
   1451         qcOutChan = qcElement[elementId]->qcOutChannel[ch];
   1452         psyOutChan = psyOutElement[elementId]->psyOutChannel[ch];
   1453         peChanData = &qcElement[elementId]->peData.peChannelData[ch];
   1454 
   1455         for (sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt;
   1456              sfbGrp += psyOutChan->sfbPerGroup) {
   1457           for (sfb = 0; sfb < psyOutChan->maxSfbPerGroup; sfb++) {
   1458             if (peChanData->sfbNActiveLines[sfbGrp + sfb] > 0) {
   1459               /* pe difference for this sfb */
   1460               if ((sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] ==
   1461                    FL2FXCONST_DBL(-1.0f)) ||
   1462                   (deltaPe == 0)) {
   1463                 thrFactorLdData = FL2FXCONST_DBL(0.f);
   1464               } else {
   1465                 /* new threshold */
   1466                 FIXP_DBL tmp = CalcInvLdData(
   1467                     sfbPeFactorsLdData[elementId][ch][sfbGrp + sfb] +
   1468                     normFactorLdData -
   1469                     sfbNActiveLinesLdData[elementId][ch][sfbGrp + sfb] -
   1470                     FL2FXCONST_DBL((float)LD_DATA_SHIFT / LD_DATA_SCALING));
   1471 
   1472                 /* limit thrFactor to 60dB */
   1473                 tmp = (deltaPe < 0) ? tmp : (-tmp);
   1474                 thrFactorLdData =
   1475                     fMin(tmp, FL2FXCONST_DBL(20.f / LD_DATA_SCALING));
   1476               }
   1477 
   1478               /* new threshold */
   1479               sfbThrLdData = qcOutChan->sfbThresholdLdData[sfbGrp + sfb];
   1480               sfbEnLdData = qcOutChan->sfbWeightedEnergyLdData[sfbGrp + sfb];
   1481 
   1482               if (thrFactorLdData < FL2FXCONST_DBL(0.f)) {
   1483                 if (sfbThrLdData > (FL2FXCONST_DBL(-1.f) - thrFactorLdData)) {
   1484                   sfbThrReducedLdData = sfbThrLdData + thrFactorLdData;
   1485                 } else {
   1486                   sfbThrReducedLdData = FL2FXCONST_DBL(-1.f);
   1487                 }
   1488               } else {
   1489                 sfbThrReducedLdData = sfbThrLdData + thrFactorLdData;
   1490               }
   1491 
   1492               /* avoid hole */
   1493               if ((sfbThrReducedLdData - sfbEnLdData >
   1494                    qcOutChan->sfbMinSnrLdData[sfbGrp + sfb]) &&
   1495                   (ahFlag[elementId][ch][sfbGrp + sfb] == AH_INACTIVE)) {
   1496                 /* sfbThrReduced = max(psyOutChan[ch]->sfbMinSnr[i] * sfbEn,
   1497                  * sfbThr); */
   1498                 if (sfbEnLdData >
   1499                     (sfbThrLdData - qcOutChan->sfbMinSnrLdData[sfbGrp + sfb])) {
   1500                   sfbThrReducedLdData =
   1501                       qcOutChan->sfbMinSnrLdData[sfbGrp + sfb] + sfbEnLdData;
   1502                 } else {
   1503                   sfbThrReducedLdData = sfbThrLdData;
   1504                 }
   1505                 ahFlag[elementId][ch][sfbGrp + sfb] = AH_ACTIVE;
   1506               }
   1507 
   1508               qcOutChan->sfbThresholdLdData[sfbGrp + sfb] = sfbThrReducedLdData;
   1509             }
   1510           }
   1511         }
   1512       }
   1513     }
   1514   }
   1515 }
   1516 
   1517 /*****************************************************************************
   1518     functionname: FDKaacEnc_reduceMinSnr
   1519     description:  if the desired pe can not be reached, reduce pe by
   1520                   reducing minSnr
   1521 *****************************************************************************/
   1522 static void FDKaacEnc_reduceMinSnr(
   1523     const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))],
   1524     const PSY_OUT_ELEMENT *const psyOutElement[((8))],
   1525     const UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB], const INT desiredPe,
   1526     INT *const redPeGlobal, const INT processElements, const INT elementOffset)
   1527 
   1528 {
   1529   INT ch, elementId, globalMaxSfb = 0;
   1530   const INT nElements = elementOffset + processElements;
   1531   INT newGlobalPe = *redPeGlobal;
   1532 
   1533   if (newGlobalPe <= desiredPe) {
   1534     goto bail;
   1535   }
   1536 
   1537   /* global maximum of maxSfbPerGroup */
   1538   for (elementId = elementOffset; elementId < nElements; elementId++) {
   1539     if (cm->elInfo[elementId].elType != ID_DSE) {
   1540       for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
   1541         globalMaxSfb =
   1542             fMax(globalMaxSfb,
   1543                  psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup);
   1544       }
   1545     }
   1546   }
   1547 
   1548   /* as long as globalPE is above desirePE reduce SNR to 1.0 dB, starting at
   1549    * highest SFB */
   1550   while ((newGlobalPe > desiredPe) && (--globalMaxSfb >= 0)) {
   1551     for (elementId = elementOffset; elementId < nElements; elementId++) {
   1552       if (cm->elInfo[elementId].elType != ID_DSE) {
   1553         PE_DATA *peData = &qcElement[elementId]->peData;
   1554 
   1555         for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
   1556           QC_OUT_CHANNEL *qcOutChan = qcElement[elementId]->qcOutChannel[ch];
   1557           PSY_OUT_CHANNEL *psyOutChan =
   1558               psyOutElement[elementId]->psyOutChannel[ch];
   1559 
   1560           /* try to reduce SNR of channel's uppermost SFB(s) */
   1561           if (globalMaxSfb < psyOutChan->maxSfbPerGroup) {
   1562             INT sfb, deltaPe = 0;
   1563 
   1564             for (sfb = globalMaxSfb; sfb < psyOutChan->sfbCnt;
   1565                  sfb += psyOutChan->sfbPerGroup) {
   1566               if (ahFlag[elementId][ch][sfb] != NO_AH &&
   1567                   qcOutChan->sfbMinSnrLdData[sfb] < SnrLdFac &&
   1568                   (qcOutChan->sfbWeightedEnergyLdData[sfb] >
   1569                    qcOutChan->sfbThresholdLdData[sfb] - SnrLdFac)) {
   1570                 /* increase threshold to new minSnr of 1dB */
   1571                 qcOutChan->sfbMinSnrLdData[sfb] = SnrLdFac;
   1572                 qcOutChan->sfbThresholdLdData[sfb] =
   1573                     qcOutChan->sfbWeightedEnergyLdData[sfb] + SnrLdFac;
   1574 
   1575                 /* calc new pe */
   1576                 /* C2 + C3*ld(1/0.8) = 1.5 */
   1577                 deltaPe -= peData->peChannelData[ch].sfbPe[sfb];
   1578 
   1579                 /* sfbPe = 1.5 * sfbNLines */
   1580                 peData->peChannelData[ch].sfbPe[sfb] =
   1581                     (3 * peData->peChannelData[ch].sfbNLines[sfb])
   1582                     << (PE_CONSTPART_SHIFT - 1);
   1583                 deltaPe += peData->peChannelData[ch].sfbPe[sfb];
   1584               }
   1585 
   1586             } /* sfb loop */
   1587 
   1588             deltaPe >>= PE_CONSTPART_SHIFT;
   1589             peData->pe += deltaPe;
   1590             peData->peChannelData[ch].pe += deltaPe;
   1591             newGlobalPe += deltaPe;
   1592 
   1593           } /* if globalMaxSfb < maxSfbPerGroup */
   1594 
   1595           /* stop if enough has been saved */
   1596           if (newGlobalPe <= desiredPe) {
   1597             goto bail;
   1598           }
   1599 
   1600         } /* ch loop */
   1601       }   /* != ID_DSE */
   1602     }     /* elementId loop */
   1603   }       /* while ( newGlobalPe > desiredPe) && (--globalMaxSfb >= 0) ) */
   1604 
   1605 bail:
   1606   /* update global PE */
   1607   *redPeGlobal = newGlobalPe;
   1608 }
   1609 
   1610 /*****************************************************************************
   1611     functionname: FDKaacEnc_allowMoreHoles
   1612     description:  if the desired pe can not be reached, some more scalefactor
   1613                   bands have to be quantized to zero
   1614 *****************************************************************************/
   1615 static void FDKaacEnc_allowMoreHoles(
   1616     const CHANNEL_MAPPING *const cm, QC_OUT_ELEMENT *const qcElement[((8))],
   1617     const PSY_OUT_ELEMENT *const psyOutElement[((8))],
   1618     const ATS_ELEMENT *const AdjThrStateElement[((8))],
   1619     UCHAR ahFlag[((8))][(2)][MAX_GROUPED_SFB], const INT desiredPe,
   1620     const INT currentPe, const int processElements, const int elementOffset) {
   1621   INT elementId;
   1622   INT nElements = elementOffset + processElements;
   1623   INT actPe = currentPe;
   1624 
   1625   if (actPe <= desiredPe) {
   1626     return; /* nothing to do */
   1627   }
   1628 
   1629   for (elementId = elementOffset; elementId < nElements; elementId++) {
   1630     if (cm->elInfo[elementId].elType != ID_DSE) {
   1631       INT ch, sfb, sfbGrp;
   1632 
   1633       PE_DATA *peData = &qcElement[elementId]->peData;
   1634       const INT nChannels = cm->elInfo[elementId].nChannelsInEl;
   1635 
   1636       QC_OUT_CHANNEL *qcOutChannel[(2)] = {NULL};
   1637       PSY_OUT_CHANNEL *psyOutChannel[(2)] = {NULL};
   1638 
   1639       for (ch = 0; ch < nChannels; ch++) {
   1640         /* init pointers */
   1641         qcOutChannel[ch] = qcElement[elementId]->qcOutChannel[ch];
   1642         psyOutChannel[ch] = psyOutElement[elementId]->psyOutChannel[ch];
   1643 
   1644         for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
   1645              sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
   1646           for (sfb = psyOutChannel[ch]->maxSfbPerGroup;
   1647                sfb < psyOutChannel[ch]->sfbPerGroup; sfb++) {
   1648             peData->peChannelData[ch].sfbPe[sfbGrp + sfb] = 0;
   1649           }
   1650         }
   1651       }
   1652 
   1653       /* for MS allow hole in the channel with less energy */
   1654       if (nChannels == 2 && psyOutChannel[0]->lastWindowSequence ==
   1655                                 psyOutChannel[1]->lastWindowSequence) {
   1656         for (sfb = psyOutChannel[0]->maxSfbPerGroup - 1; sfb >= 0; sfb--) {
   1657           for (sfbGrp = 0; sfbGrp < psyOutChannel[0]->sfbCnt;
   1658                sfbGrp += psyOutChannel[0]->sfbPerGroup) {
   1659             if (psyOutElement[elementId]->toolsInfo.msMask[sfbGrp + sfb]) {
   1660               FIXP_DBL EnergyLd_L =
   1661                   qcOutChannel[0]->sfbWeightedEnergyLdData[sfbGrp + sfb];
   1662               FIXP_DBL EnergyLd_R =
   1663                   qcOutChannel[1]->sfbWeightedEnergyLdData[sfbGrp + sfb];
   1664 
   1665               /* allow hole in side channel ? */
   1666               if ((ahFlag[elementId][1][sfbGrp + sfb] != NO_AH) &&
   1667                   (((FL2FXCONST_DBL(-0.02065512648f) >> 1) +
   1668                     (qcOutChannel[0]->sfbMinSnrLdData[sfbGrp + sfb] >> 1)) >
   1669                    ((EnergyLd_R >> 1) - (EnergyLd_L >> 1)))) {
   1670                 ahFlag[elementId][1][sfbGrp + sfb] = NO_AH;
   1671                 qcOutChannel[1]->sfbThresholdLdData[sfbGrp + sfb] =
   1672                     FL2FXCONST_DBL(0.015625f) + EnergyLd_R;
   1673                 actPe -= peData->peChannelData[1].sfbPe[sfbGrp + sfb] >>
   1674                          PE_CONSTPART_SHIFT;
   1675               }
   1676               /* allow hole in mid channel ? */
   1677               else if ((ahFlag[elementId][0][sfbGrp + sfb] != NO_AH) &&
   1678                        (((FL2FXCONST_DBL(-0.02065512648f) >> 1) +
   1679                          (qcOutChannel[1]->sfbMinSnrLdData[sfbGrp + sfb] >>
   1680                           1)) > ((EnergyLd_L >> 1) - (EnergyLd_R >> 1)))) {
   1681                 ahFlag[elementId][0][sfbGrp + sfb] = NO_AH;
   1682                 qcOutChannel[0]->sfbThresholdLdData[sfbGrp + sfb] =
   1683                     FL2FXCONST_DBL(0.015625f) + EnergyLd_L;
   1684                 actPe -= peData->peChannelData[0].sfbPe[sfbGrp + sfb] >>
   1685                          PE_CONSTPART_SHIFT;
   1686               } /* if (ahFlag) */
   1687             }   /* if MS */
   1688           }     /* sfbGrp */
   1689           if (actPe <= desiredPe) {
   1690             return; /* stop if enough has been saved */
   1691           }
   1692         } /* sfb */
   1693       }   /* MS possible ? */
   1694 
   1695     } /* EOF DSE-suppression */
   1696   }   /* EOF for all elements... */
   1697 
   1698   if (actPe > desiredPe) {
   1699     /* more holes necessary? subsequently erase bands starting with low energies
   1700      */
   1701     INT ch, sfb, sfbGrp;
   1702     INT minSfb, maxSfb;
   1703     INT enIdx, ahCnt, done;
   1704     INT startSfb[(8)];
   1705     INT sfbCnt[(8)];
   1706     INT sfbPerGroup[(8)];
   1707     INT maxSfbPerGroup[(8)];
   1708     FIXP_DBL avgEn;
   1709     FIXP_DBL minEnLD64;
   1710     FIXP_DBL avgEnLD64;
   1711     FIXP_DBL enLD64[NUM_NRG_LEVS];
   1712     INT avgEn_e;
   1713 
   1714     /* get the scaling factor over all audio elements and channels */
   1715     maxSfb = 0;
   1716     for (elementId = elementOffset; elementId < nElements; elementId++) {
   1717       if (cm->elInfo[elementId].elType != ID_DSE) {
   1718         for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
   1719           for (sfbGrp = 0;
   1720                sfbGrp < psyOutElement[elementId]->psyOutChannel[ch]->sfbCnt;
   1721                sfbGrp +=
   1722                psyOutElement[elementId]->psyOutChannel[ch]->sfbPerGroup) {
   1723             maxSfb +=
   1724                 psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup;
   1725           }
   1726         }
   1727       }
   1728     }
   1729     avgEn_e =
   1730         (DFRACT_BITS - fixnormz_D((LONG)fMax(0, maxSfb - 1))); /* ilog2() */
   1731 
   1732     ahCnt = 0;
   1733     maxSfb = 0;
   1734     minSfb = MAX_SFB;
   1735     avgEn = FL2FXCONST_DBL(0.0f);
   1736     minEnLD64 = FL2FXCONST_DBL(0.0f);
   1737 
   1738     for (elementId = elementOffset; elementId < nElements; elementId++) {
   1739       if (cm->elInfo[elementId].elType != ID_DSE) {
   1740         for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
   1741           const INT chIdx = cm->elInfo[elementId].ChannelIndex[ch];
   1742           QC_OUT_CHANNEL *qcOutChannel = qcElement[elementId]->qcOutChannel[ch];
   1743           PSY_OUT_CHANNEL *psyOutChannel =
   1744               psyOutElement[elementId]->psyOutChannel[ch];
   1745 
   1746           maxSfbPerGroup[chIdx] = psyOutChannel->maxSfbPerGroup;
   1747           sfbCnt[chIdx] = psyOutChannel->sfbCnt;
   1748           sfbPerGroup[chIdx] = psyOutChannel->sfbPerGroup;
   1749 
   1750           maxSfb = fMax(maxSfb, psyOutChannel->maxSfbPerGroup);
   1751 
   1752           if (psyOutChannel->lastWindowSequence != SHORT_WINDOW) {
   1753             startSfb[chIdx] = AdjThrStateElement[elementId]->ahParam.startSfbL;
   1754           } else {
   1755             startSfb[chIdx] = AdjThrStateElement[elementId]->ahParam.startSfbS;
   1756           }
   1757 
   1758           minSfb = fMin(minSfb, startSfb[chIdx]);
   1759 
   1760           sfbGrp = 0;
   1761           sfb = startSfb[chIdx];
   1762 
   1763           do {
   1764             for (; sfb < psyOutChannel->maxSfbPerGroup; sfb++) {
   1765               if ((ahFlag[elementId][ch][sfbGrp + sfb] != NO_AH) &&
   1766                   (qcOutChannel->sfbWeightedEnergyLdData[sfbGrp + sfb] >
   1767                    qcOutChannel->sfbThresholdLdData[sfbGrp + sfb])) {
   1768                 minEnLD64 = fixMin(minEnLD64,
   1769                                    qcOutChannel->sfbEnergyLdData[sfbGrp + sfb]);
   1770                 avgEn += qcOutChannel->sfbEnergy[sfbGrp + sfb] >> avgEn_e;
   1771                 ahCnt++;
   1772               }
   1773             }
   1774 
   1775             sfbGrp += psyOutChannel->sfbPerGroup;
   1776             sfb = startSfb[chIdx];
   1777 
   1778           } while (sfbGrp < psyOutChannel->sfbCnt);
   1779         }
   1780       } /* (cm->elInfo[elementId].elType != ID_DSE) */
   1781     }   /* (elementId = elementOffset;elementId<nElements;elementId++) */
   1782 
   1783     if ((avgEn == FL2FXCONST_DBL(0.0f)) || (ahCnt == 0)) {
   1784       avgEnLD64 = FL2FXCONST_DBL(0.0f);
   1785     } else {
   1786       avgEnLD64 = CalcLdData(avgEn) +
   1787                   (FIXP_DBL)(avgEn_e << (DFRACT_BITS - 1 - LD_DATA_SHIFT)) -
   1788                   CalcLdInt(ahCnt);
   1789     }
   1790 
   1791     /* calc some energy borders between minEn and avgEn */
   1792 
   1793     /* for (enIdx = 0; enIdx < NUM_NRG_LEVS; enIdx++) {
   1794          en[enIdx] = (2.0f*enIdx+1.0f)/(2.0f*NUM_NRG_LEVS-1.0f);
   1795        } */
   1796     enLD64[0] =
   1797         minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.06666667f));
   1798     enLD64[1] =
   1799         minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.20000000f));
   1800     enLD64[2] =
   1801         minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.33333334f));
   1802     enLD64[3] =
   1803         minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.46666667f));
   1804     enLD64[4] =
   1805         minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.60000002f));
   1806     enLD64[5] =
   1807         minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.73333335f));
   1808     enLD64[6] =
   1809         minEnLD64 + fMult((avgEnLD64 - minEnLD64), FL2FXCONST_DBL(0.86666667f));
   1810     enLD64[7] = minEnLD64 + (avgEnLD64 - minEnLD64);
   1811 
   1812     done = 0;
   1813     enIdx = 0;
   1814     sfb = maxSfb - 1;
   1815 
   1816     while (!done) {
   1817       for (elementId = elementOffset; elementId < nElements; elementId++) {
   1818         if (cm->elInfo[elementId].elType != ID_DSE) {
   1819           PE_DATA *peData = &qcElement[elementId]->peData;
   1820           for (ch = 0; ch < cm->elInfo[elementId].nChannelsInEl; ch++) {
   1821             const INT chIdx = cm->elInfo[elementId].ChannelIndex[ch];
   1822             QC_OUT_CHANNEL *qcOutChannel =
   1823                 qcElement[elementId]->qcOutChannel[ch];
   1824             if (sfb >= startSfb[chIdx] && sfb < maxSfbPerGroup[chIdx]) {
   1825               for (sfbGrp = 0; sfbGrp < sfbCnt[chIdx];
   1826                    sfbGrp += sfbPerGroup[chIdx]) {
   1827                 /* sfb energy below border ? */
   1828                 if (ahFlag[elementId][ch][sfbGrp + sfb] != NO_AH &&
   1829                     qcOutChannel->sfbEnergyLdData[sfbGrp + sfb] <
   1830                         enLD64[enIdx]) {
   1831                   /* allow hole */
   1832                   ahFlag[elementId][ch][sfbGrp + sfb] = NO_AH;
   1833                   qcOutChannel->sfbThresholdLdData[sfbGrp + sfb] =
   1834                       FL2FXCONST_DBL(0.015625f) +
   1835                       qcOutChannel->sfbWeightedEnergyLdData[sfbGrp + sfb];
   1836                   actPe -= peData->peChannelData[ch].sfbPe[sfbGrp + sfb] >>
   1837                            PE_CONSTPART_SHIFT;
   1838                 }
   1839                 if (actPe <= desiredPe) {
   1840                   return; /* stop if enough has been saved */
   1841                 }
   1842               } /* sfbGrp */
   1843             }   /* sfb */
   1844           }     /* nChannelsInEl */
   1845         }       /* ID_DSE */
   1846       }         /* elementID */
   1847 
   1848       sfb--;
   1849       if (sfb < minSfb) {
   1850         /* restart with next energy border */
   1851         sfb = maxSfb;
   1852         enIdx++;
   1853         if (enIdx >= NUM_NRG_LEVS) {
   1854           done = 1;
   1855         }
   1856       }
   1857     } /* done */
   1858   }   /* (actPe <= desiredPe) */
   1859 }
   1860 
   1861 /* reset avoid hole flags from AH_ACTIVE to AH_INACTIVE  */
   1862 static void FDKaacEnc_resetAHFlags(
   1863     UCHAR ahFlag[(2)][MAX_GROUPED_SFB], const INT nChannels,
   1864     const PSY_OUT_CHANNEL *const psyOutChannel[(2)]) {
   1865   int ch, sfb, sfbGrp;
   1866 
   1867   for (ch = 0; ch < nChannels; ch++) {
   1868     for (sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt;
   1869          sfbGrp += psyOutChannel[ch]->sfbPerGroup) {
   1870       for (sfb = 0; sfb < psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
   1871         if (ahFlag[ch][sfbGrp + sfb] == AH_ACTIVE) {
   1872           ahFlag[ch][sfbGrp + sfb] = AH_INACTIVE;
   1873         }
   1874       }
   1875     }
   1876   }
   1877 }
   1878 
   1879 static FIXP_DBL CalcRedValPower(FIXP_DBL num, FIXP_DBL denum, INT *scaling) {
   1880   FIXP_DBL value = FL2FXCONST_DBL(0.f);
   1881 
   1882   if (num >= FL2FXCONST_DBL(0.f)) {
   1883     value = fDivNorm(num, denum, scaling);
   1884   } else {
   1885     value = -fDivNorm(-num, denum, scaling);
   1886   }
   1887   value = f2Pow(value, *scaling, scaling);
   1888 
   1889   return value;
   1890 }
   1891 
   1892 /*****************************************************************************
   1893 functionname: FDKaacEnc_adaptThresholdsToPe
   1894 description:  two guesses for the reduction value and one final correction of
   1895 the thresholds
   1896 *****************************************************************************/
   1897 static void FDKaacEnc_adaptThresholdsToPe(
   1898     const CHANNEL_MAPPING *const cm,
   1899     ATS_ELEMENT *const AdjThrStateElement[((8))],
   1900     QC_OUT_ELEMENT *const qcElement[((8))],
   1901     const PSY_OUT_ELEMENT *const psyOutElement[((8))], const INT desiredPe,
   1902     const INT maxIter2ndGuess, const INT processElements,
   1903     const INT elementOffset) {
   1904   FIXP_DBL reductionValue_m;
   1905   SCHAR reductionValue_e;
   1906   UCHAR(*pAhFlag)[(2)][MAX_GROUPED_SFB];
   1907   FIXP_DBL(*pThrExp)[(2)][MAX_GROUPED_SFB];
   1908   int iter;
   1909 
   1910   INT constPartGlobal, noRedPeGlobal, nActiveLinesGlobal, redPeGlobal;
   1911   constPartGlobal = noRedPeGlobal = nActiveLinesGlobal = redPeGlobal = 0;
   1912 
   1913   int elementId;
   1914 
   1915   int nElements = elementOffset + processElements;
   1916   if (nElements > cm->nElements) {
   1917     nElements = cm->nElements;
   1918   }
   1919 
   1920   /* The reinterpret_cast is used to suppress a compiler warning. We know that
   1921    * qcElement[0]->dynMem_Ah_Flag is sufficiently aligned, so the cast is safe
   1922    */
   1923   pAhFlag = reinterpret_cast<UCHAR(*)[(2)][MAX_GROUPED_SFB]>(
   1924       reinterpret_cast<void *>(qcElement[0]->dynMem_Ah_Flag));
   1925   /* The reinterpret_cast is used to suppress a compiler warning. We know that
   1926    * qcElement[0]->dynMem_Thr_Exp is sufficiently aligned, so the cast is safe
   1927    */
   1928   pThrExp = reinterpret_cast<FIXP_DBL(*)[(2)][MAX_GROUPED_SFB]>(
   1929       reinterpret_cast<void *>(qcElement[0]->dynMem_Thr_Exp));
   1930 
   1931   /* ------------------------------------------------------- */
   1932   /* Part I: Initialize data structures and variables... */
   1933   /* ------------------------------------------------------- */
   1934   for (elementId = elementOffset; elementId < nElements; elementId++) {
   1935     if (cm->elInfo[elementId].elType != ID_DSE) {
   1936       INT nChannels = cm->elInfo[elementId].nChannelsInEl;
   1937       PE_DATA *peData = &qcElement[elementId]->peData;
   1938 
   1939       /* thresholds to the power of redExp */
   1940       FDKaacEnc_calcThreshExp(
   1941           pThrExp[elementId], qcElement[elementId]->qcOutChannel,
   1942           psyOutElement[elementId]->psyOutChannel, nChannels);
   1943 
   1944       /* lower the minSnr requirements for low energies compared to the average
   1945          energy in this frame */
   1946       FDKaacEnc_adaptMinSnr(qcElement[elementId]->qcOutChannel,
   1947                             psyOutElement[elementId]->psyOutChannel,
   1948                             &AdjThrStateElement[elementId]->minSnrAdaptParam,
   1949                             nChannels);
   1950 
   1951       /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
   1952       FDKaacEnc_initAvoidHoleFlag(
   1953           qcElement[elementId]->qcOutChannel,
   1954           psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId],
   1955           &psyOutElement[elementId]->toolsInfo, nChannels,
   1956           &AdjThrStateElement[elementId]->ahParam);
   1957 
   1958       /* sum up */
   1959       constPartGlobal += peData->constPart;
   1960       noRedPeGlobal += peData->pe;
   1961       nActiveLinesGlobal += fixMax((INT)peData->nActiveLines, 1);
   1962 
   1963     } /* EOF DSE-suppression */
   1964   }   /* EOF for all elements... */
   1965 
   1966   /*
   1967      First guess of reduction value:
   1968      avgThrExp = (float)pow(2.0f, (constPartGlobal - noRedPeGlobal)/(4.0f *
   1969      nActiveLinesGlobal)); redVal    = (float)pow(2.0f, (constPartGlobal -
   1970      desiredPe)/(4.0f * nActiveLinesGlobal)) - avgThrExp; redVal    = max(0.f,
   1971      redVal);
   1972   */
   1973   int redVal_e, avgThrExp_e, result_e;
   1974   FIXP_DBL redVal_m, avgThrExp_m;
   1975 
   1976   redVal_m = CalcRedValPower(constPartGlobal - desiredPe,
   1977                              4 * nActiveLinesGlobal, &redVal_e);
   1978   avgThrExp_m = CalcRedValPower(constPartGlobal - noRedPeGlobal,
   1979                                 4 * nActiveLinesGlobal, &avgThrExp_e);
   1980   result_e = fMax(redVal_e, avgThrExp_e) + 1;
   1981 
   1982   reductionValue_m = fMax(FL2FXCONST_DBL(0.f),
   1983                           scaleValue(redVal_m, redVal_e - result_e) -
   1984                               scaleValue(avgThrExp_m, avgThrExp_e - result_e));
   1985   reductionValue_e = result_e;
   1986 
   1987   /* ----------------------------------------------------------------------- */
   1988   /* Part II: Calculate bit consumption of initial bit constraints setup */
   1989   /* ----------------------------------------------------------------------- */
   1990   for (elementId = elementOffset; elementId < nElements; elementId++) {
   1991     if (cm->elInfo[elementId].elType != ID_DSE) {
   1992       INT nChannels = cm->elInfo[elementId].nChannelsInEl;
   1993       PE_DATA *peData = &qcElement[elementId]->peData;
   1994 
   1995       /* reduce thresholds */
   1996       FDKaacEnc_reduceThresholdsCBR(
   1997           qcElement[elementId]->qcOutChannel,
   1998           psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId],
   1999           pThrExp[elementId], nChannels, reductionValue_m, reductionValue_e);
   2000 
   2001       /* pe after first guess */
   2002       FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel,
   2003                        qcElement[elementId]->qcOutChannel, peData, nChannels);
   2004 
   2005       redPeGlobal += peData->pe;
   2006     } /* EOF DSE-suppression */
   2007   }   /* EOF for all elements... */
   2008 
   2009   /* -------------------------------------------------- */
   2010   /* Part III: Iterate until bit constraints are met */
   2011   /* -------------------------------------------------- */
   2012   iter = 0;
   2013   while ((fixp_abs(redPeGlobal - desiredPe) >
   2014           fMultI(FL2FXCONST_DBL(0.05f), desiredPe)) &&
   2015          (iter < maxIter2ndGuess)) {
   2016     INT desiredPeNoAHGlobal;
   2017     INT redPeNoAHGlobal = 0;
   2018     INT constPartNoAHGlobal = 0;
   2019     INT nActiveLinesNoAHGlobal = 0;
   2020 
   2021     for (elementId = elementOffset; elementId < nElements; elementId++) {
   2022       if (cm->elInfo[elementId].elType != ID_DSE) {
   2023         INT redPeNoAH, constPartNoAH, nActiveLinesNoAH;
   2024         INT nChannels = cm->elInfo[elementId].nChannelsInEl;
   2025         PE_DATA *peData = &qcElement[elementId]->peData;
   2026 
   2027         /* pe for bands where avoid hole is inactive */
   2028         FDKaacEnc_FDKaacEnc_calcPeNoAH(
   2029             &redPeNoAH, &constPartNoAH, &nActiveLinesNoAH, peData,
   2030             pAhFlag[elementId], psyOutElement[elementId]->psyOutChannel,
   2031             nChannels);
   2032 
   2033         redPeNoAHGlobal += redPeNoAH;
   2034         constPartNoAHGlobal += constPartNoAH;
   2035         nActiveLinesNoAHGlobal += nActiveLinesNoAH;
   2036       } /* EOF DSE-suppression */
   2037     }   /* EOF for all elements... */
   2038 
   2039     /* Calculate new redVal ... */
   2040     if (desiredPe < redPeGlobal) {
   2041       /* new desired pe without bands where avoid hole is active */
   2042       desiredPeNoAHGlobal = desiredPe - (redPeGlobal - redPeNoAHGlobal);
   2043 
   2044       /* limit desiredPeNoAH to positive values, as the PE can not become
   2045        * negative */
   2046       desiredPeNoAHGlobal = fMax(0, desiredPeNoAHGlobal);
   2047 
   2048       /* second guess (only if there are bands left where avoid hole is
   2049        * inactive)*/
   2050       if (nActiveLinesNoAHGlobal > 0) {
   2051         /*
   2052           avgThrExp = (float)pow(2.0f, (constPartNoAHGlobal - redPeNoAHGlobal) /
   2053           (4.0f * nActiveLinesNoAHGlobal)); redVal   += (float)pow(2.0f,
   2054           (constPartNoAHGlobal - desiredPeNoAHGlobal) / (4.0f *
   2055           nActiveLinesNoAHGlobal)) - avgThrExp; redVal    = max(0.0f, redVal);
   2056         */
   2057 
   2058         redVal_m = CalcRedValPower(constPartNoAHGlobal - desiredPeNoAHGlobal,
   2059                                    4 * nActiveLinesNoAHGlobal, &redVal_e);
   2060         avgThrExp_m = CalcRedValPower(constPartNoAHGlobal - redPeNoAHGlobal,
   2061                                       4 * nActiveLinesNoAHGlobal, &avgThrExp_e);
   2062         result_e = fMax(reductionValue_e, fMax(redVal_e, avgThrExp_e) + 1) + 1;
   2063 
   2064         reductionValue_m =
   2065             fMax(FL2FXCONST_DBL(0.f),
   2066                  scaleValue(reductionValue_m, reductionValue_e - result_e) +
   2067                      scaleValue(redVal_m, redVal_e - result_e) -
   2068                      scaleValue(avgThrExp_m, avgThrExp_e - result_e));
   2069         reductionValue_e = result_e;
   2070 
   2071       } /* nActiveLinesNoAHGlobal > 0 */
   2072     } else {
   2073       /* redVal *= redPeGlobal/desiredPe; */
   2074       int sc0, sc1;
   2075       reductionValue_m = fMultNorm(
   2076           reductionValue_m,
   2077           fDivNorm((FIXP_DBL)redPeGlobal, (FIXP_DBL)desiredPe, &sc0), &sc1);
   2078       reductionValue_e += sc0 + sc1;
   2079 
   2080       for (elementId = elementOffset; elementId < nElements; elementId++) {
   2081         if (cm->elInfo[elementId].elType != ID_DSE) {
   2082           FDKaacEnc_resetAHFlags(pAhFlag[elementId],
   2083                                  cm->elInfo[elementId].nChannelsInEl,
   2084                                  psyOutElement[elementId]->psyOutChannel);
   2085         } /* EOF DSE-suppression */
   2086       }   /* EOF for all elements... */
   2087     }
   2088 
   2089     redPeGlobal = 0;
   2090     /* Calculate new redVal's PE... */
   2091     for (elementId = elementOffset; elementId < nElements; elementId++) {
   2092       if (cm->elInfo[elementId].elType != ID_DSE) {
   2093         INT nChannels = cm->elInfo[elementId].nChannelsInEl;
   2094         PE_DATA *peData = &qcElement[elementId]->peData;
   2095 
   2096         /* reduce thresholds */
   2097         FDKaacEnc_reduceThresholdsCBR(
   2098             qcElement[elementId]->qcOutChannel,
   2099             psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId],
   2100             pThrExp[elementId], nChannels, reductionValue_m, reductionValue_e);
   2101 
   2102         /* pe after second guess */
   2103         FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel,
   2104                          qcElement[elementId]->qcOutChannel, peData, nChannels);
   2105         redPeGlobal += peData->pe;
   2106 
   2107       } /* EOF DSE-suppression */
   2108     }   /* EOF for all elements... */
   2109 
   2110     iter++;
   2111   } /* EOF while */
   2112 
   2113   /* ------------------------------------------------------- */
   2114   /* Part IV: if still required, further reduce constraints  */
   2115   /* ------------------------------------------------------- */
   2116   /*                  1.0*        1.15*       1.20*
   2117    *               desiredPe   desiredPe   desiredPe
   2118    *                   |           |           |
   2119    * ...XXXXXXXXXXXXXXXXXXXXXXXXXXX|           |
   2120    *                   |           |           |XXXXXXXXXXX...
   2121    *                   |           |XXXXXXXXXXX|
   2122    *            --- A ---          | --- B --- | --- C ---
   2123    *
   2124    * (X): redPeGlobal
   2125    * (A): FDKaacEnc_correctThresh()
   2126    * (B): FDKaacEnc_allowMoreHoles()
   2127    * (C): FDKaacEnc_reduceMinSnr()
   2128    */
   2129 
   2130   /* correct thresholds to get closer to the desired pe */
   2131   if (redPeGlobal > desiredPe) {
   2132     FDKaacEnc_correctThresh(cm, qcElement, psyOutElement, pAhFlag, pThrExp,
   2133                             reductionValue_m, reductionValue_e,
   2134                             desiredPe - redPeGlobal, processElements,
   2135                             elementOffset);
   2136 
   2137     /* update PE */
   2138     redPeGlobal = 0;
   2139     for (elementId = elementOffset; elementId < nElements; elementId++) {
   2140       if (cm->elInfo[elementId].elType != ID_DSE) {
   2141         INT nChannels = cm->elInfo[elementId].nChannelsInEl;
   2142         PE_DATA *peData = &qcElement[elementId]->peData;
   2143 
   2144         /* pe after correctThresh */
   2145         FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel,
   2146                          qcElement[elementId]->qcOutChannel, peData, nChannels);
   2147         redPeGlobal += peData->pe;
   2148 
   2149       } /* EOF DSE-suppression */
   2150     }   /* EOF for all elements... */
   2151   }
   2152 
   2153   if (redPeGlobal > desiredPe) {
   2154     /* reduce pe by reducing minSnr requirements */
   2155     FDKaacEnc_reduceMinSnr(
   2156         cm, qcElement, psyOutElement, pAhFlag,
   2157         (fMultI(FL2FXCONST_DBL(0.15f), desiredPe) + desiredPe), &redPeGlobal,
   2158         processElements, elementOffset);
   2159 
   2160     /* reduce pe by allowing additional spectral holes */
   2161     FDKaacEnc_allowMoreHoles(cm, qcElement, psyOutElement, AdjThrStateElement,
   2162                              pAhFlag, desiredPe, redPeGlobal, processElements,
   2163                              elementOffset);
   2164   }
   2165 }
   2166 
   2167 /* similar to FDKaacEnc_adaptThresholdsToPe(), for  VBR-mode */
   2168 static void FDKaacEnc_AdaptThresholdsVBR(
   2169     QC_OUT_CHANNEL *const qcOutChannel[(2)],
   2170     const PSY_OUT_CHANNEL *const psyOutChannel[(2)],
   2171     ATS_ELEMENT *const AdjThrStateElement,
   2172     const struct TOOLSINFO *const toolsInfo, const INT nChannels) {
   2173   UCHAR(*pAhFlag)[MAX_GROUPED_SFB];
   2174   FIXP_DBL(*pThrExp)[MAX_GROUPED_SFB];
   2175 
   2176   /* allocate scratch memory */
   2177   C_ALLOC_SCRATCH_START(_pAhFlag, UCHAR, (2) * MAX_GROUPED_SFB)
   2178   C_ALLOC_SCRATCH_START(_pThrExp, FIXP_DBL, (2) * MAX_GROUPED_SFB)
   2179   pAhFlag = (UCHAR(*)[MAX_GROUPED_SFB])_pAhFlag;
   2180   pThrExp = (FIXP_DBL(*)[MAX_GROUPED_SFB])_pThrExp;
   2181 
   2182   /* thresholds to the power of redExp */
   2183   FDKaacEnc_calcThreshExp(pThrExp, qcOutChannel, psyOutChannel, nChannels);
   2184 
   2185   /* lower the minSnr requirements for low energies compared to the average
   2186      energy in this frame */
   2187   FDKaacEnc_adaptMinSnr(qcOutChannel, psyOutChannel,
   2188                         &AdjThrStateElement->minSnrAdaptParam, nChannels);
   2189 
   2190   /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
   2191   FDKaacEnc_initAvoidHoleFlag(qcOutChannel, psyOutChannel, pAhFlag, toolsInfo,
   2192                               nChannels, &AdjThrStateElement->ahParam);
   2193 
   2194   /* reduce thresholds */
   2195   FDKaacEnc_reduceThresholdsVBR(qcOutChannel, psyOutChannel, pAhFlag, pThrExp,
   2196                                 nChannels, AdjThrStateElement->vbrQualFactor,
   2197                                 &AdjThrStateElement->chaosMeasureOld);
   2198 
   2199   /* free scratch memory */
   2200   C_ALLOC_SCRATCH_END(_pThrExp, FIXP_DBL, (2) * MAX_GROUPED_SFB)
   2201   C_ALLOC_SCRATCH_END(_pAhFlag, UCHAR, (2) * MAX_GROUPED_SFB)
   2202 }
   2203 
   2204 /*****************************************************************************
   2205 
   2206   functionname: FDKaacEnc_calcBitSave
   2207   description:  Calculates percentage of bit save, see figure below
   2208   returns:
   2209   input:        parameters and bitres-fullness
   2210   output:       percentage of bit save
   2211 
   2212 *****************************************************************************/
   2213 /*
   2214         bitsave
   2215                     maxBitSave(%)|   clipLow
   2216                                  |---\
   2217                                  |    \
   2218                                  |     \
   2219                                  |      \
   2220                                  |       \
   2221                                  |--------\--------------> bitres
   2222                                  |         \
   2223                     minBitSave(%)|          \------------
   2224                                           clipHigh      maxBitres
   2225 */
   2226 static FIXP_DBL FDKaacEnc_calcBitSave(FIXP_DBL fillLevel,
   2227                                       const FIXP_DBL clipLow,
   2228                                       const FIXP_DBL clipHigh,
   2229                                       const FIXP_DBL minBitSave,
   2230                                       const FIXP_DBL maxBitSave,
   2231                                       const FIXP_DBL bitsave_slope) {
   2232   FIXP_DBL bitsave;
   2233 
   2234   fillLevel = fixMax(fillLevel, clipLow);
   2235   fillLevel = fixMin(fillLevel, clipHigh);
   2236 
   2237   bitsave = maxBitSave - fMult((fillLevel - clipLow), bitsave_slope);
   2238 
   2239   return (bitsave);
   2240 }
   2241 
   2242 /*****************************************************************************
   2243 
   2244   functionname: FDKaacEnc_calcBitSpend
   2245   description:  Calculates percentage of bit spend, see figure below
   2246   returns:
   2247   input:        parameters and bitres-fullness
   2248   output:       percentage of bit spend
   2249 
   2250 *****************************************************************************/
   2251 /*
   2252                               bitspend      clipHigh
   2253                    maxBitSpend(%)|          /-----------maxBitres
   2254                                  |         /
   2255                                  |        /
   2256                                  |       /
   2257                                  |      /
   2258                                  |     /
   2259                                  |----/-----------------> bitres
   2260                                  |   /
   2261                    minBitSpend(%)|--/
   2262                                    clipLow
   2263 */
   2264 static FIXP_DBL FDKaacEnc_calcBitSpend(FIXP_DBL fillLevel,
   2265                                        const FIXP_DBL clipLow,
   2266                                        const FIXP_DBL clipHigh,
   2267                                        const FIXP_DBL minBitSpend,
   2268                                        const FIXP_DBL maxBitSpend,
   2269                                        const FIXP_DBL bitspend_slope) {
   2270   FIXP_DBL bitspend;
   2271 
   2272   fillLevel = fixMax(fillLevel, clipLow);
   2273   fillLevel = fixMin(fillLevel, clipHigh);
   2274 
   2275   bitspend = minBitSpend + fMult(fillLevel - clipLow, bitspend_slope);
   2276 
   2277   return (bitspend);
   2278 }
   2279 
   2280 /*****************************************************************************
   2281 
   2282   functionname: FDKaacEnc_adjustPeMinMax()
   2283   description:  adjusts peMin and peMax parameters over time
   2284   returns:
   2285   input:        current pe, peMin, peMax, bitres size
   2286   output:       adjusted peMin/peMax
   2287 
   2288 *****************************************************************************/
   2289 static void FDKaacEnc_adjustPeMinMax(const INT currPe, INT *peMin, INT *peMax) {
   2290   FIXP_DBL minFacHi = FL2FXCONST_DBL(0.3f), maxFacHi = (FIXP_DBL)MAXVAL_DBL,
   2291            minFacLo = FL2FXCONST_DBL(0.14f), maxFacLo = FL2FXCONST_DBL(0.07f);
   2292   INT diff;
   2293 
   2294   INT minDiff_fix = fMultI(FL2FXCONST_DBL(0.1666666667f), currPe);
   2295 
   2296   if (currPe > *peMax) {
   2297     diff = (currPe - *peMax);
   2298     *peMin += fMultI(minFacHi, diff);
   2299     *peMax += fMultI(maxFacHi, diff);
   2300   } else if (currPe < *peMin) {
   2301     diff = (*peMin - currPe);
   2302     *peMin -= fMultI(minFacLo, diff);
   2303     *peMax -= fMultI(maxFacLo, diff);
   2304   } else {
   2305     *peMin += fMultI(minFacHi, (currPe - *peMin));
   2306     *peMax -= fMultI(maxFacLo, (*peMax - currPe));
   2307   }
   2308 
   2309   if ((*peMax - *peMin) < minDiff_fix) {
   2310     INT peMax_fix = *peMax, peMin_fix = *peMin;
   2311     FIXP_DBL partLo_fix, partHi_fix;
   2312 
   2313     partLo_fix = (FIXP_DBL)fixMax(0, currPe - peMin_fix);
   2314     partHi_fix = (FIXP_DBL)fixMax(0, peMax_fix - currPe);
   2315 
   2316     peMax_fix =
   2317         (INT)(currPe + fMultI(fDivNorm(partHi_fix, (partLo_fix + partHi_fix)),
   2318                               minDiff_fix));
   2319     peMin_fix =
   2320         (INT)(currPe - fMultI(fDivNorm(partLo_fix, (partLo_fix + partHi_fix)),
   2321                               minDiff_fix));
   2322     peMin_fix = fixMax(0, peMin_fix);
   2323 
   2324     *peMax = peMax_fix;
   2325     *peMin = peMin_fix;
   2326   }
   2327 }
   2328 
   2329 /*****************************************************************************
   2330 
   2331   functionname: BitresCalcBitFac
   2332   description:  calculates factor of spending bits for one frame
   2333   1.0 : take all frame dynpart bits
   2334   >1.0 : take all frame dynpart bits + bitres
   2335   <1.0 : put bits in bitreservoir
   2336   returns:      BitFac
   2337   input:        bitres-fullness, pe, blockType, parameter-settings
   2338   output:
   2339 
   2340 *****************************************************************************/
   2341 /*
   2342                      bitfac(%)            pemax
   2343                    bitspend(%)   |          /-----------maxBitres
   2344                                  |         /
   2345                                  |        /
   2346                                  |       /
   2347                                  |      /
   2348                                  |     /
   2349                                  |----/-----------------> pe
   2350                                  |   /
   2351                    bitsave(%)    |--/
   2352                                     pemin
   2353 */
   2354 
   2355 void FDKaacEnc_bitresCalcBitFac(const INT bitresBits, const INT maxBitresBits,
   2356                                 const INT pe, const INT lastWindowSequence,
   2357                                 const INT avgBits, const FIXP_DBL maxBitFac,
   2358                                 const ADJ_THR_STATE *const AdjThr,
   2359                                 ATS_ELEMENT *const adjThrChan,
   2360                                 FIXP_DBL *const pBitresFac,
   2361                                 INT *const pBitresFac_e) {
   2362   const BRES_PARAM *bresParam;
   2363   INT pex;
   2364   FIXP_DBL fillLevel;
   2365   INT fillLevel_e = 0;
   2366 
   2367   FIXP_DBL bitresFac;
   2368   INT bitresFac_e;
   2369 
   2370   FIXP_DBL bitSave, bitSpend;
   2371   FIXP_DBL bitsave_slope, bitspend_slope;
   2372   FIXP_DBL fillLevel_fix = MAXVAL_DBL;
   2373 
   2374   FIXP_DBL slope = MAXVAL_DBL;
   2375 
   2376   if (lastWindowSequence != SHORT_WINDOW) {
   2377     bresParam = &(AdjThr->bresParamLong);
   2378     bitsave_slope = FL2FXCONST_DBL(0.466666666);
   2379     bitspend_slope = FL2FXCONST_DBL(0.666666666);
   2380   } else {
   2381     bresParam = &(AdjThr->bresParamShort);
   2382     bitsave_slope = (FIXP_DBL)0x2E8BA2E9;
   2383     bitspend_slope = (FIXP_DBL)0x7fffffff;
   2384   }
   2385 
   2386   // fillLevel = (float)(bitresBits+avgBits) / (float)(maxBitresBits + avgBits);
   2387   if (bitresBits < maxBitresBits) {
   2388     fillLevel_fix = fDivNorm(bitresBits, maxBitresBits);
   2389   }
   2390 
   2391   pex = fMax(pe, adjThrChan->peMin);
   2392   pex = fMin(pex, adjThrChan->peMax);
   2393 
   2394   bitSave = FDKaacEnc_calcBitSave(
   2395       fillLevel_fix, bresParam->clipSaveLow, bresParam->clipSaveHigh,
   2396       bresParam->minBitSave, bresParam->maxBitSave, bitsave_slope);
   2397 
   2398   bitSpend = FDKaacEnc_calcBitSpend(
   2399       fillLevel_fix, bresParam->clipSpendLow, bresParam->clipSpendHigh,
   2400       bresParam->minBitSpend, bresParam->maxBitSpend, bitspend_slope);
   2401 
   2402   slope = schur_div((pex - adjThrChan->peMin),
   2403                     (adjThrChan->peMax - adjThrChan->peMin), 31);
   2404 
   2405   /* scale down by 1 bit because the result of the following addition can be
   2406    * bigger than 1 (though smaller than 2) */
   2407   bitresFac = ((FIXP_DBL)(MAXVAL_DBL >> 1) - (bitSave >> 1));
   2408   bitresFac_e = 1;                                                /* exp=1 */
   2409   bitresFac = fMultAddDiv2(bitresFac, slope, bitSpend + bitSave); /* exp=1 */
   2410 
   2411   /*** limit bitresFac for small bitreservoir ***/
   2412   fillLevel = fDivNorm(bitresBits, avgBits, &fillLevel_e);
   2413   if (fillLevel_e < 0) {
   2414     fillLevel = scaleValue(fillLevel, fillLevel_e);
   2415     fillLevel_e = 0;
   2416   }
   2417   /* shift down value by 1 because of summation, ... */
   2418   fillLevel >>= 1;
   2419   fillLevel_e += 1;
   2420   /* ..., this summation: */
   2421   fillLevel += scaleValue(FL2FXCONST_DBL(0.7f), -fillLevel_e);
   2422   /* set bitresfactor to same exponent as fillLevel */
   2423   if (scaleValue(bitresFac, -fillLevel_e + 1) > fillLevel) {
   2424     bitresFac = fillLevel;
   2425     bitresFac_e = fillLevel_e;
   2426   }
   2427 
   2428   /* limit bitresFac for high bitrates */
   2429   if (scaleValue(bitresFac, bitresFac_e - (DFRACT_BITS - 1 - 24)) > maxBitFac) {
   2430     bitresFac = maxBitFac;
   2431     bitresFac_e = (DFRACT_BITS - 1 - 24);
   2432   }
   2433 
   2434   FDKaacEnc_adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax);
   2435 
   2436   /* output values */
   2437   *pBitresFac = bitresFac;
   2438   *pBitresFac_e = bitresFac_e;
   2439 }
   2440 
   2441 /*****************************************************************************
   2442 functionname: FDKaacEnc_AdjThrNew
   2443 description:  allocate ADJ_THR_STATE
   2444 *****************************************************************************/
   2445 INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE **phAdjThr, INT nElements) {
   2446   INT err = 0;
   2447   INT i;
   2448   ADJ_THR_STATE *hAdjThr = GetRam_aacEnc_AdjustThreshold();
   2449   if (hAdjThr == NULL) {
   2450     err = 1;
   2451     goto bail;
   2452   }
   2453 
   2454   for (i = 0; i < nElements; i++) {
   2455     hAdjThr->adjThrStateElem[i] = GetRam_aacEnc_AdjThrStateElement(i);
   2456     if (hAdjThr->adjThrStateElem[i] == NULL) {
   2457       err = 1;
   2458       goto bail;
   2459     }
   2460   }
   2461 
   2462 bail:
   2463   *phAdjThr = hAdjThr;
   2464   return err;
   2465 }
   2466 
   2467 /*****************************************************************************
   2468 functionname: FDKaacEnc_AdjThrInit
   2469 description:  initialize ADJ_THR_STATE
   2470 *****************************************************************************/
   2471 void FDKaacEnc_AdjThrInit(
   2472     ADJ_THR_STATE *const hAdjThr, const INT meanPe, const INT invQuant,
   2473     const CHANNEL_MAPPING *const channelMapping, const INT sampleRate,
   2474     const INT totalBitrate, const INT isLowDelay,
   2475     const AACENC_BITRES_MODE bitResMode, const INT dZoneQuantEnable,
   2476     const INT bitDistributionMode, const FIXP_DBL vbrQualFactor) {
   2477   INT i;
   2478 
   2479   FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f);
   2480   FIXP_DBL POINT6 = FL2FXCONST_DBL(0.6f);
   2481 
   2482   if (bitDistributionMode == 1) {
   2483     hAdjThr->bitDistributionMode = AACENC_BD_MODE_INTRA_ELEMENT;
   2484   } else {
   2485     hAdjThr->bitDistributionMode = AACENC_BD_MODE_INTER_ELEMENT;
   2486   }
   2487 
   2488   /* Max number of iterations in second guess is 3 for lowdelay aot and for
   2489      configurations with multiple audio elements in general, otherwise iteration
   2490      value is always 1. */
   2491   hAdjThr->maxIter2ndGuess =
   2492       (isLowDelay != 0 || channelMapping->nElements > 1) ? 3 : 1;
   2493 
   2494   /* common for all elements: */
   2495   /* parameters for bitres control */
   2496   hAdjThr->bresParamLong.clipSaveLow =
   2497       (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
   2498   hAdjThr->bresParamLong.clipSaveHigh =
   2499       (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */
   2500   hAdjThr->bresParamLong.minBitSave =
   2501       (FIXP_DBL)0xf999999a; /* FL2FXCONST_DBL(-0.05f); */
   2502   hAdjThr->bresParamLong.maxBitSave =
   2503       (FIXP_DBL)0x26666666; /* FL2FXCONST_DBL(0.3f); */
   2504   hAdjThr->bresParamLong.clipSpendLow =
   2505       (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
   2506   hAdjThr->bresParamLong.clipSpendHigh =
   2507       (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */
   2508   hAdjThr->bresParamLong.minBitSpend =
   2509       (FIXP_DBL)0xf3333333; /* FL2FXCONST_DBL(-0.10f); */
   2510   hAdjThr->bresParamLong.maxBitSpend =
   2511       (FIXP_DBL)0x33333333; /* FL2FXCONST_DBL(0.4f); */
   2512 
   2513   hAdjThr->bresParamShort.clipSaveLow =
   2514       (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
   2515   hAdjThr->bresParamShort.clipSaveHigh =
   2516       (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */
   2517   hAdjThr->bresParamShort.minBitSave =
   2518       (FIXP_DBL)0x00000000; /* FL2FXCONST_DBL(0.0f); */
   2519   hAdjThr->bresParamShort.maxBitSave =
   2520       (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
   2521   hAdjThr->bresParamShort.clipSpendLow =
   2522       (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
   2523   hAdjThr->bresParamShort.clipSpendHigh =
   2524       (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */
   2525   hAdjThr->bresParamShort.minBitSpend =
   2526       (FIXP_DBL)0xf9999998; /* FL2FXCONST_DBL(-0.05f); */
   2527   hAdjThr->bresParamShort.maxBitSpend =
   2528       (FIXP_DBL)0x40000000; /* FL2FXCONST_DBL(0.5f); */
   2529 
   2530   /* specific for each element: */
   2531   for (i = 0; i < channelMapping->nElements; i++) {
   2532     const FIXP_DBL relativeBits = channelMapping->elInfo[i].relativeBits;
   2533     const INT nChannelsInElement = channelMapping->elInfo[i].nChannelsInEl;
   2534     const INT bitrateInElement =
   2535         (relativeBits != (FIXP_DBL)MAXVAL_DBL)
   2536             ? (INT)fMultNorm(relativeBits, (FIXP_DBL)totalBitrate)
   2537             : totalBitrate;
   2538     const INT chBitrate = bitrateInElement >> (nChannelsInElement == 1 ? 0 : 1);
   2539 
   2540     ATS_ELEMENT *atsElem = hAdjThr->adjThrStateElem[i];
   2541     MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam;
   2542 
   2543     /* parameters for bitres control */
   2544     if (isLowDelay) {
   2545       atsElem->peMin = fMultI(POINT8, meanPe);
   2546       atsElem->peMax = fMultI(POINT6, meanPe) << 1;
   2547     } else {
   2548       atsElem->peMin = fMultI(POINT8, meanPe) >> 1;
   2549       atsElem->peMax = fMultI(POINT6, meanPe);
   2550     }
   2551 
   2552     /* for use in FDKaacEnc_reduceThresholdsVBR */
   2553     atsElem->chaosMeasureOld = FL2FXCONST_DBL(0.3f);
   2554 
   2555     /* additional pe offset to correct pe2bits for low bitrates */
   2556     /* ---- no longer necessary, set by table ----- */
   2557     atsElem->peOffset = 0;
   2558 
   2559     /* vbr initialisation */
   2560     atsElem->vbrQualFactor = vbrQualFactor;
   2561     if (chBitrate < 32000) {
   2562       atsElem->peOffset =
   2563           fixMax(50, 100 - fMultI((FIXP_DBL)0x666667, chBitrate));
   2564     }
   2565 
   2566     /* avoid hole parameters */
   2567     if (chBitrate >= 20000) {
   2568       atsElem->ahParam.modifyMinSnr = TRUE;
   2569       atsElem->ahParam.startSfbL = 15;
   2570       atsElem->ahParam.startSfbS = 3;
   2571     } else {
   2572       atsElem->ahParam.modifyMinSnr = FALSE;
   2573       atsElem->ahParam.startSfbL = 0;
   2574       atsElem->ahParam.startSfbS = 0;
   2575     }
   2576 
   2577     /* minSnr adaptation */
   2578     msaParam->maxRed = FL2FXCONST_DBL(0.00390625f); /* 0.25f/64.0f */
   2579     /* start adaptation of minSnr for avgEn/sfbEn > startRatio */
   2580     msaParam->startRatio = FL2FXCONST_DBL(0.05190512648f); /* ld64(10.0f) */
   2581     /* maximum minSnr reduction to minSnr^maxRed is reached for
   2582        avgEn/sfbEn >= maxRatio */
   2583     /* msaParam->maxRatio = 1000.0f; */
   2584     /*msaParam->redRatioFac = ((float)1.0f - msaParam->maxRed) /
   2585      * ((float)10.0f*log10(msaParam->startRatio/msaParam->maxRatio)/log10(2.0f)*(float)0.3010299956f);*/
   2586     msaParam->redRatioFac = FL2FXCONST_DBL(-0.375f); /* -0.0375f * 10.0f */
   2587     /*msaParam->redOffs = (float)1.0f - msaParam->redRatioFac * (float)10.0f *
   2588      * log10(msaParam->startRatio)/log10(2.0f) * (float)0.3010299956f;*/
   2589     msaParam->redOffs = FL2FXCONST_DBL(0.021484375); /* 1.375f/64.0f */
   2590 
   2591     /* init pe correction */
   2592     atsElem->peCorrectionFactor_m = FL2FXCONST_DBL(0.5f); /* 1.0 */
   2593     atsElem->peCorrectionFactor_e = 1;
   2594 
   2595     atsElem->dynBitsLast = -1;
   2596     atsElem->peLast = 0;
   2597 
   2598     /* init bits to pe factor */
   2599 
   2600     /* init bits2PeFactor */
   2601     FDKaacEnc_InitBits2PeFactor(
   2602         &atsElem->bits2PeFactor_m, &atsElem->bits2PeFactor_e, bitrateInElement,
   2603         nChannelsInElement, sampleRate, isLowDelay, dZoneQuantEnable, invQuant);
   2604 
   2605   } /* for nElements */
   2606 }
   2607 
   2608 /*****************************************************************************
   2609     functionname: FDKaacEnc_FDKaacEnc_calcPeCorrection
   2610     description:  calc desired pe
   2611 *****************************************************************************/
   2612 static void FDKaacEnc_FDKaacEnc_calcPeCorrection(
   2613     FIXP_DBL *const correctionFac_m, INT *const correctionFac_e,
   2614     const INT peAct, const INT peLast, const INT bitsLast,
   2615     const FIXP_DBL bits2PeFactor_m, const INT bits2PeFactor_e) {
   2616   if ((bitsLast > 0) && (peAct < 1.5f * peLast) && (peAct > 0.7f * peLast) &&
   2617       (FDKaacEnc_bits2pe2(bitsLast,
   2618                           fMult(FL2FXCONST_DBL(1.2f / 2.f), bits2PeFactor_m),
   2619                           bits2PeFactor_e + 1) > peLast) &&
   2620       (FDKaacEnc_bits2pe2(bitsLast,
   2621                           fMult(FL2FXCONST_DBL(0.65f), bits2PeFactor_m),
   2622                           bits2PeFactor_e) < peLast)) {
   2623     FIXP_DBL corrFac = *correctionFac_m;
   2624 
   2625     int scaling = 0;
   2626     FIXP_DBL denum = (FIXP_DBL)FDKaacEnc_bits2pe2(bitsLast, bits2PeFactor_m,
   2627                                                   bits2PeFactor_e);
   2628     FIXP_DBL newFac = fDivNorm((FIXP_DBL)peLast, denum, &scaling);
   2629 
   2630     /* dead zone, newFac and corrFac are scaled by 0.5 */
   2631     if ((FIXP_DBL)peLast <= denum) { /* ratio <= 1.f */
   2632       newFac = fixMax(
   2633           scaleValue(fixMin(fMult(FL2FXCONST_DBL(1.1f / 2.f), newFac),
   2634                             scaleValue(FL2FXCONST_DBL(1.f / 2.f), -scaling)),
   2635                      scaling),
   2636           FL2FXCONST_DBL(0.85f / 2.f));
   2637     } else { /* ratio < 1.f */
   2638       newFac = fixMax(
   2639           fixMin(scaleValue(fMult(FL2FXCONST_DBL(0.9f / 2.f), newFac), scaling),
   2640                  FL2FXCONST_DBL(1.15f / 2.f)),
   2641           FL2FXCONST_DBL(1.f / 2.f));
   2642     }
   2643 
   2644     if (((newFac > FL2FXCONST_DBL(1.f / 2.f)) &&
   2645          (corrFac < FL2FXCONST_DBL(1.f / 2.f))) ||
   2646         ((newFac < FL2FXCONST_DBL(1.f / 2.f)) &&
   2647          (corrFac > FL2FXCONST_DBL(1.f / 2.f)))) {
   2648       corrFac = FL2FXCONST_DBL(1.f / 2.f);
   2649     }
   2650 
   2651     /* faster adaptation towards 1.0, slower in the other direction */
   2652     if ((corrFac < FL2FXCONST_DBL(1.f / 2.f) && newFac < corrFac) ||
   2653         (corrFac > FL2FXCONST_DBL(1.f / 2.f) && newFac > corrFac)) {
   2654       corrFac = fMult(FL2FXCONST_DBL(0.85f), corrFac) +
   2655                 fMult(FL2FXCONST_DBL(0.15f), newFac);
   2656     } else {
   2657       corrFac = fMult(FL2FXCONST_DBL(0.7f), corrFac) +
   2658                 fMult(FL2FXCONST_DBL(0.3f), newFac);
   2659     }
   2660 
   2661     corrFac = fixMax(fixMin(corrFac, FL2FXCONST_DBL(1.15f / 2.f)),
   2662                      FL2FXCONST_DBL(0.85 / 2.f));
   2663 
   2664     *correctionFac_m = corrFac;
   2665     *correctionFac_e = 1;
   2666   } else {
   2667     *correctionFac_m = FL2FXCONST_DBL(1.f / 2.f);
   2668     *correctionFac_e = 1;
   2669   }
   2670 }
   2671 
   2672 static void FDKaacEnc_calcPeCorrectionLowBitRes(
   2673     FIXP_DBL *const correctionFac_m, INT *const correctionFac_e,
   2674     const INT peLast, const INT bitsLast, const INT bitresLevel,
   2675     const INT nChannels, const FIXP_DBL bits2PeFactor_m,
   2676     const INT bits2PeFactor_e) {
   2677   /* tuning params */
   2678   const FIXP_DBL amp = FL2FXCONST_DBL(0.005);
   2679   const FIXP_DBL maxDiff = FL2FXCONST_DBL(0.25f);
   2680 
   2681   if (bitsLast > 0) {
   2682     /* Estimate deviation of granted and used dynamic bits in previous frame, in
   2683      * PE units */
   2684     const int bitsBalLast =
   2685         peLast - FDKaacEnc_bits2pe2(bitsLast, bits2PeFactor_m, bits2PeFactor_e);
   2686 
   2687     /* reserve n bits per channel */
   2688     int headroom = (bitresLevel >= 50 * nChannels) ? 0 : (100 * nChannels);
   2689 
   2690     /* in PE units */
   2691     headroom = FDKaacEnc_bits2pe2(headroom, bits2PeFactor_m, bits2PeFactor_e);
   2692 
   2693     /*
   2694      * diff = amp * ((bitsBalLast - headroom) / (bitresLevel + headroom)
   2695      * diff = max ( min ( diff, maxDiff, -maxDiff)) / 2
   2696      */
   2697     FIXP_DBL denominator = (FIXP_DBL)FDKaacEnc_bits2pe2(
   2698                                bitresLevel, bits2PeFactor_m, bits2PeFactor_e) +
   2699                            (FIXP_DBL)headroom;
   2700 
   2701     int scaling = 0;
   2702     FIXP_DBL diff =
   2703         (bitsBalLast >= headroom)
   2704             ? fMult(amp, fDivNorm((FIXP_DBL)(bitsBalLast - headroom),
   2705                                   denominator, &scaling))
   2706             : -fMult(amp, fDivNorm(-(FIXP_DBL)(bitsBalLast - headroom),
   2707                                    denominator, &scaling));
   2708 
   2709     scaling -= 1; /* divide by 2 */
   2710 
   2711     diff = (scaling <= 0)
   2712                ? fMax(fMin(diff >> (-scaling), maxDiff >> 1), -maxDiff >> 1)
   2713                : fMax(fMin(diff, maxDiff >> (1 + scaling)),
   2714                       -maxDiff >> (1 + scaling))
   2715                      << scaling;
   2716 
   2717     /*
   2718      * corrFac += diff
   2719      * corrFac = max ( min ( corrFac/2.f, 1.f/2.f, 0.75f/2.f ) )
   2720      */
   2721     *correctionFac_m =
   2722         fMax(fMin((*correctionFac_m) + diff, FL2FXCONST_DBL(1.0f / 2.f)),
   2723              FL2FXCONST_DBL(0.75f / 2.f));
   2724     *correctionFac_e = 1;
   2725   } else {
   2726     *correctionFac_m = FL2FXCONST_DBL(0.75 / 2.f);
   2727     *correctionFac_e = 1;
   2728   }
   2729 }
   2730 
   2731 void FDKaacEnc_DistributeBits(
   2732     ADJ_THR_STATE *adjThrState, ATS_ELEMENT *AdjThrStateElement,
   2733     PSY_OUT_CHANNEL *psyOutChannel[(2)], PE_DATA *peData, INT *grantedPe,
   2734     INT *grantedPeCorr, const INT nChannels, const INT commonWindow,
   2735     const INT grantedDynBits, const INT bitresBits, const INT maxBitresBits,
   2736     const FIXP_DBL maxBitFac, const AACENC_BITRES_MODE bitResMode) {
   2737   FIXP_DBL bitFactor;
   2738   INT bitFactor_e;
   2739   INT noRedPe = peData->pe;
   2740 
   2741   /* prefer short windows for calculation of bitFactor */
   2742   INT curWindowSequence = LONG_WINDOW;
   2743   if (nChannels == 2) {
   2744     if ((psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) ||
   2745         (psyOutChannel[1]->lastWindowSequence == SHORT_WINDOW)) {
   2746       curWindowSequence = SHORT_WINDOW;
   2747     }
   2748   } else {
   2749     curWindowSequence = psyOutChannel[0]->lastWindowSequence;
   2750   }
   2751 
   2752   if (grantedDynBits >= 1) {
   2753     if (bitResMode != AACENC_BR_MODE_FULL) {
   2754       /* small or disabled bitreservoir */
   2755       *grantedPe = FDKaacEnc_bits2pe2(grantedDynBits,
   2756                                       AdjThrStateElement->bits2PeFactor_m,
   2757                                       AdjThrStateElement->bits2PeFactor_e);
   2758     } else {
   2759       /* factor dependend on current fill level and pe */
   2760       FDKaacEnc_bitresCalcBitFac(
   2761           bitresBits, maxBitresBits, noRedPe, curWindowSequence, grantedDynBits,
   2762           maxBitFac, adjThrState, AdjThrStateElement, &bitFactor, &bitFactor_e);
   2763 
   2764       /* desired pe for actual frame */
   2765       /* Worst case max of grantedDynBits is = 1024 * 5.27 * 2 */
   2766       *grantedPe = FDKaacEnc_bits2pe2(
   2767           grantedDynBits, fMult(bitFactor, AdjThrStateElement->bits2PeFactor_m),
   2768           AdjThrStateElement->bits2PeFactor_e + bitFactor_e);
   2769     }
   2770   } else {
   2771     *grantedPe = 0; /* prevent divsion by 0 */
   2772   }
   2773 
   2774   /* correction of pe value */
   2775   switch (bitResMode) {
   2776     case AACENC_BR_MODE_DISABLED:
   2777     case AACENC_BR_MODE_REDUCED:
   2778       /* correction of pe value for low bitres */
   2779       FDKaacEnc_calcPeCorrectionLowBitRes(
   2780           &AdjThrStateElement->peCorrectionFactor_m,
   2781           &AdjThrStateElement->peCorrectionFactor_e, AdjThrStateElement->peLast,
   2782           AdjThrStateElement->dynBitsLast, bitresBits, nChannels,
   2783           AdjThrStateElement->bits2PeFactor_m,
   2784           AdjThrStateElement->bits2PeFactor_e);
   2785       break;
   2786     case AACENC_BR_MODE_FULL:
   2787     default:
   2788       /* correction of pe value for high bitres */
   2789       FDKaacEnc_FDKaacEnc_calcPeCorrection(
   2790           &AdjThrStateElement->peCorrectionFactor_m,
   2791           &AdjThrStateElement->peCorrectionFactor_e,
   2792           fixMin(*grantedPe, noRedPe), AdjThrStateElement->peLast,
   2793           AdjThrStateElement->dynBitsLast, AdjThrStateElement->bits2PeFactor_m,
   2794           AdjThrStateElement->bits2PeFactor_e);
   2795       break;
   2796   }
   2797 
   2798   *grantedPeCorr =
   2799       (INT)(fMult((FIXP_DBL)(*grantedPe << Q_AVGBITS),
   2800                   AdjThrStateElement->peCorrectionFactor_m) >>
   2801             (Q_AVGBITS - AdjThrStateElement->peCorrectionFactor_e));
   2802 
   2803   /* update last pe */
   2804   AdjThrStateElement->peLast = *grantedPe;
   2805   AdjThrStateElement->dynBitsLast = -1;
   2806 }
   2807 
   2808 /*****************************************************************************
   2809 functionname: FDKaacEnc_AdjustThresholds
   2810 description:  adjust thresholds
   2811 *****************************************************************************/
   2812 void FDKaacEnc_AdjustThresholds(
   2813     ADJ_THR_STATE *const hAdjThr, QC_OUT_ELEMENT *const qcElement[((8))],
   2814     QC_OUT *const qcOut, const PSY_OUT_ELEMENT *const psyOutElement[((8))],
   2815     const INT CBRbitrateMode, const CHANNEL_MAPPING *const cm) {
   2816   int i;
   2817 
   2818   if (CBRbitrateMode) {
   2819     /* In case, no bits must be shifted between different elements, */
   2820     /* an element-wise execution of the pe-dependent threshold- */
   2821     /* adaption becomes necessary... */
   2822     if (hAdjThr->bitDistributionMode == AACENC_BD_MODE_INTRA_ELEMENT) {
   2823       for (i = 0; i < cm->nElements; i++) {
   2824         ELEMENT_INFO elInfo = cm->elInfo[i];
   2825 
   2826         if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
   2827             (elInfo.elType == ID_LFE)) {
   2828           /* qcElement[i]->grantedPe = 2000; */ /* Use this only for debugging
   2829                                                  */
   2830           // if (totalGrantedPeCorr < totalNoRedPe) {
   2831           if (qcElement[i]->grantedPeCorr < qcElement[i]->peData.pe) {
   2832             /* calc threshold necessary for desired pe */
   2833             FDKaacEnc_adaptThresholdsToPe(
   2834                 cm, hAdjThr->adjThrStateElem, qcElement, psyOutElement,
   2835                 qcElement[i]->grantedPeCorr, hAdjThr->maxIter2ndGuess,
   2836                 1, /* Process only 1 element */
   2837                 i  /* Process exactly THIS element */
   2838             );
   2839           }
   2840         } /*  -end- if(ID_SCE || ID_CPE || ID_LFE) */
   2841       }   /* -end- element loop */
   2842     }     /* AACENC_BD_MODE_INTRA_ELEMENT */
   2843     else if (hAdjThr->bitDistributionMode == AACENC_BD_MODE_INTER_ELEMENT) {
   2844       /* Use global Pe to obtain the thresholds? */
   2845       if (qcOut->totalGrantedPeCorr < qcOut->totalNoRedPe) {
   2846         /* add equal loadness quantization noise to match the */
   2847         /* desired pe calc threshold necessary for desired pe */
   2848         /* Now carried out globally to cover all(!) channels. */
   2849         FDKaacEnc_adaptThresholdsToPe(cm, hAdjThr->adjThrStateElem, qcElement,
   2850                                       psyOutElement, qcOut->totalGrantedPeCorr,
   2851                                       hAdjThr->maxIter2ndGuess,
   2852                                       cm->nElements, /* Process all elements */
   2853                                       0); /* Process exactly THIS element */
   2854       } else {
   2855         /* In case global pe doesn't need to be reduced check each element to
   2856            hold estimated bitrate below maximum element bitrate. */
   2857         for (i = 0; i < cm->nElements; i++) {
   2858           if ((cm->elInfo[i].elType == ID_SCE) ||
   2859               (cm->elInfo[i].elType == ID_CPE) ||
   2860               (cm->elInfo[i].elType == ID_LFE)) {
   2861             /* Element pe applies to dynamic bits of maximum element bitrate. */
   2862             const int maxElementPe = FDKaacEnc_bits2pe2(
   2863                 (cm->elInfo[i].nChannelsInEl * MIN_BUFSIZE_PER_EFF_CHAN) -
   2864                     qcElement[i]->staticBitsUsed - qcElement[i]->extBitsUsed,
   2865                 hAdjThr->adjThrStateElem[i]->bits2PeFactor_m,
   2866                 hAdjThr->adjThrStateElem[i]->bits2PeFactor_e);
   2867 
   2868             if (maxElementPe < qcElement[i]->peData.pe) {
   2869               FDKaacEnc_adaptThresholdsToPe(
   2870                   cm, hAdjThr->adjThrStateElem, qcElement, psyOutElement,
   2871                   maxElementPe, hAdjThr->maxIter2ndGuess, 1, i);
   2872             }
   2873           } /*  -end- if(ID_SCE || ID_CPE || ID_LFE) */
   2874         }   /* -end- element loop */
   2875       }     /* (qcOut->totalGrantedPeCorr < qcOut->totalNoRedPe) */
   2876     }       /* AACENC_BD_MODE_INTER_ELEMENT */
   2877   } else {
   2878     for (i = 0; i < cm->nElements; i++) {
   2879       ELEMENT_INFO elInfo = cm->elInfo[i];
   2880 
   2881       if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
   2882           (elInfo.elType == ID_LFE)) {
   2883         /* for VBR-mode */
   2884         FDKaacEnc_AdaptThresholdsVBR(
   2885             qcElement[i]->qcOutChannel, psyOutElement[i]->psyOutChannel,
   2886             hAdjThr->adjThrStateElem[i], &psyOutElement[i]->toolsInfo,
   2887             cm->elInfo[i].nChannelsInEl);
   2888       } /*  -end- if(ID_SCE || ID_CPE || ID_LFE) */
   2889 
   2890     } /* -end- element loop */
   2891   }
   2892   for (i = 0; i < cm->nElements; i++) {
   2893     int ch, sfb, sfbGrp;
   2894     /* no weighting of threholds and energies for mlout */
   2895     /* weight energies and thresholds */
   2896     for (ch = 0; ch < cm->elInfo[i].nChannelsInEl; ch++) {
   2897       QC_OUT_CHANNEL *pQcOutCh = qcElement[i]->qcOutChannel[ch];
   2898       for (sfbGrp = 0; sfbGrp < psyOutElement[i]->psyOutChannel[ch]->sfbCnt;
   2899            sfbGrp += psyOutElement[i]->psyOutChannel[ch]->sfbPerGroup) {
   2900         for (sfb = 0; sfb < psyOutElement[i]->psyOutChannel[ch]->maxSfbPerGroup;
   2901              sfb++) {
   2902           pQcOutCh->sfbThresholdLdData[sfb + sfbGrp] +=
   2903               pQcOutCh->sfbEnFacLd[sfb + sfbGrp];
   2904         }
   2905       }
   2906     }
   2907   }
   2908 }
   2909 
   2910 void FDKaacEnc_AdjThrClose(ADJ_THR_STATE **phAdjThr) {
   2911   INT i;
   2912   ADJ_THR_STATE *hAdjThr = *phAdjThr;
   2913 
   2914   if (hAdjThr != NULL) {
   2915     for (i = 0; i < ((8)); i++) {
   2916       if (hAdjThr->adjThrStateElem[i] != NULL) {
   2917         FreeRam_aacEnc_AdjThrStateElement(&hAdjThr->adjThrStateElem[i]);
   2918       }
   2919     }
   2920     FreeRam_aacEnc_AdjustThreshold(phAdjThr);
   2921   }
   2922 }
   2923