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