1
2/* -----------------------------------------------------------------------------------------------------------
3Software License for The Fraunhofer FDK AAC Codec Library for Android
4
5� Copyright  1995 - 2012 Fraunhofer-Gesellschaft zur F�rderung der angewandten Forschung e.V.
6  All rights reserved.
7
8 1.    INTRODUCTION
9The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software that implements
10the MPEG Advanced Audio Coding ("AAC") encoding and decoding scheme for digital audio.
11This FDK AAC Codec software is intended to be used on a wide variety of Android devices.
12
13AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient general perceptual
14audio codecs. AAC-ELD is considered the best-performing full-bandwidth communications codec by
15independent studies and is widely deployed. AAC has been standardized by ISO and IEC as part
16of the MPEG specifications.
17
18Patent licenses for necessary patent claims for the FDK AAC Codec (including those of Fraunhofer)
19may be obtained through Via Licensing (www.vialicensing.com) or through the respective patent owners
20individually for the purpose of encoding or decoding bit streams in products that are compliant with
21the ISO/IEC MPEG audio standards. Please note that most manufacturers of Android devices already license
22these patent claims through Via Licensing or directly from the patent owners, and therefore FDK AAC Codec
23software may already be covered under those patent licenses when it is used for those licensed purposes only.
24
25Commercially-licensed AAC software libraries, including floating-point versions with enhanced sound quality,
26are also available from Fraunhofer. Users are encouraged to check the Fraunhofer website for additional
27applications information and documentation.
28
292.    COPYRIGHT LICENSE
30
31Redistribution and use in source and binary forms, with or without modification, are permitted without
32payment of copyright license fees provided that you satisfy the following conditions:
33
34You must retain the complete text of this software license in redistributions of the FDK AAC Codec or
35your modifications thereto in source code form.
36
37You must retain the complete text of this software license in the documentation and/or other materials
38provided with redistributions of the FDK AAC Codec or your modifications thereto in binary form.
39You must make available free of charge copies of the complete source code of the FDK AAC Codec and your
40modifications thereto to recipients of copies in binary form.
41
42The name of Fraunhofer may not be used to endorse or promote products derived from this library without
43prior written permission.
44
45You may not charge copyright license fees for anyone to use, copy or distribute the FDK AAC Codec
46software or your modifications thereto.
47
48Your modified versions of the FDK AAC Codec must carry prominent notices stating that you changed the software
49and 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
533.    NO PATENT LICENSE
54
55NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without limitation the patents of Fraunhofer,
56ARE GRANTED BY THIS SOFTWARE LICENSE. Fraunhofer provides no warranty of patent non-infringement with
57respect to this software.
58
59You may use this FDK AAC Codec software or modifications thereto only for purposes that are authorized
60by appropriate patent licenses.
61
624.    DISCLAIMER
63
64This 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
66of merchantability and fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
67CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, or consequential damages,
68including but not limited to procurement of substitute goods or services; loss of use, data, or profits,
69or business interruption, however caused and on any theory of liability, whether in contract, strict
70liability, or tort (including negligence), arising in any way out of the use of this software, even if
71advised of the possibility of such damage.
72
735.    CONTACT INFORMATION
74
75Fraunhofer Institute for Integrated Circuits IIS
76Attention: Audio and Multimedia Departments - FDK AAC LL
77Am Wolfsmantel 33
7891058 Erlangen, Germany
79
80www.iis.fraunhofer.de/amm
81amm-info@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
114static const FIXP_DBL fadeOutFactor[FADE_OUT_LEN] = {1840644096, 1533870080, 1227096064, 920322048, 613548032, 306774016};
115
116/* forward definitions */
117
118
119static 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*****************************************************************************/
132AAC_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
178bail:
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*****************************************************************************/
192AAC_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
226bail:
227  FDKaacEnc_PsyClose(NULL, phpsyOut);
228  return ErrorStatus;
229}
230
231
232AAC_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
247AAC_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
304AAC_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
420static
421void 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
445AAC_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
1337void 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