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