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