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