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