1 /* ----------------------------------------------------------------------------- 2 Software License for The Fraunhofer FDK AAC Codec Library for Android 3 4 Copyright 1995 - 2018 Fraunhofer-Gesellschaft zur Frderung der angewandten 5 Forschung e.V. All rights reserved. 6 7 1. INTRODUCTION 8 The Fraunhofer FDK AAC Codec Library for Android ("FDK AAC Codec") is software 9 that implements the MPEG Advanced Audio Coding ("AAC") encoding and decoding 10 scheme for digital audio. This FDK AAC Codec software is intended to be used on 11 a wide variety of Android devices. 12 13 AAC's HE-AAC and HE-AAC v2 versions are regarded as today's most efficient 14 general perceptual audio codecs. AAC-ELD is considered the best-performing 15 full-bandwidth communications codec by independent studies and is widely 16 deployed. AAC has been standardized by ISO and IEC as part of the MPEG 17 specifications. 18 19 Patent licenses for necessary patent claims for the FDK AAC Codec (including 20 those of Fraunhofer) may be obtained through Via Licensing 21 (www.vialicensing.com) or through the respective patent owners individually for 22 the purpose of encoding or decoding bit streams in products that are compliant 23 with the ISO/IEC MPEG audio standards. Please note that most manufacturers of 24 Android devices already license these patent claims through Via Licensing or 25 directly from the patent owners, and therefore FDK AAC Codec software may 26 already be covered under those patent licenses when it is used for those 27 licensed purposes only. 28 29 Commercially-licensed AAC software libraries, including floating-point versions 30 with enhanced sound quality, are also available from Fraunhofer. Users are 31 encouraged to check the Fraunhofer website for additional applications 32 information and documentation. 33 34 2. COPYRIGHT LICENSE 35 36 Redistribution and use in source and binary forms, with or without modification, 37 are permitted without payment of copyright license fees provided that you 38 satisfy the following conditions: 39 40 You must retain the complete text of this software license in redistributions of 41 the FDK AAC Codec or your modifications thereto in source code form. 42 43 You must retain the complete text of this software license in the documentation 44 and/or other materials provided with redistributions of the FDK AAC Codec or 45 your modifications thereto in binary form. You must make available free of 46 charge copies of the complete source code of the FDK AAC Codec and your 47 modifications thereto to recipients of copies in binary form. 48 49 The name of Fraunhofer may not be used to endorse or promote products derived 50 from this library without prior written permission. 51 52 You may not charge copyright license fees for anyone to use, copy or distribute 53 the FDK AAC Codec software or your modifications thereto. 54 55 Your modified versions of the FDK AAC Codec must carry prominent notices stating 56 that you changed the software and the date of any change. For modified versions 57 of the FDK AAC Codec, the term "Fraunhofer FDK AAC Codec Library for Android" 58 must be replaced by the term "Third-Party Modified Version of the Fraunhofer FDK 59 AAC Codec Library for Android." 60 61 3. NO PATENT LICENSE 62 63 NO EXPRESS OR IMPLIED LICENSES TO ANY PATENT CLAIMS, including without 64 limitation the patents of Fraunhofer, ARE GRANTED BY THIS SOFTWARE LICENSE. 65 Fraunhofer provides no warranty of patent non-infringement with respect to this 66 software. 67 68 You may use this FDK AAC Codec software or modifications thereto only for 69 purposes that are authorized by appropriate patent licenses. 70 71 4. DISCLAIMER 72 73 This FDK AAC Codec software is provided by Fraunhofer on behalf of the copyright 74 holders and contributors "AS IS" and WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, 75 including but not limited to the implied warranties of merchantability and 76 fitness for a particular purpose. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 77 CONTRIBUTORS BE LIABLE for any direct, indirect, incidental, special, exemplary, 78 or consequential damages, including but not limited to procurement of substitute 79 goods or services; loss of use, data, or profits, or business interruption, 80 however caused and on any theory of liability, whether in contract, strict 81 liability, or tort (including negligence), arising in any way out of the use of 82 this software, even if advised of the possibility of such damage. 83 84 5. CONTACT INFORMATION 85 86 Fraunhofer Institute for Integrated Circuits IIS 87 Attention: Audio and Multimedia Departments - FDK AAC LL 88 Am Wolfsmantel 33 89 91058 Erlangen, Germany 90 91 www.iis.fraunhofer.de/amm 92 amm-info (at) iis.fraunhofer.de 93 ----------------------------------------------------------------------------- */ 94 95 /**************************** AAC encoder library ****************************** 96 97 Author(s): M. Lohwasser 98 99 Description: pns.c 100 101 *******************************************************************************/ 102 103 #include "aacenc_pns.h" 104 105 #include "psy_data.h" 106 #include "pnsparam.h" 107 #include "noisedet.h" 108 #include "bit_cnt.h" 109 #include "interface.h" 110 111 /* minCorrelationEnergy = (1.0e-10f)^2 ~ 2^-67 = 2^-47 * 2^-20 */ 112 static const FIXP_DBL minCorrelationEnergy = 113 FL2FXCONST_DBL(0.0); /* FL2FXCONST_DBL((float)FDKpow(2.0,-47)); */ 114 /* noiseCorrelationThresh = 0.6^2 */ 115 static const FIXP_DBL noiseCorrelationThresh = FL2FXCONST_DBL(0.36); 116 117 static void FDKaacEnc_FDKaacEnc_noiseDetection( 118 PNS_CONFIG *pnsConf, PNS_DATA *pnsData, const INT sfbActive, 119 const INT *sfbOffset, INT tnsOrder, INT tnsPredictionGain, INT tnsActive, 120 FIXP_DBL *mdctSpectrum, INT *sfbMaxScaleSpec, FIXP_SGL *sfbtonality); 121 122 static void FDKaacEnc_CalcNoiseNrgs(const INT sfbActive, INT *pnsFlag, 123 FIXP_DBL *sfbEnergyLdData, INT *noiseNrg); 124 125 /***************************************************************************** 126 127 functionname: initPnsConfiguration 128 description: fill pnsConf with pns parameters 129 returns: error status 130 input: PNS Config struct (modified) 131 bitrate, samplerate, usePns, 132 number of sfb's, pointer to sfb offset 133 output: error code 134 135 *****************************************************************************/ 136 137 AAC_ENCODER_ERROR FDKaacEnc_InitPnsConfiguration( 138 PNS_CONFIG *pnsConf, INT bitRate, INT sampleRate, INT usePns, INT sfbCnt, 139 const INT *sfbOffset, const INT numChan, const INT isLC) { 140 AAC_ENCODER_ERROR ErrorStatus; 141 142 /* init noise detection */ 143 ErrorStatus = FDKaacEnc_GetPnsParam(&pnsConf->np, bitRate, sampleRate, sfbCnt, 144 sfbOffset, &usePns, numChan, isLC); 145 if (ErrorStatus != AAC_ENC_OK) return ErrorStatus; 146 147 pnsConf->minCorrelationEnergy = minCorrelationEnergy; 148 pnsConf->noiseCorrelationThresh = noiseCorrelationThresh; 149 150 pnsConf->usePns = usePns; 151 152 return AAC_ENC_OK; 153 } 154 155 /***************************************************************************** 156 157 functionname: FDKaacEnc_PnsDetect 158 description: do decision, if PNS shall used or not 159 returns: 160 input: pns config structure 161 pns data structure (modified), 162 lastWindowSequence (long or short blocks) 163 sfbActive 164 pointer to Sfb Energy, Threshold, Offset 165 pointer to mdct Spectrum 166 length of each group 167 pointer to tonality calculated in chaosmeasure 168 tns order and prediction gain 169 calculated noiseNrg at active PNS 170 output: pnsFlag in pns data structure 171 172 *****************************************************************************/ 173 void FDKaacEnc_PnsDetect(PNS_CONFIG *pnsConf, PNS_DATA *pnsData, 174 const INT lastWindowSequence, const INT sfbActive, 175 const INT maxSfbPerGroup, FIXP_DBL *sfbThresholdLdData, 176 const INT *sfbOffset, FIXP_DBL *mdctSpectrum, 177 INT *sfbMaxScaleSpec, FIXP_SGL *sfbtonality, 178 INT tnsOrder, INT tnsPredictionGain, INT tnsActive, 179 FIXP_DBL *sfbEnergyLdData, INT *noiseNrg) 180 181 { 182 int sfb; 183 int startNoiseSfb; 184 185 /* Reset pns info. */ 186 FDKmemclear(pnsData->pnsFlag, sizeof(pnsData->pnsFlag)); 187 for (sfb = 0; sfb < MAX_GROUPED_SFB; sfb++) { 188 noiseNrg[sfb] = NO_NOISE_PNS; 189 } 190 191 /* Disable PNS and skip detection in certain cases. */ 192 if (pnsConf->usePns == 0) { 193 return; 194 } else { 195 /* AAC - LC core encoder */ 196 if ((pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMPLEXITY) && 197 (lastWindowSequence == SHORT_WINDOW)) { 198 return; 199 } 200 /* AAC - (E)LD core encoder */ 201 if (!(pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMPLEXITY) && 202 (pnsConf->np.detectionAlgorithmFlags & JUST_LONG_WINDOW) && 203 (lastWindowSequence != LONG_WINDOW)) { 204 return; 205 } 206 } 207 208 /* 209 call noise detection 210 */ 211 FDKaacEnc_FDKaacEnc_noiseDetection( 212 pnsConf, pnsData, sfbActive, sfbOffset, tnsOrder, tnsPredictionGain, 213 tnsActive, mdctSpectrum, sfbMaxScaleSpec, sfbtonality); 214 215 /* set startNoiseSfb (long) */ 216 startNoiseSfb = pnsConf->np.startSfb; 217 218 /* Set noise substitution status */ 219 for (sfb = 0; sfb < sfbActive; sfb++) { 220 /* No PNS below startNoiseSfb */ 221 if (sfb < startNoiseSfb) { 222 pnsData->pnsFlag[sfb] = 0; 223 continue; 224 } 225 226 /* 227 do noise substitution if 228 fuzzy measure is high enough 229 sfb freq > minimum sfb freq 230 signal in coder band is not masked 231 */ 232 233 if ((pnsData->noiseFuzzyMeasure[sfb] > FL2FXCONST_SGL(0.5)) && 234 ((sfbThresholdLdData[sfb] + 235 FL2FXCONST_DBL(0.5849625f / 236 64.0f)) /* thr * 1.5 = thrLd +ld(1.5)/64 */ 237 < sfbEnergyLdData[sfb])) { 238 /* 239 mark in psyout flag array that we will code 240 this band with PNS 241 */ 242 pnsData->pnsFlag[sfb] = 1; /* PNS_ON */ 243 } else { 244 pnsData->pnsFlag[sfb] = 0; /* PNS_OFF */ 245 } 246 247 /* no PNS if LTP is active */ 248 } 249 250 /* avoid PNS holes */ 251 if ((pnsData->noiseFuzzyMeasure[0] > FL2FXCONST_SGL(0.5f)) && 252 (pnsData->pnsFlag[1])) { 253 pnsData->pnsFlag[0] = 1; 254 } 255 256 for (sfb = 1; sfb < maxSfbPerGroup - 1; sfb++) { 257 if ((pnsData->noiseFuzzyMeasure[sfb] > pnsConf->np.gapFillThr) && 258 (pnsData->pnsFlag[sfb - 1]) && (pnsData->pnsFlag[sfb + 1])) { 259 pnsData->pnsFlag[sfb] = 1; 260 } 261 } 262 263 if (maxSfbPerGroup > 0) { 264 /* avoid PNS hole */ 265 if ((pnsData->noiseFuzzyMeasure[maxSfbPerGroup - 1] > 266 pnsConf->np.gapFillThr) && 267 (pnsData->pnsFlag[maxSfbPerGroup - 2])) { 268 pnsData->pnsFlag[maxSfbPerGroup - 1] = 1; 269 } 270 /* avoid single PNS band */ 271 if (pnsData->pnsFlag[maxSfbPerGroup - 2] == 0) { 272 pnsData->pnsFlag[maxSfbPerGroup - 1] = 0; 273 } 274 } 275 276 /* avoid single PNS bands */ 277 if (pnsData->pnsFlag[1] == 0) { 278 pnsData->pnsFlag[0] = 0; 279 } 280 281 for (sfb = 1; sfb < maxSfbPerGroup - 1; sfb++) { 282 if ((pnsData->pnsFlag[sfb - 1] == 0) && (pnsData->pnsFlag[sfb + 1] == 0)) { 283 pnsData->pnsFlag[sfb] = 0; 284 } 285 } 286 287 /* 288 calculate noiseNrg's 289 */ 290 FDKaacEnc_CalcNoiseNrgs(sfbActive, pnsData->pnsFlag, sfbEnergyLdData, 291 noiseNrg); 292 } 293 294 /***************************************************************************** 295 296 functionname:FDKaacEnc_FDKaacEnc_noiseDetection 297 description: wrapper for noisedet.c 298 returns: 299 input: pns config structure 300 pns data structure (modified), 301 sfbActive 302 tns order and prediction gain 303 pointer to mdct Spectrumand Sfb Energy 304 pointer to Sfb tonality 305 output: noiseFuzzyMeasure in structure pnsData 306 flags tonal / nontonal 307 308 *****************************************************************************/ 309 static void FDKaacEnc_FDKaacEnc_noiseDetection( 310 PNS_CONFIG *pnsConf, PNS_DATA *pnsData, const INT sfbActive, 311 const INT *sfbOffset, int tnsOrder, INT tnsPredictionGain, INT tnsActive, 312 FIXP_DBL *mdctSpectrum, INT *sfbMaxScaleSpec, FIXP_SGL *sfbtonality) { 313 INT condition = TRUE; 314 if (!(pnsConf->np.detectionAlgorithmFlags & IS_LOW_COMPLEXITY)) { 315 condition = (tnsOrder > 3); 316 } 317 /* 318 no PNS if heavy TNS activity 319 clear pnsData->noiseFuzzyMeasure 320 */ 321 if ((pnsConf->np.detectionAlgorithmFlags & USE_TNS_GAIN_THR) && 322 (tnsPredictionGain >= pnsConf->np.tnsGainThreshold) && condition && 323 !((pnsConf->np.detectionAlgorithmFlags & USE_TNS_PNS) && 324 (tnsPredictionGain >= pnsConf->np.tnsPNSGainThreshold) && 325 (tnsActive))) { 326 /* clear all noiseFuzzyMeasure */ 327 FDKmemclear(pnsData->noiseFuzzyMeasure, sfbActive * sizeof(FIXP_SGL)); 328 } else { 329 /* 330 call noise detection, output in pnsData->noiseFuzzyMeasure, 331 use real mdct spectral data 332 */ 333 FDKaacEnc_noiseDetect(mdctSpectrum, sfbMaxScaleSpec, sfbActive, sfbOffset, 334 pnsData->noiseFuzzyMeasure, &pnsConf->np, 335 sfbtonality); 336 } 337 } 338 339 /***************************************************************************** 340 341 functionname:FDKaacEnc_CalcNoiseNrgs 342 description: Calculate the NoiseNrg's 343 returns: 344 input: sfbActive 345 if pnsFlag calculate NoiseNrg 346 pointer to sfbEnergy and groupLen 347 pointer to noiseNrg (modified) 348 output: noiseNrg's in pnsFlaged sfb's 349 350 *****************************************************************************/ 351 352 static void FDKaacEnc_CalcNoiseNrgs(const INT sfbActive, INT *RESTRICT pnsFlag, 353 FIXP_DBL *RESTRICT sfbEnergyLdData, 354 INT *RESTRICT noiseNrg) { 355 int sfb; 356 INT tmp = (-LOG_NORM_PCM) << 2; 357 358 for (sfb = 0; sfb < sfbActive; sfb++) { 359 if (pnsFlag[sfb]) { 360 INT nrg = (-sfbEnergyLdData[sfb] + FL2FXCONST_DBL(0.5f / 64.0f)) >> 361 (DFRACT_BITS - 1 - 7); 362 noiseNrg[sfb] = tmp - nrg; 363 } 364 } 365 } 366 367 /***************************************************************************** 368 369 functionname:FDKaacEnc_CodePnsChannel 370 description: Execute pns decission 371 returns: 372 input: sfbActive 373 pns config structure 374 use PNS if pnsFlag 375 pointer to Sfb Energy, noiseNrg, Threshold 376 output: set sfbThreshold high to code pe with 0, 377 noiseNrg marks flag for pns coding 378 379 *****************************************************************************/ 380 381 void FDKaacEnc_CodePnsChannel(const INT sfbActive, PNS_CONFIG *pnsConf, 382 INT *RESTRICT pnsFlag, 383 FIXP_DBL *RESTRICT sfbEnergyLdData, 384 INT *RESTRICT noiseNrg, 385 FIXP_DBL *RESTRICT sfbThresholdLdData) { 386 INT sfb; 387 INT lastiNoiseEnergy = 0; 388 INT firstPNSband = 1; /* TRUE for first PNS-coded band */ 389 390 /* no PNS */ 391 if (!pnsConf->usePns) { 392 for (sfb = 0; sfb < sfbActive; sfb++) { 393 /* no PNS coding */ 394 noiseNrg[sfb] = NO_NOISE_PNS; 395 } 396 return; 397 } 398 399 /* code PNS */ 400 for (sfb = 0; sfb < sfbActive; sfb++) { 401 if (pnsFlag[sfb]) { 402 /* high sfbThreshold causes pe = 0 */ 403 if (noiseNrg[sfb] != NO_NOISE_PNS) 404 sfbThresholdLdData[sfb] = 405 sfbEnergyLdData[sfb] + FL2FXCONST_DBL(1.0f / LD_DATA_SCALING); 406 407 /* set noiseNrg in valid region */ 408 if (!firstPNSband) { 409 INT deltaiNoiseEnergy = noiseNrg[sfb] - lastiNoiseEnergy; 410 411 if (deltaiNoiseEnergy > CODE_BOOK_PNS_LAV) 412 noiseNrg[sfb] -= deltaiNoiseEnergy - CODE_BOOK_PNS_LAV; 413 else if (deltaiNoiseEnergy < -CODE_BOOK_PNS_LAV) 414 noiseNrg[sfb] -= deltaiNoiseEnergy + CODE_BOOK_PNS_LAV; 415 } else { 416 firstPNSband = 0; 417 } 418 lastiNoiseEnergy = noiseNrg[sfb]; 419 } else { 420 /* no PNS coding */ 421 noiseNrg[sfb] = NO_NOISE_PNS; 422 } 423 } 424 } 425 426 /***************************************************************************** 427 428 functionname:FDKaacEnc_PreProcessPnsChannelPair 429 description: Calculate the correlation of noise in a channel pair 430 431 returns: 432 input: sfbActive 433 pointer to sfb energies left, right and mid channel 434 pns config structure 435 pns data structure left and right (modified) 436 437 output: noiseEnergyCorrelation in pns data structure 438 439 *****************************************************************************/ 440 441 void FDKaacEnc_PreProcessPnsChannelPair( 442 const INT sfbActive, FIXP_DBL *RESTRICT sfbEnergyLeft, 443 FIXP_DBL *RESTRICT sfbEnergyRight, FIXP_DBL *RESTRICT sfbEnergyLeftLD, 444 FIXP_DBL *RESTRICT sfbEnergyRightLD, FIXP_DBL *RESTRICT sfbEnergyMid, 445 PNS_CONFIG *RESTRICT pnsConf, PNS_DATA *pnsDataLeft, 446 PNS_DATA *pnsDataRight) { 447 INT sfb; 448 FIXP_DBL ccf; 449 450 if (!pnsConf->usePns) return; 451 452 FIXP_DBL *RESTRICT pNoiseEnergyCorrelationL = 453 pnsDataLeft->noiseEnergyCorrelation; 454 FIXP_DBL *RESTRICT pNoiseEnergyCorrelationR = 455 pnsDataRight->noiseEnergyCorrelation; 456 457 for (sfb = 0; sfb < sfbActive; sfb++) { 458 FIXP_DBL quot = (sfbEnergyLeftLD[sfb] >> 1) + (sfbEnergyRightLD[sfb] >> 1); 459 460 if (quot < FL2FXCONST_DBL(-32.0f / (float)LD_DATA_SCALING)) 461 ccf = FL2FXCONST_DBL(0.0f); 462 else { 463 FIXP_DBL accu = 464 sfbEnergyMid[sfb] - 465 (((sfbEnergyLeft[sfb] >> 1) + (sfbEnergyRight[sfb] >> 1)) >> 1); 466 INT sign = (accu < FL2FXCONST_DBL(0.0f)) ? 1 : 0; 467 accu = fixp_abs(accu); 468 469 ccf = CalcLdData(accu) + 470 FL2FXCONST_DBL((float)1.0f / (float)LD_DATA_SCALING) - 471 quot; /* ld(accu*2) = ld(accu) + 1 */ 472 ccf = (ccf >= FL2FXCONST_DBL(0.0)) 473 ? ((FIXP_DBL)MAXVAL_DBL) 474 : (sign) ? -CalcInvLdData(ccf) : CalcInvLdData(ccf); 475 } 476 477 pNoiseEnergyCorrelationL[sfb] = ccf; 478 pNoiseEnergyCorrelationR[sfb] = ccf; 479 } 480 } 481 482 /***************************************************************************** 483 484 functionname:FDKaacEnc_PostProcessPnsChannelPair 485 description: if PNS used at left and right channel, 486 use msMask to flag correlation 487 returns: 488 input: sfbActive 489 pns config structure 490 pns data structure left and right (modified) 491 pointer to msMask, flags correlation by pns coding (modified) 492 Digest of MS coding 493 output: pnsFlag in pns data structure, 494 msFlag in msMask (flags correlation) 495 496 *****************************************************************************/ 497 498 void FDKaacEnc_PostProcessPnsChannelPair(const INT sfbActive, 499 PNS_CONFIG *pnsConf, 500 PNS_DATA *pnsDataLeft, 501 PNS_DATA *pnsDataRight, 502 INT *RESTRICT msMask, INT *msDigest) { 503 INT sfb; 504 505 if (!pnsConf->usePns) return; 506 507 for (sfb = 0; sfb < sfbActive; sfb++) { 508 /* 509 MS post processing 510 */ 511 if (msMask[sfb]) { 512 if ((pnsDataLeft->pnsFlag[sfb]) && (pnsDataRight->pnsFlag[sfb])) { 513 /* AAC only: Standard */ 514 /* do this to avoid ms flags in layers that should not have it */ 515 if (pnsDataLeft->noiseEnergyCorrelation[sfb] <= 516 pnsConf->noiseCorrelationThresh) { 517 msMask[sfb] = 0; 518 *msDigest = MS_SOME; 519 } 520 } else { 521 /* 522 No PNS coding 523 */ 524 pnsDataLeft->pnsFlag[sfb] = 0; 525 pnsDataRight->pnsFlag[sfb] = 0; 526 } 527 } 528 529 /* 530 Use MS flag to signal noise correlation if 531 pns is active in both channels 532 */ 533 if ((pnsDataLeft->pnsFlag[sfb]) && (pnsDataRight->pnsFlag[sfb])) { 534 if (pnsDataLeft->noiseEnergyCorrelation[sfb] > 535 pnsConf->noiseCorrelationThresh) { 536 msMask[sfb] = 1; 537 *msDigest = MS_SOME; 538 } 539 } 540 } 541 } 542