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