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