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: Psychoaccoustic major function block
     88 
     89 ******************************************************************************/
     90 
     91 #include "psy_const.h"
     92 
     93 #include "block_switch.h"
     94 #include "transform.h"
     95 #include "spreading.h"
     96 #include "pre_echo_control.h"
     97 #include "band_nrg.h"
     98 #include "psy_configuration.h"
     99 #include "psy_data.h"
    100 #include "ms_stereo.h"
    101 #include "interface.h"
    102 #include "psy_main.h"
    103 #include "grp_data.h"
    104 #include "tns_func.h"
    105 #include "pns_func.h"
    106 #include "tonality.h"
    107 #include "aacEnc_ram.h"
    108 #include "intensity.h"
    109 
    110 
    111 
    112 /* blending to reduce gibbs artifacts */
    113 #define FADE_OUT_LEN 6
    114 static const FIXP_DBL fadeOutFactor[FADE_OUT_LEN] = {1840644096, 1533870080, 1227096064, 920322048, 613548032, 306774016};
    115 
    116 /* forward definitions */
    117 
    118 
    119 /*****************************************************************************
    120 
    121     functionname: FDKaacEnc_PsyNew
    122     description:  allocates memory for psychoacoustic
    123     returns:      an error code
    124     input:        pointer to a psych handle
    125 
    126 *****************************************************************************/
    127 AAC_ENCODER_ERROR FDKaacEnc_PsyNew(PSY_INTERNAL  **phpsy,
    128                                    const INT       nElements,
    129                                    const INT       nChannels
    130                                   ,UCHAR          *dynamic_RAM
    131                                   )
    132 {
    133     AAC_ENCODER_ERROR ErrorStatus;
    134     PSY_INTERNAL *hPsy;
    135     INT i;
    136 
    137     hPsy = GetRam_aacEnc_PsyInternal();
    138     *phpsy = hPsy;
    139     if (hPsy == NULL) {
    140       ErrorStatus = AAC_ENC_NO_MEMORY;
    141       goto bail;
    142     }
    143 
    144     for (i=0; i<nElements; i++) {
    145         /* PSY_ELEMENT */
    146         hPsy->psyElement[i] = GetRam_aacEnc_PsyElement(i);
    147         if (hPsy->psyElement[i] == NULL) {
    148           ErrorStatus = AAC_ENC_NO_MEMORY;
    149           goto bail;
    150         }
    151     }
    152 
    153     for (i=0; i<nChannels; i++) {
    154         /* PSY_STATIC */
    155         hPsy->pStaticChannels[i] = GetRam_aacEnc_PsyStatic(i);
    156         if (hPsy->pStaticChannels[i]==NULL) {
    157           ErrorStatus = AAC_ENC_NO_MEMORY;
    158           goto bail;
    159         }
    160         /* AUDIO INPUT BUFFER */
    161         hPsy->pStaticChannels[i]->psyInputBuffer = GetRam_aacEnc_PsyInputBuffer(i);
    162         if (hPsy->pStaticChannels[i]->psyInputBuffer==NULL) {
    163           ErrorStatus = AAC_ENC_NO_MEMORY;
    164           goto bail;
    165         }
    166     }
    167 
    168     /* reusable psych memory */
    169     hPsy->psyDynamic = GetRam_aacEnc_PsyDynamic(0, dynamic_RAM);
    170 
    171     return AAC_ENC_OK;
    172 
    173 bail:
    174    FDKaacEnc_PsyClose(phpsy, NULL);
    175 
    176    return ErrorStatus;
    177 }
    178 
    179 /*****************************************************************************
    180 
    181     functionname: FDKaacEnc_PsyOutNew
    182     description:  allocates memory for psyOut struc
    183     returns:      an error code
    184     input:        pointer to a psych handle
    185 
    186 *****************************************************************************/
    187 AAC_ENCODER_ERROR FDKaacEnc_PsyOutNew(PSY_OUT   **phpsyOut,
    188                                       const INT   nElements,
    189                                       const INT   nChannels,
    190                                       const INT   nSubFrames
    191                                      ,UCHAR      *dynamic_RAM
    192                                      )
    193 {
    194   AAC_ENCODER_ERROR ErrorStatus;
    195   int n, i;
    196   int elInc = 0, chInc = 0;
    197 
    198   for (n=0; n<nSubFrames; n++) {
    199     phpsyOut[n] = GetRam_aacEnc_PsyOut(n);
    200 
    201     if (phpsyOut[n] == NULL) {
    202       ErrorStatus = AAC_ENC_NO_MEMORY;
    203       goto bail;
    204     }
    205 
    206     for (i=0; i<nChannels; i++) {
    207       phpsyOut[n]->pPsyOutChannels[i] = GetRam_aacEnc_PsyOutChannel(chInc++);
    208     }
    209 
    210     for (i=0; i<nElements; i++) {
    211       phpsyOut[n]->psyOutElement[i] = GetRam_aacEnc_PsyOutElements(elInc++);
    212       if (phpsyOut[n]->psyOutElement[i] == NULL) {
    213         ErrorStatus = AAC_ENC_NO_MEMORY;
    214         goto bail;
    215       }
    216     }
    217   } /* nSubFrames */
    218 
    219   return AAC_ENC_OK;
    220 
    221 bail:
    222   FDKaacEnc_PsyClose(NULL, phpsyOut);
    223   return ErrorStatus;
    224 }
    225 
    226 
    227 AAC_ENCODER_ERROR FDKaacEnc_psyInitStates(PSY_INTERNAL    *hPsy,
    228                                           PSY_STATIC* psyStatic,
    229                                           AUDIO_OBJECT_TYPE audioObjectType)
    230 {
    231   /* init input buffer */
    232   FDKmemclear(psyStatic->psyInputBuffer, MAX_INPUT_BUFFER_SIZE*sizeof(INT_PCM));
    233 
    234   FDKaacEnc_InitBlockSwitching(&psyStatic->blockSwitchingControl,
    235                                 isLowDelay(audioObjectType)
    236                                );
    237 
    238   return AAC_ENC_OK;
    239 }
    240 
    241 
    242 AAC_ENCODER_ERROR FDKaacEnc_psyInit(PSY_INTERNAL    *hPsy,
    243                                     PSY_OUT        **phpsyOut,
    244                                     const INT        nSubFrames,
    245                                     const INT        nMaxChannels,
    246                                     const AUDIO_OBJECT_TYPE audioObjectType,
    247                                     CHANNEL_MAPPING *cm)
    248 {
    249   AAC_ENCODER_ERROR ErrorStatus = AAC_ENC_OK;
    250   int i, ch, n, chInc = 0, resetChannels = 3;
    251 
    252   if ( (nMaxChannels>2) && (cm->nChannels==2) ) {
    253     chInc = 1;
    254     FDKaacEnc_psyInitStates(hPsy, hPsy->pStaticChannels[0], audioObjectType);
    255   }
    256 
    257   if ( (nMaxChannels==2) ) {
    258     resetChannels = 0;
    259   }
    260 
    261   for (i=0; i<cm->nElements; i++) {
    262     for (ch=0; ch<cm->elInfo[i].nChannelsInEl; ch++) {
    263       if (cm->elInfo[i].elType!=ID_LFE) {
    264         hPsy->psyElement[i]->psyStatic[ch] = hPsy->pStaticChannels[chInc];
    265         if (chInc>=resetChannels) {
    266             FDKaacEnc_psyInitStates(hPsy, hPsy->psyElement[i]->psyStatic[ch], audioObjectType);
    267         }
    268         hPsy->psyElement[i]->psyStatic[ch]->isLFE = 0;
    269       }
    270       else {
    271         hPsy->psyElement[i]->psyStatic[ch] = hPsy->pStaticChannels[nMaxChannels-1];
    272         hPsy->psyElement[i]->psyStatic[ch]->isLFE = 1;
    273       }
    274       chInc++;
    275     }
    276   }
    277 
    278   for (n=0; n<nSubFrames; n++) {
    279     chInc = 0;
    280     for (i=0; i<cm->nElements; i++) {
    281       for (ch=0; ch<cm->elInfo[i].nChannelsInEl; ch++) {
    282         phpsyOut[n]->psyOutElement[i]->psyOutChannel[ch] = phpsyOut[n]->pPsyOutChannels[chInc++];
    283       }
    284     }
    285   }
    286 
    287   return ErrorStatus;
    288 }
    289 
    290 
    291 /*****************************************************************************
    292 
    293     functionname: FDKaacEnc_psyMainInit
    294     description:  initializes psychoacoustic
    295     returns:      an error code
    296 
    297 *****************************************************************************/
    298 
    299 AAC_ENCODER_ERROR FDKaacEnc_psyMainInit(PSY_INTERNAL *hPsy,
    300                                         AUDIO_OBJECT_TYPE audioObjectType,
    301                                         CHANNEL_MAPPING *cm,
    302                                         INT sampleRate,
    303                                         INT granuleLength,
    304                                         INT bitRate,
    305                                         INT tnsMask,
    306                                         INT bandwidth,
    307                                         INT usePns,
    308                                         INT useIS,
    309                                         UINT syntaxFlags,
    310                                         ULONG initFlags)
    311 {
    312   AAC_ENCODER_ERROR ErrorStatus;
    313   int i, ch;
    314   int channelsEff = cm->nChannelsEff;
    315   int tnsChannels = 0;
    316   FB_TYPE filterBank;
    317 
    318 
    319   switch(FDKaacEnc_GetMonoStereoMode(cm->encMode)) {
    320     /* ... and map to tnsChannels */
    321     case EL_MODE_MONO:   tnsChannels = 1; break;
    322     case EL_MODE_STEREO: tnsChannels = 2; break;
    323     default:             tnsChannels = 0;
    324   }
    325 
    326   switch (audioObjectType)
    327   {
    328     default: filterBank = FB_LC;  break;
    329     case AOT_ER_AAC_LD:  filterBank = FB_LD;  break;
    330     case AOT_ER_AAC_ELD: filterBank = FB_ELD; break;
    331   }
    332 
    333   hPsy->granuleLength = granuleLength;
    334 
    335   ErrorStatus = FDKaacEnc_InitPsyConfiguration(bitRate/channelsEff, sampleRate, bandwidth, LONG_WINDOW, hPsy->granuleLength, useIS, &(hPsy->psyConf[0]), filterBank);
    336   if (ErrorStatus != AAC_ENC_OK)
    337     return ErrorStatus;
    338 
    339   ErrorStatus = FDKaacEnc_InitTnsConfiguration(
    340         (bitRate*tnsChannels)/channelsEff,
    341         sampleRate,
    342         tnsChannels,
    343         LONG_WINDOW,
    344         hPsy->granuleLength,
    345         isLowDelay(audioObjectType),
    346         (syntaxFlags&AC_SBR_PRESENT)?1:0,
    347        &(hPsy->psyConf[0].tnsConf),
    348        &hPsy->psyConf[0],
    349         (INT)(tnsMask&2),
    350         (INT)(tnsMask&8) );
    351 
    352   if (ErrorStatus != AAC_ENC_OK)
    353     return ErrorStatus;
    354 
    355   if (granuleLength > 512) {
    356     ErrorStatus = FDKaacEnc_InitPsyConfiguration(bitRate/channelsEff, sampleRate, bandwidth, SHORT_WINDOW, hPsy->granuleLength, useIS, &hPsy->psyConf[1], filterBank);
    357     if (ErrorStatus != AAC_ENC_OK)
    358       return ErrorStatus;
    359 
    360     ErrorStatus = FDKaacEnc_InitTnsConfiguration(
    361             (bitRate*tnsChannels)/channelsEff,
    362             sampleRate,
    363             tnsChannels,
    364             SHORT_WINDOW,
    365             hPsy->granuleLength,
    366             isLowDelay(audioObjectType),
    367             (syntaxFlags&AC_SBR_PRESENT)?1:0,
    368            &hPsy->psyConf[1].tnsConf,
    369            &hPsy->psyConf[1],
    370             (INT)(tnsMask&1),
    371             (INT)(tnsMask&4) );
    372 
    373     if (ErrorStatus != AAC_ENC_OK)
    374     return ErrorStatus;
    375 
    376   }
    377 
    378 
    379   for (i=0; i<cm->nElements; i++) {
    380     for (ch=0; ch<cm->elInfo[i].nChannelsInEl; ch++) {
    381       if (initFlags) {
    382         /* reset states */
    383         FDKaacEnc_psyInitStates(hPsy, hPsy->psyElement[i]->psyStatic[ch], audioObjectType);
    384       }
    385 
    386       FDKaacEnc_InitPreEchoControl(hPsy->psyElement[i]->psyStatic[ch]->sfbThresholdnm1,
    387                                   &hPsy->psyElement[i]->psyStatic[ch]->calcPreEcho,
    388                                    hPsy->psyConf[0].sfbCnt,
    389                                    hPsy->psyConf[0].sfbPcmQuantThreshold,
    390                                   &hPsy->psyElement[i]->psyStatic[ch]->mdctScalenm1);
    391     }
    392   }
    393 
    394   ErrorStatus = FDKaacEnc_InitPnsConfiguration(&hPsy->psyConf[0].pnsConf,
    395                                                bitRate/channelsEff,
    396                                                sampleRate,
    397                                                usePns,
    398                                                hPsy->psyConf[0].sfbCnt,
    399                                                hPsy->psyConf[0].sfbOffset,
    400                                                cm->elInfo[0].nChannelsInEl,
    401                                                (hPsy->psyConf[0].filterbank == FB_LC));
    402   if (ErrorStatus != AAC_ENC_OK)
    403     return ErrorStatus;
    404 
    405   ErrorStatus = FDKaacEnc_InitPnsConfiguration(&hPsy->psyConf[1].pnsConf,
    406                                                bitRate/channelsEff,
    407                                                sampleRate,
    408                                                usePns,
    409                                                hPsy->psyConf[1].sfbCnt,
    410                                                hPsy->psyConf[1].sfbOffset,
    411                                                cm->elInfo[1].nChannelsInEl,
    412                                                (hPsy->psyConf[1].filterbank == FB_LC));
    413   return ErrorStatus;
    414 }
    415 
    416 
    417 static
    418 void FDKaacEnc_deinterleaveInputBuffer(INT_PCM *pOutputSamples,
    419                                        INT_PCM *pInputSamples,
    420                                        INT nSamples,
    421                                        INT nChannels)
    422 {
    423     INT k;
    424     /* deinterlave input samples and write to output buffer */
    425     for (k=0; k<nSamples; k++) {
    426         pOutputSamples[k] = pInputSamples[k*nChannels];
    427     }
    428 }
    429 
    430 
    431 
    432 /*****************************************************************************
    433 
    434     functionname: FDKaacEnc_psyMain
    435     description:  psychoacoustic
    436     returns:      an error code
    437 
    438         This function assumes that enough input data is in the modulo buffer.
    439 
    440 *****************************************************************************/
    441 
    442 AAC_ENCODER_ERROR FDKaacEnc_psyMain(INT                 channels,
    443                                     PSY_ELEMENT        *psyElement,
    444                                     PSY_DYNAMIC        *psyDynamic,
    445                                     PSY_CONFIGURATION  *psyConf,
    446                                     PSY_OUT_ELEMENT    *RESTRICT psyOutElement,
    447                                     INT_PCM             *pInput,
    448                                     INT                 *chIdx,
    449                                     INT                  totalChannels
    450                                    )
    451 {
    452     const INT commonWindow = 1;
    453     INT maxSfbPerGroup[(2)];
    454     INT mdctSpectrum_e;
    455     INT ch;   /* counts through channels          */
    456     INT w;    /* counts through windows           */
    457     INT sfb;  /* counts through scalefactor bands */
    458     INT line; /* counts through lines             */
    459 
    460     PSY_CONFIGURATION *RESTRICT hPsyConfLong  = &psyConf[0];
    461     PSY_CONFIGURATION *RESTRICT hPsyConfShort = &psyConf[1];
    462     PSY_OUT_CHANNEL  **RESTRICT psyOutChannel = psyOutElement->psyOutChannel;
    463     FIXP_SGL sfbTonality[(2)][MAX_SFB_LONG];
    464 
    465     PSY_STATIC        **RESTRICT psyStatic = psyElement->psyStatic;
    466 
    467     PSY_DATA           *RESTRICT psyData[(2)];
    468     TNS_DATA           *RESTRICT tnsData[(2)];
    469     PNS_DATA           *RESTRICT pnsData[(2)];
    470 
    471     INT zeroSpec = TRUE; /* means all spectral lines are zero */
    472 
    473     INT blockSwitchingOffset;
    474 
    475     PSY_CONFIGURATION *RESTRICT hThisPsyConf[(2)];
    476     INT windowLength[(2)];
    477     INT nWindows[(2)];
    478     INT wOffset;
    479 
    480     INT       maxSfb[(2)];
    481     INT      *pSfbMaxScaleSpec[(2)];
    482     FIXP_DBL *pSfbEnergy[(2)];
    483     FIXP_DBL *pSfbSpreadEnergy[(2)];
    484     FIXP_DBL *pSfbEnergyLdData[(2)];
    485     FIXP_DBL *pSfbEnergyMS[(2)];
    486     FIXP_DBL *pSfbThreshold[(2)];
    487 
    488     INT isShortWindow[(2)];
    489 
    490 
    491     if (hPsyConfLong->filterbank == FB_LC) {
    492       blockSwitchingOffset = psyConf->granuleLength + (9*psyConf->granuleLength/(2*TRANS_FAC));
    493     } else {
    494       blockSwitchingOffset = psyConf->granuleLength;
    495     }
    496 
    497     for(ch = 0; ch < channels; ch++)
    498     {
    499         psyData[ch] = &psyDynamic->psyData[ch];
    500         tnsData[ch] = &psyDynamic->tnsData[ch];
    501         pnsData[ch] = &psyDynamic->pnsData[ch];
    502 
    503         psyData[ch]->mdctSpectrum = psyOutChannel[ch]->mdctSpectrum;
    504     }
    505 
    506     /* block switching */
    507     if (hPsyConfLong->filterbank != FB_ELD)
    508     {
    509       int err;
    510 
    511       for(ch = 0; ch < channels; ch++)
    512       {
    513           C_ALLOC_SCRATCH_START(pTimeSignal, INT_PCM, (1024))
    514 
    515           /* deinterleave input data and use for block switching */
    516           FDKaacEnc_deinterleaveInputBuffer( pTimeSignal,
    517                                             &pInput[chIdx[ch]],
    518                                              psyConf->granuleLength,
    519                                              totalChannels);
    520 
    521 
    522           FDKaacEnc_BlockSwitching (&psyStatic[ch]->blockSwitchingControl,
    523                                      psyConf->granuleLength,
    524                                      psyStatic[ch]->isLFE,
    525                                      pTimeSignal
    526                                    );
    527 
    528 
    529             /* fill up internal input buffer, to 2xframelength samples */
    530             FDKmemcpy(psyStatic[ch]->psyInputBuffer+blockSwitchingOffset,
    531                       pTimeSignal,
    532                       (2*psyConf->granuleLength-blockSwitchingOffset)*sizeof(INT_PCM));
    533 
    534             C_ALLOC_SCRATCH_END(pTimeSignal, INT_PCM, (1024))
    535       }
    536 
    537       /* synch left and right block type */
    538       err = FDKaacEnc_SyncBlockSwitching(&psyStatic[0]->blockSwitchingControl,
    539                                          &psyStatic[1]->blockSwitchingControl,
    540                                           channels,
    541                                           commonWindow);
    542 
    543       if (err) {
    544           return AAC_ENC_UNSUPPORTED_AOT; /* mixed up LC and LD */
    545       }
    546 
    547     }
    548     else {
    549       for(ch = 0; ch < channels; ch++)
    550       {
    551         /* deinterleave input data and use for block switching */
    552         FDKaacEnc_deinterleaveInputBuffer( psyStatic[ch]->psyInputBuffer + blockSwitchingOffset,
    553                                           &pInput[chIdx[ch]],
    554                                            psyConf->granuleLength,
    555                                            totalChannels);
    556       }
    557     }
    558 
    559     for(ch = 0; ch < channels; ch++)
    560       isShortWindow[ch]=(psyStatic[ch]->blockSwitchingControl.lastWindowSequence == SHORT_WINDOW);
    561 
    562     /* set parameters according to window length */
    563     for(ch = 0; ch < channels; ch++)
    564     {
    565         if(isShortWindow[ch]) {
    566             hThisPsyConf[ch]       = hPsyConfShort;
    567             windowLength[ch]       = psyConf->granuleLength/TRANS_FAC;
    568             nWindows[ch]           = TRANS_FAC;
    569             maxSfb[ch]             = MAX_SFB_SHORT;
    570 
    571             pSfbMaxScaleSpec[ch]   = psyData[ch]->sfbMaxScaleSpec.Short[0];
    572             pSfbEnergy[ch]         = psyData[ch]->sfbEnergy.Short[0];
    573             pSfbSpreadEnergy[ch]   = psyData[ch]->sfbSpreadEnergy.Short[0];
    574             pSfbEnergyLdData[ch]   = psyData[ch]->sfbEnergyLdData.Short[0];
    575             pSfbEnergyMS[ch]       = psyData[ch]->sfbEnergyMS.Short[0];
    576             pSfbThreshold[ch]      = psyData[ch]->sfbThreshold.Short[0];
    577 
    578         } else
    579         {
    580             hThisPsyConf[ch]       = hPsyConfLong;
    581             windowLength[ch]       = psyConf->granuleLength;
    582             nWindows[ch]           = 1;
    583             maxSfb[ch]             = MAX_GROUPED_SFB;
    584 
    585             pSfbMaxScaleSpec[ch]   = psyData[ch]->sfbMaxScaleSpec.Long;
    586             pSfbEnergy[ch]         = psyData[ch]->sfbEnergy.Long;
    587             pSfbSpreadEnergy[ch]   = psyData[ch]->sfbSpreadEnergy.Long;
    588             pSfbEnergyLdData[ch]   = psyData[ch]->sfbEnergyLdData.Long;
    589             pSfbEnergyMS[ch]       = psyData[ch]->sfbEnergyMS.Long;
    590             pSfbThreshold[ch]      = psyData[ch]->sfbThreshold.Long;
    591         }
    592     }
    593 
    594     /* Transform and get mdctScaling for all channels and windows. */
    595     for(ch = 0; ch < channels; ch++)
    596     {
    597         /* update number of active bands */
    598         if (psyStatic[ch]->isLFE) {
    599             psyData[ch]->sfbActive = hThisPsyConf[ch]->sfbActiveLFE;
    600             psyData[ch]->lowpassLine = hThisPsyConf[ch]->lowpassLineLFE;
    601         } else
    602         {
    603             psyData[ch]->sfbActive = hThisPsyConf[ch]->sfbActive;
    604             psyData[ch]->lowpassLine = hThisPsyConf[ch]->lowpassLine;
    605         }
    606 
    607         for(w = 0; w < nWindows[ch]; w++) {
    608 
    609           wOffset = w*windowLength[ch];
    610 
    611           FDKaacEnc_Transform_Real( psyStatic[ch]->psyInputBuffer + wOffset,
    612                                     psyData[ch]->mdctSpectrum+wOffset,
    613                                     psyStatic[ch]->blockSwitchingControl.lastWindowSequence,
    614                                     psyStatic[ch]->blockSwitchingControl.windowShape,
    615                                    &psyStatic[ch]->blockSwitchingControl.lastWindowShape,
    616                                     psyConf->granuleLength,
    617                                    &mdctSpectrum_e,
    618                                     hThisPsyConf[ch]->filterbank
    619                                    ,psyStatic[ch]->overlapAddBuffer
    620                                    );
    621 
    622           /* Low pass / highest sfb */
    623           FDKmemclear(&psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine+wOffset],
    624                       (windowLength[ch]-psyData[ch]->lowpassLine)*sizeof(FIXP_DBL));
    625 
    626           if ( (hPsyConfLong->filterbank != FB_LC) && (psyData[ch]->lowpassLine >= FADE_OUT_LEN) ) {
    627             /* Do blending to reduce gibbs artifacts */
    628             for (int i=0; i<FADE_OUT_LEN; i++) {
    629               psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine+wOffset - FADE_OUT_LEN + i] = fMult(psyData[ch]->mdctSpectrum[psyData[ch]->lowpassLine+wOffset - FADE_OUT_LEN + i], fadeOutFactor[i]);
    630             }
    631           }
    632 
    633 
    634           /* Check for zero spectrum. These loops will usually terminate very, very early. */
    635           for(line=0; (line<psyData[ch]->lowpassLine) && (zeroSpec==TRUE); line++) {
    636               if (psyData[ch]->mdctSpectrum[line+wOffset] != (FIXP_DBL)0) {
    637                   zeroSpec = FALSE;
    638                   break;
    639               }
    640           }
    641 
    642         } /* w loop */
    643 
    644         psyData[ch]->mdctScale = mdctSpectrum_e;
    645 
    646         /* rotate internal time samples */
    647         FDKmemmove(psyStatic[ch]->psyInputBuffer,
    648                    psyStatic[ch]->psyInputBuffer+psyConf->granuleLength,
    649                    psyConf->granuleLength*sizeof(INT_PCM));
    650 
    651 
    652         /* ... and get remaining samples from input buffer */
    653         FDKaacEnc_deinterleaveInputBuffer( psyStatic[ch]->psyInputBuffer+psyConf->granuleLength,
    654                                           &pInput[ (2*psyConf->granuleLength-blockSwitchingOffset)*totalChannels + chIdx[ch] ],
    655                                            blockSwitchingOffset-psyConf->granuleLength,
    656                                            totalChannels);
    657 
    658     } /* ch */
    659 
    660     /* Do some rescaling to get maximum possible accuracy for energies */
    661     if ( zeroSpec == FALSE) {
    662 
    663         /* Calc possible spectrum leftshift for each sfb (1 means: 1 bit left shift is possible without overflow) */
    664         INT minSpecShift = MAX_SHIFT_DBL;
    665         INT nrgShift     = MAX_SHIFT_DBL;
    666         INT finalShift   = MAX_SHIFT_DBL;
    667         FIXP_DBL currNrg = 0;
    668         FIXP_DBL maxNrg  = 0;
    669 
    670         for(ch = 0; ch < channels; ch++) {
    671             for(w = 0; w < nWindows[ch]; w++) {
    672                 wOffset = w*windowLength[ch];
    673                 FDKaacEnc_CalcSfbMaxScaleSpec(psyData[ch]->mdctSpectrum+wOffset,
    674                                               hThisPsyConf[ch]->sfbOffset,
    675                                               pSfbMaxScaleSpec[ch]+w*maxSfb[ch],
    676                                               psyData[ch]->sfbActive);
    677 
    678                 for (sfb = 0; sfb<psyData[ch]->sfbActive; sfb++)
    679                     minSpecShift = fixMin(minSpecShift, (pSfbMaxScaleSpec[ch]+w*maxSfb[ch])[sfb]);
    680             }
    681 
    682         }
    683 
    684         /* Calc possible energy leftshift for each sfb (1 means: 1 bit left shift is possible without overflow) */
    685         for(ch = 0; ch < channels; ch++) {
    686             for(w = 0; w < nWindows[ch]; w++) {
    687                 wOffset = w*windowLength[ch];
    688                 currNrg = FDKaacEnc_CheckBandEnergyOptim(psyData[ch]->mdctSpectrum+wOffset,
    689                                                         pSfbMaxScaleSpec[ch]+w*maxSfb[ch],
    690                                                         hThisPsyConf[ch]->sfbOffset,
    691                                                         psyData[ch]->sfbActive,
    692                                                         pSfbEnergy[ch]+w*maxSfb[ch],
    693                                                         pSfbEnergyLdData[ch]+w*maxSfb[ch],
    694                                                         minSpecShift-4);
    695 
    696                 maxNrg = fixMax(maxNrg, currNrg);
    697             }
    698         }
    699 
    700         if ( maxNrg != (FIXP_DBL)0 ) {
    701             nrgShift = (CountLeadingBits(maxNrg)>>1) + (minSpecShift-4);
    702         }
    703 
    704         /* 2check: Hasn't this decision to be made for both channels? */
    705         /* For short windows 1 additional bit headroom is necessary to prevent overflows when summing up energies in FDKaacEnc_groupShortData() */
    706         if(isShortWindow[0]) nrgShift--;
    707 
    708         /* both spectrum and energies mustn't overflow */
    709         finalShift = fixMin(minSpecShift, nrgShift);
    710 
    711         /* do not shift more than 3 bits more to the left than signal without blockfloating point
    712          * would be to avoid overflow of scaled PCM quantization thresholds */
    713         if (finalShift > psyData[0]->mdctScale + 3 )
    714             finalShift = psyData[0]->mdctScale + 3;
    715 
    716         FDK_ASSERT(finalShift >= 0);    /* right shift is not allowed */
    717 
    718         /* correct sfbEnergy and sfbEnergyLdData with new finalShift */
    719         FIXP_DBL ldShift = finalShift * FL2FXCONST_DBL(2.0/64);
    720         for(ch = 0; ch < channels; ch++) {
    721             for(w = 0; w < nWindows[ch]; w++) {
    722                 for(sfb=0; sfb<psyData[ch]->sfbActive; sfb++) {
    723                     INT scale = fixMax(0, (pSfbMaxScaleSpec[ch]+w*maxSfb[ch])[sfb]-4);
    724                     scale     = fixMin((scale-finalShift)<<1, DFRACT_BITS-1);
    725                     if (scale >= 0) (pSfbEnergy[ch]+w*maxSfb[ch])[sfb] >>= (scale);
    726                     else            (pSfbEnergy[ch]+w*maxSfb[ch])[sfb] <<= (-scale);
    727                     (pSfbThreshold[ch]+w*maxSfb[ch])[sfb] = fMult((pSfbEnergy[ch]+w*maxSfb[ch])[sfb], C_RATIO);
    728                     (pSfbEnergyLdData[ch]+w*maxSfb[ch])[sfb] += ldShift;
    729                 }
    730             }
    731         }
    732 
    733         if ( finalShift != 0 ) {
    734             for (ch = 0; ch < channels; ch++) {
    735                 for(w = 0; w < nWindows[ch]; w++) {
    736                     wOffset = w*windowLength[ch];
    737                     for(line=0; line<psyData[ch]->lowpassLine; line++) {
    738                         psyData[ch]->mdctSpectrum[line+wOffset] <<= finalShift;
    739                     }
    740                     /* update sfbMaxScaleSpec */
    741                     for (sfb = 0; sfb<psyData[ch]->sfbActive; sfb++)
    742                         (pSfbMaxScaleSpec[ch]+w*maxSfb[ch])[sfb] -= finalShift;
    743                 }
    744                 /* update mdctScale */
    745                 psyData[ch]->mdctScale -= finalShift;
    746             }
    747         }
    748 
    749     } else {
    750         /* all spectral lines are zero */
    751         for (ch = 0; ch < channels; ch++) {
    752             psyData[ch]->mdctScale = 0;     /* otherwise mdctScale would be for example 7 and PCM quantization thresholds would be shifted
    753                                              * 14 bits to the right causing some of them to become 0 (which causes problems later) */
    754             /* clear sfbMaxScaleSpec */
    755             for(w = 0; w < nWindows[ch]; w++) {
    756                 for (sfb = 0; sfb<psyData[ch]->sfbActive; sfb++) {
    757                     (pSfbMaxScaleSpec[ch]+w*maxSfb[ch])[sfb] = 0;
    758                     (pSfbEnergy[ch]+w*maxSfb[ch])[sfb]       = (FIXP_DBL)0;
    759                     (pSfbEnergyLdData[ch]+w*maxSfb[ch])[sfb] = FL2FXCONST_DBL(-1.0f);
    760                     (pSfbThreshold[ch]+w*maxSfb[ch])[sfb]    = (FIXP_DBL)0;
    761                 }
    762             }
    763         }
    764     }
    765 
    766     /* Advance psychoacoustics: Tonality and TNS */
    767     if (psyStatic[0]->isLFE) {
    768         tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] = 0;
    769         tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT] = 0;
    770     }
    771     else
    772     {
    773 
    774         for(ch = 0; ch < channels; ch++) {
    775             if (!isShortWindow[ch]) {
    776                 /* tonality */
    777                 FDKaacEnc_CalculateFullTonality( psyData[ch]->mdctSpectrum,
    778                                        pSfbMaxScaleSpec[ch],
    779                                        pSfbEnergyLdData[ch],
    780                                        sfbTonality[ch],
    781                                        psyData[ch]->sfbActive,
    782                                        hThisPsyConf[ch]->sfbOffset,
    783                                        hThisPsyConf[ch]->pnsConf.usePns);
    784             }
    785         }
    786 
    787         if (hPsyConfLong->tnsConf.tnsActive || hPsyConfShort->tnsConf.tnsActive) {
    788             INT tnsActive[TRANS_FAC];
    789             INT nrgScaling[2] = {0,0};
    790             INT tnsSpecShift = 0;
    791 
    792             for(ch = 0; ch < channels; ch++) {
    793                 for(w = 0; w < nWindows[ch]; w++) {
    794 
    795                     wOffset = w*windowLength[ch];
    796                     /* TNS */
    797                     FDKaacEnc_TnsDetect(
    798                                 tnsData[ch],
    799                                 &hThisPsyConf[ch]->tnsConf,
    800                                 &psyOutChannel[ch]->tnsInfo,
    801                                 hThisPsyConf[ch]->sfbCnt,
    802                                 psyData[ch]->mdctSpectrum+wOffset,
    803                                 w,
    804                                 psyStatic[ch]->blockSwitchingControl.lastWindowSequence
    805                                 );
    806                 }
    807             }
    808 
    809             if (channels == 2) {
    810               FDKaacEnc_TnsSync(
    811                       tnsData[1],
    812                       tnsData[0],
    813                       &psyOutChannel[1]->tnsInfo,
    814                       &psyOutChannel[0]->tnsInfo,
    815 
    816                       psyStatic[1]->blockSwitchingControl.lastWindowSequence,
    817                       psyStatic[0]->blockSwitchingControl.lastWindowSequence,
    818                       &hThisPsyConf[1]->tnsConf);
    819             }
    820 
    821             FDK_ASSERT(1==commonWindow); /* all checks for TNS do only work for common windows (which is always set)*/
    822             for(w = 0; w < nWindows[0]; w++)
    823             {
    824                 if (isShortWindow[0])
    825                     tnsActive[w] = tnsData[0]->dataRaw.Short.subBlockInfo[w].tnsActive[HIFILT] ||
    826                     tnsData[0]->dataRaw.Short.subBlockInfo[w].tnsActive[LOFILT] ||
    827                     tnsData[channels-1]->dataRaw.Short.subBlockInfo[w].tnsActive[HIFILT] ||
    828                     tnsData[channels-1]->dataRaw.Short.subBlockInfo[w].tnsActive[LOFILT];
    829                 else
    830                     tnsActive[w] = tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] ||
    831                     tnsData[0]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT] ||
    832                     tnsData[channels-1]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT] ||
    833                     tnsData[channels-1]->dataRaw.Long.subBlockInfo.tnsActive[LOFILT];
    834             }
    835 
    836             for(ch = 0; ch < channels; ch++) {
    837                 if (tnsActive[0] && !isShortWindow[ch]) {
    838                     /* Scale down spectrum if tns is active in one of the two channels with same lastWindowSequence */
    839                     /* first part of threshold calculation; it's not necessary to update sfbMaxScaleSpec */
    840                     INT shift = 1;
    841                     for(sfb=0; sfb<hThisPsyConf[ch]->lowpassLine; sfb++) {
    842                         psyData[ch]->mdctSpectrum[sfb] = psyData[ch]->mdctSpectrum[sfb] >> shift;
    843                     }
    844 
    845                     /* update thresholds */
    846                     for (sfb=0; sfb<psyData[ch]->sfbActive; sfb++) {
    847                         pSfbThreshold[ch][sfb] >>= (2*shift);
    848                     }
    849 
    850                     psyData[ch]->mdctScale += shift; /* update mdctScale */
    851 
    852                     /* calc sfbEnergies after tnsEncode again ! */
    853 
    854                 }
    855             }
    856 
    857             for(ch = 0; ch < channels; ch++) {
    858               for(w = 0; w < nWindows[ch]; w++)
    859                 {
    860                     wOffset = w*windowLength[ch];
    861                     FDKaacEnc_TnsEncode(
    862                                 &psyOutChannel[ch]->tnsInfo,
    863                                 tnsData[ch],
    864                                 hThisPsyConf[ch]->sfbCnt,
    865                                 &hThisPsyConf[ch]->tnsConf,
    866                                 hThisPsyConf[ch]->sfbOffset[psyData[ch]->sfbActive],/*hThisPsyConf[ch]->lowpassLine*/ /* filter stops before that line ! */
    867                                 psyData[ch]->mdctSpectrum+wOffset,
    868                                 w,
    869                                 psyStatic[ch]->blockSwitchingControl.lastWindowSequence);
    870 
    871                     if(tnsActive[w]) {
    872                             /* Calc sfb-bandwise mdct-energies for left and right channel again, */
    873                             /* if tns active in current channel or in one channel with same lastWindowSequence left and right */
    874                             FDKaacEnc_CalcSfbMaxScaleSpec(psyData[ch]->mdctSpectrum+wOffset,
    875                                                 hThisPsyConf[ch]->sfbOffset,
    876                                                 pSfbMaxScaleSpec[ch]+w*maxSfb[ch],
    877                                                 psyData[ch]->sfbActive);
    878                     }
    879                 }
    880             }
    881 
    882             for(ch = 0; ch < channels; ch++) {
    883               for(w = 0; w < nWindows[ch]; w++) {
    884 
    885                 if (tnsActive[w]) {
    886 
    887                   if (isShortWindow[ch]) {
    888                     FDKaacEnc_CalcBandEnergyOptimShort(psyData[ch]->mdctSpectrum+w*windowLength[ch],
    889                                              pSfbMaxScaleSpec[ch]+w*maxSfb[ch],
    890                                              hThisPsyConf[ch]->sfbOffset,
    891                                              psyData[ch]->sfbActive,
    892                                              pSfbEnergy[ch]+w*maxSfb[ch]);
    893                   }
    894                   else {
    895                     nrgScaling[ch] =        /* with tns, energy calculation can overflow; -> scaling */
    896                     FDKaacEnc_CalcBandEnergyOptimLong(psyData[ch]->mdctSpectrum,
    897                                            pSfbMaxScaleSpec[ch],
    898                                            hThisPsyConf[ch]->sfbOffset,
    899                                            psyData[ch]->sfbActive,
    900                                            pSfbEnergy[ch],
    901                                            pSfbEnergyLdData[ch]);
    902                     tnsSpecShift = fixMax(tnsSpecShift, nrgScaling[ch]);       /* nrgScaling is set only if nrg would have an overflow */
    903                   }
    904                 } /* if tnsActive */
    905               }
    906             } /* end channel loop */
    907 
    908             /* adapt scaling to prevent nrg overflow, only for long blocks */
    909             for(ch = 0; ch < channels; ch++) {
    910               if ( (tnsSpecShift!=0) && !isShortWindow[ch] ) {
    911                 /* scale down spectrum, nrg's and thresholds, if there was an overflow in sfbNrg calculation after tns */
    912                 for(line=0; line<hThisPsyConf[ch]->lowpassLine; line++) {
    913                   psyData[ch]->mdctSpectrum[line] >>= tnsSpecShift;
    914                 }
    915                 INT scale = (tnsSpecShift-nrgScaling[ch])<<1;
    916                 for(sfb=0; sfb<psyData[ch]->sfbActive; sfb++) {
    917                   pSfbEnergyLdData[ch][sfb]   -= scale*FL2FXCONST_DBL(1.0/LD_DATA_SCALING);
    918                   pSfbEnergy[ch][sfb]        >>= scale;
    919                   pSfbThreshold[ch][sfb]     >>= (tnsSpecShift<<1);
    920                 }
    921                 psyData[ch]->mdctScale += tnsSpecShift;  /* update mdctScale; not necessary to update sfbMaxScaleSpec */
    922 
    923               }
    924             } /* end channel loop */
    925 
    926         } /* TNS active */
    927     }  /* !isLFE */
    928 
    929 
    930 
    931 
    932 
    933 
    934     /* Advance thresholds */
    935     for(ch = 0; ch < channels; ch++) {
    936         INT headroom;
    937 
    938         FIXP_DBL clipEnergy;
    939         INT energyShift  = psyData[ch]->mdctScale*2 ;
    940         INT clipNrgShift = energyShift - THR_SHIFTBITS ;
    941 
    942         if(isShortWindow[ch])
    943             headroom = 6;
    944         else
    945             headroom = 0;
    946 
    947         if (clipNrgShift >= 0)
    948             clipEnergy = hThisPsyConf[ch]->clipEnergy >>  clipNrgShift ;
    949         else if (clipNrgShift>=-headroom)
    950             clipEnergy = hThisPsyConf[ch]->clipEnergy << -clipNrgShift ;
    951         else
    952             clipEnergy = (FIXP_DBL)MAXVAL_DBL ;
    953 
    954         for(w = 0; w < nWindows[ch]; w++)
    955         {
    956             INT i;
    957             /* limit threshold to avoid clipping */
    958             for (i=0; i<psyData[ch]->sfbActive; i++) {
    959                 *(pSfbThreshold[ch]+w*maxSfb[ch]+i) = fixMin(*(pSfbThreshold[ch]+w*maxSfb[ch]+i), clipEnergy);
    960             }
    961 
    962             /* spreading */
    963             FDKaacEnc_SpreadingMax(psyData[ch]->sfbActive,
    964                             hThisPsyConf[ch]->sfbMaskLowFactor,
    965                             hThisPsyConf[ch]->sfbMaskHighFactor,
    966                             pSfbThreshold[ch]+w*maxSfb[ch]);
    967 
    968 
    969             /* PCM quantization threshold */
    970             energyShift += PCM_QUANT_THR_SCALE;
    971             if (energyShift>=0) {
    972                energyShift = fixMin(DFRACT_BITS-1,energyShift);
    973                for (i=0; i<psyData[ch]->sfbActive;i++) {
    974                    *(pSfbThreshold[ch]+w*maxSfb[ch]+i) = fixMax(*(pSfbThreshold[ch]+w*maxSfb[ch]+i) >> THR_SHIFTBITS,
    975                                                           (hThisPsyConf[ch]->sfbPcmQuantThreshold[i] >> energyShift));
    976                }
    977             } else {
    978                energyShift = fixMin(DFRACT_BITS-1,-energyShift);
    979                for (i=0; i<psyData[ch]->sfbActive;i++) {
    980                    *(pSfbThreshold[ch]+w*maxSfb[ch]+i) = fixMax(*(pSfbThreshold[ch]+w*maxSfb[ch]+i) >> THR_SHIFTBITS,
    981                                                           (hThisPsyConf[ch]->sfbPcmQuantThreshold[i] << energyShift));
    982                }
    983             }
    984 
    985             if (!psyStatic[ch]->isLFE)
    986             {
    987                 /* preecho control */
    988                 if(psyStatic[ch]->blockSwitchingControl.lastWindowSequence == STOP_WINDOW) {
    989                     /* prevent FDKaacEnc_PreEchoControl from comparing stop
    990                        thresholds with short thresholds */
    991                     for (i=0; i<psyData[ch]->sfbActive;i++) {
    992                         psyStatic[ch]->sfbThresholdnm1[i] = (FIXP_DBL)MAXVAL_DBL;
    993                     }
    994 
    995                     psyStatic[ch]->mdctScalenm1 = 0;
    996                     psyStatic[ch]->calcPreEcho  = 0;
    997                 }
    998 
    999                 FDKaacEnc_PreEchoControl( psyStatic[ch]->sfbThresholdnm1,
   1000                                 psyStatic[ch]->calcPreEcho,
   1001                                 psyData[ch]->sfbActive,
   1002                                 hThisPsyConf[ch]->maxAllowedIncreaseFactor,
   1003                                 hThisPsyConf[ch]->minRemainingThresholdFactor,
   1004                                 pSfbThreshold[ch]+w*maxSfb[ch],
   1005                                 psyData[ch]->mdctScale,
   1006                                 &psyStatic[ch]->mdctScalenm1);
   1007 
   1008                 psyStatic[ch]->calcPreEcho = 1;
   1009 
   1010                 if(psyStatic[ch]->blockSwitchingControl.lastWindowSequence == START_WINDOW)
   1011                 {
   1012                     /* prevent FDKaacEnc_PreEchoControl in next frame to compare start
   1013                        thresholds with short thresholds */
   1014                     for (i=0; i<psyData[ch]->sfbActive;i++) {
   1015                         psyStatic[ch]->sfbThresholdnm1[i] = (FIXP_DBL)MAXVAL_DBL;
   1016                     }
   1017 
   1018                     psyStatic[ch]->mdctScalenm1 = 0;
   1019                     psyStatic[ch]->calcPreEcho  = 0;
   1020                 }
   1021 
   1022             }
   1023 
   1024             /* spread energy to avoid hole detection */
   1025             FDKmemcpy(pSfbSpreadEnergy[ch]+w*maxSfb[ch], pSfbEnergy[ch]+w*maxSfb[ch], psyData[ch]->sfbActive*sizeof(FIXP_DBL));
   1026 
   1027             FDKaacEnc_SpreadingMax(psyData[ch]->sfbActive,
   1028                          hThisPsyConf[ch]->sfbMaskLowFactorSprEn,
   1029                          hThisPsyConf[ch]->sfbMaskHighFactorSprEn,
   1030                          pSfbSpreadEnergy[ch]+w*maxSfb[ch]);
   1031         }
   1032     }
   1033 
   1034     /* Calc bandwise energies for mid and side channel. Do it only if 2 channels exist */
   1035     if (channels==2) {
   1036         for(w = 0; w < nWindows[1]; w++) {
   1037             wOffset = w*windowLength[1];
   1038             FDKaacEnc_CalcBandNrgMSOpt(psyData[0]->mdctSpectrum+wOffset,
   1039                              psyData[1]->mdctSpectrum+wOffset,
   1040                              pSfbMaxScaleSpec[0]+w*maxSfb[0],
   1041                              pSfbMaxScaleSpec[1]+w*maxSfb[1],
   1042                              hThisPsyConf[1]->sfbOffset,
   1043                              psyData[0]->sfbActive,
   1044                              pSfbEnergyMS[0]+w*maxSfb[0],
   1045                              pSfbEnergyMS[1]+w*maxSfb[1],
   1046                              (psyStatic[1]->blockSwitchingControl.lastWindowSequence != SHORT_WINDOW),
   1047                              psyData[0]->sfbEnergyMSLdData,
   1048                              psyData[1]->sfbEnergyMSLdData);
   1049         }
   1050     }
   1051 
   1052     /* group short data (maxSfb[ch] for short blocks is determined here) */
   1053     for(ch=0;ch<channels;ch++)
   1054     {
   1055         INT noSfb, i;
   1056         if(isShortWindow[ch])
   1057         {
   1058             int sfbGrp;
   1059             noSfb = psyStatic[ch]->blockSwitchingControl.noOfGroups * hPsyConfShort->sfbCnt;
   1060             /* At this point, energies and thresholds are copied/regrouped from the ".Short" to the ".Long" arrays */
   1061             FDKaacEnc_groupShortData( psyData[ch]->mdctSpectrum,
   1062                             &psyData[ch]->sfbThreshold,
   1063                             &psyData[ch]->sfbEnergy,
   1064                             &psyData[ch]->sfbEnergyMS,
   1065                             &psyData[ch]->sfbSpreadEnergy,
   1066                             hPsyConfShort->sfbCnt,
   1067                             psyData[ch]->sfbActive,
   1068                             hPsyConfShort->sfbOffset,
   1069                             hPsyConfShort->sfbMinSnrLdData,
   1070                             psyData[ch]->groupedSfbOffset,
   1071                             &maxSfbPerGroup[ch],
   1072                             psyOutChannel[ch]->sfbMinSnrLdData,
   1073                             psyStatic[ch]->blockSwitchingControl.noOfGroups,
   1074                             psyStatic[ch]->blockSwitchingControl.groupLen,
   1075                             psyConf[1].granuleLength);
   1076 
   1077 
   1078             /* calculate ldData arrays (short values are in .Long-arrays after FDKaacEnc_groupShortData) */
   1079             for (sfbGrp = 0; sfbGrp < noSfb; sfbGrp += hPsyConfShort->sfbCnt) {
   1080               LdDataVector(&psyData[ch]->sfbEnergy.Long[sfbGrp], &psyOutChannel[ch]->sfbEnergyLdData[sfbGrp], psyData[ch]->sfbActive);
   1081             }
   1082 
   1083             /* calc sfbThrld and set Values smaller 2^-31 to 2^-33*/
   1084             for (sfbGrp = 0; sfbGrp < noSfb; sfbGrp += hPsyConfShort->sfbCnt) {
   1085               LdDataVector(&psyData[ch]->sfbThreshold.Long[sfbGrp], &psyOutChannel[ch]->sfbThresholdLdData[sfbGrp], psyData[ch]->sfbActive);
   1086               for (sfb=0;sfb<psyData[ch]->sfbActive;sfb++) {
   1087                 psyOutChannel[ch]->sfbThresholdLdData[sfbGrp+sfb] =
   1088                            fixMax(psyOutChannel[ch]->sfbThresholdLdData[sfbGrp+sfb], FL2FXCONST_DBL(-0.515625f));
   1089               }
   1090             }
   1091 
   1092             if ( channels==2 ) {
   1093               for (sfbGrp = 0; sfbGrp < noSfb; sfbGrp += hPsyConfShort->sfbCnt) {
   1094                 LdDataVector(&psyData[ch]->sfbEnergyMS.Long[sfbGrp], &psyData[ch]->sfbEnergyMSLdData[sfbGrp], psyData[ch]->sfbActive);
   1095               }
   1096             }
   1097 
   1098             FDKmemcpy(psyOutChannel[ch]->sfbOffsets, psyData[ch]->groupedSfbOffset, (MAX_GROUPED_SFB+1)*sizeof(INT));
   1099 
   1100         } else {
   1101             /* maxSfb[ch] for long blocks */
   1102             for (sfb = psyData[ch]->sfbActive-1; sfb >= 0; sfb--) {
   1103                 for (line = hPsyConfLong->sfbOffset[sfb+1]-1; line >= hPsyConfLong->sfbOffset[sfb]; line--) {
   1104                     if (psyData[ch]->mdctSpectrum[line] != FL2FXCONST_SGL(0.0f)) break;
   1105                 }
   1106                 if (line > hPsyConfLong->sfbOffset[sfb]) break;
   1107             }
   1108             maxSfbPerGroup[ch] = sfb + 1;
   1109             /* ensure at least one section in ICS; workaround for existing decoder crc implementation */
   1110             maxSfbPerGroup[ch] = fixMax(fixMin(5,psyData[ch]->sfbActive),maxSfbPerGroup[ch]);
   1111 
   1112             /* sfbNrgLdData is calculated in FDKaacEnc_advancePsychLong, copy in psyOut structure */
   1113             FDKmemcpy(psyOutChannel[ch]->sfbEnergyLdData, psyData[ch]->sfbEnergyLdData.Long, psyData[ch]->sfbActive*sizeof(FIXP_DBL));
   1114 
   1115             FDKmemcpy(psyOutChannel[ch]->sfbOffsets, hPsyConfLong->sfbOffset, (MAX_GROUPED_SFB+1)*sizeof(INT));
   1116 
   1117             /* sfbMinSnrLdData modified in adjust threshold, copy necessary */
   1118             FDKmemcpy(psyOutChannel[ch]->sfbMinSnrLdData, hPsyConfLong->sfbMinSnrLdData, psyData[ch]->sfbActive*sizeof(FIXP_DBL));
   1119 
   1120             /* sfbEnergyMSLdData ist already calculated in FDKaacEnc_CalcBandNrgMSOpt; only in long case */
   1121 
   1122             /* calc sfbThrld and set Values smaller 2^-31 to 2^-33*/
   1123             LdDataVector(psyData[ch]->sfbThreshold.Long, psyOutChannel[ch]->sfbThresholdLdData, psyData[ch]->sfbActive);
   1124             for (i=0;i<psyData[ch]->sfbActive;i++) {
   1125               psyOutChannel[ch]->sfbThresholdLdData[i] =
   1126                            fixMax(psyOutChannel[ch]->sfbThresholdLdData[i], FL2FXCONST_DBL(-0.515625f));
   1127             }
   1128 
   1129 
   1130         }
   1131 
   1132 
   1133     }
   1134 
   1135 
   1136     /*
   1137         Intensity parameter intialization.
   1138      */
   1139     for(ch=0;ch<channels;ch++) {
   1140         FDKmemclear(psyOutChannel[ch]->isBook,  MAX_GROUPED_SFB*sizeof(INT));
   1141         FDKmemclear(psyOutChannel[ch]->isScale, MAX_GROUPED_SFB*sizeof(INT));
   1142     }
   1143 
   1144     for(ch=0;ch<channels;ch++) {
   1145         INT win = (isShortWindow[ch]?1:0);
   1146         if (!psyStatic[ch]->isLFE)
   1147         {
   1148             /* PNS Decision */
   1149             FDKaacEnc_PnsDetect( &(psyConf[0].pnsConf),
   1150                        pnsData[ch],
   1151                        psyStatic[ch]->blockSwitchingControl.lastWindowSequence,
   1152                        psyData[ch]->sfbActive,
   1153                        maxSfbPerGroup[ch], /* count of Sfb which are not zero. */
   1154                        psyOutChannel[ch]->sfbThresholdLdData,
   1155                        psyConf[win].sfbOffset,
   1156                        psyData[ch]->mdctSpectrum,
   1157                        psyData[ch]->sfbMaxScaleSpec.Long,
   1158                        sfbTonality[ch],
   1159                        psyOutChannel[ch]->tnsInfo.order[0][0],
   1160                        tnsData[ch]->dataRaw.Long.subBlockInfo.predictionGain[HIFILT],
   1161                        tnsData[ch]->dataRaw.Long.subBlockInfo.tnsActive[HIFILT],
   1162                        psyOutChannel[ch]->sfbEnergyLdData,
   1163                        psyOutChannel[ch]->noiseNrg );
   1164         } /* !isLFE */
   1165     }
   1166 
   1167     /*
   1168         stereo Processing
   1169     */
   1170     if(channels == 2)
   1171     {
   1172         psyOutElement->toolsInfo.msDigest = MS_NONE;
   1173         psyOutElement->commonWindow       = commonWindow;
   1174         if (psyOutElement->commonWindow)
   1175             maxSfbPerGroup[0] = maxSfbPerGroup[1] =
   1176                               fixMax(maxSfbPerGroup[0], maxSfbPerGroup[1]);
   1177 
   1178         if(psyStatic[0]->blockSwitchingControl.lastWindowSequence != SHORT_WINDOW)
   1179         {
   1180             /* PNS preprocessing depending on ms processing: PNS not in Short Window! */
   1181             FDKaacEnc_PreProcessPnsChannelPair(
   1182                                 psyData[0]->sfbActive,
   1183                                 (&psyData[0]->sfbEnergy)->Long,
   1184                                 (&psyData[1]->sfbEnergy)->Long,
   1185                                 psyOutChannel[0]->sfbEnergyLdData,
   1186                                 psyOutChannel[1]->sfbEnergyLdData,
   1187                                 psyData[0]->sfbEnergyMS.Long,
   1188                                 &(psyConf[0].pnsConf),
   1189                                 pnsData[0],
   1190                                 pnsData[1]);
   1191 
   1192             FDKaacEnc_IntensityStereoProcessing(
   1193                                 psyData[0]->sfbEnergy.Long,
   1194                                 psyData[1]->sfbEnergy.Long,
   1195                                 psyData[0]->mdctSpectrum,
   1196                                 psyData[1]->mdctSpectrum,
   1197                                 psyData[0]->sfbThreshold.Long,
   1198                                 psyData[1]->sfbThreshold.Long,
   1199                                 psyOutChannel[1]->sfbThresholdLdData,
   1200                                 psyData[0]->sfbSpreadEnergy.Long,
   1201                                 psyData[1]->sfbSpreadEnergy.Long,
   1202                                 psyOutChannel[0]->sfbEnergyLdData,
   1203                                 psyOutChannel[1]->sfbEnergyLdData,
   1204                                 &psyOutElement->toolsInfo.msDigest,
   1205                                 psyOutElement->toolsInfo.msMask,
   1206                                 psyConf[0].sfbCnt,
   1207                                 psyConf[0].sfbCnt,
   1208                                 maxSfbPerGroup[0],
   1209                                 psyConf[0].sfbOffset,
   1210                                 psyConf[0].allowIS && commonWindow,
   1211                                 psyOutChannel[1]->isBook,
   1212                                 psyOutChannel[1]->isScale,
   1213                                 pnsData);
   1214 
   1215             FDKaacEnc_MsStereoProcessing(
   1216                                 psyData,
   1217                                 psyOutChannel,
   1218                                 psyOutChannel[1]->isBook,
   1219                                 &psyOutElement->toolsInfo.msDigest,
   1220                                 psyOutElement->toolsInfo.msMask,
   1221                                 psyData[0]->sfbActive,
   1222                                 psyData[0]->sfbActive,
   1223                                 maxSfbPerGroup[0],
   1224                                 psyOutChannel[0]->sfbOffsets);
   1225 
   1226             /* PNS postprocessing */
   1227             FDKaacEnc_PostProcessPnsChannelPair(psyData[0]->sfbActive,
   1228                                 &(psyConf[0].pnsConf),
   1229                                 pnsData[0],
   1230                                 pnsData[1],
   1231                                 psyOutElement->toolsInfo.msMask,
   1232                                 &psyOutElement->toolsInfo.msDigest);
   1233 
   1234         } else {
   1235             FDKaacEnc_IntensityStereoProcessing(
   1236                                 psyData[0]->sfbEnergy.Long,
   1237                                 psyData[1]->sfbEnergy.Long,
   1238                                 psyData[0]->mdctSpectrum,
   1239                                 psyData[1]->mdctSpectrum,
   1240                                 psyData[0]->sfbThreshold.Long,
   1241                                 psyData[1]->sfbThreshold.Long,
   1242                                 psyOutChannel[1]->sfbThresholdLdData,
   1243                                 psyData[0]->sfbSpreadEnergy.Long,
   1244                                 psyData[1]->sfbSpreadEnergy.Long,
   1245                                 psyOutChannel[0]->sfbEnergyLdData,
   1246                                 psyOutChannel[1]->sfbEnergyLdData,
   1247                                 &psyOutElement->toolsInfo.msDigest,
   1248                                 psyOutElement->toolsInfo.msMask,
   1249                                 psyStatic[0]->blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt,
   1250                                 psyConf[1].sfbCnt,
   1251                                 maxSfbPerGroup[0],
   1252                                 psyData[0]->groupedSfbOffset,
   1253                                 psyConf[0].allowIS && commonWindow,
   1254                                 psyOutChannel[1]->isBook,
   1255                                 psyOutChannel[1]->isScale,
   1256                                 pnsData);
   1257 
   1258             /* it's OK to pass the ".Long" arrays here. They contain grouped short data since FDKaacEnc_groupShortData() */
   1259             FDKaacEnc_MsStereoProcessing( psyData,
   1260                                 psyOutChannel,
   1261                                 psyOutChannel[1]->isBook,
   1262                                 &psyOutElement->toolsInfo.msDigest,
   1263                                 psyOutElement->toolsInfo.msMask,
   1264                                 psyStatic[0]->blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt,
   1265                                 hPsyConfShort->sfbCnt,
   1266                                 maxSfbPerGroup[0],
   1267                                 psyOutChannel[0]->sfbOffsets);
   1268         }
   1269     }
   1270 
   1271   /*
   1272     PNS Coding
   1273   */
   1274   for(ch=0;ch<channels;ch++) {
   1275       if (psyStatic[ch]->isLFE) {
   1276           /* no PNS coding */
   1277           for(sfb = 0; sfb < psyData[ch]->sfbActive; sfb++) {
   1278             psyOutChannel[ch]->noiseNrg[sfb] = NO_NOISE_PNS;
   1279           }
   1280       } else
   1281       {
   1282           FDKaacEnc_CodePnsChannel(psyData[ch]->sfbActive,
   1283                          &(psyConf[ch].pnsConf),
   1284                          pnsData[ch]->pnsFlag,
   1285                          psyData[ch]->sfbEnergyLdData.Long,
   1286                          psyOutChannel[ch]->noiseNrg, /* this is the energy that will be written to the bitstream */
   1287                          psyOutChannel[ch]->sfbThresholdLdData);
   1288       }
   1289   }
   1290 
   1291     /*
   1292         build output
   1293     */
   1294     for(ch=0;ch<channels;ch++)
   1295     {
   1296         INT j, grp, mask;
   1297 
   1298         psyOutChannel[ch]->maxSfbPerGroup    = maxSfbPerGroup[ch];
   1299         psyOutChannel[ch]->mdctScale         = psyData[ch]->mdctScale;
   1300 
   1301         if(isShortWindow[ch]==0) {
   1302 
   1303             psyOutChannel[ch]->sfbCnt         = hPsyConfLong->sfbActive;
   1304             psyOutChannel[ch]->sfbPerGroup    = hPsyConfLong->sfbActive;
   1305             psyOutChannel[ch]->lastWindowSequence = psyStatic[ch]->blockSwitchingControl.lastWindowSequence;
   1306             psyOutChannel[ch]->windowShape    = psyStatic[ch]->blockSwitchingControl.windowShape;
   1307         }
   1308         else {
   1309             INT sfbCnt = psyStatic[ch]->blockSwitchingControl.noOfGroups*hPsyConfShort->sfbCnt;
   1310 
   1311             psyOutChannel[ch]->sfbCnt         = sfbCnt;
   1312             psyOutChannel[ch]->sfbPerGroup    = hPsyConfShort->sfbCnt;
   1313             psyOutChannel[ch]->lastWindowSequence = SHORT_WINDOW;
   1314             psyOutChannel[ch]->windowShape    = SINE_WINDOW;
   1315         }
   1316 
   1317         /* generate grouping mask */
   1318         mask = 0;
   1319         for (grp = 0; grp < psyStatic[ch]->blockSwitchingControl.noOfGroups; grp++)
   1320         {
   1321           mask <<= 1;
   1322           for (j=1; j<psyStatic[ch]->blockSwitchingControl.groupLen[grp]; j++) {
   1323               mask = (mask<<1) | 1 ;
   1324           }
   1325         }
   1326         psyOutChannel[ch]->groupingMask = mask;
   1327 
   1328         /* build interface */
   1329         FDKmemcpy(psyOutChannel[ch]->groupLen,psyStatic[ch]->blockSwitchingControl.groupLen,MAX_NO_OF_GROUPS*sizeof(INT));
   1330         FDKmemcpy(psyOutChannel[ch]->sfbEnergy,(&psyData[ch]->sfbEnergy)->Long, MAX_GROUPED_SFB*sizeof(FIXP_DBL));
   1331         FDKmemcpy(psyOutChannel[ch]->sfbSpreadEnergy,(&psyData[ch]->sfbSpreadEnergy)->Long, MAX_GROUPED_SFB*sizeof(FIXP_DBL));
   1332 //        FDKmemcpy(psyOutChannel[ch]->mdctSpectrum, psyData[ch]->mdctSpectrum, (1024)*sizeof(FIXP_DBL));
   1333     }
   1334 
   1335     return AAC_ENC_OK;
   1336 }
   1337 
   1338 
   1339 void FDKaacEnc_PsyClose(PSY_INTERNAL   **phPsyInternal,
   1340                         PSY_OUT        **phPsyOut)
   1341 {
   1342     int n, i;
   1343 
   1344 
   1345     if(phPsyInternal!=NULL) {
   1346       PSY_INTERNAL *hPsyInternal = *phPsyInternal;
   1347 
   1348       if (hPsyInternal)
   1349       {
   1350         for (i=0; i<(8); i++) {
   1351           if (hPsyInternal->pStaticChannels[i]) {
   1352             if (hPsyInternal->pStaticChannels[i]->psyInputBuffer)
   1353               FreeRam_aacEnc_PsyInputBuffer(&hPsyInternal->pStaticChannels[i]->psyInputBuffer);  /* AUDIO INPUT BUFFER */
   1354 
   1355             FreeRam_aacEnc_PsyStatic(&hPsyInternal->pStaticChannels[i]);                         /* PSY_STATIC */
   1356           }
   1357         }
   1358 
   1359         for (i=0; i<(8); i++) {
   1360           if (hPsyInternal->psyElement[i])
   1361             FreeRam_aacEnc_PsyElement(&hPsyInternal->psyElement[i]);                             /* PSY_ELEMENT */
   1362         }
   1363 
   1364 
   1365         FreeRam_aacEnc_PsyInternal(phPsyInternal);
   1366       }
   1367     }
   1368 
   1369     if (phPsyOut!=NULL) {
   1370       for (n=0; n<(1); n++) {
   1371         if (phPsyOut[n])
   1372         {
   1373           for (i=0; i<(8); i++) {
   1374             if (phPsyOut[n]->pPsyOutChannels[i])
   1375               FreeRam_aacEnc_PsyOutChannel(&phPsyOut[n]->pPsyOutChannels[i]);                  /* PSY_OUT_CHANNEL */
   1376           }
   1377 
   1378           for (i=0; i<(8); i++) {
   1379             if (phPsyOut[n]->psyOutElement[i])
   1380               FreeRam_aacEnc_PsyOutElements(&phPsyOut[n]->psyOutElement[i]);                   /* PSY_OUT_ELEMENTS */
   1381           }
   1382 
   1383           FreeRam_aacEnc_PsyOut(&phPsyOut[n]);
   1384         }
   1385       }
   1386     }
   1387 }
   1388