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