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