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