1 2/* ----------------------------------------------------------------------------------------------------------- 3Software License for The Fraunhofer FDK AAC Codec Library for Android 4 5© Copyright 1995 - 2012 Fraunhofer-Gesellschaft zur Förderung der angewandten Forschung e.V. 6 All rights reserved. 7 8 1. INTRODUCTION 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. Lohwasser 87 contents/description: pns.c 88 89******************************************************************************/ 90 91#include "aacenc_pns.h" 92#include "psy_data.h" 93#include "pnsparam.h" 94#include "noisedet.h" 95#include "bit_cnt.h" 96#include "interface.h" 97 98 99/* minCorrelationEnergy = (1.0e-10f)^2 ~ 2^-67 = 2^-47 * 2^-20 */ 100static const FIXP_DBL minCorrelationEnergy = FL2FXCONST_DBL(0.0); /* FL2FXCONST_DBL((float)FDKpow(2.0,-47)); */ 101/* noiseCorrelationThresh = 0.6^2 */ 102static const FIXP_DBL noiseCorrelationThresh = FL2FXCONST_DBL(0.36); 103 104static void FDKaacEnc_FDKaacEnc_noiseDetection( PNS_CONFIG *pnsConf, 105 PNS_DATA *pnsData, 106 const INT sfbActive, 107 const INT *sfbOffset, 108 INT tnsOrder, 109 INT tnsPredictionGain, 110 INT tnsActive, 111 FIXP_DBL *mdctSpectrum, 112 INT *sfbMaxScaleSpec, 113 FIXP_SGL *sfbtonality ); 114 115static void FDKaacEnc_CalcNoiseNrgs( const INT sfbActive, 116 INT *pnsFlag, 117 FIXP_DBL *sfbEnergyLdData, 118 INT *noiseNrg ); 119 120/***************************************************************************** 121 122 functionname: initPnsConfiguration 123 description: fill pnsConf with pns parameters 124 returns: error status 125 input: PNS Config struct (modified) 126 bitrate, samplerate, usePns, 127 number of sfb's, pointer to sfb offset 128 output: error code 129 130*****************************************************************************/ 131 132AAC_ENCODER_ERROR FDKaacEnc_InitPnsConfiguration(PNS_CONFIG *pnsConf, 133 INT bitRate, 134 INT sampleRate, 135 INT usePns, 136 INT sfbCnt, 137 const INT *sfbOffset, 138 const INT numChan, 139 const INT isLC) 140{ 141 AAC_ENCODER_ERROR ErrorStatus; 142 143 /* init noise detection */ 144 ErrorStatus = FDKaacEnc_GetPnsParam(&pnsConf->np, 145 bitRate, 146 sampleRate, 147 sfbCnt, 148 sfbOffset, 149 &usePns, 150 numChan, 151 isLC); 152 if (ErrorStatus != AAC_ENC_OK) 153 return ErrorStatus; 154 155 pnsConf->minCorrelationEnergy = minCorrelationEnergy; 156 pnsConf->noiseCorrelationThresh = noiseCorrelationThresh; 157 158 pnsConf->usePns = usePns; 159 160 return AAC_ENC_OK; 161} 162 163 164 165/***************************************************************************** 166 167 functionname: FDKaacEnc_PnsDetect 168 description: do decision, if PNS shall used or not 169 returns: 170 input: pns config structure 171 pns data structure (modified), 172 lastWindowSequence (long or short blocks) 173 sfbActive 174 pointer to Sfb Energy, Threshold, Offset 175 pointer to mdct Spectrum 176 length of each group 177 pointer to tonality calculated in chaosmeasure 178 tns order and prediction gain 179 calculated noiseNrg at active PNS 180 output: pnsFlag in pns data structure 181 182*****************************************************************************/ 183void FDKaacEnc_PnsDetect(PNS_CONFIG *pnsConf, 184 PNS_DATA *pnsData, 185 const INT lastWindowSequence, 186 const INT sfbActive, 187 const INT maxSfbPerGroup, 188 FIXP_DBL *sfbThresholdLdData, 189 const INT *sfbOffset, 190 FIXP_DBL *mdctSpectrum, 191 INT *sfbMaxScaleSpec, 192 FIXP_SGL *sfbtonality, 193 INT tnsOrder, 194 INT tnsPredictionGain, 195 INT tnsActive, 196 FIXP_DBL *sfbEnergyLdData, 197 INT *noiseNrg ) 198 199{ 200 int sfb; 201 int startNoiseSfb; 202 203 if (pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMLEXITY) { 204 if ( (!pnsConf->usePns) || /* pns enabled? */ 205 (lastWindowSequence == SHORT_WINDOW) ) /* currently only long blocks */ 206 { 207 FDKmemclear(pnsData->pnsFlag, MAX_GROUPED_SFB*sizeof(INT)); /* clear all pnsFlags */ 208 for (sfb=0; sfb<MAX_GROUPED_SFB; sfb++) { 209 noiseNrg[sfb] = NO_NOISE_PNS; /* clear nrg's of previous frame */ 210 } 211 return; 212 } 213 } 214 else { 215 if(!pnsConf->usePns) 216 return; 217 218 /* PNS only for long Windows */ 219 if (pnsConf->np.detectionAlgorithmFlags & JUST_LONG_WINDOW) { 220 if(lastWindowSequence != LONG_WINDOW) { 221 for (sfb = 0; sfb < sfbActive; sfb++) { 222 pnsData->pnsFlag[sfb] = 0; /* clear all pnsFlags */ 223 } 224 return; 225 } 226 } 227 } 228 /* 229 call noise detection 230 */ 231 FDKaacEnc_FDKaacEnc_noiseDetection( pnsConf, 232 pnsData, 233 sfbActive, 234 sfbOffset, 235 tnsOrder, 236 tnsPredictionGain, 237 tnsActive, 238 mdctSpectrum, 239 sfbMaxScaleSpec, 240 sfbtonality ); 241 242 /* set startNoiseSfb (long) */ 243 startNoiseSfb = pnsConf->np.startSfb; 244 245 /* Set noise substitution status */ 246 for(sfb = 0; sfb < sfbActive; sfb++) { 247 248 /* No PNS below startNoiseSfb */ 249 if(sfb < startNoiseSfb){ 250 pnsData->pnsFlag[sfb] = 0; 251 continue; 252 } 253 254 /* 255 do noise substitution if 256 fuzzy measure is high enough 257 sfb freq > minimum sfb freq 258 signal in coder band is not masked 259 */ 260 261 if((pnsData->noiseFuzzyMeasure[sfb] > FL2FXCONST_SGL(0.5)) && 262 ( (sfbThresholdLdData[sfb] + FL2FXCONST_DBL(0.5849625f/64.0f)) /* thr * 1.5 = thrLd +ld(1.5)/64 */ 263 < sfbEnergyLdData[sfb] ) ) 264 { 265 /* 266 mark in psyout flag array that we will code 267 this band with PNS 268 */ 269 pnsData->pnsFlag[sfb] = 1; /* PNS_ON */ 270 } 271 else{ 272 pnsData->pnsFlag[sfb] = 0; /* PNS_OFF */ 273 } 274 275 /* no PNS if LTP is active */ 276 } 277 278 /* avoid PNS holes */ 279 if((pnsData->noiseFuzzyMeasure[0]>FL2FXCONST_SGL(0.5f)) && (pnsData->pnsFlag[1])) { 280 pnsData->pnsFlag[0] = 1; 281 } 282 283 for(sfb=1; sfb<maxSfbPerGroup-1; sfb++) { 284 if((pnsData->noiseFuzzyMeasure[sfb]>pnsConf->np.gapFillThr) && 285 (pnsData->pnsFlag[sfb-1]) && (pnsData->pnsFlag[sfb+1])) { 286 pnsData->pnsFlag[sfb] = 1; 287 } 288 } 289 290 if(maxSfbPerGroup>0) { 291 /* avoid PNS hole */ 292 if((pnsData->noiseFuzzyMeasure[maxSfbPerGroup-1]>pnsConf->np.gapFillThr) && (pnsData->pnsFlag[maxSfbPerGroup-2])) { 293 pnsData->pnsFlag[maxSfbPerGroup-1] = 1; 294 } 295 /* avoid single PNS band */ 296 if(pnsData->pnsFlag[maxSfbPerGroup-2]==0) { 297 pnsData->pnsFlag[maxSfbPerGroup-1] = 0; 298 } 299 } 300 301 /* avoid single PNS bands */ 302 if(pnsData->pnsFlag[1]==0) { 303 pnsData->pnsFlag[0] = 0; 304 } 305 306 for(sfb=1; sfb<maxSfbPerGroup-1; sfb++) { 307 if((pnsData->pnsFlag[sfb-1]==0)&&(pnsData->pnsFlag[sfb+1]==0)) { 308 pnsData->pnsFlag[sfb] = 0; 309 } 310 } 311 312 313 /* 314 calculate noiseNrg's 315 */ 316 FDKaacEnc_CalcNoiseNrgs( sfbActive, 317 pnsData->pnsFlag, 318 sfbEnergyLdData, 319 noiseNrg ); 320} 321 322 323/***************************************************************************** 324 325 functionname:FDKaacEnc_FDKaacEnc_noiseDetection 326 description: wrapper for noisedet.c 327 returns: 328 input: pns config structure 329 pns data structure (modified), 330 sfbActive 331 tns order and prediction gain 332 pointer to mdct Spectrumand Sfb Energy 333 pointer to Sfb tonality 334 output: noiseFuzzyMeasure in structure pnsData 335 flags tonal / nontonal 336 337*****************************************************************************/ 338static void FDKaacEnc_FDKaacEnc_noiseDetection( PNS_CONFIG *pnsConf, 339 PNS_DATA *pnsData, 340 const INT sfbActive, 341 const INT *sfbOffset, 342 int tnsOrder, 343 INT tnsPredictionGain, 344 INT tnsActive, 345 FIXP_DBL *mdctSpectrum, 346 INT *sfbMaxScaleSpec, 347 FIXP_SGL *sfbtonality ) 348{ 349 INT condition = TRUE; 350 if ( !(pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMLEXITY) ) { 351 condition = (tnsOrder > 3); 352 } 353 /* 354 no PNS if heavy TNS activity 355 clear pnsData->noiseFuzzyMeasure 356 */ 357 if((pnsConf->np.detectionAlgorithmFlags & USE_TNS_GAIN_THR) && 358 (tnsPredictionGain >= pnsConf->np.tnsGainThreshold) && condition && 359 !((pnsConf->np.detectionAlgorithmFlags & USE_TNS_PNS) && (tnsPredictionGain >= pnsConf->np.tnsPNSGainThreshold) && (tnsActive)) ) 360 { 361 /* clear all noiseFuzzyMeasure */ 362 FDKmemclear(pnsData->noiseFuzzyMeasure, sfbActive*sizeof(FIXP_SGL)); 363 } 364 else 365 { 366 /* 367 call noise detection, output in pnsData->noiseFuzzyMeasure, 368 use real mdct spectral data 369 */ 370 FDKaacEnc_noiseDetect( mdctSpectrum, 371 sfbMaxScaleSpec, 372 sfbActive, 373 sfbOffset, 374 pnsData->noiseFuzzyMeasure, 375 &pnsConf->np, 376 sfbtonality); 377 } 378} 379 380 381/***************************************************************************** 382 383 functionname:FDKaacEnc_CalcNoiseNrgs 384 description: Calculate the NoiseNrg's 385 returns: 386 input: sfbActive 387 if pnsFlag calculate NoiseNrg 388 pointer to sfbEnergy and groupLen 389 pointer to noiseNrg (modified) 390 output: noiseNrg's in pnsFlaged sfb's 391 392*****************************************************************************/ 393 394static void FDKaacEnc_CalcNoiseNrgs( const INT sfbActive, 395 INT *RESTRICT pnsFlag, 396 FIXP_DBL *RESTRICT sfbEnergyLdData, 397 INT *RESTRICT noiseNrg ) 398{ 399 int sfb; 400 INT tmp = (-LOG_NORM_PCM)<<2; 401 402 for(sfb = 0; sfb < sfbActive; sfb++) { 403 if(pnsFlag[sfb]) { 404 INT nrg = (-sfbEnergyLdData[sfb]+FL2FXCONST_DBL(0.5f/64.0f))>>(DFRACT_BITS-1-7); 405 noiseNrg[sfb] = tmp - nrg; 406 } 407 } 408} 409 410 411/***************************************************************************** 412 413 functionname:FDKaacEnc_CodePnsChannel 414 description: Execute pns decission 415 returns: 416 input: sfbActive 417 pns config structure 418 use PNS if pnsFlag 419 pointer to Sfb Energy, noiseNrg, Threshold 420 output: set sfbThreshold high to code pe with 0, 421 noiseNrg marks flag for pns coding 422 423*****************************************************************************/ 424 425void FDKaacEnc_CodePnsChannel(const INT sfbActive, 426 PNS_CONFIG *pnsConf, 427 INT *RESTRICT pnsFlag, 428 FIXP_DBL *RESTRICT sfbEnergyLdData, 429 INT *RESTRICT noiseNrg, 430 FIXP_DBL *RESTRICT sfbThresholdLdData) 431{ 432 INT sfb; 433 INT lastiNoiseEnergy = 0; 434 INT firstPNSband = 1; /* TRUE for first PNS-coded band */ 435 436 /* no PNS */ 437 if(!pnsConf->usePns) { 438 for(sfb = 0; sfb < sfbActive; sfb++) { 439 /* no PNS coding */ 440 noiseNrg[sfb] = NO_NOISE_PNS; 441 } 442 return; 443 } 444 445 /* code PNS */ 446 for(sfb = 0; sfb < sfbActive; sfb++) { 447 if(pnsFlag[sfb]) { 448 /* high sfbThreshold causes pe = 0 */ 449 if(noiseNrg[sfb] != NO_NOISE_PNS) 450 sfbThresholdLdData[sfb] = sfbEnergyLdData[sfb] + FL2FXCONST_DBL(1.0f/LD_DATA_SCALING); 451 452 /* set noiseNrg in valid region */ 453 if(!firstPNSband) { 454 INT deltaiNoiseEnergy = noiseNrg[sfb] - lastiNoiseEnergy; 455 456 if(deltaiNoiseEnergy > CODE_BOOK_PNS_LAV) 457 noiseNrg[sfb] -= deltaiNoiseEnergy - CODE_BOOK_PNS_LAV; 458 else if(deltaiNoiseEnergy < -CODE_BOOK_PNS_LAV) 459 noiseNrg[sfb] -= deltaiNoiseEnergy + CODE_BOOK_PNS_LAV; 460 } 461 else { 462 firstPNSband = 0; 463 } 464 lastiNoiseEnergy = noiseNrg[sfb]; 465 } 466 else { 467 /* no PNS coding */ 468 noiseNrg[sfb] = NO_NOISE_PNS; 469 } 470 } 471} 472 473 474/***************************************************************************** 475 476 functionname:FDKaacEnc_PreProcessPnsChannelPair 477 description: Calculate the correlation of noise in a channel pair 478 479 returns: 480 input: sfbActive 481 pointer to sfb energies left, right and mid channel 482 pns config structure 483 pns data structure left and right (modified) 484 485 output: noiseEnergyCorrelation in pns data structure 486 487*****************************************************************************/ 488 489void FDKaacEnc_PreProcessPnsChannelPair(const INT sfbActive, 490 FIXP_DBL *RESTRICT sfbEnergyLeft, 491 FIXP_DBL *RESTRICT sfbEnergyRight, 492 FIXP_DBL *RESTRICT sfbEnergyLeftLD, 493 FIXP_DBL *RESTRICT sfbEnergyRightLD, 494 FIXP_DBL *RESTRICT sfbEnergyMid, 495 PNS_CONFIG *RESTRICT pnsConf, 496 PNS_DATA *pnsDataLeft, 497 PNS_DATA *pnsDataRight) 498{ 499 INT sfb; 500 FIXP_DBL ccf; 501 502 if(!pnsConf->usePns) 503 return; 504 505 FIXP_DBL *RESTRICT pNoiseEnergyCorrelationL = pnsDataLeft->noiseEnergyCorrelation; 506 FIXP_DBL *RESTRICT pNoiseEnergyCorrelationR = pnsDataRight->noiseEnergyCorrelation; 507 508 for(sfb=0;sfb< sfbActive;sfb++) { 509 FIXP_DBL quot = (sfbEnergyLeftLD[sfb]>>1) + (sfbEnergyRightLD[sfb]>>1); 510 511 if(quot < FL2FXCONST_DBL(-32.0f/(float)LD_DATA_SCALING)) 512 ccf = FL2FXCONST_DBL(0.0f); 513 else { 514 FIXP_DBL accu = sfbEnergyMid[sfb]- (((sfbEnergyLeft[sfb]>>1)+(sfbEnergyRight[sfb]>>1))>>1); 515 INT sign = (accu < FL2FXCONST_DBL(0.0f)) ? 1 : 0 ; 516 accu = fixp_abs(accu); 517 518 ccf = CalcLdData(accu) + FL2FXCONST_DBL((float)1.0f/(float)LD_DATA_SCALING) - quot; /* ld(accu*2) = ld(accu) + 1 */ 519 ccf = (ccf>=FL2FXCONST_DBL(0.0)) ? ((FIXP_DBL)MAXVAL_DBL) : (sign) ? -CalcInvLdData(ccf) : CalcInvLdData(ccf); 520 } 521 522 pNoiseEnergyCorrelationL[sfb] = ccf; 523 pNoiseEnergyCorrelationR[sfb] = ccf; 524 } 525} 526 527 528 529/***************************************************************************** 530 531 functionname:FDKaacEnc_PostProcessPnsChannelPair 532 description: if PNS used at left and right channel, 533 use msMask to flag correlation 534 returns: 535 input: sfbActive 536 pns config structure 537 pns data structure left and right (modified) 538 pointer to msMask, flags correlation by pns coding (modified) 539 Digest of MS coding 540 output: pnsFlag in pns data structure, 541 msFlag in msMask (flags correlation) 542 543*****************************************************************************/ 544 545void FDKaacEnc_PostProcessPnsChannelPair(const INT sfbActive, 546 PNS_CONFIG *pnsConf, 547 PNS_DATA *pnsDataLeft, 548 PNS_DATA *pnsDataRight, 549 INT *RESTRICT msMask, 550 INT *msDigest ) 551{ 552 INT sfb; 553 554 if(!pnsConf->usePns) 555 return; 556 557 for(sfb=0;sfb<sfbActive;sfb++) { 558 /* 559 MS post processing 560 */ 561 if( msMask[sfb] ) { 562 if( (pnsDataLeft->pnsFlag[sfb]) && 563 (pnsDataRight->pnsFlag[sfb]) ) { 564 /* AAC only: Standard */ 565 /* do this to avoid ms flags in layers that should not have it */ 566 if(pnsDataLeft->noiseEnergyCorrelation[sfb] <= pnsConf->noiseCorrelationThresh){ 567 msMask[sfb] = 0; 568 *msDigest = MS_SOME; 569 } 570 } 571 else { 572 /* 573 No PNS coding 574 */ 575 pnsDataLeft->pnsFlag[sfb] = 0; 576 pnsDataRight->pnsFlag[sfb] = 0; 577 } 578 } 579 580 /* 581 Use MS flag to signal noise correlation if 582 pns is active in both channels 583 */ 584 if( (pnsDataLeft->pnsFlag[sfb]) && (pnsDataRight->pnsFlag[sfb]) ) { 585 if(pnsDataLeft->noiseEnergyCorrelation[sfb] > pnsConf->noiseCorrelationThresh) { 586 msMask[sfb] = 1; 587 *msDigest = MS_SOME; 588 } 589 } 590 } 591} 592