Home | History | Annotate | Download | only in src
      1 
      2 /* -----------------------------------------------------------------------------------------------------------
      3 Software License for The Fraunhofer FDK AAC Codec Library for Android
      4 
      5  Copyright  1995 - 2015 Fraunhofer-Gesellschaft zur Frderung der angewandten Forschung e.V.
      6   All rights reserved.
      7 
      8  1.    INTRODUCTION
      9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
     10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
     11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
     12 
     13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
     14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
     15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
     16 of the MPEG specifications.
     17 
     18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
     19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
     20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
     21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
     22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
     23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
     24 
     25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
     26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
     27 applications information and documentation.
     28 
     29 2.    COPYRIGHT LICENSE
     30 
     31 Redistribution and use in source and binary forms, with or without modification, are permitted without
     32 payment of copyright license fees provided that you satisfy the following conditions:
     33 
     34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
     35 your modifications thereto in source code form.
     36 
     37 You must retain the complete text of this software license in the documentation and/or other materials
     38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
     39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
     40 modifications thereto to recipients of copies in binary form.
     41 
     42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
     43 prior written permission.
     44 
     45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
     46 software or your modifications thereto.
     47 
     48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
     49 and the date of any change. For modified versions of the FDK AAC Codec, the term
     50 "Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
     51 "Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
     52 
     53 3.    NO PATENT LICENSE
     54 
     55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
     56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
     57 respect to this software.
     58 
     59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
     60 by appropriate patent licenses.
     61 
     62 4.    DISCLAIMER
     63 
     64 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
     65 "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
     66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
     68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
     69 or business interruption, however caused and on any theory of liability, whether in contract, strict
     70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
     71 advised of the possibility of such damage.
     72 
     73 5.    CONTACT INFORMATION
     74 
     75 Fraunhofer Institute for Integrated Circuits IIS
     76 Attention: Audio and Multimedia Departments - FDK AAC LL
     77 Am Wolfsmantel 33
     78 91058 Erlangen, Germany
     79 
     80 www.iis.fraunhofer.de/amm
     81 amm-info (at) iis.fraunhofer.de
     82 ----------------------------------------------------------------------------------------------------------- */
     83 
     84 /******************************** MPEG Audio Encoder **************************
     85 
     86    Initial author:       M. Werner
     87    contents/description: Scale factor estimation
     88 
     89 ******************************************************************************/
     90 
     91 #include "sf_estim.h"
     92 #include "aacEnc_rom.h"
     93 #include "quantize.h"
     94 #include "bit_cnt.h"
     95 
     96 
     97 
     98 
     99 #define AS_PE_FAC_SHIFT 7
    100 #define DIST_FAC_SHIFT  3
    101 #define AS_PE_FAC_FLOAT (float)(1 << AS_PE_FAC_SHIFT)
    102 static const INT MAX_SCF_DELTA = 60;
    103 
    104 
    105 static const FIXP_DBL PE_C1 = FL2FXCONST_DBL(3.0f/AS_PE_FAC_FLOAT);          /* (log(8.0)/log(2)) >> AS_PE_FAC_SHIFT */
    106 static const FIXP_DBL PE_C2 = FL2FXCONST_DBL(1.3219281f/AS_PE_FAC_FLOAT);    /* (log(2.5)/log(2)) >> AS_PE_FAC_SHIFT */
    107 static const FIXP_DBL PE_C3 = FL2FXCONST_DBL(0.5593573f);                    /* 1-C2/C1 */
    108 
    109 
    110 /*
    111   Function; FDKaacEnc_FDKaacEnc_CalcFormFactorChannel
    112 
    113   Description: Calculates the formfactor
    114 
    115   sf: scale factor of the mdct spectrum
    116   sfbFormFactorLdData is scaled with the factor 1/(((2^sf)^0.5) * (2^FORM_FAC_SHIFT))
    117 */
    118 static void
    119 FDKaacEnc_FDKaacEnc_CalcFormFactorChannel(FIXP_DBL *RESTRICT sfbFormFactorLdData,
    120                       PSY_OUT_CHANNEL *RESTRICT psyOutChan)
    121 {
    122   INT j, sfb, sfbGrp;
    123   FIXP_DBL formFactor;
    124 
    125   int tmp0 = psyOutChan->sfbCnt;
    126   int tmp1 = psyOutChan->maxSfbPerGroup;
    127   int step = psyOutChan->sfbPerGroup;
    128   for(sfbGrp = 0; sfbGrp < tmp0; sfbGrp += step) {
    129     for (sfb = 0; sfb < tmp1; sfb++) {
    130       formFactor = FL2FXCONST_DBL(0.0f);
    131       /* calc sum of sqrt(spec) */
    132       for(j=psyOutChan->sfbOffsets[sfbGrp+sfb]; j<psyOutChan->sfbOffsets[sfbGrp+sfb+1]; j++ ) {
    133          formFactor += sqrtFixp(fixp_abs(psyOutChan->mdctSpectrum[j]))>>FORM_FAC_SHIFT;
    134       }
    135       sfbFormFactorLdData[sfbGrp+sfb] = CalcLdData(formFactor);
    136     }
    137     /* set sfbFormFactor for sfbs with zero spec to zero. Just for debugging. */
    138     for ( ; sfb < psyOutChan->sfbPerGroup; sfb++) {
    139       sfbFormFactorLdData[sfbGrp+sfb] = FL2FXCONST_DBL(-1.0f);
    140     }
    141   }
    142 }
    143 
    144 /*
    145   Function: FDKaacEnc_CalcFormFactor
    146 
    147   Description: Calls FDKaacEnc_FDKaacEnc_CalcFormFactorChannel() for each channel
    148 */
    149 
    150 void
    151 FDKaacEnc_CalcFormFactor(QC_OUT_CHANNEL   *qcOutChannel[(2)],
    152                PSY_OUT_CHANNEL  *psyOutChannel[(2)],
    153                const INT        nChannels)
    154 {
    155   INT j;
    156   for (j=0; j<nChannels; j++) {
    157     FDKaacEnc_FDKaacEnc_CalcFormFactorChannel(qcOutChannel[j]->sfbFormFactorLdData, psyOutChannel[j]);
    158   }
    159 }
    160 
    161 /*
    162   Function: FDKaacEnc_calcSfbRelevantLines
    163 
    164   Description: Calculates sfbNRelevantLines
    165 
    166   sfbNRelevantLines is scaled with the factor 1/((2^FORM_FAC_SHIFT) * 2.0)
    167 */
    168 static void
    169 FDKaacEnc_calcSfbRelevantLines( const FIXP_DBL *const sfbFormFactorLdData,
    170                       const FIXP_DBL *const sfbEnergyLdData,
    171                       const FIXP_DBL *const sfbThresholdLdData,
    172                       const INT *const sfbOffsets,
    173                       const INT sfbCnt,
    174                       const INT sfbPerGroup,
    175                       const INT maxSfbPerGroup,
    176                       FIXP_DBL *sfbNRelevantLines)
    177 {
    178   INT sfbOffs, sfb;
    179   FIXP_DBL sfbWidthLdData;
    180   FIXP_DBL asPeFacLdData = FL2FXCONST_DBL(0.109375);   /* AS_PE_FAC_SHIFT*ld64(2) */
    181   FIXP_DBL accu;
    182 
    183   /* sfbNRelevantLines[i] = 2^( (sfbFormFactorLdData[i] - 0.25 * (sfbEnergyLdData[i] - ld64(sfbWidth[i]/(2^7)) - AS_PE_FAC_SHIFT*ld64(2)) * 64); */
    184 
    185   FDKmemclear(sfbNRelevantLines, sfbCnt * sizeof(FIXP_DBL));
    186 
    187   for (sfbOffs=0; sfbOffs<sfbCnt; sfbOffs+=sfbPerGroup) {
    188     for(sfb=0; sfb<maxSfbPerGroup; sfb++) {
    189       /* calc sum of sqrt(spec) */
    190       if((FIXP_DBL)sfbEnergyLdData[sfbOffs+sfb] > (FIXP_DBL)sfbThresholdLdData[sfbOffs+sfb]) {
    191         INT sfbWidth = sfbOffsets[sfbOffs+sfb+1] - sfbOffsets[sfbOffs+sfb];
    192 
    193         /* avgFormFactorLdData = sqrtFixp(sqrtFixp(sfbEnergyLdData[sfbOffs+sfb]/sfbWidth)); */
    194         /* sfbNRelevantLines[sfbOffs+sfb] = sfbFormFactor[sfbOffs+sfb] / avgFormFactorLdData; */
    195         sfbWidthLdData = (FIXP_DBL)(sfbWidth << (DFRACT_BITS-1-AS_PE_FAC_SHIFT));
    196         sfbWidthLdData = CalcLdData(sfbWidthLdData);
    197 
    198         accu = sfbEnergyLdData[sfbOffs+sfb] - sfbWidthLdData - asPeFacLdData;
    199         accu = sfbFormFactorLdData[sfbOffs+sfb] - (accu >> 2);
    200 
    201         sfbNRelevantLines[sfbOffs+sfb] = CalcInvLdData(accu) >> 1;
    202       }
    203     }
    204   }
    205 }
    206 
    207 /*
    208   Function: FDKaacEnc_countSingleScfBits
    209 
    210   Description:
    211 
    212   scfBitsFract is scaled by 1/(2^(2*AS_PE_FAC_SHIFT))
    213 */
    214 static FIXP_DBL FDKaacEnc_countSingleScfBits(INT scf, INT scfLeft, INT scfRight)
    215 {
    216   FIXP_DBL scfBitsFract;
    217 
    218   scfBitsFract = (FIXP_DBL) (  FDKaacEnc_bitCountScalefactorDelta(scfLeft-scf)
    219                              + FDKaacEnc_bitCountScalefactorDelta(scf-scfRight) );
    220 
    221   scfBitsFract = scfBitsFract << (DFRACT_BITS-1-(2*AS_PE_FAC_SHIFT));
    222 
    223   return scfBitsFract; /* output scaled by 1/(2^(2*AS_PE_FAC)) */
    224 }
    225 
    226 /*
    227   Function: FDKaacEnc_calcSingleSpecPe
    228 
    229   specPe is scaled by 1/(2^(2*AS_PE_FAC_SHIFT))
    230 */
    231 static FIXP_DBL FDKaacEnc_calcSingleSpecPe(INT scf, FIXP_DBL sfbConstPePart, FIXP_DBL nLines)
    232 {
    233   FIXP_DBL specPe = FL2FXCONST_DBL(0.0f);
    234   FIXP_DBL ldRatio;
    235   FIXP_DBL scfFract;
    236 
    237   scfFract = (FIXP_DBL)(scf << (DFRACT_BITS-1-AS_PE_FAC_SHIFT));
    238 
    239   ldRatio = sfbConstPePart - fMult(FL2FXCONST_DBL(0.375f),scfFract);
    240 
    241   if (ldRatio >= PE_C1) {
    242     specPe = fMult(FL2FXCONST_DBL(0.7f),fMult(nLines,ldRatio));
    243   }
    244   else {
    245     specPe = fMult(FL2FXCONST_DBL(0.7f),fMult(nLines,(PE_C2 + fMult(PE_C3,ldRatio))));
    246   }
    247 
    248   return specPe; /* output scaled by 1/(2^(2*AS_PE_FAC)) */
    249 }
    250 
    251 /*
    252   Function: FDKaacEnc_countScfBitsDiff
    253 
    254   scfBitsDiff is scaled by 1/(2^(2*AS_PE_FAC_SHIFT))
    255 */
    256 static FIXP_DBL FDKaacEnc_countScfBitsDiff(INT *scfOld,
    257                                  INT *scfNew,
    258                                  INT sfbCnt,
    259                                  INT startSfb,
    260                                  INT stopSfb)
    261 {
    262   FIXP_DBL scfBitsFract;
    263   INT scfBitsDiff = 0;
    264   INT sfb = 0, sfbLast;
    265   INT sfbPrev, sfbNext;
    266 
    267   /* search for first relevant sfb */
    268   sfbLast = startSfb;
    269   while ((sfbLast<stopSfb) && (scfOld[sfbLast]==FDK_INT_MIN))
    270     sfbLast++;
    271   /* search for previous relevant sfb and count diff */
    272   sfbPrev = startSfb - 1;
    273   while ((sfbPrev>=0) && (scfOld[sfbPrev]==FDK_INT_MIN))
    274     sfbPrev--;
    275   if (sfbPrev>=0)
    276     scfBitsDiff += FDKaacEnc_bitCountScalefactorDelta(scfNew[sfbPrev]-scfNew[sfbLast]) -
    277                    FDKaacEnc_bitCountScalefactorDelta(scfOld[sfbPrev]-scfOld[sfbLast]);
    278   /* now loop through all sfbs and count diffs of relevant sfbs */
    279   for (sfb=sfbLast+1; sfb<stopSfb; sfb++) {
    280     if (scfOld[sfb]!=FDK_INT_MIN) {
    281       scfBitsDiff += FDKaacEnc_bitCountScalefactorDelta(scfNew[sfbLast]-scfNew[sfb]) -
    282                      FDKaacEnc_bitCountScalefactorDelta(scfOld[sfbLast]-scfOld[sfb]);
    283       sfbLast = sfb;
    284     }
    285   }
    286   /* search for next relevant sfb and count diff */
    287   sfbNext = stopSfb;
    288   while ((sfbNext<sfbCnt) && (scfOld[sfbNext]==FDK_INT_MIN))
    289     sfbNext++;
    290   if (sfbNext<sfbCnt)
    291     scfBitsDiff += FDKaacEnc_bitCountScalefactorDelta(scfNew[sfbLast]-scfNew[sfbNext]) -
    292                    FDKaacEnc_bitCountScalefactorDelta(scfOld[sfbLast]-scfOld[sfbNext]);
    293 
    294   scfBitsFract = (FIXP_DBL) (scfBitsDiff << (DFRACT_BITS-1-(2*AS_PE_FAC_SHIFT)));
    295 
    296   return scfBitsFract;
    297 }
    298 
    299 /*
    300   Function: FDKaacEnc_calcSpecPeDiff
    301 
    302   specPeDiff is scaled by 1/(2^(2*AS_PE_FAC_SHIFT))
    303 */
    304 static FIXP_DBL FDKaacEnc_calcSpecPeDiff(PSY_OUT_CHANNEL *psyOutChan,
    305                                QC_OUT_CHANNEL  *qcOutChannel,
    306                                INT *scfOld,
    307                                INT *scfNew,
    308                                FIXP_DBL *sfbConstPePart,
    309                                FIXP_DBL *sfbFormFactorLdData,
    310                                FIXP_DBL *sfbNRelevantLines,
    311                                INT startSfb,
    312                                INT stopSfb)
    313 {
    314   FIXP_DBL specPeDiff = FL2FXCONST_DBL(0.0f);
    315   FIXP_DBL scfFract = FL2FXCONST_DBL(0.0f);
    316   INT sfb;
    317 
    318   /* loop through all sfbs and count pe difference */
    319   for (sfb=startSfb; sfb<stopSfb; sfb++) {
    320     if (scfOld[sfb]!=FDK_INT_MIN) {
    321       FIXP_DBL ldRatioOld, ldRatioNew, pOld, pNew;
    322 
    323       /* sfbConstPePart[sfb] = (float)log(psyOutChan->sfbEnergy[sfb] * 6.75f / sfbFormFactor[sfb]) * LOG2_1; */
    324       /* 0.02152255861f = log(6.75)/log(2)/AS_PE_FAC_FLOAT; LOG2_1 is 1.0 for log2 */
    325       /* 0.09375f = log(64.0)/log(2.0)/64.0 = scale of sfbFormFactorLdData */
    326       if (sfbConstPePart[sfb] == (FIXP_DBL)FDK_INT_MIN)
    327         sfbConstPePart[sfb] = ((psyOutChan->sfbEnergyLdData[sfb] - sfbFormFactorLdData[sfb] - FL2FXCONST_DBL(0.09375f)) >> 1) + FL2FXCONST_DBL(0.02152255861f);
    328 
    329       scfFract = (FIXP_DBL) (scfOld[sfb] << (DFRACT_BITS-1-AS_PE_FAC_SHIFT));
    330       ldRatioOld = sfbConstPePart[sfb] - fMult(FL2FXCONST_DBL(0.375f),scfFract);
    331 
    332       scfFract = (FIXP_DBL) (scfNew[sfb] << (DFRACT_BITS-1-AS_PE_FAC_SHIFT));
    333       ldRatioNew = sfbConstPePart[sfb] - fMult(FL2FXCONST_DBL(0.375f),scfFract);
    334 
    335       if (ldRatioOld >= PE_C1)
    336         pOld = ldRatioOld;
    337       else
    338         pOld = PE_C2 + fMult(PE_C3,ldRatioOld);
    339 
    340       if (ldRatioNew >= PE_C1)
    341         pNew = ldRatioNew;
    342       else
    343         pNew = PE_C2 + fMult(PE_C3,ldRatioNew);
    344 
    345       specPeDiff += fMult(FL2FXCONST_DBL(0.7f),fMult(sfbNRelevantLines[sfb],(pNew - pOld)));
    346     }
    347   }
    348 
    349   return specPeDiff;
    350 }
    351 
    352 /*
    353   Function: FDKaacEnc_improveScf
    354 
    355   Description: Calculate the distortion by quantization and inverse quantization of the spectrum with
    356                various scalefactors. The scalefactor which provides the best results will be used.
    357 */
    358 static INT FDKaacEnc_improveScf(FIXP_DBL *spec,
    359                       SHORT *quantSpec,
    360                       SHORT *quantSpecTmp,
    361                       INT sfbWidth,
    362                       FIXP_DBL  threshLdData,
    363                       INT scf,
    364                       INT minScf,
    365                       FIXP_DBL  *distLdData,
    366                       INT *minScfCalculated,
    367                       INT dZoneQuantEnable
    368                       )
    369 {
    370    FIXP_DBL sfbDistLdData;
    371    INT scfBest = scf;
    372    INT k;
    373    FIXP_DBL distFactorLdData = FL2FXCONST_DBL(-0.0050301265);   /* ld64(1/1.25) */
    374 
    375    /* calc real distortion */
    376    sfbDistLdData = FDKaacEnc_calcSfbDist(spec,
    377                                          quantSpec,
    378                                          sfbWidth,
    379                                          scf,
    380                                          dZoneQuantEnable);
    381    *minScfCalculated = scf;
    382    /* nmr > 1.25 -> try to improve nmr */
    383    if (sfbDistLdData > (threshLdData-distFactorLdData)) {
    384       INT scfEstimated = scf;
    385       FIXP_DBL sfbDistBestLdData = sfbDistLdData;
    386       INT cnt;
    387       /* improve by bigger scf ? */
    388       cnt = 0;
    389 
    390       while ((sfbDistLdData > (threshLdData-distFactorLdData)) && (cnt++ < 3)) {
    391          scf++;
    392          sfbDistLdData = FDKaacEnc_calcSfbDist(spec,
    393                                                quantSpecTmp,
    394                                                sfbWidth,
    395                                                scf,
    396                                                dZoneQuantEnable);
    397 
    398          if (sfbDistLdData < sfbDistBestLdData) {
    399             scfBest = scf;
    400             sfbDistBestLdData = sfbDistLdData;
    401             for (k=0; k<sfbWidth; k++)
    402 	             quantSpec[k] = quantSpecTmp[k];
    403          }
    404       }
    405       /* improve by smaller scf ? */
    406       cnt = 0;
    407       scf = scfEstimated;
    408       sfbDistLdData = sfbDistBestLdData;
    409       while ((sfbDistLdData > (threshLdData-distFactorLdData)) && (cnt++ < 1) && (scf > minScf)) {
    410          scf--;
    411          sfbDistLdData = FDKaacEnc_calcSfbDist(spec,
    412                                                quantSpecTmp,
    413                                                sfbWidth,
    414                                                scf,
    415                                                dZoneQuantEnable);
    416 
    417          if (sfbDistLdData < sfbDistBestLdData) {
    418             scfBest = scf;
    419             sfbDistBestLdData = sfbDistLdData;
    420             for (k=0; k<sfbWidth; k++)
    421 	             quantSpec[k] = quantSpecTmp[k];
    422          }
    423          *minScfCalculated = scf;
    424       }
    425       *distLdData = sfbDistBestLdData;
    426    }
    427    else { /* nmr <= 1.25 -> try to find bigger scf to use less bits */
    428       FIXP_DBL sfbDistBestLdData = sfbDistLdData;
    429       FIXP_DBL sfbDistAllowedLdData = fixMin(sfbDistLdData-distFactorLdData,threshLdData);
    430       int cnt;
    431       for (cnt=0; cnt<3; cnt++) {
    432          scf++;
    433          sfbDistLdData = FDKaacEnc_calcSfbDist(spec,
    434                                                quantSpecTmp,
    435                                                sfbWidth,
    436                                                scf,
    437                                                dZoneQuantEnable);
    438 
    439          if (sfbDistLdData < sfbDistAllowedLdData) {
    440            *minScfCalculated = scfBest+1;
    441            scfBest = scf;
    442            sfbDistBestLdData = sfbDistLdData;
    443            for (k=0; k<sfbWidth; k++)
    444              quantSpec[k] = quantSpecTmp[k];
    445          }
    446       }
    447       *distLdData = sfbDistBestLdData;
    448    }
    449 
    450    /* return best scalefactor */
    451    return scfBest;
    452 }
    453 
    454 /*
    455   Function: FDKaacEnc_assimilateSingleScf
    456 
    457 */
    458 static void FDKaacEnc_assimilateSingleScf(PSY_OUT_CHANNEL *psyOutChan,
    459                                 QC_OUT_CHANNEL   *qcOutChannel,
    460                                 SHORT *quantSpec,
    461                                 SHORT *quantSpecTmp,
    462                                 INT dZoneQuantEnable,
    463                                 INT *scf,
    464                                 INT *minScf,
    465                                 FIXP_DBL *sfbDist,
    466                                 FIXP_DBL *sfbConstPePart,
    467                                 FIXP_DBL *sfbFormFactorLdData,
    468                                 FIXP_DBL *sfbNRelevantLines,
    469                                 INT *minScfCalculated,
    470                                 INT restartOnSuccess)
    471 {
    472   INT sfbLast, sfbAct, sfbNext;
    473   INT scfAct, *scfLast, *scfNext, scfMin, scfMax;
    474   INT sfbWidth, sfbOffs;
    475   FIXP_DBL enLdData;
    476   FIXP_DBL sfbPeOld, sfbPeNew;
    477   FIXP_DBL sfbDistNew;
    478   INT i, k;
    479   INT success = 0;
    480   FIXP_DBL deltaPe = FL2FXCONST_DBL(0.0f);
    481   FIXP_DBL deltaPeNew, deltaPeTmp;
    482   INT prevScfLast[MAX_GROUPED_SFB], prevScfNext[MAX_GROUPED_SFB];
    483   FIXP_DBL deltaPeLast[MAX_GROUPED_SFB];
    484   INT updateMinScfCalculated;
    485 
    486   for (i=0; i<psyOutChan->sfbCnt; i++) {
    487     prevScfLast[i] = FDK_INT_MAX;
    488     prevScfNext[i] = FDK_INT_MAX;
    489     deltaPeLast[i] = (FIXP_DBL)FDK_INT_MAX;
    490   }
    491 
    492   sfbLast = -1;
    493   sfbAct  = -1;
    494   sfbNext = -1;
    495   scfLast = 0;
    496   scfNext = 0;
    497   scfMin  = FDK_INT_MAX;
    498   scfMax  = FDK_INT_MAX;
    499   do {
    500     /* search for new relevant sfb */
    501     sfbNext++;
    502     while ((sfbNext < psyOutChan->sfbCnt) && (scf[sfbNext] == FDK_INT_MIN))
    503       sfbNext++;
    504     if ((sfbLast>=0) && (sfbAct>=0) && (sfbNext<psyOutChan->sfbCnt)) {
    505       /* relevant scfs to the left and to the right */
    506       scfAct  = scf[sfbAct];
    507       scfLast = scf + sfbLast;
    508       scfNext = scf + sfbNext;
    509       scfMin  = fixMin(*scfLast, *scfNext);
    510       scfMax  = fixMax(*scfLast, *scfNext);
    511     }
    512     else if ((sfbLast==-1) && (sfbAct>=0) && (sfbNext<psyOutChan->sfbCnt)) {
    513       /* first relevant scf */
    514       scfAct  = scf[sfbAct];
    515       scfLast = &scfAct;
    516       scfNext = scf + sfbNext;
    517       scfMin  = *scfNext;
    518       scfMax  = *scfNext;
    519     }
    520     else if ((sfbLast>=0) && (sfbAct>=0) && (sfbNext==psyOutChan->sfbCnt)) {
    521       /* last relevant scf */
    522       scfAct  = scf[sfbAct];
    523       scfLast = scf + sfbLast;
    524       scfNext = &scfAct;
    525       scfMin  = *scfLast;
    526       scfMax  = *scfLast;
    527     }
    528     if (sfbAct>=0)
    529       scfMin = fixMax(scfMin, minScf[sfbAct]);
    530 
    531     if ((sfbAct >= 0) &&
    532         (sfbLast>=0 || sfbNext<psyOutChan->sfbCnt) &&
    533         (scfAct > scfMin) &&
    534         (scfAct <= scfMin+MAX_SCF_DELTA) &&
    535         (scfAct >= scfMax-MAX_SCF_DELTA) &&
    536         (*scfLast != prevScfLast[sfbAct] ||
    537          *scfNext != prevScfNext[sfbAct] ||
    538          deltaPe < deltaPeLast[sfbAct])) {
    539       /* bigger than neighbouring scf found, try to use smaller scf */
    540       success = 0;
    541 
    542       sfbWidth = psyOutChan->sfbOffsets[sfbAct+1] - psyOutChan->sfbOffsets[sfbAct];
    543       sfbOffs = psyOutChan->sfbOffsets[sfbAct];
    544 
    545       /* estimate required bits for actual scf */
    546       enLdData = qcOutChannel->sfbEnergyLdData[sfbAct];
    547 
    548       /* sfbConstPePart[sfbAct] = (float)log(6.75f*en/sfbFormFactor[sfbAct]) * LOG2_1; */
    549       /* 0.02152255861f = log(6.75)/log(2)/AS_PE_FAC_FLOAT; LOG2_1 is 1.0 for log2 */
    550       /* 0.09375f = log(64.0)/log(2.0)/64.0 = scale of sfbFormFactorLdData */
    551       if (sfbConstPePart[sfbAct] == (FIXP_DBL)FDK_INT_MIN) {
    552         sfbConstPePart[sfbAct] = ((enLdData - sfbFormFactorLdData[sfbAct] - FL2FXCONST_DBL(0.09375f)) >> 1) + FL2FXCONST_DBL(0.02152255861f);
    553       }
    554 
    555       sfbPeOld = FDKaacEnc_calcSingleSpecPe(scfAct,sfbConstPePart[sfbAct],sfbNRelevantLines[sfbAct])
    556                 +FDKaacEnc_countSingleScfBits(scfAct, *scfLast, *scfNext);
    557 
    558       deltaPeNew = deltaPe;
    559       updateMinScfCalculated = 1;
    560 
    561       do {
    562         /* estimate required bits for smaller scf */
    563         scfAct--;
    564         /* check only if the same check was not done before */
    565         if (scfAct < minScfCalculated[sfbAct] && scfAct>=scfMax-MAX_SCF_DELTA){
    566           /* estimate required bits for new scf */
    567           sfbPeNew =  FDKaacEnc_calcSingleSpecPe(scfAct,sfbConstPePart[sfbAct],sfbNRelevantLines[sfbAct])
    568                      +FDKaacEnc_countSingleScfBits(scfAct,*scfLast, *scfNext);
    569 
    570           /* use new scf if no increase in pe and
    571              quantization error is smaller */
    572           deltaPeTmp = deltaPe + sfbPeNew - sfbPeOld;
    573           /* 0.0006103515625f = 10.0f/(2^(2*AS_PE_FAC_SHIFT)) */
    574           if (deltaPeTmp < FL2FXCONST_DBL(0.0006103515625f)) {
    575             /* distortion of new scf */
    576             sfbDistNew = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs,
    577                                                quantSpecTmp+sfbOffs,
    578                                                sfbWidth,
    579                                                scfAct,
    580                                                dZoneQuantEnable);
    581 
    582             if (sfbDistNew < sfbDist[sfbAct]) {
    583               /* success, replace scf by new one */
    584               scf[sfbAct] = scfAct;
    585               sfbDist[sfbAct] = sfbDistNew;
    586 
    587               for (k=0; k<sfbWidth; k++)
    588                 quantSpec[sfbOffs+k] = quantSpecTmp[sfbOffs+k];
    589 
    590               deltaPeNew = deltaPeTmp;
    591               success = 1;
    592             }
    593             /* mark as already checked */
    594             if (updateMinScfCalculated)
    595               minScfCalculated[sfbAct] = scfAct;
    596           }
    597           else {
    598             /* from this scf value on not all new values have been checked */
    599             updateMinScfCalculated = 0;
    600           }
    601         }
    602       } while (scfAct > scfMin);
    603 
    604       deltaPe = deltaPeNew;
    605 
    606       /* save parameters to avoid multiple computations of the same sfb */
    607       prevScfLast[sfbAct] = *scfLast;
    608       prevScfNext[sfbAct] = *scfNext;
    609       deltaPeLast[sfbAct] = deltaPe;
    610     }
    611 
    612     if (success && restartOnSuccess) {
    613       /* start again at first sfb */
    614       sfbLast = -1;
    615       sfbAct  = -1;
    616       sfbNext = -1;
    617       scfLast = 0;
    618       scfNext = 0;
    619       scfMin  = FDK_INT_MAX;
    620       scfMax  = FDK_INT_MAX;
    621       success = 0;
    622     }
    623     else {
    624       /* shift sfbs for next band */
    625       sfbLast = sfbAct;
    626       sfbAct  = sfbNext;
    627     }
    628   } while (sfbNext < psyOutChan->sfbCnt);
    629 }
    630 
    631 /*
    632   Function: FDKaacEnc_assimilateMultipleScf
    633 
    634 */
    635 static void FDKaacEnc_assimilateMultipleScf(PSY_OUT_CHANNEL *psyOutChan,
    636                                   QC_OUT_CHANNEL  *qcOutChannel,
    637                                   SHORT *quantSpec,
    638                                   SHORT *quantSpecTmp,
    639                                   INT dZoneQuantEnable,
    640                                   INT *scf,
    641                                   INT *minScf,
    642                                   FIXP_DBL *sfbDist,
    643                                   FIXP_DBL *sfbConstPePart,
    644                                   FIXP_DBL *sfbFormFactorLdData,
    645                                   FIXP_DBL *sfbNRelevantLines)
    646 {
    647   INT sfb, startSfb, stopSfb;
    648   INT scfTmp[MAX_GROUPED_SFB], scfMin, scfMax, scfAct;
    649   INT possibleRegionFound;
    650   INT sfbWidth, sfbOffs, i, k;
    651   FIXP_DBL sfbDistNew[MAX_GROUPED_SFB], distOldSum, distNewSum;
    652   INT deltaScfBits;
    653   FIXP_DBL deltaSpecPe;
    654   FIXP_DBL deltaPe = FL2FXCONST_DBL(0.0f);
    655   FIXP_DBL deltaPeNew;
    656   INT sfbCnt = psyOutChan->sfbCnt;
    657 
    658   /* calc min and max scalfactors */
    659   scfMin = FDK_INT_MAX;
    660   scfMax = FDK_INT_MIN;
    661   for (sfb=0; sfb<sfbCnt; sfb++) {
    662     if (scf[sfb]!=FDK_INT_MIN) {
    663       scfMin = fixMin(scfMin, scf[sfb]);
    664       scfMax = fixMax(scfMax, scf[sfb]);
    665     }
    666   }
    667 
    668   if (scfMax != FDK_INT_MIN && scfMax <= scfMin+MAX_SCF_DELTA) {
    669 
    670     scfAct = scfMax;
    671 
    672     do {
    673       /* try smaller scf */
    674       scfAct--;
    675       for (i=0; i<MAX_GROUPED_SFB; i++)
    676         scfTmp[i] = scf[i];
    677       stopSfb = 0;
    678       do {
    679         /* search for region where all scfs are bigger than scfAct */
    680         sfb = stopSfb;
    681         while (sfb<sfbCnt && (scf[sfb]==FDK_INT_MIN || scf[sfb] <= scfAct))
    682           sfb++;
    683         startSfb = sfb;
    684         sfb++;
    685         while (sfb<sfbCnt && (scf[sfb]==FDK_INT_MIN || scf[sfb] > scfAct))
    686           sfb++;
    687         stopSfb = sfb;
    688 
    689         /* check if in all sfb of a valid region scfAct >= minScf[sfb] */
    690         possibleRegionFound = 0;
    691         if (startSfb < sfbCnt) {
    692           possibleRegionFound = 1;
    693           for (sfb=startSfb; sfb<stopSfb; sfb++) {
    694             if (scf[sfb] != FDK_INT_MIN)
    695               if (scfAct < minScf[sfb]) {
    696                 possibleRegionFound = 0;
    697                 break;
    698               }
    699           }
    700         }
    701 
    702         if (possibleRegionFound) { /* region found */
    703 
    704           /* replace scfs in region by scfAct */
    705           for (sfb=startSfb; sfb<stopSfb; sfb++) {
    706             if (scfTmp[sfb] != FDK_INT_MIN)
    707               scfTmp[sfb] = scfAct;
    708           }
    709 
    710           /* estimate change in bit demand for new scfs */
    711           deltaScfBits = FDKaacEnc_countScfBitsDiff(scf,scfTmp,sfbCnt,startSfb,stopSfb);
    712 
    713           deltaSpecPe = FDKaacEnc_calcSpecPeDiff(psyOutChan, qcOutChannel, scf, scfTmp, sfbConstPePart,
    714                                        sfbFormFactorLdData, sfbNRelevantLines,
    715                                        startSfb, stopSfb);
    716 
    717           deltaPeNew = deltaPe + (FIXP_DBL)deltaScfBits + deltaSpecPe;
    718 
    719           /* new bit demand small enough ? */
    720           /* 0.0006103515625f = 10.0f/(2^(2*AS_PE_FAC_SHIFT)) */
    721           if (deltaPeNew < FL2FXCONST_DBL(0.0006103515625f)) {
    722 
    723             /* quantize and calc sum of new distortion */
    724             distOldSum = distNewSum = FL2FXCONST_DBL(0.0f);
    725             for (sfb=startSfb; sfb<stopSfb; sfb++) {
    726               if (scfTmp[sfb] != FDK_INT_MIN) {
    727                 distOldSum += CalcInvLdData(sfbDist[sfb]) >> DIST_FAC_SHIFT;
    728 
    729                 sfbWidth = psyOutChan->sfbOffsets[sfb+1] - psyOutChan->sfbOffsets[sfb];
    730                 sfbOffs = psyOutChan->sfbOffsets[sfb];
    731 
    732                 sfbDistNew[sfb] = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs,
    733                                               quantSpecTmp+sfbOffs,
    734                                               sfbWidth,
    735                                               scfAct,
    736                                               dZoneQuantEnable);
    737 
    738                 if (sfbDistNew[sfb] >qcOutChannel->sfbThresholdLdData[sfb]) {
    739                   /* no improvement, skip further dist. calculations */
    740                   distNewSum = distOldSum << 1;
    741                   break;
    742                 }
    743                 distNewSum += CalcInvLdData(sfbDistNew[sfb]) >> DIST_FAC_SHIFT;
    744               }
    745             }
    746             /* distortion smaller ? -> use new scalefactors */
    747             if (distNewSum < distOldSum) {
    748               deltaPe = deltaPeNew;
    749               for (sfb=startSfb; sfb<stopSfb; sfb++) {
    750                 if (scf[sfb] != FDK_INT_MIN) {
    751                   sfbWidth = psyOutChan->sfbOffsets[sfb+1] -
    752                              psyOutChan->sfbOffsets[sfb];
    753                   sfbOffs = psyOutChan->sfbOffsets[sfb];
    754                   scf[sfb] = scfAct;
    755                   sfbDist[sfb] = sfbDistNew[sfb];
    756 
    757                   for (k=0; k<sfbWidth; k++)
    758                     quantSpec[sfbOffs+k] = quantSpecTmp[sfbOffs+k];
    759                 }
    760               }
    761             }
    762 
    763           }
    764         }
    765 
    766       } while (stopSfb <= sfbCnt);
    767 
    768     } while (scfAct > scfMin);
    769   }
    770 }
    771 
    772 /*
    773   Function: FDKaacEnc_FDKaacEnc_assimilateMultipleScf2
    774 
    775 */
    776 static void FDKaacEnc_FDKaacEnc_assimilateMultipleScf2(PSY_OUT_CHANNEL *psyOutChan,
    777                                    QC_OUT_CHANNEL  *qcOutChannel,
    778                                    SHORT *quantSpec,
    779                                    SHORT *quantSpecTmp,
    780                                    INT dZoneQuantEnable,
    781                                    INT *scf,
    782                                    INT *minScf,
    783                                    FIXP_DBL *sfbDist,
    784                                    FIXP_DBL *sfbConstPePart,
    785                                    FIXP_DBL *sfbFormFactorLdData,
    786                                    FIXP_DBL *sfbNRelevantLines)
    787 {
    788   INT sfb, startSfb, stopSfb;
    789   INT scfTmp[MAX_GROUPED_SFB], scfAct, scfNew;
    790   INT scfPrev, scfNext, scfPrevNextMin, scfPrevNextMax, scfLo, scfHi;
    791   INT scfMin, scfMax;
    792   INT *sfbOffs = psyOutChan->sfbOffsets;
    793   FIXP_DBL sfbDistNew[MAX_GROUPED_SFB], sfbDistMax[MAX_GROUPED_SFB];
    794   FIXP_DBL distOldSum, distNewSum;
    795   INT deltaScfBits;
    796   FIXP_DBL deltaSpecPe;
    797   FIXP_DBL deltaPe = FL2FXCONST_DBL(0.0f);
    798   FIXP_DBL deltaPeNew = FL2FXCONST_DBL(0.0f);
    799   INT sfbCnt = psyOutChan->sfbCnt;
    800   INT bSuccess, bCheckScf;
    801   INT i,k;
    802 
    803   /* calc min and max scalfactors */
    804   scfMin = FDK_INT_MAX;
    805   scfMax = FDK_INT_MIN;
    806   for (sfb=0; sfb<sfbCnt; sfb++) {
    807     if (scf[sfb]!=FDK_INT_MIN) {
    808       scfMin = fixMin(scfMin, scf[sfb]);
    809       scfMax = fixMax(scfMax, scf[sfb]);
    810     }
    811   }
    812 
    813   stopSfb = 0;
    814   scfAct = FDK_INT_MIN;
    815   do {
    816     /* search for region with same scf values scfAct */
    817     scfPrev = scfAct;
    818 
    819     sfb = stopSfb;
    820     while (sfb<sfbCnt && (scf[sfb]==FDK_INT_MIN))
    821       sfb++;
    822     startSfb = sfb;
    823     scfAct = scf[startSfb];
    824     sfb++;
    825     while (sfb<sfbCnt && ((scf[sfb]==FDK_INT_MIN) || (scf[sfb]==scf[startSfb])))
    826       sfb++;
    827     stopSfb = sfb;
    828 
    829     if (stopSfb < sfbCnt)
    830       scfNext = scf[stopSfb];
    831     else
    832       scfNext = scfAct;
    833 
    834     if (scfPrev == FDK_INT_MIN)
    835       scfPrev = scfAct;
    836 
    837     scfPrevNextMax = fixMax(scfPrev, scfNext);
    838     scfPrevNextMin = fixMin(scfPrev, scfNext);
    839 
    840     /* try to reduce bits by checking scf values in the range
    841        scf[startSfb]...scfHi */
    842     scfHi = fixMax(scfPrevNextMax, scfAct);
    843     /* try to find a better solution by reducing the scf difference to
    844        the nearest possible lower scf */
    845     if (scfPrevNextMax >= scfAct)
    846       scfLo = fixMin(scfAct, scfPrevNextMin);
    847     else
    848       scfLo = scfPrevNextMax;
    849 
    850     if (startSfb < sfbCnt && scfHi-scfLo <= MAX_SCF_DELTA) { /* region found */
    851       /* 1. try to save bits by coarser quantization */
    852       if (scfHi > scf[startSfb]) {
    853         /* calculate the allowed distortion */
    854         for (sfb=startSfb; sfb<stopSfb; sfb++) {
    855           if (scf[sfb] != FDK_INT_MIN) {
    856             /* sfbDistMax[sfb] = (float)pow(qcOutChannel->sfbThreshold[sfb]*sfbDist[sfb]*sfbDist[sfb],1.0f/3.0f); */
    857             /* sfbDistMax[sfb] = fixMax(sfbDistMax[sfb],qcOutChannel->sfbEnergy[sfb]*FL2FXCONST_DBL(1.e-3f)); */
    858             /* -0.15571537944 = ld64(1.e-3f)*/
    859             sfbDistMax[sfb] = fMult(FL2FXCONST_DBL(1.0f/3.0f),qcOutChannel->sfbThresholdLdData[sfb])+fMult(FL2FXCONST_DBL(1.0f/3.0f),sfbDist[sfb])+fMult(FL2FXCONST_DBL(1.0f/3.0f),sfbDist[sfb]);
    860             sfbDistMax[sfb] = fixMax(sfbDistMax[sfb],qcOutChannel->sfbEnergyLdData[sfb]-FL2FXCONST_DBL(0.15571537944));
    861             sfbDistMax[sfb] = fixMin(sfbDistMax[sfb],qcOutChannel->sfbThresholdLdData[sfb]);
    862           }
    863         }
    864 
    865         /* loop over all possible scf values for this region */
    866         bCheckScf = 1;
    867         for (scfNew=scf[startSfb]+1; scfNew<=scfHi; scfNew++) {
    868 	         for (k=0; k<MAX_GROUPED_SFB; k++)
    869             scfTmp[k] = scf[k];
    870 
    871           /* replace scfs in region by scfNew */
    872           for (sfb=startSfb; sfb<stopSfb; sfb++) {
    873             if (scfTmp[sfb] != FDK_INT_MIN)
    874               scfTmp[sfb] = scfNew;
    875           }
    876 
    877           /* estimate change in bit demand for new scfs */
    878           deltaScfBits = FDKaacEnc_countScfBitsDiff(scf,scfTmp,sfbCnt,startSfb,stopSfb);
    879 
    880           deltaSpecPe = FDKaacEnc_calcSpecPeDiff(psyOutChan, qcOutChannel, scf, scfTmp, sfbConstPePart,
    881                                        sfbFormFactorLdData, sfbNRelevantLines,
    882                                        startSfb, stopSfb);
    883 
    884           deltaPeNew = deltaPe + (FIXP_DBL)deltaScfBits + deltaSpecPe;
    885 
    886           /* new bit demand small enough ? */
    887           if (deltaPeNew < FL2FXCONST_DBL(0.0f)) {
    888             bSuccess = 1;
    889 
    890             /* quantize and calc sum of new distortion */
    891             for (sfb=startSfb; sfb<stopSfb; sfb++) {
    892               if (scfTmp[sfb] != FDK_INT_MIN) {
    893                 sfbDistNew[sfb] = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs[sfb],
    894                                               quantSpecTmp+sfbOffs[sfb],
    895                                               sfbOffs[sfb+1]-sfbOffs[sfb],
    896                                               scfNew,
    897                                               dZoneQuantEnable);
    898 
    899                 if (sfbDistNew[sfb] > sfbDistMax[sfb]) {
    900                   /* no improvement, skip further dist. calculations */
    901                   bSuccess = 0;
    902                   if (sfbDistNew[sfb] == qcOutChannel->sfbEnergyLdData[sfb]) {
    903                     /* if whole sfb is already quantized to 0, further
    904                        checks with even coarser quant. are useless*/
    905                     bCheckScf = 0;
    906                   }
    907                   break;
    908                 }
    909               }
    910             }
    911             if (bCheckScf==0) /* further calculations useless ? */
    912                 break;
    913             /* distortion small enough ? -> use new scalefactors */
    914             if (bSuccess) {
    915               deltaPe = deltaPeNew;
    916               for (sfb=startSfb; sfb<stopSfb; sfb++) {
    917                 if (scf[sfb] != FDK_INT_MIN) {
    918                   scf[sfb] = scfNew;
    919                   sfbDist[sfb] = sfbDistNew[sfb];
    920 
    921                   for (k=0; k<sfbOffs[sfb+1]-sfbOffs[sfb]; k++)
    922                     quantSpec[sfbOffs[sfb]+k] = quantSpecTmp[sfbOffs[sfb]+k];
    923                 }
    924               }
    925             }
    926           }
    927         }
    928       }
    929 
    930       /* 2. only if coarser quantization was not successful, try to find
    931          a better solution by finer quantization and reducing bits for
    932          scalefactor coding */
    933       if (scfAct==scf[startSfb] &&
    934           scfLo < scfAct &&
    935           scfMax-scfMin <= MAX_SCF_DELTA) {
    936 
    937         int bminScfViolation = 0;
    938 
    939         for (k=0; k<MAX_GROUPED_SFB; k++)
    940           scfTmp[k] = scf[k];
    941 
    942         scfNew = scfLo;
    943 
    944         /* replace scfs in region by scfNew and
    945            check if in all sfb scfNew >= minScf[sfb] */
    946         for (sfb=startSfb; sfb<stopSfb; sfb++) {
    947           if (scfTmp[sfb] != FDK_INT_MIN) {
    948             scfTmp[sfb] = scfNew;
    949             if (scfNew < minScf[sfb])
    950               bminScfViolation = 1;
    951           }
    952         }
    953 
    954         if (!bminScfViolation) {
    955           /* estimate change in bit demand for new scfs */
    956           deltaScfBits = FDKaacEnc_countScfBitsDiff(scf,scfTmp,sfbCnt,startSfb,stopSfb);
    957 
    958           deltaSpecPe = FDKaacEnc_calcSpecPeDiff(psyOutChan, qcOutChannel, scf, scfTmp, sfbConstPePart,
    959                                        sfbFormFactorLdData, sfbNRelevantLines,
    960                                        startSfb, stopSfb);
    961 
    962           deltaPeNew = deltaPe + (FIXP_DBL)deltaScfBits + deltaSpecPe;
    963         }
    964 
    965         /* new bit demand small enough ? */
    966         if (!bminScfViolation && deltaPeNew < FL2FXCONST_DBL(0.0f)) {
    967 
    968           /* quantize and calc sum of new distortion */
    969           distOldSum = distNewSum = FL2FXCONST_DBL(0.0f);
    970           for (sfb=startSfb; sfb<stopSfb; sfb++) {
    971             if (scfTmp[sfb] != FDK_INT_MIN) {
    972               distOldSum += CalcInvLdData(sfbDist[sfb]) >> DIST_FAC_SHIFT;
    973 
    974               sfbDistNew[sfb] = FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+sfbOffs[sfb],
    975                                                       quantSpecTmp+sfbOffs[sfb],
    976                                                       sfbOffs[sfb+1]-sfbOffs[sfb],
    977                                                       scfNew,
    978                                                       dZoneQuantEnable);
    979 
    980               if (sfbDistNew[sfb] > qcOutChannel->sfbThresholdLdData[sfb]) {
    981                 /* no improvement, skip further dist. calculations */
    982                 distNewSum = distOldSum << 1;
    983                 break;
    984               }
    985               distNewSum += CalcInvLdData(sfbDistNew[sfb]) >> DIST_FAC_SHIFT;
    986             }
    987           }
    988           /* distortion smaller ? -> use new scalefactors */
    989           if (distNewSum < fMult(FL2FXCONST_DBL(0.8f),distOldSum)) {
    990             deltaPe = deltaPeNew;
    991             for (sfb=startSfb; sfb<stopSfb; sfb++) {
    992               if (scf[sfb] != FDK_INT_MIN) {
    993                 scf[sfb] = scfNew;
    994                 sfbDist[sfb] = sfbDistNew[sfb];
    995 
    996                 for (k=0; k<sfbOffs[sfb+1]-sfbOffs[sfb]; k++)
    997                   quantSpec[sfbOffs[sfb]+k] = quantSpecTmp[sfbOffs[sfb]+k];
    998               }
    999             }
   1000           }
   1001         }
   1002       }
   1003 
   1004       /* 3. try to find a better solution (save bits) by only reducing the
   1005          scalefactor without new quantization */
   1006       if (scfMax-scfMin <= MAX_SCF_DELTA-3) { /* 3 bec. scf is reduced 3 times,
   1007                                                  see for loop below */
   1008 
   1009         for (k=0; k<sfbCnt; k++)
   1010           scfTmp[k] = scf[k];
   1011 
   1012         for (i=0; i<3; i++) {
   1013           scfNew = scfTmp[startSfb]-1;
   1014           /* replace scfs in region by scfNew */
   1015           for (sfb=startSfb; sfb<stopSfb; sfb++) {
   1016             if (scfTmp[sfb] != FDK_INT_MIN)
   1017               scfTmp[sfb] = scfNew;
   1018           }
   1019           /* estimate change in bit demand for new scfs */
   1020           deltaScfBits = FDKaacEnc_countScfBitsDiff(scf,scfTmp,sfbCnt,startSfb,stopSfb);
   1021           deltaPeNew = deltaPe + (FIXP_DBL)deltaScfBits;
   1022           /* new bit demand small enough ? */
   1023           if (deltaPeNew <= FL2FXCONST_DBL(0.0f)) {
   1024 
   1025             bSuccess = 1;
   1026             distOldSum = distNewSum = FL2FXCONST_DBL(0.0f);
   1027             for (sfb=startSfb; sfb<stopSfb; sfb++) {
   1028               if (scfTmp[sfb] != FDK_INT_MIN) {
   1029                 FIXP_DBL sfbEnQ;
   1030                 /* calc the energy and distortion of the quantized spectrum for
   1031                    a smaller scf */
   1032                 FDKaacEnc_calcSfbQuantEnergyAndDist(qcOutChannel->mdctSpectrum+sfbOffs[sfb],
   1033                                           quantSpec+sfbOffs[sfb],
   1034                                           sfbOffs[sfb+1]-sfbOffs[sfb], scfNew,
   1035                                           &sfbEnQ, &sfbDistNew[sfb]);
   1036 
   1037                 distOldSum += CalcInvLdData(sfbDist[sfb]) >> DIST_FAC_SHIFT;
   1038                 distNewSum += CalcInvLdData(sfbDistNew[sfb]) >> DIST_FAC_SHIFT;
   1039 
   1040                 /*  0.00259488556167 = ld64(1.122f) */
   1041                 /* -0.00778722686652 = ld64(0.7079f) */
   1042                 if ((sfbDistNew[sfb] > (sfbDist[sfb]+FL2FXCONST_DBL(0.00259488556167f))) || (sfbEnQ < (qcOutChannel->sfbEnergyLdData[sfb] - FL2FXCONST_DBL(0.00778722686652f)))){
   1043                   bSuccess = 0;
   1044                   break;
   1045                 }
   1046               }
   1047             }
   1048             /* distortion smaller ? -> use new scalefactors */
   1049             if (distNewSum < distOldSum && bSuccess) {
   1050               deltaPe = deltaPeNew;
   1051               for (sfb=startSfb; sfb<stopSfb; sfb++) {
   1052                 if (scf[sfb] != FDK_INT_MIN) {
   1053                   scf[sfb] = scfNew;
   1054                   sfbDist[sfb] = sfbDistNew[sfb];
   1055                 }
   1056               }
   1057             }
   1058           }
   1059         }
   1060       }
   1061     }
   1062   } while (stopSfb <= sfbCnt);
   1063 
   1064 }
   1065 
   1066 static void
   1067 FDKaacEnc_FDKaacEnc_EstimateScaleFactorsChannel(QC_OUT_CHANNEL   *qcOutChannel,
   1068                             PSY_OUT_CHANNEL  *psyOutChannel,
   1069                             INT *RESTRICT scf,
   1070                             INT *RESTRICT globalGain,
   1071                             FIXP_DBL *RESTRICT sfbFormFactorLdData
   1072                             ,const INT invQuant,
   1073                             SHORT *RESTRICT quantSpec,
   1074                             const INT dZoneQuantEnable
   1075                             )
   1076 {
   1077   INT i, j, sfb, sfbOffs;
   1078   INT scfInt;
   1079   INT maxSf;
   1080   INT minSf;
   1081   FIXP_DBL threshLdData;
   1082   FIXP_DBL energyLdData;
   1083   FIXP_DBL energyPartLdData;
   1084   FIXP_DBL thresholdPartLdData;
   1085   FIXP_DBL scfFract;
   1086   FIXP_DBL maxSpec;
   1087   FIXP_DBL absSpec;
   1088   INT minScfCalculated[MAX_GROUPED_SFB];
   1089   FIXP_DBL sfbDistLdData[MAX_GROUPED_SFB];
   1090   C_ALLOC_SCRATCH_START(quantSpecTmp, SHORT, (1024));
   1091   INT minSfMaxQuant[MAX_GROUPED_SFB];
   1092 
   1093   FIXP_DBL threshConstLdData=FL2FXCONST_DBL(0.04304511722f); /* log10(6.75)/log10(2.0)/64.0 */
   1094   FIXP_DBL convConst=FL2FXCONST_DBL(0.30102999566f); /* log10(2.0) */
   1095   FIXP_DBL c1Const=FL2FXCONST_DBL(-0.27083183594f); /* C1 = -69.33295 => C1/2^8 */
   1096 
   1097 
   1098 
   1099   if (invQuant>0) {
   1100     FDKmemclear(quantSpec, (1024)*sizeof(SHORT));
   1101   }
   1102 
   1103   /* scfs without energy or with thresh>energy are marked with FDK_INT_MIN */
   1104   for(i=0; i<psyOutChannel->sfbCnt; i++) {
   1105     scf[i] = FDK_INT_MIN;
   1106   }
   1107 
   1108   for (i=0; i<MAX_GROUPED_SFB; i++) {
   1109     minSfMaxQuant[i] = FDK_INT_MIN;
   1110   }
   1111 
   1112   for (sfbOffs=0; sfbOffs<psyOutChannel->sfbCnt; sfbOffs+=psyOutChannel->sfbPerGroup) {
   1113     for(sfb=0; sfb<psyOutChannel->maxSfbPerGroup; sfb++) {
   1114 
   1115       threshLdData = qcOutChannel->sfbThresholdLdData[sfbOffs+sfb];
   1116       energyLdData = qcOutChannel->sfbEnergyLdData[sfbOffs+sfb];
   1117 
   1118       sfbDistLdData[sfbOffs+sfb] = energyLdData;
   1119 
   1120 
   1121       if (energyLdData > threshLdData) {
   1122         FIXP_DBL tmp;
   1123 
   1124         /* energyPart = (float)log10(sfbFormFactor[sfbOffs+sfb]); */
   1125         /* 0.09375f = log(64.0)/log(2.0)/64.0 = scale of sfbFormFactorLdData */
   1126         energyPartLdData = sfbFormFactorLdData[sfbOffs+sfb] + FL2FXCONST_DBL(0.09375f);
   1127 
   1128         /* influence of allowed distortion */
   1129         /* thresholdPart = (float)log10(6.75*thresh+FLT_MIN); */
   1130         thresholdPartLdData = threshConstLdData + threshLdData;
   1131 
   1132         /* scf calc */
   1133         /* scfFloat = 8.8585f * (thresholdPart - energyPart); */
   1134         scfFract = thresholdPartLdData - energyPartLdData;
   1135         /* conversion from log2 to log10 */
   1136         scfFract = fMult(convConst,scfFract);
   1137         /* (8.8585f * scfFract)/8 = 8/8 * scfFract + 0.8585 * scfFract/8 */
   1138         scfFract = scfFract + fMult(FL2FXCONST_DBL(0.8585f),scfFract >> 3);
   1139 
   1140         /* integer scalefactor */
   1141         /* scfInt = (int)floor(scfFloat); */
   1142         scfInt = (INT)(scfFract>>((DFRACT_BITS-1)-3-LD_DATA_SHIFT)); /* 3 bits => scfFract/8.0; 6 bits => ld64 */
   1143 
   1144         /* maximum of spectrum */
   1145         maxSpec = FL2FXCONST_DBL(0.0f);
   1146 
   1147         for(j=psyOutChannel->sfbOffsets[sfbOffs+sfb]; j<psyOutChannel->sfbOffsets[sfbOffs+sfb+1]; j++ ){
   1148           absSpec = fixp_abs(qcOutChannel->mdctSpectrum[j]);
   1149           maxSpec = (absSpec > maxSpec) ? absSpec : maxSpec;
   1150         }
   1151 
   1152         /* lower scf limit to avoid quantized values bigger than MAX_QUANT */
   1153         /* C1 = -69.33295f, C2 = 5.77078f = 4/log(2) */
   1154         /* minSfMaxQuant[sfbOffs+sfb] = (int)ceil(C1 + C2*log(maxSpec)); */
   1155         /* C1/2^8 + 4/log(2.0)*log(maxSpec)/2^8  => C1/2^8 + log(maxSpec)/log(2.0)*4/2^8 => C1/2^8 + log(maxSpec)/log(2.0)/64.0 */
   1156 
   1157         //minSfMaxQuant[sfbOffs+sfb] = ((INT) ((c1Const + CalcLdData(maxSpec)) >> ((DFRACT_BITS-1)-8))) + 1;
   1158         tmp = CalcLdData(maxSpec);
   1159         if (c1Const>FL2FXCONST_DBL(-1.f)-tmp) {
   1160           minSfMaxQuant[sfbOffs+sfb] = ((INT) ((c1Const + tmp) >> ((DFRACT_BITS-1)-8))) + 1;
   1161         }
   1162         else {
   1163           minSfMaxQuant[sfbOffs+sfb] = ((INT) (FL2FXCONST_DBL(-1.f) >> ((DFRACT_BITS-1)-8))) + 1;
   1164         }
   1165 
   1166         scfInt = fixMax(scfInt, minSfMaxQuant[sfbOffs+sfb]);
   1167 
   1168 
   1169         /* find better scalefactor with analysis by synthesis */
   1170         if (invQuant>0) {
   1171           scfInt = FDKaacEnc_improveScf(qcOutChannel->mdctSpectrum+psyOutChannel->sfbOffsets[sfbOffs+sfb],
   1172                               quantSpec+psyOutChannel->sfbOffsets[sfbOffs+sfb],
   1173                               quantSpecTmp+psyOutChannel->sfbOffsets[sfbOffs+sfb],
   1174                               psyOutChannel->sfbOffsets[sfbOffs+sfb+1]-psyOutChannel->sfbOffsets[sfbOffs+sfb],
   1175                               threshLdData, scfInt, minSfMaxQuant[sfbOffs+sfb],
   1176                               &sfbDistLdData[sfbOffs+sfb], &minScfCalculated[sfbOffs+sfb],
   1177                               dZoneQuantEnable
   1178                               );
   1179         }
   1180         scf[sfbOffs+sfb] = scfInt;
   1181       }
   1182     }
   1183   }
   1184 
   1185 
   1186   if (invQuant>1) {
   1187     /* try to decrease scf differences */
   1188     FIXP_DBL sfbConstPePart[MAX_GROUPED_SFB];
   1189     FIXP_DBL sfbNRelevantLines[MAX_GROUPED_SFB];
   1190 
   1191     for (i=0; i<psyOutChannel->sfbCnt; i++)
   1192       sfbConstPePart[i] = (FIXP_DBL)FDK_INT_MIN;
   1193 
   1194     FDKaacEnc_calcSfbRelevantLines( sfbFormFactorLdData,
   1195                           qcOutChannel->sfbEnergyLdData,
   1196                           qcOutChannel->sfbThresholdLdData,
   1197                           psyOutChannel->sfbOffsets,
   1198                           psyOutChannel->sfbCnt,
   1199                           psyOutChannel->sfbPerGroup,
   1200                           psyOutChannel->maxSfbPerGroup,
   1201                           sfbNRelevantLines);
   1202 
   1203 
   1204     FDKaacEnc_assimilateSingleScf(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp,
   1205                         dZoneQuantEnable,
   1206                         scf,
   1207                         minSfMaxQuant, sfbDistLdData, sfbConstPePart,
   1208                         sfbFormFactorLdData, sfbNRelevantLines, minScfCalculated, 1);
   1209 
   1210     if(invQuant > 1) {
   1211       FDKaacEnc_assimilateMultipleScf(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp,
   1212                         dZoneQuantEnable,
   1213                         scf,
   1214                         minSfMaxQuant, sfbDistLdData, sfbConstPePart,
   1215                         sfbFormFactorLdData, sfbNRelevantLines);
   1216 
   1217       FDKaacEnc_assimilateMultipleScf(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp,
   1218                         dZoneQuantEnable,
   1219                         scf,
   1220                         minSfMaxQuant, sfbDistLdData, sfbConstPePart,
   1221                         sfbFormFactorLdData, sfbNRelevantLines);
   1222 
   1223 
   1224       FDKaacEnc_FDKaacEnc_assimilateMultipleScf2(psyOutChannel, qcOutChannel, quantSpec, quantSpecTmp,
   1225                         dZoneQuantEnable,
   1226                         scf,
   1227                         minSfMaxQuant, sfbDistLdData, sfbConstPePart,
   1228                         sfbFormFactorLdData, sfbNRelevantLines);
   1229     }
   1230   }
   1231 
   1232 
   1233   /* get min scalefac */
   1234   minSf = FDK_INT_MAX;
   1235   for (sfbOffs=0; sfbOffs<psyOutChannel->sfbCnt; sfbOffs+=psyOutChannel->sfbPerGroup) {
   1236     for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) {
   1237       if (scf[sfbOffs+sfb]!=FDK_INT_MIN)
   1238         minSf = fixMin(minSf,scf[sfbOffs+sfb]);
   1239     }
   1240   }
   1241 
   1242   /* limit scf delta */
   1243   for (sfbOffs=0; sfbOffs<psyOutChannel->sfbCnt; sfbOffs+=psyOutChannel->sfbPerGroup) {
   1244     for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) {
   1245       if ((scf[sfbOffs+sfb] != FDK_INT_MIN) && (minSf+MAX_SCF_DELTA) < scf[sfbOffs+sfb]) {
   1246         scf[sfbOffs+sfb] = minSf + MAX_SCF_DELTA;
   1247         if (invQuant > 0) { /* changed bands need to be quantized again */
   1248           sfbDistLdData[sfbOffs+sfb] =
   1249                FDKaacEnc_calcSfbDist(qcOutChannel->mdctSpectrum+psyOutChannel->sfbOffsets[sfbOffs+sfb],
   1250                                      quantSpec+psyOutChannel->sfbOffsets[sfbOffs+sfb],
   1251                                      psyOutChannel->sfbOffsets[sfbOffs+sfb+1]-psyOutChannel->sfbOffsets[sfbOffs+sfb],
   1252                                      scf[sfbOffs+sfb],
   1253                                      dZoneQuantEnable
   1254                                      );
   1255         }
   1256       }
   1257     }
   1258   }
   1259 
   1260 
   1261   /* get max scalefac for global gain */
   1262   maxSf = FDK_INT_MIN;
   1263   for (sfbOffs=0; sfbOffs<psyOutChannel->sfbCnt; sfbOffs+=psyOutChannel->sfbPerGroup) {
   1264     for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) {
   1265       maxSf = fixMax(maxSf,scf[sfbOffs+sfb]);
   1266     }
   1267   }
   1268 
   1269   /* calc loop scalefactors, if spec is not all zero (i.e. maxSf == -99) */
   1270   if( maxSf > FDK_INT_MIN ) {
   1271     *globalGain = maxSf;
   1272     for (sfbOffs=0; sfbOffs<psyOutChannel->sfbCnt; sfbOffs+=psyOutChannel->sfbPerGroup) {
   1273       for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) {
   1274         if( scf[sfbOffs+sfb] == FDK_INT_MIN ) {
   1275           scf[sfbOffs+sfb] = 0;
   1276           /* set band explicitely to zero */
   1277           for(j=psyOutChannel->sfbOffsets[sfbOffs+sfb]; j<psyOutChannel->sfbOffsets[sfbOffs+sfb+1]; j++ ) {
   1278             qcOutChannel->mdctSpectrum[j] = FL2FXCONST_DBL(0.0f);
   1279           }
   1280         }
   1281         else {
   1282           scf[sfbOffs+sfb] = maxSf - scf[sfbOffs+sfb];
   1283         }
   1284       }
   1285     }
   1286   }
   1287   else{
   1288     *globalGain = 0;
   1289     /* set spectrum explicitely to zero */
   1290     for (sfbOffs=0; sfbOffs<psyOutChannel->sfbCnt; sfbOffs+=psyOutChannel->sfbPerGroup) {
   1291       for (sfb = 0; sfb < psyOutChannel->maxSfbPerGroup; sfb++) {
   1292         scf[sfbOffs+sfb] = 0;
   1293         /* set band explicitely to zero */
   1294         for(j=psyOutChannel->sfbOffsets[sfbOffs+sfb]; j<psyOutChannel->sfbOffsets[sfbOffs+sfb+1]; j++ ) {
   1295           qcOutChannel->mdctSpectrum[j] = FL2FXCONST_DBL(0.0f);
   1296         }
   1297       }
   1298     }
   1299   }
   1300 
   1301   /* free quantSpecTmp from scratch */
   1302   C_ALLOC_SCRATCH_END(quantSpecTmp, SHORT, (1024));
   1303 
   1304 
   1305 }
   1306 
   1307 void
   1308 FDKaacEnc_EstimateScaleFactors(PSY_OUT_CHANNEL *psyOutChannel[],
   1309                      QC_OUT_CHANNEL* qcOutChannel[],
   1310                      const int invQuant,
   1311                      const INT dZoneQuantEnable,
   1312                      const int nChannels)
   1313 {
   1314   int ch;
   1315 
   1316   for (ch = 0; ch < nChannels; ch++)
   1317   {
   1318       FDKaacEnc_FDKaacEnc_EstimateScaleFactorsChannel(qcOutChannel[ch],
   1319                                   psyOutChannel[ch],
   1320                                   qcOutChannel[ch]->scf,
   1321                                   &qcOutChannel[ch]->globalGain,
   1322                                   qcOutChannel[ch]->sfbFormFactorLdData
   1323                                   ,invQuant,
   1324                                   qcOutChannel[ch]->quantSpec,
   1325                                   dZoneQuantEnable
   1326                                   );
   1327   }
   1328 
   1329 }
   1330 
   1331