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