Home | History | Annotate | Download | only in src
      1 
      2 /* -----------------------------------------------------------------------------------------------------------
      3 Software License for The Fraunhofer FDK AAC Codec Library for Android
      4 
      5  Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Frderung der angewandten Forschung e.V.
      6   All rights reserved.
      7 
      8  1.    INTRODUCTION
      9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
     10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
     11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
     12 
     13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
     14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
     15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
     16 of the MPEG specifications.
     17 
     18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
     19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
     20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
     21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
     22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
     23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
     24 
     25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
     26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
     27 applications information and documentation.
     28 
     29 2.    COPYRIGHT LICENSE
     30 
     31 Redistribution and use in source and binary forms, with or without modification, are permitted without
     32 payment of copyright license fees provided that you satisfy the following conditions:
     33 
     34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
     35 your modifications thereto in source code form.
     36 
     37 You must retain the complete text of this software license in the documentation and/or other materials
     38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
     39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
     40 modifications thereto to recipients of copies in binary form.
     41 
     42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
     43 prior written permission.
     44 
     45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
     46 software or your modifications thereto.
     47 
     48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
     49 and the date of any change. For modified versions of the FDK AAC Codec, the term
     50 "Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
     51 "Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
     52 
     53 3.    NO PATENT LICENSE
     54 
     55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
     56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
     57 respect to this software.
     58 
     59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
     60 by appropriate patent licenses.
     61 
     62 4.    DISCLAIMER
     63 
     64 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
     65 "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
     66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
     68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
     69 or business interruption, however caused and on any theory of liability, whether in contract, strict
     70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
     71 advised of the possibility of such damage.
     72 
     73 5.    CONTACT INFORMATION
     74 
     75 Fraunhofer Institute for Integrated Circuits IIS
     76 Attention: Audio and Multimedia Departments - FDK AAC LL
     77 Am Wolfsmantel 33
     78 91058 Erlangen, Germany
     79 
     80 www.iis.fraunhofer.de/amm
     81 amm-info (at) iis.fraunhofer.de
     82 ----------------------------------------------------------------------------------------------------------- */
     83 
     84 /******************************** MPEG Audio Encoder **************************
     85 
     86     Initial author:       M. Werner
     87     contents/description: Threshold compensation
     88 
     89 ******************************************************************************/
     90 
     91 #include "common_fix.h"
     92 
     93 #include "adj_thr_data.h"
     94 #include "adj_thr.h"
     95 #include "qc_data.h"
     96 #include "sf_estim.h"
     97 #include "aacEnc_ram.h"
     98 
     99 
    100 
    101 
    102 #define INV_INT_TAB_SIZE  (8)
    103 static const FIXP_DBL invInt[INV_INT_TAB_SIZE] =
    104 {
    105   0x7fffffff, 0x7fffffff, 0x40000000, 0x2aaaaaaa, 0x20000000, 0x19999999, 0x15555555, 0x12492492
    106 };
    107 
    108 
    109 #define INV_SQRT4_TAB_SIZE  (8)
    110 static const FIXP_DBL invSqrt4[INV_SQRT4_TAB_SIZE] =
    111 {
    112   0x7fffffff, 0x7fffffff, 0x6ba27e65, 0x61424bb5, 0x5a827999, 0x55994845, 0x51c8e33c, 0x4eb160d1
    113 };
    114 
    115 
    116 /*static const INT      invRedExp = 4;*/
    117 static const FIXP_DBL  SnrLdMin1 = (FIXP_DBL)0xfcad0ddf; /*FL2FXCONST_DBL(FDKlog(0.316)/FDKlog(2.0)/LD_DATA_SCALING);*/
    118 static const FIXP_DBL  SnrLdMin2 = (FIXP_DBL)0x0351e1a2; /*FL2FXCONST_DBL(FDKlog(3.16) /FDKlog(2.0)/LD_DATA_SCALING);*/
    119 static const FIXP_DBL  SnrLdFac  = (FIXP_DBL)0xff5b2c3e; /*FL2FXCONST_DBL(FDKlog(0.8)  /FDKlog(2.0)/LD_DATA_SCALING);*/
    120 
    121 static const FIXP_DBL  SnrLdMin3 = (FIXP_DBL)0xfe000000; /*FL2FXCONST_DBL(FDKlog(0.5)  /FDKlog(2.0)/LD_DATA_SCALING);*/
    122 static const FIXP_DBL  SnrLdMin4 = (FIXP_DBL)0x02000000; /*FL2FXCONST_DBL(FDKlog(2.0)  /FDKlog(2.0)/LD_DATA_SCALING);*/
    123 static const FIXP_DBL  SnrLdMin5 = (FIXP_DBL)0xfc000000; /*FL2FXCONST_DBL(FDKlog(0.25) /FDKlog(2.0)/LD_DATA_SCALING);*/
    124 
    125 
    126 /*
    127 The bits2Pe factors are choosen for the case that some times
    128 the crash recovery strategy will be activated once.
    129 */
    130 
    131 typedef struct {
    132   INT                 bitrate;
    133   ULONG               bits2PeFactor_mono;
    134   ULONG               bits2PeFactor_mono_slope;
    135   ULONG               bits2PeFactor_stereo;
    136   ULONG               bits2PeFactor_stereo_slope;
    137   ULONG               bits2PeFactor_mono_scfOpt;
    138   ULONG               bits2PeFactor_mono_scfOpt_slope;
    139   ULONG               bits2PeFactor_stereo_scfOpt;
    140   ULONG               bits2PeFactor_stereo_scfOpt_slope;
    141 
    142 } BIT_PE_SFAC;
    143 
    144 typedef struct {
    145   const INT           sampleRate;
    146   const BIT_PE_SFAC * pPeTab;
    147   const INT           nEntries;
    148 
    149 } BITS2PE_CFG_TAB;
    150 
    151 static const BIT_PE_SFAC S_Bits2PeTab16000[] = {
    152   { 10000, 0x228F5C29, 0x02FEF55D, 0x1D70A3D7, 0x09BC9D6D, 0x228F5C29, 0x02FEF55D, 0x1C28F5C3, 0x0CBB92CA},
    153   { 24000, 0x23D70A3D, 0x029F16B1, 0x2199999A, 0x07DD4413, 0x23D70A3D, 0x029F16B1, 0x2199999A, 0x07DD4413},
    154   { 32000, 0x247AE148, 0x11B1D92B, 0x23851EB8, 0x01F75105, 0x247AE148, 0x110A137F, 0x23851EB8, 0x01F75105},
    155   { 48000, 0x2D1EB852, 0x6833C600, 0x247AE148, 0x014F8B59, 0x2CCCCCCD, 0x68DB8BAC, 0x247AE148, 0x01F75105},
    156   { 64000, 0x25c28f40, 0x00000000, 0x251EB852, 0x01480000, 0x25c28f40, 0x00000000, 0x2570A3D7, 0x01480000},
    157   { 96000, 0x25c28f40, 0x00000000, 0x26000000, 0x01000000, 0x25c28f40, 0x00000000, 0x26000000, 0x01000000},
    158   {128000, 0x25c28f40, 0x00000000, 0x270a3d80, 0x01000000, 0x25c28f40, 0x00000000, 0x270a3d80, 0x01000000},
    159   {148000, 0x25c28f40, 0x00000000, 0x28000000, 0x00000000, 0x25c28f40, 0x00000000, 0x28000000, 0x00000000}
    160 };
    161 
    162 static const BIT_PE_SFAC S_Bits2PeTab22050[] = {
    163   { 16000, 0x1a8f5c29, 0x1797cc3a, 0x128f5c29, 0x18e75793, 0x175c28f6, 0x221426fe, 0x00000000, 0x5a708ede},
    164   { 24000, 0x2051eb85, 0x092ccf6c, 0x18a3d70a, 0x13a92a30, 0x1fae147b, 0xbcbe61d,  0x16147ae1, 0x18e75793},
    165   { 32000, 0x228f5c29, 0x029f16b1, 0x1d70a3d7, 0x088509c0, 0x228f5c29, 0x29f16b1,  0x1c28f5c3, 0x0b242071},
    166   { 48000, 0x23d70a3d, 0x014f8b59, 0x2199999a, 0x03eea20a, 0x23d70a3d, 0x14f8b59,  0x2199999a, 0x03eea20a},
    167   { 64000, 0x247ae148, 0x08d8ec96, 0x23851eb8, 0x00fba882, 0x247ae148, 0x88509c0,  0x23851eb8, 0x00fba882},
    168   { 96000, 0x2d1eb852, 0x3419e300, 0x247ae148, 0x00a7c5ac, 0x2ccccccd, 0x346dc5d6, 0x247ae148, 0x00fba882},
    169   {128000, 0x25c28f40, 0x00000000, 0x251eb852, 0x029f16b1, 0x60000000, 0x25c28f40, 0x2570a3d7, 0x009f16b1},
    170   {148000, 0x25c28f40, 0x00000000, 0x26b851ec, 0x00000000, 0x60000000, 0x25c28f40, 0x270a3d71, 0x00000000}
    171 };
    172 
    173 static const BIT_PE_SFAC S_Bits2PeTab24000[] = {
    174   { 16000, 0x19eb851f, 0x13a92a30, 0x1147ae14, 0x164840e1, 0x1999999a, 0x12599ed8, 0x00000000, 0x46c764ae},
    175   { 24000, 0x1eb851ec, 0x0d1b7176, 0x16b851ec, 0x18e75793, 0x1e147ae1, 0x0fba8827, 0x1147ae14, 0x2c9081c3},
    176   { 32000, 0x21eb851f, 0x049667b6, 0x1ccccccd, 0x07357e67, 0x21eb851f, 0x03eea20a, 0x1c28f5c3, 0x07357e67},
    177   { 48000, 0x2428f5c3, 0x014f8b59, 0x2051eb85, 0x053e2d62, 0x23d70a3d, 0x01f75105, 0x1fae147b, 0x07357e67},
    178   { 64000, 0x24cccccd, 0x05e5f30e, 0x22e147ae, 0x01a36e2f, 0x24cccccd, 0x05e5f30e, 0x23333333, 0x014f8b59},
    179   { 96000, 0x2a8f5c29, 0x24b33db0, 0x247ae148, 0x00fba882, 0x2a8f5c29, 0x26fe718b, 0x247ae148, 0x00fba882},
    180   {128000, 0x4e666666, 0x1cd5f99c, 0x2570a3d7, 0x010c6f7a, 0x50a3d70a, 0x192a7371, 0x2570a3d7, 0x010c6f7a},
    181   {148000, 0x25c28f40, 0x00000000, 0x26147ae1, 0x00000000, 0x25c28f40, 0x00000000, 0x26147ae1, 0x00000000}
    182 };
    183 
    184 static const BIT_PE_SFAC S_Bits2PeTab32000[] = {
    185   { 16000, 0x247ae140, 0xFFFFAC1E, 0x270a3d80, 0xFFFE9B7C, 0x14ccccc0, 0x000110A1, 0x15c28f60, 0xFFFEEF5F},
    186   { 24000, 0x23333340, 0x0fba8827, 0x21999980, 0x1b866e44, 0x18f5c280, 0x0fba8827, 0x119999a0, 0x4d551d69},
    187   { 32000, 0x1d70a3d7, 0x07357e67, 0x17ae147b, 0x09d49518, 0x1b851eb8, 0x0a7c5ac4, 0x12e147ae, 0x110a137f},
    188   { 48000, 0x20f5c28f, 0x049667b6, 0x1c7ae148, 0x053e2d62, 0x20a3d70a, 0x053e2d62, 0x1b333333, 0x05e5f30e},
    189   { 64000, 0x23333333, 0x029f16b1, 0x1f0a3d71, 0x02f2f987, 0x23333333, 0x029f16b1, 0x1e147ae1, 0x03eea20a},
    190   { 96000, 0x25c28f5c, 0x2c3c9eed, 0x21eb851f, 0x01f75105, 0x25c28f5c, 0x0a7c5ac4, 0x21eb851f, 0x01a36e2f},
    191   {128000, 0x50f5c28f, 0x18a43bb4, 0x23d70a3d, 0x010c6f7a, 0x30000000, 0x168b5cc0, 0x23851eb8, 0x0192a737},
    192   {148000, 0x25c28f40, 0x00000000, 0x247ae148, 0x00dfb23b, 0x3dc28f5c, 0x300f4aaf, 0x247ae148, 0x01bf6476},
    193   {160000, 0x25c28f40, 0xb15b5740, 0x24cccccd, 0x053e2d62, 0x4f5c28f6, 0xbefd0072, 0x251eb852, 0x04fb1184},
    194   {200000, 0x25c28f40, 0x00000000, 0x2b333333, 0x0836be91, 0x25c28f40, 0x00000000, 0x2b333333, 0x0890390f},
    195   {320000, 0x25c28f40, 0x00000000, 0x4947ae14, 0x00000000, 0x25c28f40, 0x00000000, 0x4a8f5c29, 0x00000000}
    196 };
    197 
    198 static const BIT_PE_SFAC S_Bits2PeTab44100[] = {
    199   { 16000, 0x10a3d70a, 0x1797cc3a, 0x00000000, 0x00000000, 0x00000000, 0x59210386, 0x00000000, 0x00000000},
    200   { 24000, 0x16666666, 0x1797cc3a, 0x00000000, 0x639d5e4a, 0x15c28f5c, 0x12599ed8, 0x00000000, 0x5bc01a37},
    201   { 32000, 0x1c28f5c3, 0x049667b6, 0x1851eb85, 0x049667b6, 0x1a3d70a4, 0x088509c0, 0x16666666, 0x053e2d62},
    202   { 48000, 0x1e666666, 0x05e5f30e, 0x1a8f5c29, 0x049667b6, 0x1e666666, 0x05e5f30e, 0x18f5c28f, 0x05e5f30e},
    203   { 64000, 0x2147ae14, 0x0346dc5d, 0x1ccccccd, 0x02f2f987, 0x2147ae14, 0x02f2f987, 0x1bd70a3d, 0x039abf34},
    204   { 96000, 0x247ae148, 0x068db8bb, 0x1fae147b, 0x029f16b1, 0x2428f5c3, 0x0639d5e5, 0x1f5c28f6, 0x029f16b1},
    205   {128000, 0x2ae147ae, 0x1b435265, 0x223d70a4, 0x0192a737, 0x2a3d70a4, 0x1040bfe4, 0x21eb851f, 0x0192a737},
    206   {148000, 0x3b851eb8, 0x2832069c, 0x23333333, 0x00dfb23b, 0x3428f5c3, 0x2054c288, 0x22e147ae, 0x00dfb23b},
    207   {160000, 0x4a3d70a4, 0xc32ebe5a, 0x23851eb8, 0x01d5c316, 0x40000000, 0xcb923a2b, 0x23333333, 0x01d5c316},
    208   {200000, 0x25c28f40, 0x00000000, 0x25c28f5c, 0x0713f078, 0x25c28f40, 0x00000000, 0x2570a3d7, 0x072a4f17},
    209   {320000, 0x25c28f40, 0x00000000, 0x3fae147b, 0x00000000, 0x25c28f40, 0x00000000, 0x3fae147b, 0x00000000}
    210 };
    211 
    212 static const BIT_PE_SFAC S_Bits2PeTab48000[] = {
    213   { 16000, 0x0f5c28f6, 0x31ceaf25, 0x00000000, 0x00000000, 0x00000000, 0x74a771c9, 0x00000000, 0x00000000},
    214   { 24000, 0x1b851eb8, 0x029f16b1, 0x00000000, 0x663c74fb, 0x1c7ae148, 0xe47991bd, 0x00000000, 0x49667b5f},
    215   { 32000, 0x1c28f5c3, 0x029f16b1, 0x18f5c28f, 0x07357e67, 0x15c28f5c, 0x0f12c27a, 0x11eb851f, 0x13016484},
    216   { 48000, 0x1d70a3d7, 0x053e2d62, 0x1c7ae148, 0xfe08aefc, 0x1d1eb852, 0x068db8bb, 0x1b333333, 0xfeb074a8},
    217   { 64000, 0x20000000, 0x03eea20a, 0x1b851eb8, 0x0346dc5d, 0x2051eb85, 0x0346dc5d, 0x1a8f5c29, 0x039abf34},
    218   { 96000, 0x23d70a3d, 0x053e2d62, 0x1eb851ec, 0x029f16b1, 0x23851eb8, 0x04ea4a8c, 0x1e147ae1, 0x02f2f987},
    219   {128000, 0x28f5c28f, 0x14727dcc, 0x2147ae14, 0x0218def4, 0x2851eb85, 0x0e27e0f0, 0x20f5c28f, 0x0218def4},
    220   {148000, 0x3570a3d7, 0x1cd5f99c, 0x228f5c29, 0x01bf6476, 0x30f5c28f, 0x18777e75, 0x223d70a4, 0x01bf6476},
    221   {160000, 0x40000000, 0xcb923a2b, 0x23333333, 0x0192a737, 0x39eb851f, 0xd08d4bae, 0x22e147ae, 0x0192a737},
    222   {200000, 0x25c28f40, 0x00000000, 0x251eb852, 0x06775a1b, 0x25c28f40, 0x00000000, 0x24cccccd, 0x06a4175a},
    223   {320000, 0x25c28f40, 0x00000000, 0x3ccccccd, 0x00000000, 0x25c28f40, 0x00000000, 0x3d1eb852, 0x00000000}
    224 };
    225 
    226 static const BITS2PE_CFG_TAB bits2PeConfigTab[] = {
    227   { 16000, S_Bits2PeTab16000, sizeof(S_Bits2PeTab16000)/sizeof(BIT_PE_SFAC) },
    228   { 22050, S_Bits2PeTab22050, sizeof(S_Bits2PeTab22050)/sizeof(BIT_PE_SFAC) },
    229   { 24000, S_Bits2PeTab24000, sizeof(S_Bits2PeTab24000)/sizeof(BIT_PE_SFAC) },
    230   { 32000, S_Bits2PeTab32000, sizeof(S_Bits2PeTab32000)/sizeof(BIT_PE_SFAC) },
    231   { 44100, S_Bits2PeTab44100, sizeof(S_Bits2PeTab44100)/sizeof(BIT_PE_SFAC) },
    232   { 48000, S_Bits2PeTab48000, sizeof(S_Bits2PeTab48000)/sizeof(BIT_PE_SFAC) }
    233 };
    234 
    235 
    236 
    237 /* values for avoid hole flag */
    238 enum _avoid_hole_state {
    239     NO_AH              =0,
    240     AH_INACTIVE        =1,
    241     AH_ACTIVE          =2
    242 };
    243 
    244 
    245 /*  Q format definitions */
    246 #define Q_BITFAC    (24)   /* Q scaling used in FDKaacEnc_bitresCalcBitFac() calculation */
    247 #define Q_AVGBITS   (17)   /* scale bit values */
    248 
    249 
    250 /*****************************************************************************
    251     functionname: FDKaacEnc_InitBits2PeFactor
    252     description:  retrieve bits2PeFactor from table
    253 *****************************************************************************/
    254 static void FDKaacEnc_InitBits2PeFactor(
    255         FIXP_DBL *bits2PeFactor_m,
    256         INT *bits2PeFactor_e,
    257         const INT bitRate,
    258         const INT nChannels,
    259         const INT sampleRate,
    260         const INT advancedBitsToPe,
    261         const INT dZoneQuantEnable,
    262         const INT invQuant
    263         )
    264 {
    265   /* default bits2pe factor */
    266   FIXP_DBL bit2PE_m = FL2FXCONST_DBL(1.18f/(1<<(1)));
    267   INT      bit2PE_e = 1;
    268 
    269   /* make use of advanced bits to pe factor table */
    270   if (advancedBitsToPe) {
    271 
    272     int i;
    273     const BIT_PE_SFAC *peTab = NULL;
    274     INT size = 0;
    275 
    276 
    277     /* Get correct table entry */
    278     for (i=0; i<(INT)(sizeof(bits2PeConfigTab)/sizeof(BITS2PE_CFG_TAB)); i++) {
    279       if (sampleRate >= bits2PeConfigTab[i].sampleRate) {
    280         peTab = bits2PeConfigTab[i].pPeTab;
    281         size  = bits2PeConfigTab[i].nEntries;
    282       }
    283     }
    284 
    285     if ( (peTab!=NULL) && (size!=0) ) {
    286 
    287       INT startB      = -1;
    288       LONG startPF    = 0;
    289       LONG peSlope    = 0;
    290 
    291       /* stereo or mono mode and invQuant used or not */
    292       for (i=0; i<size-1; i++)
    293       {
    294         if ((peTab[i].bitrate<=bitRate) && ((peTab[i+1].bitrate>bitRate) || ((i==size-2)) ))
    295         {
    296           if (nChannels==1)
    297           {
    298             startPF = (!invQuant) ? peTab[i].bits2PeFactor_mono   : peTab[i].bits2PeFactor_mono_scfOpt;
    299             peSlope = (!invQuant) ? peTab[i].bits2PeFactor_mono_slope : peTab[i].bits2PeFactor_mono_scfOpt_slope;
    300             /*endPF   = (!invQuant) ? peTab[i+1].bits2PeFactor_mono : peTab[i+1].bits2PeFactor_mono_scfOpt;
    301             endB=peTab[i+1].bitrate;*/
    302             startB=peTab[i].bitrate;
    303             break;
    304           }
    305           else
    306           {
    307             startPF = (!invQuant) ? peTab[i].bits2PeFactor_stereo   : peTab[i].bits2PeFactor_stereo_scfOpt;
    308             peSlope = (!invQuant) ? peTab[i].bits2PeFactor_stereo_slope : peTab[i].bits2PeFactor_stereo_scfOpt_slope;
    309             /*endPF   = (!invQuant) ? peTab[i+1].bits2PeFactor_stereo : peTab[i+1].bits2PeFactor_stereo_scfOpt;
    310             endB=peTab[i+1].bitrate;*/
    311             startB=peTab[i].bitrate;
    312             break;
    313           }
    314         }
    315       } /* for i */
    316 
    317       /* if a configuration is available */
    318       if (startB!=-1) {
    319         /* linear interpolate to actual PEfactor */
    320         FIXP_DBL peFac = fMult((FIXP_DBL)(bitRate-startB)<<14, (FIXP_DBL)peSlope) << 2;
    321         FIXP_DBL bit2PE = peFac + (FIXP_DBL)startPF; /* startPF_float = startPF << 2 */
    322 
    323         /* sanity check if bits2pe value is high enough */
    324         if ( bit2PE >= (FL2FXCONST_DBL(0.35f) >> 2) ) {
    325           bit2PE_m = bit2PE;
    326           bit2PE_e = 2; /*  table is fixed scaled */
    327         }
    328       } /* br */
    329     } /* sr */
    330   } /* advancedBitsToPe */
    331 
    332 
    333   if (dZoneQuantEnable)
    334   {
    335     if(bit2PE_m >= (FL2FXCONST_DBL(0.6f))>>bit2PE_e)
    336     {
    337       /* Additional headroom for addition */
    338       bit2PE_m >>= 1;
    339       bit2PE_e  += 1;
    340     }
    341 
    342     /* the quantTendencyCompensator compensates a lower bit consumption due to increasing the tendency to quantize low spectral values to the lower quantizer border for bitrates below a certain bitrate threshold --> see also function calcSfbDistLD in quantize.c */
    343     if ((bitRate/nChannels > 32000) && (bitRate/nChannels <= 40000)) {
    344       bit2PE_m += (FL2FXCONST_DBL(0.4f))>>bit2PE_e;
    345     }
    346     else if (bitRate/nChannels > 20000) {
    347       bit2PE_m += (FL2FXCONST_DBL(0.3f))>>bit2PE_e;
    348     }
    349     else if (bitRate/nChannels >= 16000) {
    350       bit2PE_m += (FL2FXCONST_DBL(0.3f))>>bit2PE_e;
    351     }
    352     else {
    353       bit2PE_m += (FL2FXCONST_DBL(0.0f))>>bit2PE_e;
    354     }
    355   }
    356 
    357 
    358   /***** 3.) Return bits2pe factor *****/
    359   *bits2PeFactor_m = bit2PE_m;
    360   *bits2PeFactor_e = bit2PE_e;
    361 }
    362 
    363 
    364 /*****************************************************************************
    365 functionname: FDKaacEnc_bits2pe2
    366 description:  convert from bits to pe
    367 *****************************************************************************/
    368 static INT FDKaacEnc_bits2pe2(
    369         const INT                 bits,
    370         const FIXP_DBL            factor_m,
    371         const INT                 factor_e
    372         )
    373 {
    374    return (INT)(fMult(factor_m, (FIXP_DBL)(bits<<Q_AVGBITS)) >> (Q_AVGBITS-factor_e));
    375 }
    376 
    377 /*****************************************************************************
    378 functionname: FDKaacEnc_calcThreshExp
    379 description:  loudness calculation (threshold to the power of redExp)
    380 *****************************************************************************/
    381 static void FDKaacEnc_calcThreshExp(FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB],
    382                           QC_OUT_CHANNEL*  qcOutChannel[(2)],
    383                           PSY_OUT_CHANNEL*  psyOutChannel[(2)],
    384                           const INT nChannels)
    385 {
    386    INT ch, sfb, sfbGrp;
    387    FIXP_DBL thrExpLdData;
    388 
    389    for (ch=0; ch<nChannels; ch++) {
    390      for(sfbGrp = 0;sfbGrp < psyOutChannel[ch]->sfbCnt;sfbGrp+= psyOutChannel[ch]->sfbPerGroup) {
    391        for (sfb=0; sfb<psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
    392          thrExpLdData = psyOutChannel[ch]->sfbThresholdLdData[sfbGrp+sfb]>>2 ;
    393          thrExp[ch][sfbGrp+sfb] = CalcInvLdData(thrExpLdData);
    394        }
    395      }
    396    }
    397 }
    398 
    399 
    400 /*****************************************************************************
    401     functionname: FDKaacEnc_adaptMinSnr
    402     description:  reduce minSnr requirements for bands with relative low energies
    403 *****************************************************************************/
    404 static void FDKaacEnc_adaptMinSnr(QC_OUT_CHANNEL     *qcOutChannel[(2)],
    405                                   PSY_OUT_CHANNEL    *psyOutChannel[(2)],
    406                                   MINSNR_ADAPT_PARAM *msaParam,
    407                                   const INT           nChannels)
    408 {
    409   INT ch, sfb, sfbGrp, nSfb;
    410   FIXP_DBL avgEnLD64, dbRatio, minSnrRed;
    411   FIXP_DBL minSnrLimitLD64 = FL2FXCONST_DBL(-0.00503012648262f); /* ld64(0.8f) */
    412   FIXP_DBL nSfbLD64;
    413   FIXP_DBL accu;
    414 
    415   for (ch=0; ch<nChannels; ch++) {
    416     /* calc average energy per scalefactor band */
    417     nSfb = 0;
    418     accu = FL2FXCONST_DBL(0.0f);
    419 
    420     for (sfbGrp=0; sfbGrp < psyOutChannel[ch]->sfbCnt; sfbGrp+=psyOutChannel[ch]->sfbPerGroup) {
    421       for (sfb=0; sfb<psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
    422         accu += psyOutChannel[ch]->sfbEnergy[sfbGrp+sfb]>>6;
    423 				 nSfb++;
    424 			 }
    425     }
    426 
    427     if ((accu == FL2FXCONST_DBL(0.0f)) || (nSfb == 0)) {
    428       avgEnLD64 = FL2FXCONST_DBL(-1.0f);
    429     }
    430     else {
    431       nSfbLD64  = CalcLdInt(nSfb);
    432       avgEnLD64 = CalcLdData(accu);
    433       avgEnLD64 = avgEnLD64 + FL2FXCONST_DBL(0.09375f) - nSfbLD64;  /* 0.09375f: compensate shift with 6 */
    434     }
    435 
    436     /* reduce minSnr requirement by minSnr^minSnrRed dependent on avgEn/sfbEn */
    437     for (sfbGrp=0; sfbGrp < psyOutChannel[ch]->sfbCnt; sfbGrp+=psyOutChannel[ch]->sfbPerGroup) {
    438       for (sfb=0; sfb<psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
    439         if ( (msaParam->startRatio + qcOutChannel[ch]->sfbEnergyLdData[sfbGrp+sfb]) < avgEnLD64 ) {
    440           dbRatio = fMult((avgEnLD64 - qcOutChannel[ch]->sfbEnergyLdData[sfbGrp+sfb]),FL2FXCONST_DBL(0.3010299956f)); /* scaled by (1.0f/(10.0f*64.0f)) */
    441           minSnrRed = msaParam->redOffs + fMult(msaParam->redRatioFac,dbRatio); /* scaled by 1.0f/64.0f*/
    442           minSnrRed = fixMax(minSnrRed, msaParam->maxRed); /* scaled by 1.0f/64.0f*/
    443           qcOutChannel[ch]->sfbMinSnrLdData[sfbGrp+sfb] = (fMult(qcOutChannel[ch]->sfbMinSnrLdData[sfbGrp+sfb],minSnrRed)) << 6;
    444           qcOutChannel[ch]->sfbMinSnrLdData[sfbGrp+sfb] = fixMin(minSnrLimitLD64, qcOutChannel[ch]->sfbMinSnrLdData[sfbGrp+sfb]);
    445         }
    446       }
    447     }
    448   }
    449 }
    450 
    451 
    452 /*****************************************************************************
    453 functionname: FDKaacEnc_initAvoidHoleFlag
    454 description:  determine bands where avoid hole is not necessary resp. possible
    455 *****************************************************************************/
    456 static void FDKaacEnc_initAvoidHoleFlag(QC_OUT_CHANNEL  *qcOutChannel[(2)],
    457                               PSY_OUT_CHANNEL *psyOutChannel[(2)],
    458                               UCHAR ahFlag[(2)][MAX_GROUPED_SFB],
    459                               struct TOOLSINFO *toolsInfo,
    460                               const INT nChannels,
    461                               const PE_DATA *peData,
    462                               AH_PARAM *ahParam)
    463 {
    464    INT ch, sfb, sfbGrp;
    465    FIXP_DBL sfbEn, sfbEnm1;
    466    FIXP_DBL sfbEnLdData;
    467    FIXP_DBL avgEnLdData;
    468 
    469    /* decrease spread energy by 3dB for long blocks, resp. 2dB for shorts
    470       (avoid more holes in long blocks) */
    471    for (ch=0; ch<nChannels; ch++) {
    472       INT sfbGrp, sfb;
    473       QC_OUT_CHANNEL*  qcOutChan  = qcOutChannel[ch];
    474 
    475       if (psyOutChannel[ch]->lastWindowSequence != SHORT_WINDOW) {
    476          for (sfbGrp = 0;sfbGrp < psyOutChannel[ch]->sfbCnt;sfbGrp+= psyOutChannel[ch]->sfbPerGroup)
    477            for (sfb=0; sfb<psyOutChannel[ch]->maxSfbPerGroup; sfb++)
    478               qcOutChan->sfbSpreadEnergy[sfbGrp+sfb] >>= 1 ;
    479       }
    480       else {
    481          for (sfbGrp = 0;sfbGrp < psyOutChannel[ch]->sfbCnt;sfbGrp+= psyOutChannel[ch]->sfbPerGroup)
    482            for (sfb=0; sfb<psyOutChannel[ch]->maxSfbPerGroup; sfb++)
    483               qcOutChan->sfbSpreadEnergy[sfbGrp+sfb] =
    484                    fMult(FL2FXCONST_DBL(0.63f),
    485                          qcOutChan->sfbSpreadEnergy[sfbGrp+sfb]) ;
    486       }
    487    }
    488 
    489    /* increase minSnr for local peaks, decrease it for valleys */
    490    if (ahParam->modifyMinSnr) {
    491       for(ch=0; ch<nChannels; ch++) {
    492          QC_OUT_CHANNEL*  qcOutChan  = qcOutChannel[ch];
    493          for(sfbGrp = 0;sfbGrp < psyOutChannel[ch]->sfbCnt;sfbGrp+= psyOutChannel[ch]->sfbPerGroup){
    494             for (sfb=0; sfb<psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
    495                FIXP_DBL sfbEnp1, avgEn;
    496                if (sfb > 0)
    497                   sfbEnm1 = qcOutChan->sfbEnergy[sfbGrp+sfb-1];
    498                else
    499                   sfbEnm1 = qcOutChan->sfbEnergy[sfbGrp+sfb];
    500 
    501                if (sfb < psyOutChannel[ch]->maxSfbPerGroup-1)
    502                   sfbEnp1 = qcOutChan->sfbEnergy[sfbGrp+sfb+1];
    503                else
    504                   sfbEnp1 = qcOutChan->sfbEnergy[sfbGrp+sfb];
    505 
    506                avgEn = (sfbEnm1>>1) + (sfbEnp1>>1);
    507                avgEnLdData = CalcLdData(avgEn);
    508                sfbEn = qcOutChan->sfbEnergy[sfbGrp+sfb];
    509                sfbEnLdData = qcOutChan->sfbEnergyLdData[sfbGrp+sfb];
    510                /* peak ? */
    511                if (sfbEn > avgEn) {
    512                   FIXP_DBL tmpMinSnrLdData;
    513                   if (psyOutChannel[ch]->lastWindowSequence==LONG_WINDOW)
    514                      tmpMinSnrLdData = fixMax( SnrLdFac + (FIXP_DBL)(avgEnLdData - sfbEnLdData), (FIXP_DBL)SnrLdMin1 ) ;
    515                   else
    516                      tmpMinSnrLdData = fixMax( SnrLdFac + (FIXP_DBL)(avgEnLdData - sfbEnLdData), (FIXP_DBL)SnrLdMin3 ) ;
    517 
    518                   qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] =
    519                      fixMin(qcOutChan->sfbMinSnrLdData[sfbGrp+sfb], tmpMinSnrLdData);
    520                }
    521                /* valley ? */
    522                if ( ((sfbEnLdData+(FIXP_DBL)SnrLdMin4) < (FIXP_DBL)avgEnLdData) && (sfbEn > FL2FXCONST_DBL(0.0)) ) {
    523                   FIXP_DBL tmpMinSnrLdData = avgEnLdData - sfbEnLdData -(FIXP_DBL)SnrLdMin4 + qcOutChan->sfbMinSnrLdData[sfbGrp+sfb];
    524                   tmpMinSnrLdData = fixMin((FIXP_DBL)SnrLdFac, tmpMinSnrLdData);
    525                   qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] = fixMin(tmpMinSnrLdData,
    526                         (FIXP_DBL)(qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] + SnrLdMin2 ));
    527                }
    528             }
    529          }
    530       }
    531    }
    532 
    533    /* stereo: adapt the minimum requirements sfbMinSnr of mid and
    534       side channels to avoid spending unnoticable bits */
    535    if (nChannels == 2) {
    536       QC_OUT_CHANNEL*  qcOutChanM  = qcOutChannel[0];
    537       QC_OUT_CHANNEL*  qcOutChanS  = qcOutChannel[1];
    538       PSY_OUT_CHANNEL*  psyOutChanM  = psyOutChannel[0];
    539       for(sfbGrp = 0;sfbGrp < psyOutChanM->sfbCnt;sfbGrp+= psyOutChanM->sfbPerGroup){
    540         for (sfb=0; sfb<psyOutChanM->maxSfbPerGroup; sfb++) {
    541           if (toolsInfo->msMask[sfbGrp+sfb]) {
    542              FIXP_DBL maxSfbEnLd = fixMax(qcOutChanM->sfbEnergyLdData[sfbGrp+sfb],qcOutChanS->sfbEnergyLdData[sfbGrp+sfb]);
    543              FIXP_DBL maxThrLd, sfbMinSnrTmpLd;
    544 
    545              if ( ((SnrLdMin5>>1) + (maxSfbEnLd>>1) + (qcOutChanM->sfbMinSnrLdData[sfbGrp+sfb]>>1)) <= FL2FXCONST_DBL(-0.5f))
    546                maxThrLd = FL2FXCONST_DBL(-1.0f) ;
    547              else
    548                maxThrLd = SnrLdMin5 + maxSfbEnLd + qcOutChanM->sfbMinSnrLdData[sfbGrp+sfb];
    549 
    550              if (qcOutChanM->sfbEnergy[sfbGrp+sfb] > FL2FXCONST_DBL(0.0f))
    551                sfbMinSnrTmpLd = maxThrLd - qcOutChanM->sfbEnergyLdData[sfbGrp+sfb];
    552              else
    553                sfbMinSnrTmpLd = FL2FXCONST_DBL(0.0f);
    554 
    555              qcOutChanM->sfbMinSnrLdData[sfbGrp+sfb] = fixMax(qcOutChanM->sfbMinSnrLdData[sfbGrp+sfb],sfbMinSnrTmpLd);
    556 
    557              if (qcOutChanM->sfbMinSnrLdData[sfbGrp+sfb] <= FL2FXCONST_DBL(0.0f))
    558                 qcOutChanM->sfbMinSnrLdData[sfbGrp+sfb] = fixMin(qcOutChanM->sfbMinSnrLdData[sfbGrp+sfb], (FIXP_DBL)SnrLdFac);
    559 
    560              if (qcOutChanS->sfbEnergy[sfbGrp+sfb] > FL2FXCONST_DBL(0.0f))
    561                sfbMinSnrTmpLd = maxThrLd - qcOutChanS->sfbEnergyLdData[sfbGrp+sfb];
    562              else
    563                sfbMinSnrTmpLd = FL2FXCONST_DBL(0.0f);
    564 
    565              qcOutChanS->sfbMinSnrLdData[sfbGrp+sfb] = fixMax(qcOutChanS->sfbMinSnrLdData[sfbGrp+sfb],sfbMinSnrTmpLd);
    566 
    567              if (qcOutChanS->sfbMinSnrLdData[sfbGrp+sfb] <= FL2FXCONST_DBL(0.0f))
    568                 qcOutChanS->sfbMinSnrLdData[sfbGrp+sfb] = fixMin(qcOutChanS->sfbMinSnrLdData[sfbGrp+sfb],(FIXP_DBL)SnrLdFac);
    569 
    570              if (qcOutChanM->sfbEnergy[sfbGrp+sfb]>qcOutChanM->sfbSpreadEnergy[sfbGrp+sfb])
    571                 qcOutChanS->sfbSpreadEnergy[sfbGrp+sfb] =
    572                    fMult(qcOutChanS->sfbEnergy[sfbGrp+sfb], FL2FXCONST_DBL(0.9f));
    573 
    574              if (qcOutChanS->sfbEnergy[sfbGrp+sfb]>qcOutChanS->sfbSpreadEnergy[sfbGrp+sfb])
    575                 qcOutChanM->sfbSpreadEnergy[sfbGrp+sfb] =
    576                    fMult(qcOutChanM->sfbEnergy[sfbGrp+sfb], FL2FXCONST_DBL(0.9f));
    577           }
    578         }
    579       }
    580    }
    581 
    582    /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
    583    for(ch=0; ch<nChannels; ch++) {
    584       QC_OUT_CHANNEL  *qcOutChan  = qcOutChannel[ch];
    585       PSY_OUT_CHANNEL  *psyOutChan  = psyOutChannel[ch];
    586       for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
    587         for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
    588           if ((qcOutChan->sfbSpreadEnergy[sfbGrp+sfb] > qcOutChan->sfbEnergy[sfbGrp+sfb])
    589               || (qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] > FL2FXCONST_DBL(0.0f))) {
    590              ahFlag[ch][sfbGrp+sfb] = NO_AH;
    591           }
    592           else {
    593              ahFlag[ch][sfbGrp+sfb] = AH_INACTIVE;
    594           }
    595         }
    596       }
    597    }
    598 }
    599 
    600 
    601 
    602 /**
    603  * \brief  Calculate constants that do not change during successive pe calculations.
    604  *
    605  * \param peData                Pointer to structure containing PE data of current element.
    606  * \param psyOutChannel         Pointer to PSY_OUT_CHANNEL struct holding nChannels elements.
    607  * \param qcOutChannel          Pointer to QC_OUT_CHANNEL struct holding nChannels elements.
    608  * \param nChannels             Number of channels in element.
    609  * \param peOffset              Fixed PE offset defined while FDKaacEnc_AdjThrInit() depending on bitrate.
    610  *
    611  * \return  void
    612  */
    613 static
    614 void FDKaacEnc_preparePe(PE_DATA *peData,
    615                PSY_OUT_CHANNEL* psyOutChannel[(2)],
    616                QC_OUT_CHANNEL* qcOutChannel[(2)],
    617                const INT nChannels,
    618                const INT peOffset)
    619 {
    620     INT ch;
    621 
    622     for(ch=0; ch<nChannels; ch++) {
    623         PSY_OUT_CHANNEL *psyOutChan = psyOutChannel[ch];
    624         FDKaacEnc_prepareSfbPe(&peData->peChannelData[ch],
    625             psyOutChan->sfbEnergyLdData,
    626             psyOutChan->sfbThresholdLdData,
    627             qcOutChannel[ch]->sfbFormFactorLdData,
    628             psyOutChan->sfbOffsets,
    629             psyOutChan->sfbCnt,
    630             psyOutChan->sfbPerGroup,
    631             psyOutChan->maxSfbPerGroup);
    632     }
    633     peData->offset = peOffset;
    634 }
    635 
    636 /**
    637  * \brief  Calculate weighting factor for threshold adjustment.
    638  *
    639  * Calculate weighting factor to be applied at energies and thresholds in ld64 format.
    640  *
    641  * \param peData,               Pointer to PE data in current element.
    642  * \param psyOutChannel         Pointer to PSY_OUT_CHANNEL struct holding nChannels elements.
    643  * \param qcOutChannel          Pointer to QC_OUT_CHANNEL struct holding nChannels elements.
    644  * \param toolsInfo             Pointer to tools info struct of current element.
    645  * \param adjThrStateElement    Pointer to ATS_ELEMENT holding enFacPatch states.
    646  * \param nChannels             Number of channels in element.
    647  * \param usePatchTool          Apply the weighting tool 0 (no) else (yes).
    648  *
    649  * \return  void
    650  */
    651 static
    652 void FDKaacEnc_calcWeighting(PE_DATA *peData,
    653                PSY_OUT_CHANNEL* psyOutChannel[(2)],
    654                QC_OUT_CHANNEL* qcOutChannel[(2)],
    655                struct TOOLSINFO *toolsInfo,
    656                ATS_ELEMENT* adjThrStateElement,
    657                const INT nChannels,
    658                const INT usePatchTool)
    659 {
    660     int ch, noShortWindowInFrame = TRUE;
    661     INT exePatchM = 0;
    662 
    663     for (ch=0; ch<nChannels; ch++) {
    664         if (psyOutChannel[ch]->lastWindowSequence == SHORT_WINDOW) {
    665             noShortWindowInFrame = FALSE;
    666         }
    667         FDKmemclear(qcOutChannel[ch]->sfbEnFacLd, MAX_GROUPED_SFB*sizeof(FIXP_DBL));
    668     }
    669 
    670     if (usePatchTool==0) {
    671         return; /* tool is disabled */
    672     }
    673 
    674     for (ch=0; ch<nChannels; ch++) {
    675 
    676         PSY_OUT_CHANNEL *psyOutChan = psyOutChannel[ch];
    677 
    678         if (noShortWindowInFrame) { /* retain energy ratio between blocks of different length */
    679 
    680             FIXP_DBL nrgSum14, nrgSum12, nrgSum34, nrgTotal;
    681             FIXP_DBL nrgFacLd_14, nrgFacLd_12, nrgFacLd_34;
    682             INT usePatch, exePatch;
    683             int sfb, sfbGrp, nLinesSum = 0;
    684 
    685             nrgSum14 = nrgSum12 = nrgSum34 = nrgTotal = FL2FXCONST_DBL(0.f);
    686 
    687             /* calculate flatness of audible spectrum, i.e. spectrum above masking threshold. */
    688             for (sfbGrp = 0;sfbGrp < psyOutChannel[ch]->sfbCnt; sfbGrp+=psyOutChannel[ch]->sfbPerGroup) {
    689               for (sfb=0; sfb<psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
    690                 FIXP_DBL nrgFac12 = CalcInvLdData(psyOutChan->sfbEnergyLdData[sfbGrp+sfb]>>1); /* nrg^(1/2) */
    691                 FIXP_DBL nrgFac14 = CalcInvLdData(psyOutChan->sfbEnergyLdData[sfbGrp+sfb]>>2); /* nrg^(1/4) */
    692 
    693                 /* maximal number of bands is 64, results scaling factor 6 */
    694                 nLinesSum += peData->peChannelData[ch].sfbNLines[sfbGrp+sfb];             /* relevant lines */
    695                 nrgTotal  += ( psyOutChan->sfbEnergy[sfbGrp+sfb] >> 6 );                  /* sum up nrg */
    696                 nrgSum12  += ( nrgFac12 >> 6 );                                           /* sum up nrg^(2/4) */
    697                 nrgSum14  += ( nrgFac14 >> 6 );                                           /* sum up nrg^(1/4) */
    698                 nrgSum34  += ( fMult(nrgFac14, nrgFac12) >> 6 );                          /* sum up nrg^(3/4) */
    699               }
    700             }
    701 
    702             nrgTotal = CalcLdData(nrgTotal);                                              /* get ld64 of total nrg */
    703 
    704             nrgFacLd_14 = CalcLdData(nrgSum14) - nrgTotal;                                /* ld64(nrgSum14/nrgTotal) */
    705             nrgFacLd_12 = CalcLdData(nrgSum12) - nrgTotal;                                /* ld64(nrgSum12/nrgTotal) */
    706             nrgFacLd_34 = CalcLdData(nrgSum34) - nrgTotal;                                /* ld64(nrgSum34/nrgTotal) */
    707 
    708             adjThrStateElement->chaosMeasureEnFac[ch] = FDKmax( FL2FXCONST_DBL(0.1875f), fDivNorm(nLinesSum,psyOutChan->sfbOffsets[psyOutChan->sfbCnt]) );
    709 
    710             usePatch = (adjThrStateElement->chaosMeasureEnFac[ch] > FL2FXCONST_DBL(0.78125f));
    711             exePatch = ((usePatch) && (adjThrStateElement->lastEnFacPatch[ch]));
    712 
    713             for (sfbGrp = 0;sfbGrp < psyOutChannel[ch]->sfbCnt; sfbGrp+=psyOutChannel[ch]->sfbPerGroup) {
    714               for (sfb=0; sfb<psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
    715 
    716                 INT sfbExePatch;
    717 
    718                 /* for MS coupled SFBs, also execute patch in side channel if done in mid channel */
    719                 if ((ch == 1) && (toolsInfo->msMask[sfbGrp+sfb])) {
    720                     sfbExePatch = exePatchM;
    721                 }
    722                 else {
    723                     sfbExePatch = exePatch;
    724                 }
    725 
    726                 if ( (sfbExePatch) && (psyOutChan->sfbEnergy[sfbGrp+sfb]>FL2FXCONST_DBL(0.f)) )
    727                 {
    728                     /* execute patch based on spectral flatness calculated above */
    729                     if (adjThrStateElement->chaosMeasureEnFac[ch] > FL2FXCONST_DBL(0.8125f)) {
    730                         qcOutChannel[ch]->sfbEnFacLd[sfbGrp+sfb] = ( (nrgFacLd_14 + (psyOutChan->sfbEnergyLdData[sfbGrp+sfb]+(psyOutChan->sfbEnergyLdData[sfbGrp+sfb]>>1)))>>1 ); /* sfbEnergy^(3/4) */
    731                     }
    732                     else if (adjThrStateElement->chaosMeasureEnFac[ch] > FL2FXCONST_DBL(0.796875f)) {
    733                         qcOutChannel[ch]->sfbEnFacLd[sfbGrp+sfb] = ( (nrgFacLd_12 + psyOutChan->sfbEnergyLdData[sfbGrp+sfb])>>1 );          /* sfbEnergy^(2/4) */
    734                     }
    735                     else {
    736                         qcOutChannel[ch]->sfbEnFacLd[sfbGrp+sfb] = ( (nrgFacLd_34 + (psyOutChan->sfbEnergyLdData[sfbGrp+sfb]>>1))>>1 );     /* sfbEnergy^(1/4) */
    737                     }
    738                     qcOutChannel[ch]->sfbEnFacLd[sfbGrp+sfb] = fixMin(qcOutChannel[ch]->sfbEnFacLd[sfbGrp+sfb],(FIXP_DBL)0);
    739 
    740                 }
    741               }
    742             } /* sfb loop */
    743 
    744             adjThrStateElement->lastEnFacPatch[ch] = usePatch;
    745             exePatchM = exePatch;
    746         }
    747         else {
    748             /* !noShortWindowInFrame */
    749             adjThrStateElement->chaosMeasureEnFac[ch] = FL2FXCONST_DBL(0.75f);
    750             adjThrStateElement->lastEnFacPatch[ch] = TRUE; /* allow use of sfbEnFac patch in upcoming frame */
    751         }
    752 
    753     } /* ch loop */
    754 
    755 }
    756 
    757 
    758 
    759 
    760 /*****************************************************************************
    761 functionname: FDKaacEnc_calcPe
    762 description:  calculate pe for both channels
    763 *****************************************************************************/
    764 static
    765 void FDKaacEnc_calcPe(PSY_OUT_CHANNEL* psyOutChannel[(2)],
    766             QC_OUT_CHANNEL* qcOutChannel[(2)],
    767             PE_DATA *peData,
    768             const INT nChannels)
    769 {
    770    INT ch;
    771 
    772    peData->pe = peData->offset;
    773    peData->constPart = 0;
    774    peData->nActiveLines = 0;
    775    for(ch=0; ch<nChannels; ch++) {
    776       PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch];
    777       FDKaacEnc_calcSfbPe(&peData->peChannelData[ch],
    778                 qcOutChannel[ch]->sfbWeightedEnergyLdData,
    779                 qcOutChannel[ch]->sfbThresholdLdData,
    780                 psyOutChannel[ch]->sfbCnt,
    781                 psyOutChannel[ch]->sfbPerGroup,
    782                 psyOutChannel[ch]->maxSfbPerGroup,
    783                 psyOutChannel[ch]->isBook,
    784                 psyOutChannel[ch]->isScale);
    785 
    786       peData->pe += peChanData->pe;
    787       peData->constPart += peChanData->constPart;
    788       peData->nActiveLines += peChanData->nActiveLines;
    789    }
    790 }
    791 
    792 void FDKaacEnc_peCalculation(PE_DATA *peData,
    793                              PSY_OUT_CHANNEL* psyOutChannel[(2)],
    794                              QC_OUT_CHANNEL* qcOutChannel[(2)],
    795                              struct TOOLSINFO *toolsInfo,
    796                              ATS_ELEMENT* adjThrStateElement,
    797                              const INT nChannels)
    798 {
    799   /* constants that will not change during successive pe calculations */
    800   FDKaacEnc_preparePe(peData, psyOutChannel, qcOutChannel, nChannels, adjThrStateElement->peOffset);
    801 
    802   /* calculate weighting factor for threshold adjustment */
    803   FDKaacEnc_calcWeighting(peData, psyOutChannel, qcOutChannel, toolsInfo, adjThrStateElement, nChannels, 1);
    804 {
    805     /* no weighting of threholds and energies for mlout */
    806     /* weight energies and thresholds */
    807     int ch;
    808     for (ch=0; ch<nChannels; ch++) {
    809 
    810         int sfb, sfbGrp;
    811         QC_OUT_CHANNEL* pQcOutCh = qcOutChannel[ch];
    812 
    813         for (sfbGrp = 0;sfbGrp < psyOutChannel[ch]->sfbCnt; sfbGrp+=psyOutChannel[ch]->sfbPerGroup) {
    814           for (sfb=0; sfb<psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
    815             pQcOutCh->sfbWeightedEnergyLdData[sfb+sfbGrp] = pQcOutCh->sfbEnergyLdData[sfb+sfbGrp] - pQcOutCh->sfbEnFacLd[sfb+sfbGrp];
    816             pQcOutCh->sfbThresholdLdData[sfb+sfbGrp]     -= pQcOutCh->sfbEnFacLd[sfb+sfbGrp];
    817           }
    818         }
    819     }
    820 }
    821 
    822   /* pe without reduction */
    823   FDKaacEnc_calcPe(psyOutChannel, qcOutChannel, peData, nChannels);
    824 }
    825 
    826 
    827 
    828 /*****************************************************************************
    829 functionname: FDKaacEnc_FDKaacEnc_calcPeNoAH
    830 description:  sum the pe data only for bands where avoid hole is inactive
    831 *****************************************************************************/
    832 static void FDKaacEnc_FDKaacEnc_calcPeNoAH(INT *pe,
    833                        INT *constPart,
    834                        INT    *nActiveLines,
    835                        PE_DATA *peData,
    836                        UCHAR ahFlag[(2)][MAX_GROUPED_SFB],
    837                        PSY_OUT_CHANNEL* psyOutChannel[(2)],
    838                        const INT nChannels)
    839 {
    840     INT ch, sfb,sfbGrp;
    841 
    842     INT pe_tmp = peData->offset;
    843     INT constPart_tmp = 0;
    844     INT nActiveLines_tmp = 0;
    845     for(ch=0; ch<nChannels; ch++) {
    846         PE_CHANNEL_DATA *peChanData = &peData->peChannelData[ch];
    847         for(sfbGrp = 0;sfbGrp < psyOutChannel[ch]->sfbCnt;sfbGrp+= psyOutChannel[ch]->sfbPerGroup){
    848             for (sfb=0; sfb<psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
    849                 if(ahFlag[ch][sfbGrp+sfb] < AH_ACTIVE) {
    850                     pe_tmp += peChanData->sfbPe[sfbGrp+sfb];
    851                     constPart_tmp += peChanData->sfbConstPart[sfbGrp+sfb];
    852                     nActiveLines_tmp += peChanData->sfbNActiveLines[sfbGrp+sfb];
    853                 }
    854             }
    855         }
    856     }
    857     /* correct scaled pe and constPart values */
    858     *pe = pe_tmp >> PE_CONSTPART_SHIFT;
    859     *constPart = constPart_tmp >> PE_CONSTPART_SHIFT;
    860 
    861 	*nActiveLines = nActiveLines_tmp;
    862 }
    863 
    864 
    865 /*****************************************************************************
    866 functionname: FDKaacEnc_reduceThresholdsCBR
    867 description:  apply reduction formula
    868 *****************************************************************************/
    869 static const FIXP_DBL limitThrReducedLdData = (FIXP_DBL)0x00008000; /*FL2FXCONST_DBL(FDKpow(2.0,-LD_DATA_SCALING/4.0));*/
    870 
    871 static void FDKaacEnc_reduceThresholdsCBR(QC_OUT_CHANNEL*  qcOutChannel[(2)],
    872                                 PSY_OUT_CHANNEL* psyOutChannel[(2)],
    873                                 UCHAR ahFlag[(2)][MAX_GROUPED_SFB],
    874                                 FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB],
    875                                 const INT nChannels,
    876                                 const FIXP_DBL redVal,
    877                                 const SCHAR redValScaling)
    878 {
    879    INT ch, sfb, sfbGrp;
    880    FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData;
    881    FIXP_DBL sfbThrExp;
    882 
    883     for(ch=0; ch<nChannels; ch++) {
    884       QC_OUT_CHANNEL *qcOutChan = qcOutChannel[ch];
    885       for(sfbGrp = 0; sfbGrp < psyOutChannel[ch]->sfbCnt; sfbGrp+= psyOutChannel[ch]->sfbPerGroup){
    886         for (sfb=0; sfb<psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
    887          sfbEnLdData  = qcOutChan->sfbWeightedEnergyLdData[sfbGrp+sfb];
    888          sfbThrLdData = qcOutChan->sfbThresholdLdData[sfbGrp+sfb];
    889          sfbThrExp    = thrExp[ch][sfbGrp+sfb];
    890          if ((sfbEnLdData > sfbThrLdData) && (ahFlag[ch][sfbGrp+sfb] != AH_ACTIVE)) {
    891 
    892             /* threshold reduction formula:
    893              float tmp = thrExp[ch][sfb]+redVal;
    894              tmp *= tmp;
    895              sfbThrReduced = tmp*tmp;
    896             */
    897             int minScale = fixMin(CountLeadingBits(sfbThrExp), CountLeadingBits(redVal) - (DFRACT_BITS-1-redValScaling) )-1;
    898 
    899             /* 4*log( sfbThrExp + redVal ) */
    900             sfbThrReducedLdData = CalcLdData(fAbs(scaleValue(sfbThrExp, minScale) + scaleValue(redVal,(DFRACT_BITS-1-redValScaling)+minScale)))
    901                                              - (FIXP_DBL)(minScale<<(DFRACT_BITS-1-LD_DATA_SHIFT));
    902             sfbThrReducedLdData <<= 2;
    903 
    904             /* avoid holes */
    905             if ( ((sfbThrReducedLdData - sfbEnLdData) > qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] )
    906                     && (ahFlag[ch][sfbGrp+sfb] != NO_AH) )
    907             {
    908               if (qcOutChan->sfbMinSnrLdData[sfbGrp+sfb]  > (FL2FXCONST_DBL(-1.0f) - sfbEnLdData) ){
    909                    sfbThrReducedLdData = fixMax((qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] + sfbEnLdData), sfbThrLdData);
    910               }
    911               else sfbThrReducedLdData = sfbThrLdData;
    912               ahFlag[ch][sfbGrp+sfb] = AH_ACTIVE;
    913             }
    914 
    915             /* minimum of 29 dB Ratio for Thresholds */
    916             if ((sfbEnLdData+(FIXP_DBL)MAXVAL_DBL) > FL2FXCONST_DBL(9.6336206/LD_DATA_SCALING)){
    917                 sfbThrReducedLdData = fixMax(sfbThrReducedLdData, (sfbEnLdData - FL2FXCONST_DBL(9.6336206/LD_DATA_SCALING)));
    918             }
    919 
    920             qcOutChan->sfbThresholdLdData[sfbGrp+sfb] = sfbThrReducedLdData;
    921          }
    922         }
    923       }
    924    }
    925 }
    926 
    927 /* similar to prepareSfbPe1() */
    928 static FIXP_DBL FDKaacEnc_calcChaosMeasure(PSY_OUT_CHANNEL *psyOutChannel,
    929                                  const FIXP_DBL  *sfbFormFactorLdData)
    930 {
    931   #define SCALE_FORM_FAC     (4)    /* (SCALE_FORM_FAC+FORM_FAC_SHIFT) >= ld(FRAME_LENGTH)*/
    932   #define SCALE_NRGS         (8)
    933   #define SCALE_NLINES      (16)
    934   #define SCALE_NRGS_SQRT4   (2)    /* 0.25 * SCALE_NRGS */
    935   #define SCALE_NLINES_P34  (12)    /* 0.75 * SCALE_NLINES */
    936 
    937   INT   sfbGrp, sfb;
    938   FIXP_DBL chaosMeasure;
    939   INT frameNLines = 0;
    940   FIXP_DBL frameFormFactor = FL2FXCONST_DBL(0.f);
    941   FIXP_DBL frameEnergy = FL2FXCONST_DBL(0.f);
    942 
    943   for (sfbGrp=0; sfbGrp<psyOutChannel->sfbCnt; sfbGrp+=psyOutChannel->sfbPerGroup) {
    944     for (sfb=0; sfb<psyOutChannel->maxSfbPerGroup; sfb++){
    945       if (psyOutChannel->sfbEnergyLdData[sfbGrp+sfb] > psyOutChannel->sfbThresholdLdData[sfbGrp+sfb]) {
    946         frameFormFactor += (CalcInvLdData(sfbFormFactorLdData[sfbGrp+sfb])>>SCALE_FORM_FAC);
    947         frameNLines     += (psyOutChannel->sfbOffsets[sfbGrp+sfb+1] - psyOutChannel->sfbOffsets[sfbGrp+sfb]);
    948         frameEnergy     += (psyOutChannel->sfbEnergy[sfbGrp+sfb]>>SCALE_NRGS);
    949       }
    950     }
    951   }
    952 
    953   if(frameNLines > 0){
    954 
    955     /*  frameNActiveLines = frameFormFactor*2^FORM_FAC_SHIFT * ((frameEnergy *2^SCALE_NRGS)/frameNLines)^-0.25
    956         chaosMeasure      = frameNActiveLines / frameNLines */
    957     chaosMeasure =
    958            CalcInvLdData( (((CalcLdData(frameFormFactor)>>1) -
    959                             (CalcLdData(frameEnergy)>>(2+1))) -
    960                            (fMultDiv2(FL2FXCONST_DBL(0.75f),CalcLdData((FIXP_DBL)frameNLines<<(DFRACT_BITS-1-SCALE_NLINES))) -
    961                             (((FIXP_DBL)(SCALE_FORM_FAC-SCALE_NRGS_SQRT4+FORM_FAC_SHIFT-(SCALE_NLINES_P34))<<(DFRACT_BITS-1-LD_DATA_SHIFT))>>1))
    962                           )<<1 );
    963   } else {
    964 
    965     /* assuming total chaos, if no sfb is above thresholds */
    966     chaosMeasure = FL2FXCONST_DBL(1.f);
    967   }
    968 
    969   return chaosMeasure;
    970 }
    971 
    972 /* apply reduction formula for VBR-mode */
    973 static void FDKaacEnc_reduceThresholdsVBR(QC_OUT_CHANNEL* qcOutChannel[(2)],
    974                                 PSY_OUT_CHANNEL* psyOutChannel[(2)],
    975                                 UCHAR ahFlag[(2)][MAX_GROUPED_SFB],
    976                                 FIXP_DBL thrExp[(2)][MAX_GROUPED_SFB],
    977                                 const INT nChannels,
    978                                 const FIXP_DBL  vbrQualFactor,
    979                                 FIXP_DBL* chaosMeasureOld)
    980 {
    981   INT ch, sfbGrp, sfb;
    982   FIXP_DBL chGroupEnergy[TRANS_FAC][2];/*energy for each group and channel*/
    983   FIXP_DBL chChaosMeasure[2];
    984   FIXP_DBL frameEnergy = FL2FXCONST_DBL(1e-10f);
    985   FIXP_DBL chaosMeasure = FL2FXCONST_DBL(0.f);
    986   FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrExp;
    987   FIXP_DBL sfbThrReducedLdData;
    988   FIXP_DBL chaosMeasureAvg;
    989   INT groupCnt; /* loop counter */
    990   FIXP_DBL redVal[TRANS_FAC]; /* reduction values; in short-block case one redVal for each group */
    991   QC_OUT_CHANNEL  *qcOutChan  = NULL;
    992   PSY_OUT_CHANNEL  *psyOutChan  = NULL;
    993 
    994 #define SCALE_GROUP_ENERGY   (8)
    995 
    996 #define CONST_CHAOS_MEAS_AVG_FAC_0  (FL2FXCONST_DBL(0.25f))
    997 #define CONST_CHAOS_MEAS_AVG_FAC_1  (FL2FXCONST_DBL(1.f-0.25f))
    998 
    999 #define MIN_LDTHRESH                (FL2FXCONST_DBL(-0.515625f))
   1000 
   1001 
   1002   for(ch=0; ch<nChannels; ch++){
   1003     qcOutChan  = qcOutChannel[ch];
   1004     psyOutChan  = psyOutChannel[ch];
   1005 
   1006     /* adding up energy for each channel and each group separately */
   1007     FIXP_DBL chEnergy = FL2FXCONST_DBL(0.f);
   1008     groupCnt=0;
   1009 
   1010     for (sfbGrp=0; sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup, groupCnt++) {
   1011       chGroupEnergy[groupCnt][ch] = FL2FXCONST_DBL(0.f);
   1012       for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++){
   1013         chGroupEnergy[groupCnt][ch] += (psyOutChan->sfbEnergy[sfbGrp+sfb]>>SCALE_GROUP_ENERGY);
   1014       }
   1015       chEnergy += chGroupEnergy[groupCnt][ch];
   1016     }
   1017     frameEnergy += chEnergy;
   1018 
   1019     /* chaosMeasure */
   1020     if (psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) {
   1021       chChaosMeasure[ch] = FL2FXCONST_DBL(0.5f); /* assume a constant chaos measure of 0.5f for short blocks */
   1022     } else {
   1023       chChaosMeasure[ch] = FDKaacEnc_calcChaosMeasure(psyOutChannel[ch], qcOutChannel[ch]->sfbFormFactorLdData);
   1024     }
   1025     chaosMeasure += fMult(chChaosMeasure[ch], chEnergy);
   1026   }
   1027 
   1028   if(frameEnergy > chaosMeasure) {
   1029     INT scale = CntLeadingZeros(frameEnergy) - 1;
   1030     FIXP_DBL num   = chaosMeasure<<scale;
   1031     FIXP_DBL denum = frameEnergy<<scale;
   1032     chaosMeasure   = schur_div(num,denum,16);
   1033   }
   1034   else {
   1035     chaosMeasure = FL2FXCONST_DBL(1.f);
   1036   }
   1037 
   1038   chaosMeasureAvg = fMult(CONST_CHAOS_MEAS_AVG_FAC_0, chaosMeasure) +
   1039                     fMult(CONST_CHAOS_MEAS_AVG_FAC_1, *chaosMeasureOld);      /* averaging chaos measure */
   1040   *chaosMeasureOld = chaosMeasure = (fixMin(chaosMeasure, chaosMeasureAvg));  /* use min-value, safe for next frame */
   1041 
   1042   /* characteristic curve
   1043      chaosMeasure = 0.2f + 0.7f/0.3f * (chaosMeasure - 0.2f);
   1044      chaosMeasure = fixMin(1.0f, fixMax(0.1f, chaosMeasure));
   1045      constants scaled by 4.f
   1046   */
   1047   chaosMeasure = ((FL2FXCONST_DBL(0.2f)>>2) + fMult(FL2FXCONST_DBL(0.7f/(4.f*0.3f)), (chaosMeasure - FL2FXCONST_DBL(0.2f))));
   1048   chaosMeasure = (fixMin((FIXP_DBL)(FL2FXCONST_DBL(1.0f)>>2), fixMax((FIXP_DBL)(FL2FXCONST_DBL(0.1f)>>2), chaosMeasure)))<<2;
   1049 
   1050   /* calculation of reduction value */
   1051   if (psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW){ /* short-blocks */
   1052     FDK_ASSERT(TRANS_FAC==8);
   1053     #define   WIN_TYPE_SCALE   (3)
   1054 
   1055     INT sfbGrp, groupCnt=0;
   1056     for (sfbGrp=0; sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup,groupCnt++) {
   1057 
   1058       FIXP_DBL groupEnergy = FL2FXCONST_DBL(0.f);
   1059 
   1060       for(ch=0;ch<nChannels;ch++){
   1061         groupEnergy += chGroupEnergy[groupCnt][ch];   /* adding up the channels groupEnergy */
   1062       }
   1063 
   1064       FDK_ASSERT(psyOutChannel[0]->groupLen[groupCnt]<=INV_INT_TAB_SIZE);
   1065       groupEnergy = fMult(groupEnergy,invInt[psyOutChannel[0]->groupLen[groupCnt]]);  /* correction of group energy */
   1066       groupEnergy = fixMin(groupEnergy, frameEnergy>>WIN_TYPE_SCALE);                 /* do not allow an higher redVal as calculated framewise */
   1067 
   1068       groupEnergy>>=2; /* 2*WIN_TYPE_SCALE = 6 => 6+2 = 8 ==> 8/4 = int number */
   1069 
   1070       redVal[groupCnt] = fMult(fMult(vbrQualFactor,chaosMeasure),
   1071                                CalcInvLdData(CalcLdData(groupEnergy)>>2) )
   1072                          << (int)( ( 2 + (2*WIN_TYPE_SCALE) + SCALE_GROUP_ENERGY )>>2 ) ;
   1073 
   1074     }
   1075   } else { /* long-block */
   1076 
   1077     redVal[0] = fMult( fMult(vbrQualFactor,chaosMeasure),
   1078                        CalcInvLdData(CalcLdData(frameEnergy)>>2) )
   1079                 << (int)( SCALE_GROUP_ENERGY>>2 ) ;
   1080   }
   1081 
   1082   for(ch=0; ch<nChannels; ch++) {
   1083     qcOutChan  = qcOutChannel[ch];
   1084     psyOutChan  = psyOutChannel[ch];
   1085 
   1086     for (sfbGrp=0; sfbGrp<psyOutChan->sfbCnt; sfbGrp+=psyOutChan->sfbPerGroup) {
   1087       for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++){
   1088 
   1089         sfbEnLdData  = (qcOutChan->sfbWeightedEnergyLdData[sfbGrp+sfb]);
   1090         sfbThrLdData = (qcOutChan->sfbThresholdLdData[sfbGrp+sfb]);
   1091         sfbThrExp    = thrExp[ch][sfbGrp+sfb];
   1092 
   1093         if ( (sfbThrLdData>=MIN_LDTHRESH) && (sfbEnLdData > sfbThrLdData) && (ahFlag[ch][sfbGrp+sfb] != AH_ACTIVE)) {
   1094 
   1095           /* Short-Window */
   1096           if (psyOutChannel[ch]->lastWindowSequence == SHORT_WINDOW) {
   1097             const int groupNumber = (int) sfb/psyOutChan->sfbPerGroup;
   1098 
   1099             FDK_ASSERT(INV_SQRT4_TAB_SIZE>psyOutChan->groupLen[groupNumber]);
   1100 
   1101             sfbThrExp = fMult(sfbThrExp, fMult( FL2FXCONST_DBL(2.82f/4.f), invSqrt4[psyOutChan->groupLen[groupNumber]]))<<2 ;
   1102 
   1103             if ( sfbThrExp <= (limitThrReducedLdData-redVal[groupNumber]) ) {
   1104                 sfbThrReducedLdData = FL2FXCONST_DBL(-1.0f);
   1105             }
   1106             else {
   1107                 if ((FIXP_DBL)redVal[groupNumber] >= FL2FXCONST_DBL(1.0f)-sfbThrExp)
   1108                     sfbThrReducedLdData = FL2FXCONST_DBL(0.0f);
   1109                 else {
   1110                     /* threshold reduction formula */
   1111                     sfbThrReducedLdData = CalcLdData(sfbThrExp + redVal[groupNumber]);
   1112                     sfbThrReducedLdData <<= 2;
   1113                 }
   1114             }
   1115             sfbThrReducedLdData += ( CalcLdInt(psyOutChan->groupLen[groupNumber]) -
   1116                                      ((FIXP_DBL)6<<(DFRACT_BITS-1-LD_DATA_SHIFT)) );
   1117           }
   1118 
   1119           /* Long-Window */
   1120           else {
   1121             if ((FIXP_DBL)redVal[0] >= FL2FXCONST_DBL(1.0f)-sfbThrExp) {
   1122               sfbThrReducedLdData = FL2FXCONST_DBL(0.0f);
   1123             }
   1124             else {
   1125               /* threshold reduction formula */
   1126               sfbThrReducedLdData = CalcLdData(sfbThrExp + redVal[0]);
   1127               sfbThrReducedLdData <<= 2;
   1128             }
   1129           }
   1130 
   1131           /* avoid holes */
   1132           if ( ((sfbThrReducedLdData - sfbEnLdData) > qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] )
   1133                   && (ahFlag[ch][sfbGrp+sfb] != NO_AH) )
   1134           {
   1135             if (qcOutChan->sfbMinSnrLdData[sfbGrp+sfb]  > (FL2FXCONST_DBL(-1.0f) - sfbEnLdData) ){
   1136                  sfbThrReducedLdData = fixMax((qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] + sfbEnLdData), sfbThrLdData);
   1137             }
   1138             else sfbThrReducedLdData = sfbThrLdData;
   1139             ahFlag[ch][sfbGrp+sfb] = AH_ACTIVE;
   1140           }
   1141 
   1142           if (sfbThrReducedLdData<FL2FXCONST_DBL(-0.5f))
   1143                sfbThrReducedLdData = FL2FXCONST_DBL(-1.f);
   1144 
   1145           /* minimum of 29 dB Ratio for Thresholds */
   1146           if ((sfbEnLdData+FL2FXCONST_DBL(1.0f)) > FL2FXCONST_DBL(9.6336206/LD_DATA_SCALING)){
   1147             sfbThrReducedLdData = fixMax(sfbThrReducedLdData, sfbEnLdData - FL2FXCONST_DBL(9.6336206/LD_DATA_SCALING));
   1148           }
   1149 
   1150           sfbThrReducedLdData = fixMax(MIN_LDTHRESH,sfbThrReducedLdData);
   1151 
   1152           qcOutChan->sfbThresholdLdData[sfbGrp+sfb] = sfbThrReducedLdData;
   1153         }
   1154       }
   1155     }
   1156   }
   1157 }
   1158 
   1159 /*****************************************************************************
   1160 functionname: FDKaacEnc_correctThresh
   1161 description:  if pe difference deltaPe between desired pe and real pe is small enough,
   1162 the difference can be distributed among the scale factor bands.
   1163 New thresholds can be derived from this pe-difference
   1164 *****************************************************************************/
   1165 static void FDKaacEnc_correctThresh(CHANNEL_MAPPING* cm,
   1166                           QC_OUT_ELEMENT*  qcElement[(8)],
   1167                           PSY_OUT_ELEMENT* psyOutElement[(8)],
   1168                           UCHAR            ahFlag[(8)][(2)][MAX_GROUPED_SFB],
   1169                           FIXP_DBL         thrExp[(8)][(2)][MAX_GROUPED_SFB],
   1170                           const            FIXP_DBL redVal[(8)],
   1171                           const            SCHAR redValScaling[(8)],
   1172                           const            INT deltaPe,
   1173                           const            INT processElements,
   1174                           const            INT elementOffset)
   1175 {
   1176    INT ch, sfb, sfbGrp;
   1177    QC_OUT_CHANNEL *qcOutChan;
   1178    PSY_OUT_CHANNEL *psyOutChan;
   1179    PE_CHANNEL_DATA *peChanData;
   1180    FIXP_DBL thrFactorLdData;
   1181    FIXP_DBL sfbEnLdData, sfbThrLdData, sfbThrReducedLdData;
   1182    FIXP_DBL *sfbPeFactorsLdData[(8)][(2)];
   1183    FIXP_DBL sfbNActiveLinesLdData[(8)][(2)][MAX_GROUPED_SFB];
   1184    INT      normFactorInt;
   1185    FIXP_DBL normFactorLdData;
   1186 
   1187    INT nElements = elementOffset+processElements;
   1188    INT elementId;
   1189 
   1190    /* scratch is empty; use temporal memory from quantSpec in QC_OUT_CHANNEL */
   1191    for(elementId=elementOffset;elementId<nElements;elementId++) {
   1192      for(ch=0; ch<cm->elInfo[elementId].nChannelsInEl; ch++) {
   1193        SHORT* ptr = qcElement[elementId]->qcOutChannel[ch]->quantSpec;
   1194        sfbPeFactorsLdData[elementId][ch] = (FIXP_DBL*)ptr;
   1195      }
   1196    }
   1197 
   1198    /* for each sfb calc relative factors for pe changes */
   1199    normFactorInt = 0;
   1200 
   1201    for(elementId=elementOffset;elementId<nElements;elementId++) {
   1202      if (cm->elInfo[elementId].elType != ID_DSE) {
   1203 
   1204        for(ch=0; ch<cm->elInfo[elementId].nChannelsInEl; ch++) {
   1205 
   1206           qcOutChan = qcElement[elementId]->qcOutChannel[ch];
   1207           psyOutChan = psyOutElement[elementId]->psyOutChannel[ch];
   1208           peChanData = &qcElement[elementId]->peData.peChannelData[ch];
   1209 
   1210           for(sfbGrp = 0; sfbGrp < psyOutChan->sfbCnt; sfbGrp+= psyOutChan->sfbPerGroup){
   1211             for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
   1212 
   1213              if ( peChanData->sfbNActiveLines[sfbGrp+sfb] == 0 ) {
   1214                 sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] = FL2FXCONST_DBL(-1.0f);
   1215              }
   1216              else {
   1217                 /* Both CalcLdInt and CalcLdData can be used!
   1218                  * No offset has to be subtracted, because sfbNActiveLinesLdData
   1219                  * is shorted while thrFactor calculation */
   1220                 sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] = CalcLdInt(peChanData->sfbNActiveLines[sfbGrp+sfb]);
   1221              }
   1222              if ( ((ahFlag[elementId][ch][sfbGrp+sfb] < AH_ACTIVE) || (deltaPe > 0)) &&
   1223                    peChanData->sfbNActiveLines[sfbGrp+sfb] != 0 )
   1224              {
   1225                 if (thrExp[elementId][ch][sfbGrp+sfb] > -redVal[elementId]) {
   1226 
   1227                    /* sfbPeFactors[ch][sfbGrp+sfb] = peChanData->sfbNActiveLines[sfbGrp+sfb] /
   1228                                      (thrExp[elementId][ch][sfbGrp+sfb] + redVal[elementId]); */
   1229 
   1230                    int minScale = fixMin(CountLeadingBits(thrExp[elementId][ch][sfbGrp+sfb]), CountLeadingBits(redVal[elementId]) - (DFRACT_BITS-1-redValScaling[elementId]) ) - 1;
   1231 
   1232                    /* sumld = ld64( sfbThrExp + redVal ) */
   1233                    FIXP_DBL sumLd = CalcLdData(scaleValue(thrExp[elementId][ch][sfbGrp+sfb], minScale) + scaleValue(redVal[elementId], (DFRACT_BITS-1-redValScaling[elementId])+minScale))
   1234                                                - (FIXP_DBL)(minScale<<(DFRACT_BITS-1-LD_DATA_SHIFT));
   1235 
   1236                    if (sumLd < FL2FXCONST_DBL(0.f)) {
   1237                       sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] - sumLd;
   1238                    }
   1239                    else {
   1240                      if ( sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] > (FL2FXCONST_DBL(-1.f) + sumLd) ) {
   1241                        sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] - sumLd;
   1242                      }
   1243                      else {
   1244                       sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb];
   1245                      }
   1246                    }
   1247 
   1248                    normFactorInt += (INT)CalcInvLdData(sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb]);
   1249                 }
   1250                 else sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = FL2FXCONST_DBL(1.0f);
   1251              }
   1252              else sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] = FL2FXCONST_DBL(-1.0f);
   1253             }
   1254           }
   1255        }
   1256      }
   1257    }
   1258 
   1259    /* normFactorLdData = ld64(deltaPe/normFactorInt) */
   1260    normFactorLdData = CalcLdData((FIXP_DBL)((deltaPe<0) ? (-deltaPe) : (deltaPe))) - CalcLdData((FIXP_DBL)normFactorInt);
   1261 
   1262    /* distribute the pe difference to the scalefactors
   1263       and calculate the according thresholds */
   1264    for(elementId=elementOffset;elementId<nElements;elementId++) {
   1265      if (cm->elInfo[elementId].elType != ID_DSE) {
   1266 
   1267        for(ch=0; ch<cm->elInfo[elementId].nChannelsInEl; ch++) {
   1268           qcOutChan = qcElement[elementId]->qcOutChannel[ch];
   1269           psyOutChan = psyOutElement[elementId]->psyOutChannel[ch];
   1270           peChanData = &qcElement[elementId]->peData.peChannelData[ch];
   1271 
   1272           for(sfbGrp = 0;sfbGrp < psyOutChan->sfbCnt;sfbGrp+= psyOutChan->sfbPerGroup){
   1273             for (sfb=0; sfb<psyOutChan->maxSfbPerGroup; sfb++) {
   1274 
   1275               if (peChanData->sfbNActiveLines[sfbGrp+sfb] > 0) {
   1276 
   1277                  /* pe difference for this sfb */
   1278                  if ( (sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb]==FL2FXCONST_DBL(-1.0f)) ||
   1279                       (deltaPe==0) )
   1280                  {
   1281                    thrFactorLdData = FL2FXCONST_DBL(0.f);
   1282                  }
   1283                  else {
   1284                    /* new threshold */
   1285                    FIXP_DBL tmp = CalcInvLdData(sfbPeFactorsLdData[elementId][ch][sfbGrp+sfb] + normFactorLdData - sfbNActiveLinesLdData[elementId][ch][sfbGrp+sfb] - FL2FXCONST_DBL((float)LD_DATA_SHIFT/LD_DATA_SCALING));
   1286 
   1287                    /* limit thrFactor to 60dB */
   1288                    tmp = (deltaPe<0) ? tmp : (-tmp);
   1289                    thrFactorLdData = FDKmin(tmp, FL2FXCONST_DBL(20.f/LD_DATA_SCALING));
   1290                  }
   1291 
   1292                  /* new threshold */
   1293                  sfbThrLdData = qcOutChan->sfbThresholdLdData[sfbGrp+sfb];
   1294                  sfbEnLdData  = qcOutChan->sfbWeightedEnergyLdData[sfbGrp+sfb];
   1295 
   1296                  if (thrFactorLdData < FL2FXCONST_DBL(0.f)) {
   1297                    if( sfbThrLdData > (FL2FXCONST_DBL(-1.f)-thrFactorLdData) ) {
   1298                      sfbThrReducedLdData = sfbThrLdData + thrFactorLdData;
   1299                    }
   1300                    else {
   1301                      sfbThrReducedLdData = FL2FXCONST_DBL(-1.f);
   1302                    }
   1303                  }
   1304                  else{
   1305                     sfbThrReducedLdData = sfbThrLdData + thrFactorLdData;
   1306                  }
   1307 
   1308                  /* avoid hole */
   1309                  if ( (sfbThrReducedLdData - sfbEnLdData > qcOutChan->sfbMinSnrLdData[sfbGrp+sfb]) &&
   1310                       (ahFlag[elementId][ch][sfbGrp+sfb] == AH_INACTIVE) )
   1311                  {
   1312                     /* sfbThrReduced = max(psyOutChan[ch]->sfbMinSnr[i] * sfbEn, sfbThr); */
   1313                     if ( sfbEnLdData > (sfbThrLdData-qcOutChan->sfbMinSnrLdData[sfbGrp+sfb]) ) {
   1314                         sfbThrReducedLdData = qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] + sfbEnLdData;
   1315                     }
   1316                     else {
   1317                         sfbThrReducedLdData = sfbThrLdData;
   1318                     }
   1319                     ahFlag[elementId][ch][sfbGrp+sfb] = AH_ACTIVE;
   1320                  }
   1321 
   1322                  qcOutChan->sfbThresholdLdData[sfbGrp+sfb] = sfbThrReducedLdData;
   1323               }
   1324             }
   1325           }
   1326        }
   1327      }
   1328    }
   1329 }
   1330 
   1331 /*****************************************************************************
   1332     functionname: FDKaacEnc_reduceMinSnr
   1333     description:  if the desired pe can not be reached, reduce pe by
   1334                   reducing minSnr
   1335 *****************************************************************************/
   1336 void FDKaacEnc_reduceMinSnr(CHANNEL_MAPPING* cm,
   1337                             QC_OUT_ELEMENT*  qcElement[(8)],
   1338                             PSY_OUT_ELEMENT* psyOutElement[(8)],
   1339                             UCHAR            ahFlag[(8)][(2)][MAX_GROUPED_SFB],
   1340                             const            INT desiredPe,
   1341                             INT*             redPeGlobal,
   1342                             const            INT processElements,
   1343                             const            INT elementOffset)
   1344 
   1345 {
   1346    INT elementId;
   1347    INT nElements = elementOffset+processElements;
   1348 
   1349    INT newGlobalPe = *redPeGlobal;
   1350 
   1351    for(elementId=elementOffset;elementId<nElements;elementId++) {
   1352      if (cm->elInfo[elementId].elType != ID_DSE) {
   1353        INT ch;
   1354        INT maxSfbPerGroup[2];
   1355        INT sfbCnt[2];
   1356        INT sfbPerGroup[2];
   1357 
   1358        for(ch=0; ch<cm->elInfo[elementId].nChannelsInEl; ch++) {
   1359          maxSfbPerGroup[ch] = psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup-1;
   1360          sfbCnt[ch]         = psyOutElement[elementId]->psyOutChannel[ch]->sfbCnt;
   1361          sfbPerGroup[ch]    = psyOutElement[elementId]->psyOutChannel[ch]->sfbPerGroup;
   1362        }
   1363 
   1364        PE_DATA *peData = &qcElement[elementId]->peData;
   1365 
   1366        do
   1367        {
   1368          for(ch=0; ch<cm->elInfo[elementId].nChannelsInEl; ch++) {
   1369 
   1370             INT sfb, sfbGrp;
   1371             QC_OUT_CHANNEL  *qcOutChan = qcElement[elementId]->qcOutChannel[ch];
   1372             INT noReduction = 1;
   1373 
   1374             if (maxSfbPerGroup[ch]>=0) {  /* sfb in next channel */
   1375               INT deltaPe = 0;
   1376               sfb = maxSfbPerGroup[ch]--;
   1377               noReduction = 0;
   1378 
   1379               for (sfbGrp = 0; sfbGrp < sfbCnt[ch]; sfbGrp += sfbPerGroup[ch]) {
   1380 
   1381                 if (ahFlag[elementId][ch][sfbGrp+sfb] != NO_AH &&
   1382                     qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] < SnrLdFac)
   1383                 {
   1384                   /* increase threshold to new minSnr of 1dB */
   1385                   qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] = SnrLdFac;
   1386 
   1387                   /* sfbThrReduced = max(psyOutChan[ch]->sfbMinSnr[i] * sfbEn, sfbThr); */
   1388                   if ( qcOutChan->sfbWeightedEnergyLdData[sfbGrp+sfb] >= qcOutChan->sfbThresholdLdData[sfbGrp+sfb] - qcOutChan->sfbMinSnrLdData[sfbGrp+sfb] ) {
   1389 
   1390                      qcOutChan->sfbThresholdLdData[sfbGrp+sfb] = qcOutChan->sfbWeightedEnergyLdData[sfbGrp+sfb] + qcOutChan->sfbMinSnrLdData[sfbGrp+sfb];
   1391 
   1392                      /* calc new pe */
   1393                      /* C2 + C3*ld(1/0.8) = 1.5 */
   1394                      deltaPe -= (peData->peChannelData[ch].sfbPe[sfbGrp+sfb]>>PE_CONSTPART_SHIFT);
   1395 
   1396                      /* sfbPe = 1.5 * sfbNLines */
   1397                      peData->peChannelData[ch].sfbPe[sfbGrp+sfb] = (3*peData->peChannelData[ch].sfbNLines[sfbGrp+sfb]) << (PE_CONSTPART_SHIFT-1);
   1398                      deltaPe += (peData->peChannelData[ch].sfbPe[sfbGrp+sfb]>>PE_CONSTPART_SHIFT);
   1399                    }
   1400                 }
   1401 
   1402               } /* sfbGrp loop */
   1403 
   1404               peData->pe += deltaPe;
   1405               peData->peChannelData[ch].pe += deltaPe;
   1406               newGlobalPe += deltaPe;
   1407 
   1408               /* stop if enough has been saved */
   1409               if (peData->pe <= desiredPe) {
   1410                 goto bail;
   1411               }
   1412 
   1413             } /* sfb > 0 */
   1414 
   1415             if ( (ch==(cm->elInfo[elementId].nChannelsInEl-1)) && noReduction ) {
   1416               goto bail;
   1417             }
   1418 
   1419          } /* ch loop */
   1420 
   1421        } while ( peData->pe > desiredPe);
   1422 
   1423      } /* != ID_DSE */
   1424    } /* element loop */
   1425 
   1426 
   1427 bail:
   1428    /* update global PE */
   1429    *redPeGlobal = newGlobalPe;
   1430 }
   1431 
   1432 
   1433 /*****************************************************************************
   1434     functionname: FDKaacEnc_allowMoreHoles
   1435     description:  if the desired pe can not be reached, some more scalefactor
   1436                   bands have to be quantized to zero
   1437 *****************************************************************************/
   1438 static void FDKaacEnc_allowMoreHoles(CHANNEL_MAPPING* cm,
   1439                            QC_OUT_ELEMENT*  qcElement[(8)],
   1440                            PSY_OUT_ELEMENT* psyOutElement[(8)],
   1441                            ATS_ELEMENT*     AdjThrStateElement[(8)],
   1442                            UCHAR            ahFlag[(8)][(2)][MAX_GROUPED_SFB],
   1443                            const INT        desiredPe,
   1444                            const INT        currentPe,
   1445                            const int        processElements,
   1446                            const int        elementOffset)
   1447 {
   1448   INT elementId;
   1449   INT nElements = elementOffset+processElements;
   1450   INT actPe = currentPe;
   1451 
   1452   if (actPe <= desiredPe) {
   1453     return; /* nothing to do */
   1454   }
   1455 
   1456   for (elementId = elementOffset;elementId<nElements;elementId++) {
   1457     if (cm->elInfo[elementId].elType != ID_DSE) {
   1458 
   1459       INT ch, sfb, sfbGrp;
   1460 
   1461       PE_DATA *peData = &qcElement[elementId]->peData;
   1462       const INT nChannels = cm->elInfo[elementId].nChannelsInEl;
   1463 
   1464       QC_OUT_CHANNEL*  qcOutChannel[(2)] = {NULL};
   1465       PSY_OUT_CHANNEL* psyOutChannel[(2)] = {NULL};
   1466 
   1467       for (ch=0; ch<nChannels; ch++) {
   1468 
   1469         /* init pointers */
   1470         qcOutChannel[ch] = qcElement[elementId]->qcOutChannel[ch];
   1471         psyOutChannel[ch] = psyOutElement[elementId]->psyOutChannel[ch];
   1472 
   1473         for(sfbGrp=0; sfbGrp < psyOutChannel[ch]->sfbCnt; sfbGrp+= psyOutChannel[ch]->sfbPerGroup) {
   1474           for (sfb=psyOutChannel[ch]->maxSfbPerGroup; sfb<psyOutChannel[ch]->sfbPerGroup; sfb++) {
   1475             peData->peChannelData[ch].sfbPe[sfbGrp+sfb] = 0;
   1476           }
   1477         }
   1478       }
   1479 
   1480       /* for MS allow hole in the channel with less energy */
   1481       if ( nChannels==2 && psyOutChannel[0]->lastWindowSequence==psyOutChannel[1]->lastWindowSequence ) {
   1482 
   1483         for (sfb=0; sfb<psyOutChannel[0]->maxSfbPerGroup; sfb++) {
   1484           for(sfbGrp=0; sfbGrp < psyOutChannel[0]->sfbCnt; sfbGrp+=psyOutChannel[0]->sfbPerGroup) {
   1485             if (psyOutElement[elementId]->toolsInfo.msMask[sfbGrp+sfb]) {
   1486               FIXP_DBL EnergyLd_L = qcOutChannel[0]->sfbWeightedEnergyLdData[sfbGrp+sfb];
   1487               FIXP_DBL EnergyLd_R = qcOutChannel[1]->sfbWeightedEnergyLdData[sfbGrp+sfb];
   1488 
   1489               /* allow hole in side channel ? */
   1490               if ( (ahFlag[elementId][1][sfbGrp+sfb] != NO_AH) &&
   1491                    (((FL2FXCONST_DBL(-0.02065512648f)>>1) + (qcOutChannel[0]->sfbMinSnrLdData[sfbGrp+sfb]>>1))
   1492                         > ((EnergyLd_R>>1) - (EnergyLd_L>>1))) )
   1493               {
   1494                   ahFlag[elementId][1][sfbGrp+sfb] = NO_AH;
   1495                   qcOutChannel[1]->sfbThresholdLdData[sfbGrp+sfb] = FL2FXCONST_DBL(0.015625f) + EnergyLd_R;
   1496                   actPe -= peData->peChannelData[1].sfbPe[sfbGrp+sfb]>>PE_CONSTPART_SHIFT;
   1497               }
   1498               /* allow hole in mid channel ? */
   1499               else if ( (ahFlag[elementId][0][sfbGrp+sfb] != NO_AH) &&
   1500                         (((FL2FXCONST_DBL(-0.02065512648f)>>1) + (qcOutChannel[1]->sfbMinSnrLdData[sfbGrp+sfb]>>1))
   1501                              > ((EnergyLd_L>>1) - (EnergyLd_R>>1))) )
   1502               {
   1503                   ahFlag[elementId][0][sfbGrp+sfb] = NO_AH;
   1504                   qcOutChannel[0]->sfbThresholdLdData[sfbGrp+sfb] = FL2FXCONST_DBL(0.015625f) + EnergyLd_L;
   1505                   actPe -= peData->peChannelData[0].sfbPe[sfbGrp+sfb]>>PE_CONSTPART_SHIFT;
   1506               } /* if (ahFlag) */
   1507             } /* if MS */
   1508           } /* sfbGrp */
   1509           if (actPe <= desiredPe) {
   1510             return; /* stop if enough has been saved */
   1511           }
   1512         } /* sfb */
   1513       } /* MS possible ? */
   1514 
   1515       /* more holes necessary? subsequently erase bands
   1516          starting with low energies */
   1517       INT startSfb[2];
   1518       FIXP_DBL avgEnLD64,minEnLD64;
   1519       INT ahCnt;
   1520       FIXP_DBL ahCntLD64;
   1521       INT enIdx;
   1522       FIXP_DBL enLD64[4];
   1523       FIXP_DBL avgEn;
   1524 
   1525       /* do not go below startSfb */
   1526       for (ch=0; ch<nChannels; ch++) {
   1527         if (psyOutChannel[ch]->lastWindowSequence != SHORT_WINDOW)
   1528           startSfb[ch] = AdjThrStateElement[elementId]->ahParam.startSfbL;
   1529         else
   1530           startSfb[ch] = AdjThrStateElement[elementId]->ahParam.startSfbS;
   1531       }
   1532 
   1533       /* calc avg and min energies of bands that avoid holes */
   1534       avgEn = FL2FXCONST_DBL(0.0f);
   1535       minEnLD64 = FL2FXCONST_DBL(0.0f);
   1536       ahCnt = 0;
   1537 
   1538       for (ch=0; ch<nChannels; ch++) {
   1539 
   1540         sfbGrp=0;
   1541         sfb=startSfb[ch];
   1542 
   1543         do {
   1544           for (; sfb<psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
   1545             if ((ahFlag[elementId][ch][sfbGrp+sfb]!=NO_AH) &&
   1546                 (qcOutChannel[ch]->sfbWeightedEnergyLdData[sfbGrp+sfb] > qcOutChannel[ch]->sfbThresholdLdData[sfbGrp+sfb])){
   1547               minEnLD64 = fixMin(minEnLD64,qcOutChannel[ch]->sfbEnergyLdData[sfbGrp+sfb]);
   1548               avgEn += qcOutChannel[ch]->sfbEnergy[sfbGrp+sfb] >> 6;
   1549               ahCnt++;
   1550             }
   1551           }
   1552 
   1553           sfbGrp += psyOutChannel[ch]->sfbPerGroup;
   1554           sfb=0;
   1555 
   1556         } while (sfbGrp < psyOutChannel[ch]->sfbCnt);
   1557       }
   1558 
   1559       if ( (avgEn == FL2FXCONST_DBL(0.0f)) || (ahCnt == 0) ) {
   1560         avgEnLD64 = FL2FXCONST_DBL(0.0f);
   1561       }
   1562       else {
   1563         avgEnLD64 = CalcLdData(avgEn);
   1564         ahCntLD64 = CalcLdInt(ahCnt);
   1565         avgEnLD64 = avgEnLD64 + FL2FXCONST_DBL(0.09375f) - ahCntLD64; /* compensate shift with 6 */
   1566       }
   1567 
   1568       /* calc some energy borders between minEn and avgEn */
   1569       /* for (enIdx=0; enIdx<4; enIdx++) */
   1570         /* en[enIdx] = minEn * (float)FDKpow(avgEn/(minEn+FLT_MIN), (2*enIdx+1)/7.0f); */
   1571       enLD64[0] = minEnLD64 + fMult((avgEnLD64-minEnLD64),FL2FXCONST_DBL(0.14285714285f));
   1572       enLD64[1] = minEnLD64 + fMult((avgEnLD64-minEnLD64),FL2FXCONST_DBL(0.42857142857f));
   1573       enLD64[2] = minEnLD64 + fMult((avgEnLD64-minEnLD64),FL2FXCONST_DBL(0.71428571428f));
   1574       enLD64[3] = minEnLD64 + (avgEnLD64-minEnLD64);
   1575 
   1576       for (enIdx=0; enIdx<4; enIdx++) {
   1577         INT noReduction = 1;
   1578 
   1579         INT maxSfbPerGroup[2];
   1580         INT sfbCnt[2];
   1581         INT sfbPerGroup[2];
   1582 
   1583         for(ch=0; ch<cm->elInfo[elementId].nChannelsInEl; ch++) {
   1584           maxSfbPerGroup[ch] = psyOutElement[elementId]->psyOutChannel[ch]->maxSfbPerGroup-1;
   1585           sfbCnt[ch]         = psyOutElement[elementId]->psyOutChannel[ch]->sfbCnt;
   1586           sfbPerGroup[ch]    = psyOutElement[elementId]->psyOutChannel[ch]->sfbPerGroup;
   1587         }
   1588 
   1589         do {
   1590 
   1591           noReduction = 1;
   1592 
   1593           for(ch=0; ch<cm->elInfo[elementId].nChannelsInEl; ch++) {
   1594 
   1595             INT sfb, sfbGrp;
   1596 
   1597             /* start with lowest energy border at highest sfb */
   1598             if (maxSfbPerGroup[ch]>=startSfb[ch]) {  /* sfb in next channel */
   1599               sfb = maxSfbPerGroup[ch]--;
   1600               noReduction = 0;
   1601 
   1602               for (sfbGrp = 0; sfbGrp < sfbCnt[ch]; sfbGrp += sfbPerGroup[ch]) {
   1603                 /* sfb energy below border ? */
   1604                 if (ahFlag[elementId][ch][sfbGrp+sfb] != NO_AH && qcOutChannel[ch]->sfbEnergyLdData[sfbGrp+sfb] < enLD64[enIdx]) {
   1605                   /* allow hole */
   1606                   ahFlag[elementId][ch][sfbGrp+sfb] = NO_AH;
   1607                   qcOutChannel[ch]->sfbThresholdLdData[sfbGrp+sfb] = FL2FXCONST_DBL(0.015625f) + qcOutChannel[ch]->sfbWeightedEnergyLdData[sfbGrp+sfb];
   1608                   actPe -= peData->peChannelData[ch].sfbPe[sfbGrp+sfb]>>PE_CONSTPART_SHIFT;
   1609                 }
   1610               } /* sfbGrp  */
   1611 
   1612               if (actPe <= desiredPe) {
   1613                 return; /* stop if enough has been saved */
   1614               }
   1615             } /* sfb > 0 */
   1616           } /* ch loop */
   1617 
   1618         } while( (noReduction == 0) && (actPe > desiredPe) );
   1619 
   1620         if (actPe <= desiredPe) {
   1621           return; /* stop if enough has been saved */
   1622         }
   1623 
   1624       } /* enIdx loop */
   1625 
   1626     } /* EOF DSE-suppression */
   1627   } /* EOF for all elements... */
   1628 
   1629 }
   1630 
   1631 /* reset avoid hole flags from AH_ACTIVE to AH_INACTIVE  */
   1632 static void FDKaacEnc_resetAHFlags( UCHAR ahFlag[(2)][MAX_GROUPED_SFB],
   1633                           const int nChannels,
   1634                           PSY_OUT_CHANNEL  *psyOutChannel[(2)])
   1635 {
   1636   int ch, sfb, sfbGrp;
   1637 
   1638   for(ch=0; ch<nChannels; ch++) {
   1639     for (sfbGrp=0; sfbGrp < psyOutChannel[ch]->sfbCnt; sfbGrp+=psyOutChannel[ch]->sfbPerGroup) {
   1640       for (sfb=0; sfb<psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
   1641         if ( ahFlag[ch][sfbGrp+sfb] == AH_ACTIVE) {
   1642           ahFlag[ch][sfbGrp+sfb] = AH_INACTIVE;
   1643         }
   1644       }
   1645     }
   1646   }
   1647 }
   1648 
   1649 
   1650 static FIXP_DBL CalcRedValPower(FIXP_DBL num,
   1651                                 FIXP_DBL denum,
   1652                                 INT*     scaling )
   1653 {
   1654     FIXP_DBL value = FL2FXCONST_DBL(0.f);
   1655 
   1656     if (num>=FL2FXCONST_DBL(0.f)) {
   1657       value = fDivNorm( num, denum, scaling);
   1658     }
   1659     else {
   1660       value = -fDivNorm( -num, denum, scaling);
   1661     }
   1662     value = f2Pow(value, *scaling, scaling);
   1663     *scaling = DFRACT_BITS-1-*scaling;
   1664 
   1665     return value;
   1666 }
   1667 
   1668 
   1669 /*****************************************************************************
   1670 functionname: FDKaacEnc_adaptThresholdsToPe
   1671 description:  two guesses for the reduction value and one final correction of the thresholds
   1672 *****************************************************************************/
   1673 static void FDKaacEnc_adaptThresholdsToPe(CHANNEL_MAPPING*  cm,
   1674                                 ATS_ELEMENT*      AdjThrStateElement[(8)],
   1675                                 QC_OUT_ELEMENT*   qcElement[(8)],
   1676                                 PSY_OUT_ELEMENT*  psyOutElement[(8)],
   1677                                 const INT         desiredPe,
   1678                                 const INT         maxIter2ndGuess,
   1679                                 const INT         processElements,
   1680                                 const INT         elementOffset)
   1681 {
   1682    FIXP_DBL redValue[(8)];
   1683    SCHAR    redValScaling[(8)];
   1684    UCHAR    pAhFlag[(8)][(2)][MAX_GROUPED_SFB];
   1685    FIXP_DBL pThrExp[(8)][(2)][MAX_GROUPED_SFB];
   1686    int iter;
   1687 
   1688    INT constPartGlobal, noRedPeGlobal, nActiveLinesGlobal, redPeGlobal;
   1689    constPartGlobal = noRedPeGlobal = nActiveLinesGlobal = redPeGlobal = 0;
   1690 
   1691    int elementId;
   1692 
   1693    int nElements = elementOffset+processElements;
   1694    if(nElements > cm->nElements) {
   1695      nElements = cm->nElements;
   1696    }
   1697 
   1698    /* ------------------------------------------------------- */
   1699    /* Part I: Initialize data structures and variables... */
   1700    /* ------------------------------------------------------- */
   1701    for (elementId = elementOffset;elementId<nElements;elementId++) {
   1702      if (cm->elInfo[elementId].elType != ID_DSE) {
   1703 
   1704        INT nChannels = cm->elInfo[elementId].nChannelsInEl;
   1705        PE_DATA *peData    = &qcElement[elementId]->peData;
   1706 
   1707        /* thresholds to the power of redExp */
   1708        FDKaacEnc_calcThreshExp(pThrExp[elementId], qcElement[elementId]->qcOutChannel, psyOutElement[elementId]->psyOutChannel, nChannels);
   1709 
   1710        /* lower the minSnr requirements for low energies compared to the average
   1711           energy in this frame */
   1712        FDKaacEnc_adaptMinSnr(qcElement[elementId]->qcOutChannel, psyOutElement[elementId]->psyOutChannel, &AdjThrStateElement[elementId]->minSnrAdaptParam, nChannels);
   1713 
   1714        /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
   1715        FDKaacEnc_initAvoidHoleFlag(qcElement[elementId]->qcOutChannel, psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId], &psyOutElement[elementId]->toolsInfo, nChannels, peData, &AdjThrStateElement[elementId]->ahParam);
   1716 
   1717        /* sum up */
   1718        constPartGlobal    += peData->constPart;
   1719        noRedPeGlobal      += peData->pe;
   1720        nActiveLinesGlobal += fixMax((INT)peData->nActiveLines, 1);
   1721 
   1722      } /* EOF DSE-suppression */
   1723    } /* EOF for all elements... */
   1724 
   1725    /* ----------------------------------------------------------------------- */
   1726    /* Part II: Calculate bit consumption of initial bit constraints setup */
   1727    /* ----------------------------------------------------------------------- */
   1728    for (elementId = elementOffset;elementId<nElements;elementId++) {
   1729      if (cm->elInfo[elementId].elType != ID_DSE) {
   1730        /*
   1731        redVal = ( 2 ^ ( (constPartGlobal-desiredPe) / (invRedExp*nActiveLinesGlobal) )
   1732                 - 2 ^ ( (constPartGlobal-noRedPeGlobal) / (invRedExp*nActiveLinesGlobal) ) )
   1733        */
   1734 
   1735 
   1736        INT nChannels = cm->elInfo[elementId].nChannelsInEl;
   1737        PE_DATA *peData    = &qcElement[elementId]->peData;
   1738 
   1739        /* first guess of reduction value */
   1740        int scale0=0, scale1=0;
   1741        FIXP_DBL tmp0 = CalcRedValPower( constPartGlobal-desiredPe, 4*nActiveLinesGlobal, &scale0 );
   1742        FIXP_DBL tmp1 = CalcRedValPower( constPartGlobal-noRedPeGlobal, 4*nActiveLinesGlobal, &scale1 );
   1743 
   1744        int scalMin = FDKmin(scale0, scale1)-1;
   1745 
   1746        redValue[elementId]  = scaleValue(tmp0,(scalMin-scale0)) - scaleValue(tmp1,(scalMin-scale1));
   1747        redValScaling[elementId] = scalMin;
   1748 
   1749        /* reduce thresholds */
   1750        FDKaacEnc_reduceThresholdsCBR(qcElement[elementId]->qcOutChannel, psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId], pThrExp[elementId], nChannels, redValue[elementId], redValScaling[elementId]);
   1751 
   1752        /* pe after first guess */
   1753        FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel, qcElement[elementId]->qcOutChannel, peData, nChannels);
   1754 
   1755        redPeGlobal += peData->pe;
   1756      } /* EOF DSE-suppression */
   1757    } /* EOF for all elements... */
   1758 
   1759    /* -------------------------------------------------- */
   1760    /* Part III: Iterate until bit constraints are met */
   1761    /* -------------------------------------------------- */
   1762    iter = 0;
   1763    while ((fixp_abs(redPeGlobal - desiredPe) > fMultI(FL2FXCONST_DBL(0.05f),desiredPe)) && (iter < maxIter2ndGuess)) {
   1764 
   1765      INT desiredPeNoAHGlobal;
   1766      INT redPeNoAHGlobal = 0;
   1767      INT constPartNoAHGlobal = 0;
   1768      INT nActiveLinesNoAHGlobal = 0;
   1769 
   1770      for (elementId = elementOffset;elementId<nElements;elementId++) {
   1771        if (cm->elInfo[elementId].elType != ID_DSE) {
   1772 
   1773          INT redPeNoAH, constPartNoAH, nActiveLinesNoAH;
   1774          INT nChannels = cm->elInfo[elementId].nChannelsInEl;
   1775          PE_DATA *peData    = &qcElement[elementId]->peData;
   1776 
   1777          /* pe for bands where avoid hole is inactive */
   1778          FDKaacEnc_FDKaacEnc_calcPeNoAH(&redPeNoAH, &constPartNoAH, &nActiveLinesNoAH,
   1779                     peData, pAhFlag[elementId], psyOutElement[elementId]->psyOutChannel, nChannels);
   1780 
   1781          redPeNoAHGlobal += redPeNoAH;
   1782          constPartNoAHGlobal += constPartNoAH;
   1783          nActiveLinesNoAHGlobal += nActiveLinesNoAH;
   1784        } /* EOF DSE-suppression */
   1785      } /* EOF for all elements... */
   1786 
   1787      /* Calculate new redVal ... */
   1788      if(desiredPe < redPeGlobal) {
   1789 
   1790        /* new desired pe without bands where avoid hole is active */
   1791        desiredPeNoAHGlobal = desiredPe - (redPeGlobal - redPeNoAHGlobal);
   1792 
   1793        /* limit desiredPeNoAH to positive values, as the PE can not become negative */
   1794        desiredPeNoAHGlobal = FDKmax(0,desiredPeNoAHGlobal);
   1795 
   1796        /* second guess (only if there are bands left where avoid hole is inactive)*/
   1797        if (nActiveLinesNoAHGlobal > 0) {
   1798          for (elementId = elementOffset;elementId<nElements;elementId++) {
   1799            if (cm->elInfo[elementId].elType != ID_DSE) {
   1800              /*
   1801              redVal += ( 2 ^ ( (constPartNoAHGlobal-desiredPeNoAHGlobal) / (invRedExp*nActiveLinesNoAHGlobal) )
   1802                        - 2 ^ ( (constPartNoAHGlobal-redPeNoAHGlobal) / (invRedExp*nActiveLinesNoAHGlobal) ) )
   1803              */
   1804              int scale0 = 0;
   1805              int scale1 = 0;
   1806 
   1807              FIXP_DBL tmp0 = CalcRedValPower( constPartNoAHGlobal-desiredPeNoAHGlobal, 4*nActiveLinesNoAHGlobal, &scale0 );
   1808              FIXP_DBL tmp1 = CalcRedValPower( constPartNoAHGlobal-redPeNoAHGlobal, 4*nActiveLinesNoAHGlobal, &scale1 );
   1809 
   1810              int scalMin = FDKmin(scale0, scale1)-1;
   1811 
   1812              tmp0 = scaleValue(tmp0,(scalMin-scale0)) - scaleValue(tmp1,(scalMin-scale1));
   1813              scale0 = scalMin;
   1814 
   1815              /* old reduction value */
   1816              tmp1 = redValue[elementId];
   1817              scale1 = redValScaling[elementId];
   1818 
   1819              scalMin = fixMin(scale0,scale1)-1;
   1820 
   1821              /* sum up old and new reduction value */
   1822              redValue[elementId] = scaleValue(tmp0,(scalMin-scale0)) + scaleValue(tmp1,(scalMin-scale1));
   1823              redValScaling[elementId] = scalMin;
   1824 
   1825            } /* EOF DSE-suppression */
   1826          } /* EOF for all elements... */
   1827        } /* nActiveLinesNoAHGlobal > 0 */
   1828      }
   1829      else {
   1830         /* desiredPe >= redPeGlobal */
   1831         for (elementId = elementOffset;elementId<nElements;elementId++) {
   1832           if (cm->elInfo[elementId].elType != ID_DSE) {
   1833 
   1834             INT redVal_scale = 0;
   1835             FIXP_DBL tmp = fDivNorm((FIXP_DBL)redPeGlobal, (FIXP_DBL)desiredPe, &redVal_scale);
   1836 
   1837             /* redVal *= redPeGlobal/desiredPe; */
   1838             redValue[elementId] = fMult(redValue[elementId], tmp);
   1839             redValScaling[elementId] -= redVal_scale;
   1840 
   1841             FDKaacEnc_resetAHFlags(pAhFlag[elementId], cm->elInfo[elementId].nChannelsInEl, psyOutElement[elementId]->psyOutChannel);
   1842           } /* EOF DSE-suppression */
   1843         } /* EOF for all elements... */
   1844      }
   1845 
   1846      redPeGlobal = 0;
   1847      /* Calculate new redVal's PE... */
   1848      for (elementId = elementOffset;elementId<nElements;elementId++) {
   1849        if (cm->elInfo[elementId].elType != ID_DSE) {
   1850 
   1851          INT nChannels = cm->elInfo[elementId].nChannelsInEl;
   1852          PE_DATA *peData    = &qcElement[elementId]->peData;
   1853 
   1854          /* reduce thresholds */
   1855          FDKaacEnc_reduceThresholdsCBR(qcElement[elementId]->qcOutChannel, psyOutElement[elementId]->psyOutChannel, pAhFlag[elementId], pThrExp[elementId], nChannels, redValue[elementId], redValScaling[elementId]);
   1856 
   1857          /* pe after second guess */
   1858          FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel, qcElement[elementId]->qcOutChannel, peData, nChannels);
   1859          redPeGlobal += peData->pe;
   1860 
   1861        } /* EOF DSE-suppression */
   1862      } /* EOF for all elements... */
   1863 
   1864      iter++;
   1865    } /* EOF while */
   1866 
   1867 
   1868    /* ------------------------------------------------------- */
   1869    /* Part IV: if still required, further reduce constraints  */
   1870    /* ------------------------------------------------------- */
   1871    /*                  1.0*        1.15*       1.20*
   1872     *               desiredPe   desiredPe   desiredPe
   1873     *                   |           |           |
   1874     * ...XXXXXXXXXXXXXXXXXXXXXXXXXXX|           |
   1875     *                   |           |           |XXXXXXXXXXX...
   1876     *                   |           |XXXXXXXXXXX|
   1877     *            --- A ---          | --- B --- | --- C ---
   1878     *
   1879     * (X): redPeGlobal
   1880     * (A): FDKaacEnc_correctThresh()
   1881     * (B): FDKaacEnc_allowMoreHoles()
   1882     * (C): FDKaacEnc_reduceMinSnr()
   1883    */
   1884 
   1885    /* correct thresholds to get closer to the desired pe */
   1886    if ( redPeGlobal > desiredPe ) {
   1887      FDKaacEnc_correctThresh(cm, qcElement, psyOutElement, pAhFlag, pThrExp, redValue, redValScaling,
   1888                    desiredPe - redPeGlobal, processElements, elementOffset);
   1889 
   1890      /* update PE */
   1891      redPeGlobal = 0;
   1892      for(elementId=elementOffset;elementId<nElements;elementId++) {
   1893        if (cm->elInfo[elementId].elType != ID_DSE) {
   1894 
   1895          INT nChannels = cm->elInfo[elementId].nChannelsInEl;
   1896          PE_DATA *peData    = &qcElement[elementId]->peData;
   1897 
   1898          /* pe after correctThresh */
   1899          FDKaacEnc_calcPe(psyOutElement[elementId]->psyOutChannel, qcElement[elementId]->qcOutChannel, peData, nChannels);
   1900          redPeGlobal += peData->pe;
   1901 
   1902        } /* EOF DSE-suppression */
   1903      } /* EOF for all elements... */
   1904    }
   1905 
   1906    if ( redPeGlobal > desiredPe ) {
   1907      /* reduce pe by reducing minSnr requirements */
   1908      FDKaacEnc_reduceMinSnr(cm, qcElement, psyOutElement, pAhFlag,
   1909                             (fMultI(FL2FXCONST_DBL(0.15f),desiredPe) + desiredPe),
   1910                             &redPeGlobal, processElements, elementOffset);
   1911 
   1912      /* reduce pe by allowing additional spectral holes */
   1913      FDKaacEnc_allowMoreHoles(cm, qcElement, psyOutElement, AdjThrStateElement, pAhFlag,
   1914                     desiredPe, redPeGlobal, processElements, elementOffset);
   1915    }
   1916 
   1917 }
   1918 
   1919 /* similar to FDKaacEnc_adaptThresholdsToPe(), for  VBR-mode */
   1920 void FDKaacEnc_AdaptThresholdsVBR(QC_OUT_CHANNEL* qcOutChannel[(2)],
   1921                                PSY_OUT_CHANNEL* psyOutChannel[(2)],
   1922                                ATS_ELEMENT* AdjThrStateElement,
   1923                                struct TOOLSINFO *toolsInfo,
   1924                                PE_DATA *peData,
   1925                                const INT nChannels)
   1926 {
   1927    UCHAR    (*pAhFlag)[MAX_GROUPED_SFB];
   1928    FIXP_DBL (*pThrExp)[MAX_GROUPED_SFB];
   1929 
   1930    /* allocate scratch memory */
   1931    C_ALLOC_SCRATCH_START(_pAhFlag, UCHAR, (2)*MAX_GROUPED_SFB)
   1932    C_ALLOC_SCRATCH_START(_pThrExp, FIXP_DBL, (2)*MAX_GROUPED_SFB)
   1933    pAhFlag = (UCHAR(*)[MAX_GROUPED_SFB])_pAhFlag;
   1934    pThrExp = (FIXP_DBL(*)[MAX_GROUPED_SFB])_pThrExp;
   1935 
   1936    /* thresholds to the power of redExp */
   1937    FDKaacEnc_calcThreshExp(pThrExp, qcOutChannel, psyOutChannel, nChannels);
   1938 
   1939    /* lower the minSnr requirements for low energies compared to the average
   1940       energy in this frame */
   1941    FDKaacEnc_adaptMinSnr(qcOutChannel, psyOutChannel, &AdjThrStateElement->minSnrAdaptParam, nChannels);
   1942 
   1943    /* init ahFlag (0: no ah necessary, 1: ah possible, 2: ah active */
   1944    FDKaacEnc_initAvoidHoleFlag(qcOutChannel, psyOutChannel, pAhFlag, toolsInfo,
   1945                      nChannels, peData, &AdjThrStateElement->ahParam);
   1946 
   1947    /* reduce thresholds */
   1948    FDKaacEnc_reduceThresholdsVBR(qcOutChannel, psyOutChannel, pAhFlag, pThrExp, nChannels,
   1949                        AdjThrStateElement->vbrQualFactor,
   1950                        &AdjThrStateElement->chaosMeasureOld);
   1951 
   1952    /* free scratch memory */
   1953    C_ALLOC_SCRATCH_END(_pThrExp, FIXP_DBL, (2)*MAX_GROUPED_SFB)
   1954    C_ALLOC_SCRATCH_END(_pAhFlag, UCHAR, (2)*MAX_GROUPED_SFB)
   1955 }
   1956 
   1957 
   1958 /*****************************************************************************
   1959 
   1960   functionname: FDKaacEnc_calcBitSave
   1961   description:  Calculates percentage of bit save, see figure below
   1962   returns:
   1963   input:        parameters and bitres-fullness
   1964   output:       percentage of bit save
   1965 
   1966 *****************************************************************************/
   1967 /*
   1968         bitsave
   1969                     maxBitSave(%)|   clipLow
   1970                                  |---\
   1971                                  |    \
   1972                                  |     \
   1973                                  |      \
   1974                                  |       \
   1975                                  |--------\--------------> bitres
   1976                                  |         \
   1977                     minBitSave(%)|          \------------
   1978                                           clipHigh      maxBitres
   1979 */
   1980 static FIXP_DBL FDKaacEnc_calcBitSave(FIXP_DBL fillLevel,
   1981     const FIXP_DBL clipLow,
   1982     const FIXP_DBL clipHigh,
   1983     const FIXP_DBL minBitSave,
   1984     const FIXP_DBL maxBitSave,
   1985     const FIXP_DBL bitsave_slope)
   1986 {
   1987     FIXP_DBL bitsave;
   1988 
   1989     fillLevel = fixMax(fillLevel, clipLow);
   1990     fillLevel = fixMin(fillLevel, clipHigh);
   1991 
   1992     bitsave = maxBitSave - fMult((fillLevel-clipLow), bitsave_slope);
   1993 
   1994     return (bitsave);
   1995 }
   1996 
   1997 /*****************************************************************************
   1998 
   1999   functionname: FDKaacEnc_calcBitSpend
   2000   description:  Calculates percentage of bit spend, see figure below
   2001   returns:
   2002   input:        parameters and bitres-fullness
   2003   output:       percentage of bit spend
   2004 
   2005 *****************************************************************************/
   2006 /*
   2007                               bitspend      clipHigh
   2008                    maxBitSpend(%)|          /-----------maxBitres
   2009                                  |         /
   2010                                  |        /
   2011                                  |       /
   2012                                  |      /
   2013                                  |     /
   2014                                  |----/-----------------> bitres
   2015                                  |   /
   2016                    minBitSpend(%)|--/
   2017                                    clipLow
   2018 */
   2019 static FIXP_DBL FDKaacEnc_calcBitSpend(FIXP_DBL fillLevel,
   2020     const FIXP_DBL clipLow,
   2021     const FIXP_DBL clipHigh,
   2022     const FIXP_DBL minBitSpend,
   2023     const FIXP_DBL maxBitSpend,
   2024     const FIXP_DBL bitspend_slope)
   2025 {
   2026     FIXP_DBL bitspend;
   2027 
   2028     fillLevel = fixMax(fillLevel, clipLow);
   2029     fillLevel = fixMin(fillLevel, clipHigh);
   2030 
   2031     bitspend = minBitSpend + fMult(fillLevel-clipLow, bitspend_slope);
   2032 
   2033     return (bitspend);
   2034 }
   2035 
   2036 
   2037 /*****************************************************************************
   2038 
   2039   functionname: FDKaacEnc_adjustPeMinMax()
   2040   description:  adjusts peMin and peMax parameters over time
   2041   returns:
   2042   input:        current pe, peMin, peMax, bitres size
   2043   output:       adjusted peMin/peMax
   2044 
   2045 *****************************************************************************/
   2046 static void FDKaacEnc_adjustPeMinMax(const INT currPe,
   2047     INT      *peMin,
   2048     INT      *peMax)
   2049 {
   2050   FIXP_DBL minFacHi = FL2FXCONST_DBL(0.3f), maxFacHi = (FIXP_DBL)MAXVAL_DBL, minFacLo = FL2FXCONST_DBL(0.14f), maxFacLo = FL2FXCONST_DBL(0.07f);
   2051     INT diff;
   2052 
   2053     INT minDiff_fix = fMultI(FL2FXCONST_DBL(0.1666666667f), currPe);
   2054 
   2055     if (currPe > *peMax)
   2056     {
   2057         diff = (currPe-*peMax) ;
   2058         *peMin += fMultI(minFacHi,diff);
   2059         *peMax += fMultI(maxFacHi,diff);
   2060     }
   2061     else if (currPe < *peMin)
   2062     {
   2063         diff = (*peMin-currPe) ;
   2064         *peMin -= fMultI(minFacLo,diff);
   2065         *peMax -= fMultI(maxFacLo,diff);
   2066     }
   2067     else
   2068     {
   2069         *peMin += fMultI(minFacHi, (currPe - *peMin));
   2070         *peMax -= fMultI(maxFacLo, (*peMax - currPe));
   2071     }
   2072 
   2073     if ((*peMax - *peMin) < minDiff_fix)
   2074     {
   2075         INT peMax_fix = *peMax, peMin_fix = *peMin;
   2076         FIXP_DBL partLo_fix, partHi_fix;
   2077 
   2078         partLo_fix = (FIXP_DBL)fixMax(0, currPe - peMin_fix);
   2079         partHi_fix = (FIXP_DBL)fixMax(0, peMax_fix - currPe);
   2080 
   2081         peMax_fix = (INT)(currPe + fMultI(fDivNorm(partHi_fix, (partLo_fix+partHi_fix)), minDiff_fix));
   2082         peMin_fix = (INT)(currPe - fMultI(fDivNorm(partLo_fix, (partLo_fix+partHi_fix)), minDiff_fix));
   2083         peMin_fix = fixMax(0, peMin_fix);
   2084 
   2085         *peMax = peMax_fix;
   2086         *peMin = peMin_fix;
   2087     }
   2088 }
   2089 
   2090 
   2091 
   2092 /*****************************************************************************
   2093 
   2094   functionname: BitresCalcBitFac
   2095   description:  calculates factor of spending bits for one frame
   2096   1.0 : take all frame dynpart bits
   2097   >1.0 : take all frame dynpart bits + bitres
   2098   <1.0 : put bits in bitreservoir
   2099   returns:      BitFac
   2100   input:        bitres-fullness, pe, blockType, parameter-settings
   2101   output:
   2102 
   2103 *****************************************************************************/
   2104 /*
   2105                      bitfac(%)            pemax
   2106                    bitspend(%)   |          /-----------maxBitres
   2107                                  |         /
   2108                                  |        /
   2109                                  |       /
   2110                                  |      /
   2111                                  |     /
   2112                                  |----/-----------------> pe
   2113                                  |   /
   2114                    bitsave(%)    |--/
   2115                                     pemin
   2116 */
   2117 
   2118 static FIXP_DBL FDKaacEnc_bitresCalcBitFac(const INT       bitresBits,
   2119     const INT        maxBitresBits,
   2120     const INT        pe,
   2121     const INT        lastWindowSequence,
   2122     const INT        avgBits,
   2123     const FIXP_DBL   maxBitFac,
   2124     ADJ_THR_STATE   *AdjThr,
   2125     ATS_ELEMENT     *adjThrChan)
   2126 {
   2127     BRES_PARAM *bresParam;
   2128     INT pex;
   2129 
   2130     INT qmin, qbr, qbres, qmbr;
   2131     FIXP_DBL bitSave, bitSpend;
   2132 
   2133     FIXP_DBL bitresFac_fix, tmp_cst, tmp_fix;
   2134     FIXP_DBL pe_pers, bits_ratio, maxBrVal;
   2135     FIXP_DBL bitsave_slope, bitspend_slope, maxBitFac_tmp;
   2136     FIXP_DBL fillLevel_fix = (FIXP_DBL)0x7fffffff;
   2137     FIXP_DBL UNITY = (FIXP_DBL)0x7fffffff;
   2138     FIXP_DBL POINT7 = (FIXP_DBL)0x5999999A;
   2139 
   2140     if (maxBitresBits > bitresBits) {
   2141       fillLevel_fix = fDivNorm(bitresBits, maxBitresBits);
   2142     }
   2143 
   2144     if (lastWindowSequence != SHORT_WINDOW)
   2145     {
   2146         bresParam = &(AdjThr->bresParamLong);
   2147         bitsave_slope = (FIXP_DBL)0x3BBBBBBC;
   2148         bitspend_slope = (FIXP_DBL)0x55555555;
   2149     }
   2150     else
   2151     {
   2152         bresParam = &(AdjThr->bresParamShort);
   2153         bitsave_slope = (FIXP_DBL)0x2E8BA2E9;
   2154         bitspend_slope = (FIXP_DBL)0x7fffffff;
   2155     }
   2156 
   2157     pex = fixMax(pe, adjThrChan->peMin);
   2158     pex = fixMin(pex, adjThrChan->peMax);
   2159 
   2160     bitSave = FDKaacEnc_calcBitSave(fillLevel_fix,
   2161         bresParam->clipSaveLow, bresParam->clipSaveHigh,
   2162         bresParam->minBitSave, bresParam->maxBitSave, bitsave_slope);
   2163 
   2164     bitSpend = FDKaacEnc_calcBitSpend(fillLevel_fix,
   2165         bresParam->clipSpendLow, bresParam->clipSpendHigh,
   2166         bresParam->minBitSpend, bresParam->maxBitSpend, bitspend_slope);
   2167 
   2168     pe_pers = (pex > adjThrChan->peMin) ? fDivNorm(pex - adjThrChan->peMin, adjThrChan->peMax - adjThrChan->peMin) : 0;
   2169     tmp_fix = fMult(((FIXP_DBL)bitSpend + (FIXP_DBL)bitSave), pe_pers);
   2170     bitresFac_fix = (UNITY>>1) - ((FIXP_DBL)bitSave>>1) + (tmp_fix>>1); qbres = (DFRACT_BITS-2);
   2171 
   2172     /* (float)bitresBits/(float)avgBits */
   2173     bits_ratio = fDivNorm(bitresBits, avgBits, &qbr);
   2174     qbr = DFRACT_BITS-1-qbr;
   2175 
   2176     /* Add 0.7 in q31 to bits_ratio in qbr */
   2177     /* 0.7f + (float)bitresBits/(float)avgBits */
   2178     qmin = fixMin(qbr, (DFRACT_BITS-1));
   2179     bits_ratio = bits_ratio >> (qbr - qmin);
   2180     tmp_cst = POINT7 >> ((DFRACT_BITS-1) - qmin);
   2181     maxBrVal = (bits_ratio>>1) + (tmp_cst>>1); qmbr = qmin - 1;
   2182 
   2183     /* bitresFac_fix = fixMin(bitresFac_fix, 0.7 + bitresBits/avgBits); */
   2184     bitresFac_fix = bitresFac_fix >> (qbres - qmbr); qbres = qmbr;
   2185     bitresFac_fix = fixMin(bitresFac_fix, maxBrVal);
   2186 
   2187     /* Compare with maxBitFac */
   2188     qmin = fixMin(Q_BITFAC, qbres);
   2189     bitresFac_fix = bitresFac_fix >> (qbres - qmin);
   2190     maxBitFac_tmp = maxBitFac >> (Q_BITFAC - qmin);
   2191     if(maxBitFac_tmp < bitresFac_fix)
   2192     {
   2193         bitresFac_fix = maxBitFac;
   2194     }
   2195     else
   2196     {
   2197         if(qmin < Q_BITFAC)
   2198         {
   2199             bitresFac_fix = bitresFac_fix << (Q_BITFAC-qmin);
   2200         }
   2201         else
   2202         {
   2203             bitresFac_fix = bitresFac_fix >> (qmin-Q_BITFAC);
   2204         }
   2205     }
   2206 
   2207     FDKaacEnc_adjustPeMinMax(pe, &adjThrChan->peMin, &adjThrChan->peMax);
   2208 
   2209     return bitresFac_fix;
   2210 }
   2211 
   2212 
   2213 /*****************************************************************************
   2214 functionname: FDKaacEnc_AdjThrNew
   2215 description:  allocate ADJ_THR_STATE
   2216 *****************************************************************************/
   2217 INT FDKaacEnc_AdjThrNew(ADJ_THR_STATE** phAdjThr,
   2218                         INT             nElements)
   2219 {
   2220     INT err = 0;
   2221     INT i;
   2222     ADJ_THR_STATE* hAdjThr = GetRam_aacEnc_AdjustThreshold();
   2223     if (hAdjThr==NULL) {
   2224         err = 1;
   2225         goto bail;
   2226     }
   2227 
   2228     for (i=0; i<nElements; i++) {
   2229         hAdjThr->adjThrStateElem[i] =  GetRam_aacEnc_AdjThrStateElement(i);
   2230         if (hAdjThr->adjThrStateElem[i]==NULL) {
   2231           err = 1;
   2232           goto bail;
   2233         }
   2234     }
   2235 
   2236 bail:
   2237     *phAdjThr = hAdjThr;
   2238     return err;
   2239 }
   2240 
   2241 
   2242 /*****************************************************************************
   2243 functionname: FDKaacEnc_AdjThrInit
   2244 description:  initialize ADJ_THR_STATE
   2245 *****************************************************************************/
   2246 void FDKaacEnc_AdjThrInit(
   2247         ADJ_THR_STATE   *hAdjThr,
   2248         const INT       meanPe,
   2249         ELEMENT_BITS    *elBits[(8)],
   2250         INT             invQuant,
   2251         INT             nElements,
   2252         INT             nChannelsEff,
   2253         INT             sampleRate,
   2254         INT             advancedBitsToPe,
   2255         FIXP_DBL        vbrQualFactor,
   2256         const INT       dZoneQuantEnable
   2257         )
   2258 {
   2259   INT i;
   2260 
   2261   FIXP_DBL POINT8 = FL2FXCONST_DBL(0.8f);
   2262   FIXP_DBL POINT6 = FL2FXCONST_DBL(0.6f);
   2263 
   2264   /* Max number of iterations in second guess is 3 for lowdelay aot and for configurations with
   2265      multiple audio elements in general, otherwise iteration value is always 1. */
   2266   hAdjThr->maxIter2ndGuess = (advancedBitsToPe!=0 || nElements>1) ? 3 : 1;
   2267 
   2268   /* common for all elements: */
   2269   /* parameters for bitres control */
   2270   hAdjThr->bresParamLong.clipSaveLow   = (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
   2271   hAdjThr->bresParamLong.clipSaveHigh  = (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */
   2272   hAdjThr->bresParamLong.minBitSave    = (FIXP_DBL)0xf999999a; /* FL2FXCONST_DBL(-0.05f); */
   2273   hAdjThr->bresParamLong.maxBitSave    = (FIXP_DBL)0x26666666; /* FL2FXCONST_DBL(0.3f); */
   2274   hAdjThr->bresParamLong.clipSpendLow  = (FIXP_DBL)0x1999999a; /* FL2FXCONST_DBL(0.2f); */
   2275   hAdjThr->bresParamLong.clipSpendHigh = (FIXP_DBL)0x7999999a; /* FL2FXCONST_DBL(0.95f); */
   2276   hAdjThr->bresParamLong.minBitSpend   = (FIXP_DBL)0xf3333333; /* FL2FXCONST_DBL(-0.10f); */
   2277   hAdjThr->bresParamLong.maxBitSpend   = (FIXP_DBL)0x33333333; /* FL2FXCONST_DBL(0.4f); */
   2278 
   2279   hAdjThr->bresParamShort.clipSaveLow   = (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
   2280   hAdjThr->bresParamShort.clipSaveHigh  = (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */
   2281   hAdjThr->bresParamShort.minBitSave    = (FIXP_DBL)0x00000000; /* FL2FXCONST_DBL(0.0f); */
   2282   hAdjThr->bresParamShort.maxBitSave    = (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
   2283   hAdjThr->bresParamShort.clipSpendLow  = (FIXP_DBL)0x199999a0; /* FL2FXCONST_DBL(0.2f); */
   2284   hAdjThr->bresParamShort.clipSpendHigh = (FIXP_DBL)0x5fffffff; /* FL2FXCONST_DBL(0.75f); */
   2285   hAdjThr->bresParamShort.minBitSpend   = (FIXP_DBL)0xf9999998; /* FL2FXCONST_DBL(-0.05f); */
   2286   hAdjThr->bresParamShort.maxBitSpend   = (FIXP_DBL)0x40000000; /* FL2FXCONST_DBL(0.5f); */
   2287 
   2288   /* specific for each element: */
   2289   for (i=0; i<nElements; i++) {
   2290     ATS_ELEMENT* atsElem = hAdjThr->adjThrStateElem[i];
   2291     MINSNR_ADAPT_PARAM *msaParam = &atsElem->minSnrAdaptParam;
   2292     INT chBitrate = elBits[i]->chBitrateEl;
   2293 
   2294     /* parameters for bitres control */
   2295     atsElem->peMin = fMultI(POINT8, meanPe) >> 1;
   2296     atsElem->peMax = fMultI(POINT6, meanPe);
   2297 
   2298     /* for use in FDKaacEnc_reduceThresholdsVBR */
   2299     atsElem->chaosMeasureOld = FL2FXCONST_DBL(0.3f);
   2300 
   2301     /* additional pe offset to correct pe2bits for low bitrates */
   2302     atsElem->peOffset = 0;
   2303 
   2304     /* vbr initialisation */
   2305     atsElem->vbrQualFactor = vbrQualFactor;
   2306     if (chBitrate < 32000)
   2307     {
   2308       atsElem->peOffset = fixMax(50, 100-fMultI((FIXP_DBL)0x666667, chBitrate));
   2309     }
   2310 
   2311     /* avoid hole parameters */
   2312     if (chBitrate > 20000) {
   2313       atsElem->ahParam.modifyMinSnr = TRUE;
   2314       atsElem->ahParam.startSfbL = 15;
   2315       atsElem->ahParam.startSfbS = 3;
   2316     }
   2317     else {
   2318       atsElem->ahParam.modifyMinSnr = FALSE;
   2319       atsElem->ahParam.startSfbL = 0;
   2320       atsElem->ahParam.startSfbS = 0;
   2321     }
   2322 
   2323     /* minSnr adaptation */
   2324     msaParam->maxRed = FL2FXCONST_DBL(0.00390625f); /* 0.25f/64.0f */
   2325     /* start adaptation of minSnr for avgEn/sfbEn > startRatio */
   2326     msaParam->startRatio = FL2FXCONST_DBL(0.05190512648f); /* ld64(10.0f) */
   2327     /* maximum minSnr reduction to minSnr^maxRed is reached for
   2328        avgEn/sfbEn >= maxRatio */
   2329     /* msaParam->maxRatio = 1000.0f; */
   2330     /*msaParam->redRatioFac = ((float)1.0f - msaParam->maxRed) / ((float)10.0f*log10(msaParam->startRatio/msaParam->maxRatio)/log10(2.0f)*(float)0.3010299956f);*/
   2331     msaParam->redRatioFac = FL2FXCONST_DBL(-0.375f); /* -0.0375f * 10.0f */
   2332     /*msaParam->redOffs = (float)1.0f - msaParam->redRatioFac * (float)10.0f * log10(msaParam->startRatio)/log10(2.0f) * (float)0.3010299956f;*/
   2333     msaParam->redOffs = FL2FXCONST_DBL(0.021484375); /* 1.375f/64.0f */
   2334 
   2335     /* init pe correction */
   2336     atsElem->peCorrectionFactor_m = FL2FXCONST_DBL(0.5f); /* 1.0 */
   2337     atsElem->peCorrectionFactor_e = 1;
   2338 
   2339     atsElem->dynBitsLast = -1;
   2340     atsElem->peLast = 0;
   2341 
   2342     /* init bits to pe factor */
   2343 
   2344     /* init bits2PeFactor */
   2345     FDKaacEnc_InitBits2PeFactor(
   2346               &atsElem->bits2PeFactor_m,
   2347               &atsElem->bits2PeFactor_e,
   2348               chBitrate*nChannelsEff, /* overall bitrate */
   2349               nChannelsEff,    /* number of channels */
   2350               sampleRate,
   2351               advancedBitsToPe,
   2352               dZoneQuantEnable,
   2353               invQuant
   2354               );
   2355 
   2356   } /* for nElements */
   2357 
   2358 }
   2359 
   2360 
   2361 /*****************************************************************************
   2362     functionname: FDKaacEnc_FDKaacEnc_calcPeCorrection
   2363     description:  calc desired pe
   2364 *****************************************************************************/
   2365 static void FDKaacEnc_FDKaacEnc_calcPeCorrection(
   2366         FIXP_DBL *const           correctionFac_m,
   2367         INT *const                correctionFac_e,
   2368         const INT                 peAct,
   2369         const INT                 peLast,
   2370         const INT                 bitsLast,
   2371         const FIXP_DBL            bits2PeFactor_m,
   2372         const INT                 bits2PeFactor_e
   2373         )
   2374 {
   2375   if ( (bitsLast > 0) && (peAct < 1.5f*peLast) && (peAct > 0.7f*peLast) &&
   2376        (FDKaacEnc_bits2pe2(bitsLast, fMult(FL2FXCONST_DBL(1.2f/2.f), bits2PeFactor_m), bits2PeFactor_e+1) > peLast) &&
   2377        (FDKaacEnc_bits2pe2(bitsLast, fMult(FL2FXCONST_DBL(0.65f),    bits2PeFactor_m), bits2PeFactor_e  ) < peLast) )
   2378   {
   2379     FIXP_DBL corrFac = *correctionFac_m;
   2380 
   2381     int scaling = 0;
   2382     FIXP_DBL denum = (FIXP_DBL)FDKaacEnc_bits2pe2(bitsLast, bits2PeFactor_m, bits2PeFactor_e);
   2383     FIXP_DBL newFac = fDivNorm((FIXP_DBL)peLast, denum, &scaling);
   2384 
   2385     /* dead zone, newFac and corrFac are scaled by 0.5 */
   2386     if ((FIXP_DBL)peLast <= denum) { /* ratio <= 1.f */
   2387       newFac = fixMax(scaleValue(fixMin( fMult(FL2FXCONST_DBL(1.1f/2.f), newFac), scaleValue(FL2FXCONST_DBL(  1.f/2.f), -scaling)), scaling), FL2FXCONST_DBL(0.85f/2.f) );
   2388     }
   2389     else { /* ratio < 1.f */
   2390      newFac = fixMax( fixMin( scaleValue(fMult(FL2FXCONST_DBL(0.9f/2.f), newFac), scaling), FL2FXCONST_DBL(1.15f/2.f) ), FL2FXCONST_DBL(   1.f/2.f) );
   2391     }
   2392 
   2393     if (   ((newFac > FL2FXCONST_DBL(1.f/2.f)) && (corrFac < FL2FXCONST_DBL(1.f/2.f)))
   2394         || ((newFac < FL2FXCONST_DBL(1.f/2.f)) && (corrFac > FL2FXCONST_DBL(1.f/2.f))))
   2395     {
   2396       corrFac = FL2FXCONST_DBL(1.f/2.f);
   2397     }
   2398 
   2399     /* faster adaptation towards 1.0, slower in the other direction */
   2400     if ( (corrFac < FL2FXCONST_DBL(1.f/2.f) && newFac < corrFac)
   2401       || (corrFac > FL2FXCONST_DBL(1.f/2.f) && newFac > corrFac) )
   2402     {
   2403       corrFac = fMult(FL2FXCONST_DBL(0.85f), corrFac) + fMult(FL2FXCONST_DBL(0.15f), newFac);
   2404     }
   2405     else {
   2406       corrFac = fMult(FL2FXCONST_DBL(0.7f), corrFac) + fMult(FL2FXCONST_DBL(0.3f), newFac);
   2407     }
   2408 
   2409     corrFac = fixMax( fixMin( corrFac, FL2FXCONST_DBL(1.15f/2.f) ), FL2FXCONST_DBL(0.85/2.f) );
   2410 
   2411     *correctionFac_m = corrFac;
   2412     *correctionFac_e = 1;
   2413   }
   2414   else {
   2415     *correctionFac_m = FL2FXCONST_DBL(1.f/2.f);
   2416     *correctionFac_e = 1;
   2417   }
   2418 }
   2419 
   2420 
   2421 static void FDKaacEnc_calcPeCorrectionLowBitRes(
   2422         FIXP_DBL *const           correctionFac_m,
   2423         INT *const                correctionFac_e,
   2424         const INT                 peLast,
   2425         const INT                 bitsLast,
   2426         const INT                 bitresLevel,
   2427         const INT                 nChannels,
   2428         const FIXP_DBL            bits2PeFactor_m,
   2429         const INT                 bits2PeFactor_e
   2430         )
   2431 {
   2432   /* tuning params */
   2433   const FIXP_DBL amp     = FL2FXCONST_DBL(0.005);
   2434   const FIXP_DBL maxDiff = FL2FXCONST_DBL(0.25f);
   2435 
   2436   if (bitsLast > 0) {
   2437 
   2438     /* Estimate deviation of granted and used dynamic bits in previous frame, in PE units */
   2439     const int bitsBalLast = peLast - FDKaacEnc_bits2pe2(
   2440           bitsLast,
   2441           bits2PeFactor_m,
   2442           bits2PeFactor_e);
   2443 
   2444     /* reserve n bits per channel */
   2445     int headroom = (bitresLevel>=50*nChannels) ? 0 : (100*nChannels);
   2446 
   2447     /* in PE units */
   2448     headroom = FDKaacEnc_bits2pe2(
   2449           headroom,
   2450           bits2PeFactor_m,
   2451           bits2PeFactor_e);
   2452 
   2453     /*
   2454      * diff = amp * ((bitsBalLast - headroom) / (bitresLevel + headroom)
   2455      * diff = max ( min ( diff, maxDiff, -maxDiff)) / 2
   2456      */
   2457     FIXP_DBL denominator = (FIXP_DBL)FDKaacEnc_bits2pe2(bitresLevel, bits2PeFactor_m, bits2PeFactor_e) + (FIXP_DBL)headroom;
   2458 
   2459     int scaling = 0;
   2460     FIXP_DBL diff = (bitsBalLast>=headroom)
   2461          ?  fMult(amp, fDivNorm( (FIXP_DBL)(bitsBalLast - headroom), denominator, &scaling))
   2462          : -fMult(amp, fDivNorm(-(FIXP_DBL)(bitsBalLast - headroom), denominator, &scaling)) ;
   2463 
   2464     scaling -= 1; /* divide by 2 */
   2465 
   2466     diff = (scaling<=0) ? FDKmax( FDKmin (diff>>(-scaling), maxDiff>>1), -maxDiff>>1)
   2467                         : FDKmax( FDKmin (diff, maxDiff>>(1+scaling)), -maxDiff>>(1+scaling)) << scaling;
   2468 
   2469     /*
   2470      * corrFac += diff
   2471      * corrFac = max ( min ( corrFac/2.f, 1.f/2.f, 0.75f/2.f ) )
   2472      */
   2473     *correctionFac_m = FDKmax(FDKmin((*correctionFac_m)+diff, FL2FXCONST_DBL(1.0f/2.f)), FL2FXCONST_DBL(0.75f/2.f)) ;
   2474     *correctionFac_e = 1;
   2475   }
   2476   else {
   2477     *correctionFac_m = FL2FXCONST_DBL(0.75/2.f);
   2478     *correctionFac_e = 1;
   2479   }
   2480 }
   2481 
   2482 void FDKaacEnc_DistributeBits(ADJ_THR_STATE *adjThrState,
   2483     ATS_ELEMENT       *AdjThrStateElement,
   2484     PSY_OUT_CHANNEL   *psyOutChannel[(2)],
   2485     PE_DATA           *peData,
   2486     INT               *grantedPe,
   2487     INT               *grantedPeCorr,
   2488     const INT         nChannels,
   2489     const INT         commonWindow,
   2490     const INT         grantedDynBits,
   2491     const INT         bitresBits,
   2492     const INT         maxBitresBits,
   2493     const FIXP_DBL    maxBitFac,
   2494     const INT         bitDistributionMode)
   2495 {
   2496   FIXP_DBL bitFactor;
   2497   INT noRedPe = peData->pe;
   2498 
   2499   /* prefer short windows for calculation of bitFactor */
   2500   INT curWindowSequence = LONG_WINDOW;
   2501   if (nChannels==2) {
   2502     if ((psyOutChannel[0]->lastWindowSequence == SHORT_WINDOW) ||
   2503         (psyOutChannel[1]->lastWindowSequence == SHORT_WINDOW)) {
   2504         curWindowSequence = SHORT_WINDOW;
   2505     }
   2506   }
   2507   else {
   2508     curWindowSequence = psyOutChannel[0]->lastWindowSequence;
   2509   }
   2510 
   2511   if (grantedDynBits >= 1) {
   2512     if (bitDistributionMode!=0) {
   2513       *grantedPe = FDKaacEnc_bits2pe2(grantedDynBits, AdjThrStateElement->bits2PeFactor_m, AdjThrStateElement->bits2PeFactor_e);
   2514     }
   2515     else
   2516     {
   2517     /* factor dependend on current fill level and pe */
   2518     bitFactor = FDKaacEnc_bitresCalcBitFac(bitresBits, maxBitresBits, noRedPe,
   2519                                  curWindowSequence, grantedDynBits, maxBitFac,
   2520                                  adjThrState,
   2521                                  AdjThrStateElement
   2522                                  );
   2523 
   2524     /* desired pe for actual frame */
   2525     /* Worst case max of grantedDynBits is = 1024 * 5.27 * 2 */
   2526     *grantedPe = FDKaacEnc_bits2pe2(grantedDynBits,
   2527                      fMult(bitFactor, AdjThrStateElement->bits2PeFactor_m), AdjThrStateElement->bits2PeFactor_e+(DFRACT_BITS-1-Q_BITFAC)
   2528                      );
   2529     }
   2530   }
   2531   else {
   2532     *grantedPe = 0; /* prevent divsion by 0 */
   2533   }
   2534 
   2535   /* correction of pe value */
   2536   switch (bitDistributionMode) {
   2537   case 2:
   2538   case 1:
   2539     FDKaacEnc_calcPeCorrectionLowBitRes(
   2540            &AdjThrStateElement->peCorrectionFactor_m,
   2541            &AdjThrStateElement->peCorrectionFactor_e,
   2542             AdjThrStateElement->peLast,
   2543             AdjThrStateElement->dynBitsLast,
   2544             bitresBits,
   2545             nChannels,
   2546             AdjThrStateElement->bits2PeFactor_m,
   2547             AdjThrStateElement->bits2PeFactor_e
   2548         );
   2549     break;
   2550   case 0:
   2551   default:
   2552       FDKaacEnc_FDKaacEnc_calcPeCorrection(
   2553            &AdjThrStateElement->peCorrectionFactor_m,
   2554            &AdjThrStateElement->peCorrectionFactor_e,
   2555             fixMin(*grantedPe, noRedPe),
   2556             AdjThrStateElement->peLast,
   2557             AdjThrStateElement->dynBitsLast,
   2558             AdjThrStateElement->bits2PeFactor_m,
   2559             AdjThrStateElement->bits2PeFactor_e
   2560             );
   2561     break;
   2562   }
   2563 
   2564   *grantedPeCorr = (INT)(fMult((FIXP_DBL)(*grantedPe<<Q_AVGBITS), AdjThrStateElement->peCorrectionFactor_m) >> (Q_AVGBITS-AdjThrStateElement->peCorrectionFactor_e));
   2565 
   2566   /* update last pe */
   2567   AdjThrStateElement->peLast = *grantedPe;
   2568   AdjThrStateElement->dynBitsLast = -1;
   2569 
   2570 }
   2571 
   2572 /*****************************************************************************
   2573 functionname: FDKaacEnc_AdjustThresholds
   2574 description:  adjust thresholds
   2575 *****************************************************************************/
   2576 void FDKaacEnc_AdjustThresholds(ATS_ELEMENT*        AdjThrStateElement[(8)],
   2577                                 QC_OUT_ELEMENT*     qcElement[(8)],
   2578                                 QC_OUT*             qcOut,
   2579                                 PSY_OUT_ELEMENT*    psyOutElement[(8)],
   2580                                 INT                 CBRbitrateMode,
   2581                                 INT                 maxIter2ndGuess,
   2582                                 CHANNEL_MAPPING*    cm)
   2583 {
   2584     int i;
   2585     if (CBRbitrateMode)
   2586     {
   2587         /* In case, no bits must be shifted between different elements, */
   2588         /* an element-wise execution of the pe-dependent threshold- */
   2589         /* adaption becomes necessary... */
   2590             for (i=0; i<cm->nElements; i++)
   2591             {
   2592                 ELEMENT_INFO elInfo = cm->elInfo[i];
   2593 
   2594                 if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
   2595                     (elInfo.elType == ID_LFE))
   2596                 {
   2597                     /* qcElement[i]->grantedPe = 2000; */  /* Use this only for debugging */
   2598                     //if (totalGrantedPeCorr < totalNoRedPe) {
   2599                     if (qcElement[i]->grantedPe < qcElement[i]->peData.pe)
   2600                     {
   2601                         /* calc threshold necessary for desired pe */
   2602                         FDKaacEnc_adaptThresholdsToPe(cm,
   2603                                             AdjThrStateElement,
   2604                                             qcElement,
   2605                                             psyOutElement,
   2606                                             qcElement[i]->grantedPeCorr,
   2607                                             maxIter2ndGuess,
   2608                                             1,         /* Process only 1 element */
   2609                                             i);        /* Process exactly THIS element */
   2610 
   2611                     }
   2612 
   2613                 }  /*  -end- if(ID_SCE || ID_CPE || ID_LFE) */
   2614 
   2615             }  /* -end- element loop */
   2616     }
   2617     else {
   2618         for (i=0; i<cm->nElements; i++)
   2619         {
   2620             ELEMENT_INFO elInfo = cm->elInfo[i];
   2621 
   2622             if ((elInfo.elType == ID_SCE) || (elInfo.elType == ID_CPE) ||
   2623                 (elInfo.elType == ID_LFE))
   2624             {
   2625                   /* for VBR-mode */
   2626                   FDKaacEnc_AdaptThresholdsVBR(qcElement[i]->qcOutChannel,
   2627                                             psyOutElement[i]->psyOutChannel,
   2628                                             AdjThrStateElement[i],
   2629                                             &psyOutElement[i]->toolsInfo,
   2630                                             &qcElement[i]->peData,
   2631                                             cm->elInfo[i].nChannelsInEl);
   2632             }  /*  -end- if(ID_SCE || ID_CPE || ID_LFE) */
   2633 
   2634         }  /* -end- element loop */
   2635 
   2636     }
   2637     for (i=0; i<cm->nElements; i++) {
   2638         int ch,sfb,sfbGrp;
   2639         /* no weighting of threholds and energies for mlout */
   2640         /* weight energies and thresholds */
   2641         for (ch=0; ch<cm->elInfo[i].nChannelsInEl; ch++) {
   2642             QC_OUT_CHANNEL* pQcOutCh = qcElement[i]->qcOutChannel[ch];
   2643             for (sfbGrp = 0;sfbGrp < psyOutElement[i]->psyOutChannel[ch]->sfbCnt; sfbGrp+=psyOutElement[i]->psyOutChannel[ch]->sfbPerGroup) {
   2644                 for (sfb=0; sfb<psyOutElement[i]->psyOutChannel[ch]->maxSfbPerGroup; sfb++) {
   2645                     pQcOutCh->sfbThresholdLdData[sfb+sfbGrp] += pQcOutCh->sfbEnFacLd[sfb+sfbGrp];
   2646                 }
   2647             }
   2648         }
   2649     }
   2650 }
   2651 
   2652 void FDKaacEnc_AdjThrClose(ADJ_THR_STATE** phAdjThr)
   2653 {
   2654     INT i;
   2655     ADJ_THR_STATE* hAdjThr = *phAdjThr;
   2656 
   2657     if (hAdjThr!=NULL) {
   2658       for (i=0; i<(8); i++) {
   2659         if (hAdjThr->adjThrStateElem[i]!=NULL) {
   2660           FreeRam_aacEnc_AdjThrStateElement(&hAdjThr->adjThrStateElem[i]);
   2661         }
   2662       }
   2663       FreeRam_aacEnc_AdjustThreshold(phAdjThr);
   2664     }
   2665 }
   2666 
   2667