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