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:       A. Horndasch (code originally from lwr) / Josef Hoepfl (FDK)
     87    contents/description: intensity stereo processing
     88 
     89 ******************************************************************************/
     90 
     91 #include "intensity.h"
     92 #include "interface.h"
     93 #include "psy_configuration.h"
     94 #include "psy_const.h"
     95 #include "qc_main.h"
     96 #include "bit_cnt.h"
     97 
     98 /* only set an IS seed it left/right channel correlation is above IS_CORR_THRESH */
     99 #define IS_CORR_THRESH                FL2FXCONST_DBL(0.95f)
    100 
    101 /* when expanding the IS region to more SFBs only accept an error that is
    102  * not more than IS_TOTAL_ERROR_THRESH overall and
    103  * not more than IS_LOCAL_ERROR_THRESH for the current SFB */
    104 #define IS_TOTAL_ERROR_THRESH         FL2FXCONST_DBL(0.04f)
    105 #define IS_LOCAL_ERROR_THRESH         FL2FXCONST_DBL(0.01f)
    106 
    107 /* the maximum allowed change of the intensity direction (unit: IS scale) - scaled with factor 0.25 - */
    108 #define IS_DIRECTION_DEVIATION_THRESH_SF 2
    109 #define IS_DIRECTION_DEVIATION_THRESH FL2FXCONST_DBL(2.0f/(1<<IS_DIRECTION_DEVIATION_THRESH_SF))
    110 
    111 /* IS regions need to have a minimal percentage of the overall loudness, e.g. 0.06 == 6% */
    112 #define IS_REGION_MIN_LOUDNESS        FL2FXCONST_DBL(0.1f)
    113 
    114 /* only perform IS if IS_MIN_SFBS neighboring SFBs can be processed */
    115 #define IS_MIN_SFBS                   6
    116 
    117 /* only do IS if
    118  * if IS_LEFT_RIGHT_RATIO_THRESH < sfbEnergyLeft[sfb]/sfbEnergyRight[sfb] < 1 / IS_LEFT_RIGHT_RATIO_THRESH
    119  * -> no IS if the panning angle is not far from the middle, MS will do */
    120 /* this is equivalent to a scale of +/-1.02914634566 */
    121 #define IS_LEFT_RIGHT_RATIO_THRESH    FL2FXCONST_DBL(0.7f)
    122 
    123 /* scalefactor of realScale */
    124 #define REAL_SCALE_SF                    1
    125 
    126 /* scalefactor overallLoudness */
    127 #define OVERALL_LOUDNESS_SF              6
    128 
    129 /* scalefactor for sum over max samples per goup */
    130 #define MAX_SFB_PER_GROUP_SF             6
    131 
    132 /* scalefactor for sum of mdct spectrum */
    133 #define MDCT_SPEC_SF                     6
    134 
    135 
    136 typedef struct
    137 {
    138 
    139   FIXP_DBL corr_thresh;                 /*!< Only set an IS seed it left/right channel correlation is above corr_thresh */
    140 
    141   FIXP_DBL total_error_thresh;          /*!< When expanding the IS region to more SFBs only accept an error that is
    142                                              not more than 'total_error_thresh' overall. */
    143 
    144   FIXP_DBL local_error_thresh;          /*!< When expanding the IS region to more SFBs only accept an error that is
    145                                              not more than 'local_error_thresh' for the current SFB. */
    146 
    147   FIXP_DBL direction_deviation_thresh;  /*!< The maximum allowed change of the intensity direction (unit: IS scale) */
    148 
    149   FIXP_DBL is_region_min_loudness;      /*!< IS regions need to have a minimal percentage of the overall loudness, e.g. 0.06 == 6% */
    150 
    151   INT      min_is_sfbs;                 /*!< Only perform IS if 'min_is_sfbs' neighboring SFBs can be processed */
    152 
    153   FIXP_DBL left_right_ratio_threshold;  /*!< No IS if the panning angle is not far from the middle, MS will do */
    154 
    155 } INTENSITY_PARAMETERS;
    156 
    157 
    158 /*****************************************************************************
    159 
    160     functionname: calcSfbMaxScale
    161 
    162     description:  Calc max value in scalefactor band
    163 
    164     input:        *mdctSpectrum
    165                    l1
    166                    l2
    167 
    168     output:       none
    169 
    170     returns:      scalefactor
    171 
    172 *****************************************************************************/
    173 static INT
    174 calcSfbMaxScale(const FIXP_DBL *mdctSpectrum,
    175                 const INT       l1,
    176                 const INT       l2)
    177 {
    178   INT i;
    179   INT sfbMaxScale;
    180   FIXP_DBL maxSpc;
    181 
    182   maxSpc = FL2FXCONST_DBL(0.0);
    183   for (i=l1; i<l2; i++) {
    184     FIXP_DBL tmp = fixp_abs((FIXP_DBL)mdctSpectrum[i]);
    185     maxSpc = fixMax(maxSpc, tmp);
    186   }
    187   sfbMaxScale = (maxSpc==FL2FXCONST_DBL(0.0)) ? (DFRACT_BITS-2) : CntLeadingZeros(maxSpc)-1;
    188 
    189   return sfbMaxScale;
    190  }
    191 
    192 
    193 /*****************************************************************************
    194 
    195     functionname: FDKaacEnc_initIsParams
    196 
    197     description:  Initialization of intensity parameters
    198 
    199     input:        isParams
    200 
    201     output:       isParams
    202 
    203     returns:      none
    204 
    205 *****************************************************************************/
    206 static void
    207 FDKaacEnc_initIsParams(INTENSITY_PARAMETERS *isParams)
    208 {
    209   isParams->corr_thresh                = IS_CORR_THRESH;
    210   isParams->total_error_thresh         = IS_TOTAL_ERROR_THRESH;
    211   isParams->local_error_thresh         = IS_LOCAL_ERROR_THRESH;
    212   isParams->direction_deviation_thresh = IS_DIRECTION_DEVIATION_THRESH;
    213   isParams->is_region_min_loudness     = IS_REGION_MIN_LOUDNESS;
    214   isParams->min_is_sfbs                = IS_MIN_SFBS;
    215   isParams->left_right_ratio_threshold = IS_LEFT_RIGHT_RATIO_THRESH;
    216 }
    217 
    218 
    219 /*****************************************************************************
    220 
    221     functionname: FDKaacEnc_prepareIntensityDecision
    222 
    223     description:  Prepares intensity decision
    224 
    225     input:        sfbEnergyLeft
    226                   sfbEnergyRight
    227                   sfbEnergyLdDataLeft
    228                   sfbEnergyLdDataRight
    229                   mdctSpectrumLeft
    230                   sfbEnergyLdDataRight
    231                   isParams
    232 
    233     output:       hrrErr            scale: none
    234                   isMask            scale: none
    235                   realScale         scale: LD_DATA_SHIFT + REAL_SCALE_SF
    236                   normSfbLoudness   scale: none
    237 
    238     returns:      none
    239 
    240 *****************************************************************************/
    241 static void
    242 FDKaacEnc_prepareIntensityDecision(const FIXP_DBL    *sfbEnergyLeft,
    243                                    const FIXP_DBL    *sfbEnergyRight,
    244                                    const FIXP_DBL    *sfbEnergyLdDataLeft,
    245                                    const FIXP_DBL    *sfbEnergyLdDataRight,
    246                                    const FIXP_DBL    *mdctSpectrumLeft,
    247                                    const FIXP_DBL    *mdctSpectrumRight,
    248                                    const INTENSITY_PARAMETERS *isParams,
    249                                    FIXP_DBL    *hrrErr,
    250                                    INT         *isMask,
    251                                    FIXP_DBL    *realScale,
    252                                    FIXP_DBL    *normSfbLoudness,
    253                                    const INT    sfbCnt,
    254                                    const INT    sfbPerGroup,
    255                                    const INT    maxSfbPerGroup,
    256                                    const INT   *sfbOffset)
    257 {
    258   INT j,sfb,sfboffs;
    259   INT grpCounter;
    260 
    261   /* temporary variables to compute loudness */
    262   FIXP_DBL overallLoudness[MAX_NO_OF_GROUPS];
    263 
    264   /* temporary variables to compute correlation */
    265   FIXP_DBL channelCorr[MAX_GROUPED_SFB];
    266   FIXP_DBL ml, mr;
    267   FIXP_DBL prod_lr;
    268   FIXP_DBL square_l, square_r;
    269   FIXP_DBL tmp_l, tmp_r;
    270   FIXP_DBL inv_n;
    271 
    272   FDKmemclear(channelCorr,     MAX_GROUPED_SFB*sizeof(FIXP_DBL));
    273   FDKmemclear(normSfbLoudness, MAX_GROUPED_SFB*sizeof(FIXP_DBL));
    274   FDKmemclear(overallLoudness, MAX_NO_OF_GROUPS*sizeof(FIXP_DBL));
    275   FDKmemclear(realScale,       MAX_GROUPED_SFB*sizeof(FIXP_DBL));
    276 
    277   for (grpCounter = 0, sfboffs = 0; sfboffs < sfbCnt; sfboffs += sfbPerGroup, grpCounter++) {
    278     overallLoudness[grpCounter] = FL2FXCONST_DBL(0.0f);
    279     for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
    280       INT sL,sR,s;
    281       FIXP_DBL isValue = sfbEnergyLdDataLeft[sfb+sfboffs]-sfbEnergyLdDataRight[sfb+sfboffs];
    282 
    283       /* delimitate intensity scale value to representable range */
    284       realScale[sfb + sfboffs] = fixMin(FL2FXCONST_DBL(60.f/(1<<(REAL_SCALE_SF+LD_DATA_SHIFT))), fixMax(FL2FXCONST_DBL(-60.f/(1<<(REAL_SCALE_SF+LD_DATA_SHIFT))), isValue));
    285 
    286       sL = fixMax(0,(CntLeadingZeros(sfbEnergyLeft[sfb + sfboffs])-1));
    287       sR = fixMax(0,(CntLeadingZeros(sfbEnergyRight[sfb + sfboffs])-1));
    288       s  = (fixMin(sL,sR)>>2)<<2;
    289       normSfbLoudness[sfb + sfboffs] = sqrtFixp(sqrtFixp(((sfbEnergyLeft[sfb + sfboffs]<<s) >> 1) + ((sfbEnergyRight[sfb + sfboffs]<<s) >> 1))) >> (s>>2);
    290 
    291       overallLoudness[grpCounter] += normSfbLoudness[sfb + sfboffs] >> OVERALL_LOUDNESS_SF;
    292       /* don't do intensity if
    293        * - panning angle is too close to the middle or
    294        * - one channel is non-existent or
    295        * - if it is dual mono */
    296       if(   (sfbEnergyLeft[sfb + sfboffs] >= fMult(isParams->left_right_ratio_threshold,sfbEnergyRight[sfb + sfboffs]))
    297          && (fMult(isParams->left_right_ratio_threshold,sfbEnergyLeft[sfb + sfboffs]) <= sfbEnergyRight[sfb + sfboffs]) ) {
    298 
    299         /* this will prevent post processing from considering this SFB for merging */
    300         hrrErr[sfb + sfboffs] = FL2FXCONST_DBL(1.0/8.0);
    301       }
    302     }
    303   }
    304 
    305   for (grpCounter = 0, sfboffs = 0; sfboffs < sfbCnt; sfboffs += sfbPerGroup, grpCounter++) {
    306     INT invOverallLoudnessSF;
    307     FIXP_DBL invOverallLoudness;
    308 
    309     if (overallLoudness[grpCounter] == FL2FXCONST_DBL(0.0)) {
    310       invOverallLoudness = FL2FXCONST_DBL(0.0);
    311       invOverallLoudnessSF = 0;
    312     }
    313     else {
    314       invOverallLoudness = fDivNorm((FIXP_DBL)MAXVAL_DBL, overallLoudness[grpCounter],&invOverallLoudnessSF);
    315       invOverallLoudnessSF = invOverallLoudnessSF - OVERALL_LOUDNESS_SF + 1; /* +1: compensate fMultDiv2() in subsequent loop */
    316     }
    317     invOverallLoudnessSF = fixMin(fixMax(invOverallLoudnessSF,-(DFRACT_BITS-1)),DFRACT_BITS-1);
    318 
    319     for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
    320       FIXP_DBL tmp;
    321 
    322       tmp = fMultDiv2((normSfbLoudness[sfb + sfboffs]>>OVERALL_LOUDNESS_SF)<<OVERALL_LOUDNESS_SF,invOverallLoudness);
    323 
    324       normSfbLoudness[sfb + sfboffs] = scaleValue(tmp, invOverallLoudnessSF);
    325 
    326       channelCorr[sfb + sfboffs] = FL2FXCONST_DBL(0.0f);
    327 
    328       FDK_ASSERT(50 >= 49);
    329       /* max width of scalefactorband is 96; width's are always even */
    330       /* inv_n is scaled with factor 2 to compensate fMultDiv2() in subsequent loops */
    331       inv_n = GetInvInt((sfbOffset[sfb + sfboffs + 1] - sfbOffset[sfb + sfboffs])>>1);
    332 
    333       if (inv_n > FL2FXCONST_DBL(0.0f)) {
    334         INT s,sL,sR;
    335 
    336         /* correlation := Pearson's product-moment coefficient */
    337         /* compute correlation between channels and check if it is over threshold */
    338         ml       = FL2FXCONST_DBL(0.0f);
    339         mr       = FL2FXCONST_DBL(0.0f);
    340         prod_lr  = FL2FXCONST_DBL(0.0f);
    341         square_l = FL2FXCONST_DBL(0.0f);
    342         square_r = FL2FXCONST_DBL(0.0f);
    343 
    344         sL = calcSfbMaxScale(mdctSpectrumLeft,sfbOffset[sfb+sfboffs],sfbOffset[sfb+sfboffs+1]);
    345         sR = calcSfbMaxScale(mdctSpectrumRight,sfbOffset[sfb+sfboffs],sfbOffset[sfb+sfboffs+1]);
    346         s = fixMin(sL,sR);
    347 
    348         for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; j++) {
    349           ml += fMultDiv2((mdctSpectrumLeft[j]  << s),inv_n);             // scaled with mdctScale - s + inv_n
    350           mr += fMultDiv2((mdctSpectrumRight[j] << s),inv_n);             // scaled with mdctScale - s + inv_n
    351         }
    352         ml = fMultDiv2(ml,inv_n);                                         // scaled with mdctScale - s + inv_n
    353         mr = fMultDiv2(mr,inv_n);                                         // scaled with mdctScale - s + inv_n
    354 
    355         for (j = sfbOffset[sfb + sfboffs]; j < sfbOffset[sfb + sfboffs + 1]; j++) {
    356           tmp_l = fMultDiv2((mdctSpectrumLeft[j]  << s),inv_n) - ml;      // scaled with mdctScale - s + inv_n
    357           tmp_r = fMultDiv2((mdctSpectrumRight[j] << s),inv_n) - mr;      // scaled with mdctScale - s + inv_n
    358 
    359           prod_lr  += fMultDiv2(tmp_l,tmp_r);                             // scaled with 2*(mdctScale - s + inv_n) + 1
    360           square_l += fPow2Div2(tmp_l);                                   // scaled with 2*(mdctScale - s + inv_n) + 1
    361           square_r += fPow2Div2(tmp_r);                                   // scaled with 2*(mdctScale - s + inv_n) + 1
    362         }
    363         prod_lr  = prod_lr  << 1;                                         // scaled with 2*(mdctScale - s + inv_n)
    364         square_l = square_l << 1;                                         // scaled with 2*(mdctScale - s + inv_n)
    365         square_r = square_r << 1;                                         // scaled with 2*(mdctScale - s + inv_n)
    366 
    367         if (square_l > FL2FXCONST_DBL(0.0f) && square_r > FL2FXCONST_DBL(0.0f)) {
    368           INT channelCorrSF = 0;
    369 
    370           /* local scaling of square_l and square_r is compensated after sqrt calculation */
    371           sL  = fixMax(0,(CntLeadingZeros(square_l)-1));
    372           sR  = fixMax(0,(CntLeadingZeros(square_r)-1));
    373           s   = ((sL + sR)>>1)<<1;
    374           sL  = fixMin(sL,s);
    375           sR  = s-sL;
    376           tmp = fMult(square_l<<sL,square_r<<sR);
    377           tmp = sqrtFixp(tmp);
    378 
    379           FDK_ASSERT(tmp > FL2FXCONST_DBL(0.0f));
    380 
    381           /* numerator and denominator have the same scaling */
    382           if (prod_lr < FL2FXCONST_DBL(0.0f) ) {
    383             channelCorr[sfb + sfboffs] = -(fDivNorm(-prod_lr,tmp,&channelCorrSF));
    384 
    385           }
    386           else {
    387             channelCorr[sfb + sfboffs] =  (fDivNorm( prod_lr,tmp,&channelCorrSF));
    388           }
    389           channelCorrSF = fixMin(fixMax(( channelCorrSF + ((sL+sR)>>1)),-(DFRACT_BITS-1)),DFRACT_BITS-1);
    390 
    391           if (channelCorrSF < 0) {
    392             channelCorr[sfb + sfboffs] = channelCorr[sfb + sfboffs] >> (-channelCorrSF);
    393           }
    394           else {
    395             /* avoid overflows due to limited computational accuracy */
    396             if ( fAbs(channelCorr[sfb + sfboffs]) > (((FIXP_DBL)MAXVAL_DBL)>>channelCorrSF) ) {
    397               if (channelCorr[sfb + sfboffs] < FL2FXCONST_DBL(0.0f))
    398                 channelCorr[sfb + sfboffs] = -(FIXP_DBL) MAXVAL_DBL;
    399               else
    400                 channelCorr[sfb + sfboffs] =  (FIXP_DBL) MAXVAL_DBL;
    401             }
    402             else {
    403               channelCorr[sfb + sfboffs] = channelCorr[sfb + sfboffs] << channelCorrSF;
    404             }
    405           }
    406         }
    407       }
    408 
    409       /* for post processing: hrrErr is the error in terms of (too little) correlation
    410        * weighted with the loudness of the SFB; SFBs with small hrrErr can be merged */
    411       if (hrrErr[sfb + sfboffs] == FL2FXCONST_DBL(1.0/8.0)) {
    412         continue;
    413       }
    414 
    415       hrrErr[sfb + sfboffs] = fMultDiv2((FL2FXCONST_DBL(0.25f)-(channelCorr[sfb + sfboffs]>>2)),normSfbLoudness[sfb + sfboffs]);
    416 
    417       /* set IS mask/vector to 1, if correlation is high enough */
    418       if (fAbs(channelCorr[sfb + sfboffs]) >= isParams->corr_thresh) {
    419         isMask[sfb + sfboffs] = 1;
    420       }
    421     }
    422   }
    423 }
    424 
    425 
    426 /*****************************************************************************
    427 
    428     functionname: FDKaacEnc_finalizeIntensityDecision
    429 
    430     description:  Finalizes intensity decision
    431 
    432     input:        isParams          scale: none
    433                   hrrErr            scale: none
    434                   realIsScale       scale: LD_DATA_SHIFT + REAL_SCALE_SF
    435                   normSfbLoudness   scale: none
    436 
    437     output:       isMask            scale: none
    438 
    439     returns:      none
    440 
    441 *****************************************************************************/
    442 static void
    443 FDKaacEnc_finalizeIntensityDecision(const FIXP_DBL *hrrErr,
    444                                     INT            *isMask,
    445                                     const FIXP_DBL *realIsScale,
    446                                     const FIXP_DBL *normSfbLoudness,
    447                                     const INTENSITY_PARAMETERS *isParams,
    448                                     const INT       sfbCnt,
    449                                     const INT       sfbPerGroup,
    450                                     const INT       maxSfbPerGroup)
    451 {
    452   INT sfb,sfboffs, j;
    453   INT startIsSfb = 0;
    454   INT inIsBlock;
    455   INT currentIsSfbCount;
    456   FIXP_DBL overallHrrError;
    457   FIXP_DBL isScaleLast = FL2FXCONST_DBL(0.0f);
    458   FIXP_DBL isRegionLoudness;
    459 
    460   for (sfboffs = 0; sfboffs < sfbCnt; sfboffs += sfbPerGroup) {
    461     inIsBlock = 0;
    462     currentIsSfbCount = 0;
    463     overallHrrError = FL2FXCONST_DBL(0.0f);
    464     isRegionLoudness = FL2FXCONST_DBL(0.0f);
    465     for (sfb = 0; sfb < maxSfbPerGroup; sfb++) {
    466       if (isMask[sfboffs + sfb] == 1) {
    467         if (currentIsSfbCount == 0) {
    468           startIsSfb = sfboffs + sfb;
    469           isScaleLast = realIsScale[sfboffs + sfb];
    470         }
    471         inIsBlock = 1;
    472         currentIsSfbCount++;
    473         overallHrrError  += hrrErr[sfboffs + sfb] >> (MAX_SFB_PER_GROUP_SF-3);
    474         isRegionLoudness += normSfbLoudness[sfboffs + sfb] >> MAX_SFB_PER_GROUP_SF;
    475       }
    476       else {
    477         /* based on correlation, IS should not be used
    478          * -> use it anyway, if overall error is below threshold
    479          *    and if local error does not exceed threshold
    480          * otherwise: check if there are enough IS SFBs
    481          */
    482         if (inIsBlock) {
    483           overallHrrError  += hrrErr[sfboffs + sfb] >> (MAX_SFB_PER_GROUP_SF-3);
    484           isRegionLoudness += normSfbLoudness[sfboffs + sfb] >> MAX_SFB_PER_GROUP_SF;
    485 
    486           if ( (hrrErr[sfboffs + sfb] < (isParams->local_error_thresh>>3)) && (overallHrrError < (isParams->total_error_thresh>>MAX_SFB_PER_GROUP_SF)) ) {
    487             currentIsSfbCount++;
    488             /* overwrite correlation based decision */
    489             isMask[sfboffs + sfb] = 1;
    490           } else {
    491             inIsBlock = 0;
    492           }
    493         }
    494       }
    495       /* check for large direction deviation */
    496       if (inIsBlock) {
    497         if( fAbs(isScaleLast-realIsScale[sfboffs + sfb]) < (isParams->direction_deviation_thresh>>(REAL_SCALE_SF+LD_DATA_SHIFT-IS_DIRECTION_DEVIATION_THRESH_SF)) ) {
    498           isScaleLast = realIsScale[sfboffs + sfb];
    499         }
    500         else{
    501           isMask[sfboffs + sfb] = 0;
    502           inIsBlock = 0;
    503           currentIsSfbCount--;
    504         }
    505       }
    506 
    507       if (currentIsSfbCount > 0 && (!inIsBlock || sfb == maxSfbPerGroup - 1)) {
    508         /* not enough SFBs -> do not use IS */
    509         if (currentIsSfbCount < isParams->min_is_sfbs || (isRegionLoudness < isParams->is_region_min_loudness>>MAX_SFB_PER_GROUP_SF)) {
    510           for(j = startIsSfb; j <= sfboffs + sfb; j++) {
    511             isMask[j] = 0;
    512           }
    513         }
    514         currentIsSfbCount = 0;
    515         overallHrrError = FL2FXCONST_DBL(0.0f);
    516         isRegionLoudness = FL2FXCONST_DBL(0.0f);
    517       }
    518     }
    519   }
    520 }
    521 
    522 
    523 /*****************************************************************************
    524 
    525     functionname: FDKaacEnc_IntensityStereoProcessing
    526 
    527     description:  Intensity stereo processing tool
    528 
    529     input:        sfbEnergyLeft
    530                   sfbEnergyRight
    531                   mdctSpectrumLeft
    532                   mdctSpectrumRight
    533                   sfbThresholdLeft
    534                   sfbThresholdRight
    535                   sfbSpreadEnLeft
    536                   sfbSpreadEnRight
    537                   sfbEnergyLdDataLeft
    538                   sfbEnergyLdDataRight
    539 
    540     output:       isBook
    541                   isScale
    542                   pnsData->pnsFlag
    543                   msDigest                 zeroed from start to sfbCnt
    544                   msMask                   zeroed from start to sfbCnt
    545                   mdctSpectrumRight        zeroed where isBook!=0
    546                   sfbEnergyRight           zeroed where isBook!=0
    547                   sfbSpreadEnRight       zeroed where isBook!=0
    548                   sfbThresholdRight        zeroed where isBook!=0
    549                   sfbEnergyLdDataRight     FL2FXCONST_DBL(-1.0) where isBook!=0
    550                   sfbThresholdLdDataRight  FL2FXCONST_DBL(-0.515625f) where isBook!=0
    551 
    552     returns:      none
    553 
    554 *****************************************************************************/
    555 void FDKaacEnc_IntensityStereoProcessing(
    556         FIXP_DBL                  *sfbEnergyLeft,
    557         FIXP_DBL                  *sfbEnergyRight,
    558         FIXP_DBL                  *mdctSpectrumLeft,
    559         FIXP_DBL                  *mdctSpectrumRight,
    560         FIXP_DBL                  *sfbThresholdLeft,
    561         FIXP_DBL                  *sfbThresholdRight,
    562         FIXP_DBL                  *sfbThresholdLdDataRight,
    563         FIXP_DBL                  *sfbSpreadEnLeft,
    564         FIXP_DBL                  *sfbSpreadEnRight,
    565         FIXP_DBL                  *sfbEnergyLdDataLeft,
    566         FIXP_DBL                  *sfbEnergyLdDataRight,
    567         INT                       *msDigest,
    568         INT                       *msMask,
    569         const INT                  sfbCnt,
    570         const INT                  sfbPerGroup,
    571         const INT                  maxSfbPerGroup,
    572         const INT                 *sfbOffset,
    573         const INT                  allowIS,
    574         INT                       *isBook,
    575         INT                       *isScale,
    576         PNS_DATA         *RESTRICT pnsData[2]
    577         )
    578 {
    579   INT sfb,sfboffs, j;
    580   FIXP_DBL scale;
    581   FIXP_DBL lr;
    582   FIXP_DBL hrrErr[MAX_GROUPED_SFB];
    583   FIXP_DBL normSfbLoudness[MAX_GROUPED_SFB];
    584   FIXP_DBL realIsScale[MAX_GROUPED_SFB];
    585   INTENSITY_PARAMETERS isParams;
    586   INT isMask[MAX_GROUPED_SFB];
    587 
    588   FDKmemclear((void*)isBook,sfbCnt*sizeof(INT));
    589   FDKmemclear((void*)isMask,sfbCnt*sizeof(INT));
    590   FDKmemclear((void*)realIsScale,sfbCnt*sizeof(FIXP_DBL));
    591   FDKmemclear((void*)isScale,sfbCnt*sizeof(INT));
    592   FDKmemclear((void*)hrrErr,sfbCnt*sizeof(FIXP_DBL));
    593 
    594   if (!allowIS)
    595     return;
    596 
    597   FDKaacEnc_initIsParams(&isParams);
    598 
    599   /* compute / set the following values per SFB:
    600    * - left/right ratio between channels
    601    * - normalized loudness
    602    *   + loudness == average of energy in channels to 0.25
    603    *   + normalization: division by sum of all SFB loudnesses
    604    * - isMask (is set to 0 if channels are the same or one is 0)
    605    */
    606    FDKaacEnc_prepareIntensityDecision(sfbEnergyLeft,
    607                                       sfbEnergyRight,
    608                                       sfbEnergyLdDataLeft,
    609                                       sfbEnergyLdDataRight,
    610                                       mdctSpectrumLeft,
    611                                       mdctSpectrumRight,
    612                                       &isParams,
    613                                       hrrErr,
    614                                       isMask,
    615                                       realIsScale,
    616                                       normSfbLoudness,
    617                                       sfbCnt,
    618                                       sfbPerGroup,
    619                                       maxSfbPerGroup,
    620                                       sfbOffset);
    621 
    622   FDKaacEnc_finalizeIntensityDecision(hrrErr,
    623                                       isMask,
    624                                       realIsScale,
    625                                       normSfbLoudness,
    626                                       &isParams,
    627                                       sfbCnt,
    628                                       sfbPerGroup,
    629                                       maxSfbPerGroup);
    630 
    631   for (sfb=0; sfb<sfbCnt; sfb+=sfbPerGroup) {
    632     for (sfboffs=0; sfboffs<maxSfbPerGroup; sfboffs++) {
    633       INT sL, sR;
    634       FIXP_DBL inv_n;
    635 
    636       msMask[sfb+sfboffs] = 0;
    637       if (isMask[sfb+sfboffs] == 0) {
    638         continue;
    639       }
    640 
    641       if (   (sfbEnergyLeft[sfb+sfboffs] < sfbThresholdLeft[sfb+sfboffs])
    642           &&(fMult(FL2FXCONST_DBL(1.0f/1.5f),sfbEnergyRight[sfb+sfboffs]) > sfbThresholdRight[sfb+sfboffs]) ) {
    643         continue;
    644       }
    645       /* NEW: if there is a big-enough IS region, switch off PNS */
    646       if (pnsData[0]) {
    647         if(pnsData[0]->pnsFlag[sfb+sfboffs]) {
    648           pnsData[0]->pnsFlag[sfb+sfboffs] = 0;
    649         }
    650         if(pnsData[1]->pnsFlag[sfb+sfboffs]) {
    651           pnsData[1]->pnsFlag[sfb+sfboffs] = 0;
    652         }
    653       }
    654 
    655       inv_n = GetInvInt((sfbOffset[sfb + sfboffs + 1] - sfbOffset[sfb + sfboffs])>>1);  // scaled with 2 to compensate fMultDiv2() in subsequent loop
    656       sL = calcSfbMaxScale(mdctSpectrumLeft,sfbOffset[sfb+sfboffs],sfbOffset[sfb+sfboffs+1]);
    657       sR = calcSfbMaxScale(mdctSpectrumRight,sfbOffset[sfb+sfboffs],sfbOffset[sfb+sfboffs+1]);
    658 
    659       lr = FL2FXCONST_DBL(0.0f);
    660       for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++)
    661         lr += fMultDiv2(fMultDiv2(mdctSpectrumLeft[j]<<sL,mdctSpectrumRight[j]<<sR),inv_n);
    662       lr = lr<<1;
    663 
    664       if (lr < FL2FXCONST_DBL(0.0f)) {
    665         /* This means OUT OF phase intensity stereo, cf. standard */
    666         INT s0, s1, s2;
    667         FIXP_DBL tmp, d, ed = FL2FXCONST_DBL(0.0f);
    668 
    669         s0 = fixMin(sL,sR);
    670         for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
    671           d = ((mdctSpectrumLeft[j]<<s0)>>1) - ((mdctSpectrumRight[j]<<s0)>>1);
    672           ed += fMultDiv2(d,d)>>(MDCT_SPEC_SF-1);
    673         }
    674         msMask[sfb+sfboffs] = 1;
    675         tmp = fDivNorm(sfbEnergyLeft[sfb+sfboffs],ed,&s1);
    676         s2 = (s1) + (2*s0) - 2 - MDCT_SPEC_SF;
    677         if (s2 & 1) {
    678           tmp = tmp>>1;
    679           s2 = s2+1;
    680         }
    681         s2 = (s2>>1) + 1;  // +1 compensate fMultDiv2() in subsequent loop
    682         s2 = fixMin(fixMax(s2,-(DFRACT_BITS-1)),(DFRACT_BITS-1));
    683         scale = sqrtFixp(tmp);
    684         if (s2 < 0) {
    685           s2 = -s2;
    686           for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
    687             mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j],scale) - fMultDiv2(mdctSpectrumRight[j],scale)) >> s2;
    688             mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f);
    689           }
    690         }
    691         else {
    692           for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
    693             mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j],scale) - fMultDiv2(mdctSpectrumRight[j],scale)) << s2;
    694             mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f);
    695           }
    696         }
    697       }
    698       else {
    699         /* This means IN phase intensity stereo, cf. standard */
    700         INT s0,s1,s2;
    701         FIXP_DBL tmp, s, es = FL2FXCONST_DBL(0.0f);
    702 
    703         s0 = fixMin(sL,sR);
    704         for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
    705           s   = ((mdctSpectrumLeft[j]<<s0)>>1) + ((mdctSpectrumRight[j]<<s0)>>1);
    706           es += fMultDiv2(s,s)>>(MDCT_SPEC_SF-1);     // scaled 2*(mdctScale - s0 + 1) + MDCT_SPEC_SF
    707         }
    708         msMask[sfb+sfboffs] = 0;
    709         tmp = fDivNorm(sfbEnergyLeft[sfb+sfboffs],es,&s1);
    710         s2 = (s1) + (2*s0) - 2 - MDCT_SPEC_SF;
    711         if (s2 & 1) {
    712           tmp = tmp>>1;
    713           s2 = s2 + 1;
    714         }
    715         s2 = (s2>>1) + 1; // +1 compensate fMultDiv2() in subsequent loop
    716         s2 = fixMin(fixMax(s2,-(DFRACT_BITS-1)),(DFRACT_BITS-1));
    717         scale = sqrtFixp(tmp);
    718         if (s2 < 0) {
    719           s2 = -s2;
    720           for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
    721             mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j],scale) + fMultDiv2(mdctSpectrumRight[j],scale)) >> s2;
    722             mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f);
    723           }
    724         }
    725         else {
    726           for (j=sfbOffset[sfb+sfboffs]; j<sfbOffset[sfb+sfboffs+1]; j++) {
    727             mdctSpectrumLeft[j] = (fMultDiv2(mdctSpectrumLeft[j],scale) + fMultDiv2(mdctSpectrumRight[j],scale)) << s2;
    728             mdctSpectrumRight[j] = FL2FXCONST_DBL(0.0f);
    729           }
    730         }
    731       }
    732 
    733       isBook[sfb+sfboffs] = CODE_BOOK_IS_IN_PHASE_NO;
    734 
    735       if ( realIsScale[sfb+sfboffs] < FL2FXCONST_DBL(0.0f) ) {
    736         isScale[sfb+sfboffs] = (INT)(((realIsScale[sfb+sfboffs]>>1)-FL2FXCONST_DBL(0.5f/(1<<(REAL_SCALE_SF+LD_DATA_SHIFT+1))))>>(DFRACT_BITS-1-REAL_SCALE_SF-LD_DATA_SHIFT-1)) + 1;
    737       }
    738       else {
    739         isScale[sfb+sfboffs] = (INT)(((realIsScale[sfb+sfboffs]>>1)+FL2FXCONST_DBL(0.5f/(1<<(REAL_SCALE_SF+LD_DATA_SHIFT+1))))>>(DFRACT_BITS-1-REAL_SCALE_SF-LD_DATA_SHIFT-1));
    740       }
    741 
    742       sfbEnergyRight[sfb+sfboffs] = FL2FXCONST_DBL(0.0f);
    743       sfbEnergyLdDataRight[sfb+sfboffs] = FL2FXCONST_DBL(-1.0f);
    744       sfbThresholdRight[sfb+sfboffs] = FL2FXCONST_DBL(0.0f);
    745       sfbThresholdLdDataRight[sfb+sfboffs] = FL2FXCONST_DBL(-0.515625f);
    746       sfbSpreadEnRight[sfb+sfboffs] = FL2FXCONST_DBL(0.0f);
    747 
    748       *msDigest = MS_SOME;
    749     }
    750   }
    751 }
    752 
    753