Home | History | Annotate | Download | only in src
      1 
      2 /* -----------------------------------------------------------------------------------------------------------
      3 Software License for The Fraunhofer FDK AAC Codec Library for Android
      4 
      5  Copyright  1995 - 2013 Fraunhofer-Gesellschaft zur Frderung der angewandten Forschung e.V.
      6   All rights reserved.
      7 
      8  1.    INTRODUCTION
      9 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
     10 the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
     11 This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
     12 
     13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
     14 audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
     15 independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
     16 of the MPEG specifications.
     17 
     18 Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
     19 may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
     20 individually for the purpose of encoding or decoding bit streams in products that are compliant with
     21 the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
     22 these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
     23 software may already be covered under those patent licenses when it is used for those licensed purposes only.
     24 
     25 Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
     26 are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
     27 applications information and documentation.
     28 
     29 2.    COPYRIGHT LICENSE
     30 
     31 Redistribution and use in source and binary forms, with or without modification, are permitted without
     32 payment of copyright license fees provided that you satisfy the following conditions:
     33 
     34 You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
     35 your modifications thereto in source code form.
     36 
     37 You must retain the complete text of this software license in the documentation and/or other materials
     38 provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
     39 You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
     40 modifications thereto to recipients of copies in binary form.
     41 
     42 The name of Fraunhofer may not be used to endorse or promote products derived from this library without
     43 prior written permission.
     44 
     45 You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
     46 software or your modifications thereto.
     47 
     48 Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
     49 and the date of any change. For modified versions of the FDK AAC Codec, the term
     50 "Fraunhofer FDK AAC Codec Library for Android" must be replaced by the term
     51 "Third-Party Modified Version of the Fraunhofer FDK AAC Codec Library for Android."
     52 
     53 3.    NO PATENT LICENSE
     54 
     55 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
     56 ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
     57 respect to this software.
     58 
     59 You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
     60 by appropriate patent licenses.
     61 
     62 4.    DISCLAIMER
     63 
     64 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright holders and contributors
     65 "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, including but not limited to the implied warranties
     66 of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
     67 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
     68 including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
     69 or business interruption, however caused and on any theory of liability, whether in contract, strict
     70 liability, or tort (including negligence), arising in any way out of the use of this software, even if
     71 advised of the possibility of such damage.
     72 
     73 5.    CONTACT INFORMATION
     74 
     75 Fraunhofer Institute for Integrated Circuits IIS
     76 Attention: Audio and Multimedia Departments - FDK AAC LL
     77 Am Wolfsmantel 33
     78 91058 Erlangen, Germany
     79 
     80 www.iis.fraunhofer.de/amm
     81 amm-info (at) iis.fraunhofer.de
     82 ----------------------------------------------------------------------------------------------------------- */
     83 
     84 /******************************** MPEG Audio Encoder **************************
     85 
     86    Initial author:       M. Lohwasser
     87    contents/description: pns.c
     88 
     89 ******************************************************************************/
     90 
     91 #include "aacenc_pns.h"
     92 #include "psy_data.h"
     93 #include "pnsparam.h"
     94 #include "noisedet.h"
     95 #include "bit_cnt.h"
     96 #include "interface.h"
     97 
     98 
     99 /* minCorrelationEnergy = (1.0e-10f)^2 ~ 2^-67 = 2^-47 * 2^-20 */
    100 static const FIXP_DBL minCorrelationEnergy = FL2FXCONST_DBL(0.0); /* FL2FXCONST_DBL((float)FDKpow(2.0,-47)); */
    101 /* noiseCorrelationThresh = 0.6^2 */
    102 static const FIXP_DBL noiseCorrelationThresh = FL2FXCONST_DBL(0.36);
    103 
    104 static void FDKaacEnc_FDKaacEnc_noiseDetection( PNS_CONFIG  *pnsConf,
    105                             PNS_DATA    *pnsData,
    106                             const INT   sfbActive,
    107                             const INT   *sfbOffset,
    108                             INT          tnsOrder,
    109                             INT         tnsPredictionGain,
    110                             INT         tnsActive,
    111                             FIXP_DBL    *mdctSpectrum,
    112                             INT         *sfbMaxScaleSpec,
    113                             FIXP_SGL    *sfbtonality );
    114 
    115 static void FDKaacEnc_CalcNoiseNrgs( const INT   sfbActive,
    116                            INT         *pnsFlag,
    117                            FIXP_DBL    *sfbEnergyLdData,
    118                            INT         *noiseNrg );
    119 
    120 /*****************************************************************************
    121 
    122     functionname: initPnsConfiguration
    123     description:  fill pnsConf with pns parameters
    124     returns:      error status
    125     input:        PNS Config struct (modified)
    126                   bitrate, samplerate, usePns,
    127                   number of sfb's, pointer to sfb offset
    128     output:       error code
    129 
    130 *****************************************************************************/
    131 
    132 AAC_ENCODER_ERROR FDKaacEnc_InitPnsConfiguration(PNS_CONFIG *pnsConf,
    133                                                  INT         bitRate,
    134                                                  INT         sampleRate,
    135                                                  INT         usePns,
    136                                                  INT         sfbCnt,
    137                                                  const INT  *sfbOffset,
    138                                                  const INT   numChan,
    139                                                  const INT   isLC)
    140 {
    141   AAC_ENCODER_ERROR ErrorStatus;
    142 
    143   /* init noise detection */
    144   ErrorStatus = FDKaacEnc_GetPnsParam(&pnsConf->np,
    145                                       bitRate,
    146                                       sampleRate,
    147                                       sfbCnt,
    148                                       sfbOffset,
    149                                       &usePns,
    150                                       numChan,
    151                                       isLC);
    152   if (ErrorStatus != AAC_ENC_OK)
    153     return ErrorStatus;
    154 
    155   pnsConf->minCorrelationEnergy = minCorrelationEnergy;
    156   pnsConf->noiseCorrelationThresh = noiseCorrelationThresh;
    157 
    158   pnsConf->usePns = usePns;
    159 
    160   return AAC_ENC_OK;
    161 }
    162 
    163 
    164 
    165 /*****************************************************************************
    166 
    167     functionname: FDKaacEnc_PnsDetect
    168     description:  do decision, if PNS shall used or not
    169     returns:
    170     input:        pns config structure
    171                   pns data structure (modified),
    172                   lastWindowSequence (long or short blocks)
    173                   sfbActive
    174                   pointer to Sfb Energy, Threshold, Offset
    175                   pointer to mdct Spectrum
    176                   length of each group
    177                   pointer to tonality calculated in chaosmeasure
    178                   tns order and prediction gain
    179                   calculated noiseNrg at active PNS
    180     output:       pnsFlag in pns data structure
    181 
    182 *****************************************************************************/
    183 void FDKaacEnc_PnsDetect(PNS_CONFIG  *pnsConf,
    184                          PNS_DATA    *pnsData,
    185                          const INT    lastWindowSequence,
    186                          const INT    sfbActive,
    187                          const INT    maxSfbPerGroup,
    188                          FIXP_DBL    *sfbThresholdLdData,
    189                          const INT   *sfbOffset,
    190                          FIXP_DBL    *mdctSpectrum,
    191                          INT         *sfbMaxScaleSpec,
    192                          FIXP_SGL    *sfbtonality,
    193                          INT          tnsOrder,
    194                          INT          tnsPredictionGain,
    195                          INT          tnsActive,
    196                          FIXP_DBL    *sfbEnergyLdData,
    197                          INT         *noiseNrg )
    198 
    199 {
    200   int sfb;
    201   int startNoiseSfb;
    202 
    203   if (pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMLEXITY) {
    204     if ( (!pnsConf->usePns) ||              /* pns enabled? */
    205            (lastWindowSequence == SHORT_WINDOW) ) /* currently only long blocks */
    206     {
    207       FDKmemclear(pnsData->pnsFlag, MAX_GROUPED_SFB*sizeof(INT)); /* clear all pnsFlags */
    208       for (sfb=0; sfb<MAX_GROUPED_SFB; sfb++) {
    209           noiseNrg[sfb] = NO_NOISE_PNS;                           /* clear nrg's of previous frame */
    210       }
    211       return;
    212     }
    213   }
    214   else {
    215     if(!pnsConf->usePns)
    216       return;
    217 
    218     /* PNS only for long Windows */
    219     if (pnsConf->np.detectionAlgorithmFlags & JUST_LONG_WINDOW) {
    220       if(lastWindowSequence != LONG_WINDOW) {
    221         for (sfb = 0; sfb < sfbActive; sfb++) {
    222           pnsData->pnsFlag[sfb] = 0;    /* clear all pnsFlags */
    223         }
    224         return;
    225       }
    226     }
    227   }
    228   /*
    229     call noise detection
    230   */
    231   FDKaacEnc_FDKaacEnc_noiseDetection( pnsConf,
    232                   pnsData,
    233                   sfbActive,
    234                   sfbOffset,
    235                   tnsOrder,
    236                   tnsPredictionGain,
    237                   tnsActive,
    238                   mdctSpectrum,
    239                   sfbMaxScaleSpec,
    240                   sfbtonality );
    241 
    242   /* set startNoiseSfb (long) */
    243   startNoiseSfb = pnsConf->np.startSfb;
    244 
    245   /* Set noise substitution status */
    246   for(sfb = 0; sfb < sfbActive; sfb++) {
    247 
    248     /* No PNS below startNoiseSfb */
    249     if(sfb < startNoiseSfb){
    250       pnsData->pnsFlag[sfb] = 0;
    251       continue;
    252     }
    253 
    254     /*
    255       do noise substitution if
    256       fuzzy measure is high enough
    257       sfb freq > minimum sfb freq
    258       signal in coder band is not masked
    259     */
    260 
    261     if((pnsData->noiseFuzzyMeasure[sfb] > FL2FXCONST_SGL(0.5)) &&
    262        ( (sfbThresholdLdData[sfb] + FL2FXCONST_DBL(0.5849625f/64.0f))  /* thr * 1.5 = thrLd +ld(1.5)/64 */
    263          < sfbEnergyLdData[sfb] ) )
    264     {
    265       /*
    266         mark in psyout flag array that we will code
    267         this band with PNS
    268       */
    269       pnsData->pnsFlag[sfb] = 1; /* PNS_ON */
    270     }
    271     else{
    272       pnsData->pnsFlag[sfb] = 0; /* PNS_OFF */
    273     }
    274 
    275     /* no PNS if LTP is active */
    276   }
    277 
    278   /* avoid PNS holes */
    279   if((pnsData->noiseFuzzyMeasure[0]>FL2FXCONST_SGL(0.5f)) && (pnsData->pnsFlag[1])) {
    280     pnsData->pnsFlag[0] = 1;
    281   }
    282 
    283   for(sfb=1; sfb<maxSfbPerGroup-1; sfb++) {
    284     if((pnsData->noiseFuzzyMeasure[sfb]>pnsConf->np.gapFillThr) &&
    285        (pnsData->pnsFlag[sfb-1]) && (pnsData->pnsFlag[sfb+1])) {
    286       pnsData->pnsFlag[sfb] = 1;
    287     }
    288   }
    289 
    290   if(maxSfbPerGroup>0) {
    291     /* avoid PNS hole */
    292     if((pnsData->noiseFuzzyMeasure[maxSfbPerGroup-1]>pnsConf->np.gapFillThr) && (pnsData->pnsFlag[maxSfbPerGroup-2])) {
    293       pnsData->pnsFlag[maxSfbPerGroup-1] = 1;
    294     }
    295     /* avoid single PNS band */
    296     if(pnsData->pnsFlag[maxSfbPerGroup-2]==0) {
    297       pnsData->pnsFlag[maxSfbPerGroup-1] = 0;
    298     }
    299   }
    300 
    301   /* avoid single PNS bands */
    302   if(pnsData->pnsFlag[1]==0) {
    303     pnsData->pnsFlag[0] = 0;
    304   }
    305 
    306   for(sfb=1; sfb<maxSfbPerGroup-1; sfb++) {
    307     if((pnsData->pnsFlag[sfb-1]==0)&&(pnsData->pnsFlag[sfb+1]==0)) {
    308       pnsData->pnsFlag[sfb] = 0;
    309     }
    310   }
    311 
    312 
    313   /*
    314     calculate noiseNrg's
    315   */
    316   FDKaacEnc_CalcNoiseNrgs( sfbActive,
    317                  pnsData->pnsFlag,
    318                  sfbEnergyLdData,
    319                  noiseNrg );
    320 }
    321 
    322 
    323 /*****************************************************************************
    324 
    325     functionname:FDKaacEnc_FDKaacEnc_noiseDetection
    326     description: wrapper for noisedet.c
    327     returns:
    328     input:       pns config structure
    329                  pns data structure (modified),
    330                  sfbActive
    331                  tns order and prediction gain
    332                  pointer to mdct Spectrumand Sfb Energy
    333                  pointer to Sfb tonality
    334     output:      noiseFuzzyMeasure in structure pnsData
    335                  flags tonal / nontonal
    336 
    337 *****************************************************************************/
    338 static void FDKaacEnc_FDKaacEnc_noiseDetection( PNS_CONFIG  *pnsConf,
    339                             PNS_DATA    *pnsData,
    340                             const INT   sfbActive,
    341                             const INT   *sfbOffset,
    342                             int          tnsOrder,
    343                             INT         tnsPredictionGain,
    344                             INT         tnsActive,
    345                             FIXP_DBL    *mdctSpectrum,
    346                             INT         *sfbMaxScaleSpec,
    347                             FIXP_SGL    *sfbtonality )
    348 {
    349     INT condition = TRUE;
    350     if ( !(pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMLEXITY) ) {
    351       condition = (tnsOrder > 3);
    352     }
    353     /*
    354     no PNS if heavy TNS activity
    355     clear pnsData->noiseFuzzyMeasure
    356     */
    357     if((pnsConf->np.detectionAlgorithmFlags & USE_TNS_GAIN_THR) &&
    358       (tnsPredictionGain >= pnsConf->np.tnsGainThreshold) && condition &&
    359       !((pnsConf->np.detectionAlgorithmFlags & USE_TNS_PNS) && (tnsPredictionGain >= pnsConf->np.tnsPNSGainThreshold) && (tnsActive)) )
    360     {
    361         /* clear all noiseFuzzyMeasure */
    362         FDKmemclear(pnsData->noiseFuzzyMeasure, sfbActive*sizeof(FIXP_SGL));
    363     }
    364     else
    365     {
    366         /*
    367         call noise detection, output in pnsData->noiseFuzzyMeasure,
    368         use real mdct spectral data
    369         */
    370         FDKaacEnc_noiseDetect( mdctSpectrum,
    371             sfbMaxScaleSpec,
    372             sfbActive,
    373             sfbOffset,
    374             pnsData->noiseFuzzyMeasure,
    375             &pnsConf->np,
    376             sfbtonality);
    377     }
    378 }
    379 
    380 
    381 /*****************************************************************************
    382 
    383     functionname:FDKaacEnc_CalcNoiseNrgs
    384     description: Calculate the NoiseNrg's
    385     returns:
    386     input:       sfbActive
    387                  if pnsFlag calculate NoiseNrg
    388                  pointer to sfbEnergy and groupLen
    389                  pointer to noiseNrg (modified)
    390     output:      noiseNrg's in pnsFlaged sfb's
    391 
    392 *****************************************************************************/
    393 
    394 static void FDKaacEnc_CalcNoiseNrgs( const INT    sfbActive,
    395                            INT         *RESTRICT pnsFlag,
    396                            FIXP_DBL    *RESTRICT sfbEnergyLdData,
    397                            INT         *RESTRICT noiseNrg )
    398 {
    399   int sfb;
    400   INT tmp = (-LOG_NORM_PCM)<<2;
    401 
    402   for(sfb = 0; sfb < sfbActive; sfb++) {
    403     if(pnsFlag[sfb]) {
    404       INT nrg = (-sfbEnergyLdData[sfb]+FL2FXCONST_DBL(0.5f/64.0f))>>(DFRACT_BITS-1-7);
    405       noiseNrg[sfb] = tmp - nrg;
    406     }
    407   }
    408 }
    409 
    410 
    411 /*****************************************************************************
    412 
    413     functionname:FDKaacEnc_CodePnsChannel
    414     description: Execute pns decission
    415     returns:
    416     input:       sfbActive
    417                  pns config structure
    418                  use PNS if pnsFlag
    419                  pointer to Sfb Energy, noiseNrg, Threshold
    420     output:      set sfbThreshold high to code pe with 0,
    421                  noiseNrg marks flag for pns coding
    422 
    423 *****************************************************************************/
    424 
    425 void FDKaacEnc_CodePnsChannel(const INT     sfbActive,
    426                               PNS_CONFIG    *pnsConf,
    427                               INT           *RESTRICT pnsFlag,
    428                               FIXP_DBL      *RESTRICT sfbEnergyLdData,
    429                               INT           *RESTRICT noiseNrg,
    430                               FIXP_DBL      *RESTRICT sfbThresholdLdData)
    431 {
    432   INT sfb;
    433   INT lastiNoiseEnergy = 0;
    434   INT firstPNSband = 1; /* TRUE for first PNS-coded band */
    435 
    436   /* no PNS */
    437   if(!pnsConf->usePns) {
    438     for(sfb = 0; sfb < sfbActive; sfb++) {
    439       /* no PNS coding */
    440       noiseNrg[sfb] = NO_NOISE_PNS;
    441     }
    442     return;
    443   }
    444 
    445   /* code PNS */
    446   for(sfb = 0; sfb < sfbActive; sfb++) {
    447     if(pnsFlag[sfb]) {
    448       /* high sfbThreshold causes pe = 0 */
    449       if(noiseNrg[sfb] != NO_NOISE_PNS)
    450         sfbThresholdLdData[sfb] = sfbEnergyLdData[sfb] + FL2FXCONST_DBL(1.0f/LD_DATA_SCALING);
    451 
    452       /* set noiseNrg in valid region */
    453       if(!firstPNSband) {
    454         INT deltaiNoiseEnergy = noiseNrg[sfb] - lastiNoiseEnergy;
    455 
    456         if(deltaiNoiseEnergy > CODE_BOOK_PNS_LAV)
    457             noiseNrg[sfb] -= deltaiNoiseEnergy - CODE_BOOK_PNS_LAV;
    458         else if(deltaiNoiseEnergy < -CODE_BOOK_PNS_LAV)
    459             noiseNrg[sfb] -= deltaiNoiseEnergy + CODE_BOOK_PNS_LAV;
    460       }
    461       else {
    462         firstPNSband = 0;
    463       }
    464       lastiNoiseEnergy = noiseNrg[sfb];
    465     }
    466     else {
    467       /* no PNS coding */
    468       noiseNrg[sfb] = NO_NOISE_PNS;
    469     }
    470   }
    471 }
    472 
    473 
    474 /*****************************************************************************
    475 
    476     functionname:FDKaacEnc_PreProcessPnsChannelPair
    477     description: Calculate the correlation of noise in a channel pair
    478 
    479     returns:
    480     input:       sfbActive
    481                  pointer to sfb energies left, right and mid channel
    482                  pns config structure
    483                  pns data structure left and right (modified)
    484 
    485     output:      noiseEnergyCorrelation in pns data structure
    486 
    487 *****************************************************************************/
    488 
    489 void FDKaacEnc_PreProcessPnsChannelPair(const INT   sfbActive,
    490                                         FIXP_DBL   *RESTRICT sfbEnergyLeft,
    491                                         FIXP_DBL   *RESTRICT sfbEnergyRight,
    492                                         FIXP_DBL   *RESTRICT sfbEnergyLeftLD,
    493                                         FIXP_DBL   *RESTRICT sfbEnergyRightLD,
    494                                         FIXP_DBL   *RESTRICT sfbEnergyMid,
    495                                         PNS_CONFIG *RESTRICT pnsConf,
    496                                         PNS_DATA   *pnsDataLeft,
    497                                         PNS_DATA   *pnsDataRight)
    498 {
    499   INT sfb;
    500   FIXP_DBL ccf;
    501 
    502   if(!pnsConf->usePns)
    503     return;
    504 
    505   FIXP_DBL *RESTRICT pNoiseEnergyCorrelationL = pnsDataLeft->noiseEnergyCorrelation;
    506   FIXP_DBL *RESTRICT pNoiseEnergyCorrelationR = pnsDataRight->noiseEnergyCorrelation;
    507 
    508   for(sfb=0;sfb< sfbActive;sfb++) {
    509     FIXP_DBL quot = (sfbEnergyLeftLD[sfb]>>1) + (sfbEnergyRightLD[sfb]>>1);
    510 
    511     if(quot < FL2FXCONST_DBL(-32.0f/(float)LD_DATA_SCALING))
    512       ccf = FL2FXCONST_DBL(0.0f);
    513     else {
    514       FIXP_DBL accu = sfbEnergyMid[sfb]- (((sfbEnergyLeft[sfb]>>1)+(sfbEnergyRight[sfb]>>1))>>1);
    515       INT sign = (accu < FL2FXCONST_DBL(0.0f)) ? 1 : 0 ;
    516       accu = fixp_abs(accu);
    517 
    518       ccf = CalcLdData(accu) + FL2FXCONST_DBL((float)1.0f/(float)LD_DATA_SCALING) - quot;   /* ld(accu*2) = ld(accu) + 1 */
    519       ccf = (ccf>=FL2FXCONST_DBL(0.0)) ? ((FIXP_DBL)MAXVAL_DBL) : (sign) ? -CalcInvLdData(ccf) : CalcInvLdData(ccf);
    520     }
    521 
    522     pNoiseEnergyCorrelationL[sfb] = ccf;
    523     pNoiseEnergyCorrelationR[sfb] = ccf;
    524   }
    525 }
    526 
    527 
    528 
    529 /*****************************************************************************
    530 
    531     functionname:FDKaacEnc_PostProcessPnsChannelPair
    532     description: if PNS used at left and right channel,
    533                  use msMask to flag correlation
    534     returns:
    535     input:       sfbActive
    536                  pns config structure
    537                  pns data structure left and right (modified)
    538                  pointer to msMask, flags correlation by pns coding (modified)
    539                  Digest of MS coding
    540     output:      pnsFlag in pns data structure,
    541                  msFlag in msMask (flags correlation)
    542 
    543 *****************************************************************************/
    544 
    545 void FDKaacEnc_PostProcessPnsChannelPair(const INT   sfbActive,
    546                                          PNS_CONFIG  *pnsConf,
    547                                          PNS_DATA    *pnsDataLeft,
    548                                          PNS_DATA    *pnsDataRight,
    549                                          INT         *RESTRICT msMask,
    550                                          INT         *msDigest )
    551 {
    552   INT sfb;
    553 
    554   if(!pnsConf->usePns)
    555     return;
    556 
    557   for(sfb=0;sfb<sfbActive;sfb++) {
    558     /*
    559       MS post processing
    560     */
    561     if( msMask[sfb] ) {
    562       if( (pnsDataLeft->pnsFlag[sfb]) &&
    563           (pnsDataRight->pnsFlag[sfb]) ) {
    564         /* AAC only: Standard */
    565         /* do this to avoid ms flags in layers that should not have it */
    566         if(pnsDataLeft->noiseEnergyCorrelation[sfb] <= pnsConf->noiseCorrelationThresh){
    567           msMask[sfb] = 0;
    568           *msDigest = MS_SOME;
    569         }
    570       }
    571       else {
    572         /*
    573           No PNS coding
    574         */
    575         pnsDataLeft->pnsFlag[sfb] = 0;
    576         pnsDataRight->pnsFlag[sfb] = 0;
    577       }
    578     }
    579 
    580     /*
    581       Use MS flag to signal noise correlation if
    582       pns is active in both channels
    583     */
    584     if( (pnsDataLeft->pnsFlag[sfb]) && (pnsDataRight->pnsFlag[sfb]) ) {
    585       if(pnsDataLeft->noiseEnergyCorrelation[sfb] > pnsConf->noiseCorrelationThresh) {
    586         msMask[sfb] = 1;
    587         *msDigest = MS_SOME;
    588       }
    589     }
    590   }
    591 }
    592