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