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