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