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