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