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 /************************* MPEG-D DRC decoder library ************************** 96 97 Author(s): 98 99 Description: 100 101 *******************************************************************************/ 102 103 #include "drcDec_types.h" 104 #include "drcDec_gainDecoder.h" 105 #include "drcGainDec_preprocess.h" 106 #include "drcDec_tools.h" 107 #include "FDK_matrixCalloc.h" 108 #include "drcDec_rom.h" 109 110 #define SLOPE_FACTOR_DB_TO_LINEAR \ 111 FL2FXCONST_DBL(0.1151f * (float)(1 << 3)) /* ln(10) / 20 */ 112 113 typedef struct { 114 int drcSetEffect; 115 DUCKING_MODIFICATION* pDMod; 116 GAIN_MODIFICATION* pGMod; 117 int drcCharacteristicPresent; 118 CHARACTERISTIC_FORMAT characteristicFormatSource[2]; 119 const CUSTOM_DRC_CHAR* pCCharSource[2]; 120 CHARACTERISTIC_FORMAT characteristicFormatTarget[2]; 121 const CUSTOM_DRC_CHAR* pCCharTarget[2]; 122 int slopeIsNegative; 123 int limiterPeakTargetPresent; 124 FIXP_SGL limiterPeakTarget; 125 FIXP_DBL loudnessNormalizationGainDb; 126 FIXP_SGL compress; 127 FIXP_SGL boost; 128 } NODE_MODIFICATION; 129 130 static DRC_ERROR _getCicpCharacteristic( 131 const int cicpCharacteristic, 132 CHARACTERISTIC_FORMAT pCharacteristicFormat[2], 133 const CUSTOM_DRC_CHAR* pCCharSource[2]) { 134 if ((cicpCharacteristic < 1) || (cicpCharacteristic > 11)) { 135 return DE_NOT_OK; 136 } 137 138 if (cicpCharacteristic < 7) { /* sigmoid characteristic */ 139 pCharacteristicFormat[CS_LEFT] = CF_SIGMOID; 140 pCCharSource[CS_LEFT] = 141 (const CUSTOM_DRC_CHAR*)(&cicpDrcCharSigmoidLeft[cicpCharacteristic - 142 1]); 143 pCharacteristicFormat[CS_RIGHT] = CF_SIGMOID; 144 pCCharSource[CS_RIGHT] = 145 (const CUSTOM_DRC_CHAR*)(&cicpDrcCharSigmoidRight[cicpCharacteristic - 146 1]); 147 } else { /* nodes characteristic */ 148 pCharacteristicFormat[CS_LEFT] = CF_NODES; 149 pCCharSource[CS_LEFT] = 150 (const CUSTOM_DRC_CHAR*)(&cicpDrcCharNodesLeft[cicpCharacteristic - 7]); 151 pCharacteristicFormat[CS_RIGHT] = CF_NODES; 152 pCCharSource[CS_RIGHT] = 153 (const CUSTOM_DRC_CHAR*)(&cicpDrcCharNodesRight[cicpCharacteristic - 154 7]); 155 } 156 return DE_OK; 157 } 158 159 static int _getSign(FIXP_SGL in) { 160 if (in > (FIXP_DBL)0) return 1; 161 if (in < (FIXP_DBL)0) return -1; 162 return 0; 163 } 164 165 static DRC_ERROR _getSlopeSign(const CHARACTERISTIC_FORMAT drcCharFormat, 166 const CUSTOM_DRC_CHAR* pCChar, int* pSlopeSign) { 167 if (drcCharFormat == CF_SIGMOID) { 168 *pSlopeSign = (pCChar->sigmoid.flipSign ? 1 : -1); 169 } else { 170 int k, slopeSign = 0, tmp_slopeSign; 171 for (k = 0; k < pCChar->nodes.characteristicNodeCount; k++) { 172 if (pCChar->nodes.nodeLevel[k + 1] > pCChar->nodes.nodeLevel[k]) { 173 tmp_slopeSign = 174 _getSign(pCChar->nodes.nodeGain[k + 1] - pCChar->nodes.nodeGain[k]); 175 } else { 176 tmp_slopeSign = -_getSign(pCChar->nodes.nodeGain[k + 1] - 177 pCChar->nodes.nodeGain[k]); 178 } 179 if ((slopeSign || tmp_slopeSign) && (slopeSign == -tmp_slopeSign)) 180 return DE_NOT_OK; /* DRC characteristic is not invertible */ 181 else 182 slopeSign = tmp_slopeSign; 183 } 184 *pSlopeSign = slopeSign; 185 } 186 return DE_OK; 187 } 188 189 static DRC_ERROR _isSlopeNegative(const CHARACTERISTIC_FORMAT drcCharFormat[2], 190 const CUSTOM_DRC_CHAR* pCChar[2], 191 int* pSlopeIsNegative) { 192 DRC_ERROR err = DE_OK; 193 int slopeSign[2] = {0, 0}; 194 195 err = _getSlopeSign(drcCharFormat[CS_LEFT], pCChar[CS_LEFT], 196 &slopeSign[CS_LEFT]); 197 if (err) return err; 198 199 err = _getSlopeSign(drcCharFormat[CS_RIGHT], pCChar[CS_RIGHT], 200 &slopeSign[CS_RIGHT]); 201 if (err) return err; 202 203 if ((slopeSign[CS_LEFT] || slopeSign[CS_RIGHT]) && 204 (slopeSign[CS_LEFT] == -slopeSign[CS_RIGHT])) 205 return DE_NOT_OK; /* DRC characteristic is not invertible */ 206 207 *pSlopeIsNegative = (slopeSign[CS_LEFT] < 0); 208 return DE_OK; 209 } 210 211 static DRC_ERROR _prepareDrcCharacteristic(const DRC_CHARACTERISTIC* pDChar, 212 DRC_COEFFICIENTS_UNI_DRC* pCoef, 213 const int b, 214 NODE_MODIFICATION* pNodeMod) { 215 DRC_ERROR err = DE_OK; 216 pNodeMod->drcCharacteristicPresent = pDChar->present; 217 if (pNodeMod->drcCharacteristicPresent) { 218 if (pDChar->isCICP == 1) { 219 err = _getCicpCharacteristic(pDChar->cicpIndex, 220 pNodeMod->characteristicFormatSource, 221 pNodeMod->pCCharSource); 222 if (err) return err; 223 } else { 224 pNodeMod->characteristicFormatSource[CS_LEFT] = 225 (CHARACTERISTIC_FORMAT) 226 pCoef->characteristicLeftFormat[pDChar->custom.left]; 227 pNodeMod->pCCharSource[CS_LEFT] = 228 &(pCoef->customCharacteristicLeft[pDChar->custom.left]); 229 pNodeMod->characteristicFormatSource[CS_RIGHT] = 230 (CHARACTERISTIC_FORMAT) 231 pCoef->characteristicRightFormat[pDChar->custom.right]; 232 pNodeMod->pCCharSource[CS_RIGHT] = 233 &(pCoef->customCharacteristicRight[pDChar->custom.right]); 234 } 235 err = _isSlopeNegative(pNodeMod->characteristicFormatSource, 236 pNodeMod->pCCharSource, &pNodeMod->slopeIsNegative); 237 if (err) return err; 238 239 if (pNodeMod->pGMod != NULL) { 240 if (pNodeMod->pGMod[b].targetCharacteristicLeftPresent) { 241 pNodeMod->characteristicFormatTarget[CS_LEFT] = 242 (CHARACTERISTIC_FORMAT)pCoef->characteristicLeftFormat 243 [pNodeMod->pGMod[b].targetCharacteristicLeftIndex]; 244 pNodeMod->pCCharTarget[CS_LEFT] = 245 &(pCoef->customCharacteristicLeft 246 [pNodeMod->pGMod[b].targetCharacteristicLeftIndex]); 247 } 248 if (pNodeMod->pGMod[b].targetCharacteristicRightPresent) { 249 pNodeMod->characteristicFormatTarget[CS_RIGHT] = 250 (CHARACTERISTIC_FORMAT)pCoef->characteristicRightFormat 251 [pNodeMod->pGMod[b].targetCharacteristicRightIndex]; 252 pNodeMod->pCCharTarget[CS_RIGHT] = 253 &(pCoef->customCharacteristicRight 254 [pNodeMod->pGMod[b].targetCharacteristicRightIndex]); 255 } 256 } 257 } 258 return DE_OK; 259 } 260 261 static DRC_ERROR _compressorIO_sigmoid_common( 262 const FIXP_DBL tmp, /* e = 7 */ 263 const FIXP_DBL gainDbLimit, /* e = 6 */ 264 const FIXP_DBL exp, /* e = 5 */ 265 const int inverse, FIXP_DBL* out) /* e = 7 */ 266 { 267 FIXP_DBL x, tmp1, tmp2, invExp, denom; 268 int e_x, e_tmp1, e_tmp2, e_invExp, e_denom, e_out; 269 270 if (exp < FL2FXCONST_DBL(1.0f / (float)(1 << 5))) { 271 return DE_NOT_OK; 272 } 273 274 /* x = tmp / gainDbLimit; */ 275 x = fDivNormSigned(tmp, gainDbLimit, &e_x); 276 e_x += 7 - 6; 277 if (x < (FIXP_DBL)0) { 278 return DE_NOT_OK; 279 } 280 281 /* out = tmp / pow(1.0f +/- pow(x, exp), 1.0f/exp); */ 282 tmp1 = fPow(x, e_x, exp, 5, &e_tmp1); 283 if (inverse) tmp1 = -tmp1; 284 tmp2 = fAddNorm(FL2FXCONST_DBL(1.0f / (float)(1 << 1)), 1, tmp1, e_tmp1, 285 &e_tmp2); 286 invExp = fDivNorm(FL2FXCONST_DBL(1.0f / (float)(1 << 1)), exp, &e_invExp); 287 e_invExp += 1 - 5; 288 denom = fPow(tmp2, e_tmp2, invExp, e_invExp, &e_denom); 289 *out = fDivNormSigned(tmp, denom, &e_out); 290 e_out += 7 - e_denom; 291 *out = scaleValueSaturate(*out, e_out - 7); 292 return DE_OK; 293 } 294 295 static DRC_ERROR _compressorIO_sigmoid(const CUSTOM_DRC_CHAR_SIGMOID* pCChar, 296 const FIXP_DBL inLevelDb, /* e = 7 */ 297 FIXP_DBL* outGainDb) /* e = 7 */ 298 { 299 FIXP_DBL tmp; 300 FIXP_SGL exp = pCChar->exp; 301 DRC_ERROR err = DE_OK; 302 303 tmp = fMultDiv2((DRC_INPUT_LOUDNESS_TARGET >> 1) - (inLevelDb >> 1), 304 pCChar->ioRatio); 305 tmp = SATURATE_LEFT_SHIFT(tmp, 2 + 1 + 1, DFRACT_BITS); 306 if (exp < (FIXP_SGL)MAXVAL_SGL) { 307 /* x = tmp / gainDbLimit; */ 308 /* *outGainDb = tmp / pow(1.0f + pow(x, exp), 1.0f/exp); */ 309 err = _compressorIO_sigmoid_common(tmp, FX_SGL2FX_DBL(pCChar->gain), 310 FX_SGL2FX_DBL(exp), 0, outGainDb); 311 if (err) return err; 312 } else { 313 *outGainDb = 314 tmp; /* scaling of outGainDb (7) is equal to scaling of tmp (7) */ 315 } 316 if (pCChar->flipSign == 1) { 317 *outGainDb = -*outGainDb; 318 } 319 return err; 320 } 321 322 static DRC_ERROR _compressorIO_sigmoid_inverse( 323 const CUSTOM_DRC_CHAR_SIGMOID* pCChar, const FIXP_SGL gainDb, 324 FIXP_DBL* inLev) { 325 DRC_ERROR err = DE_OK; 326 FIXP_SGL ioRatio = pCChar->ioRatio; 327 FIXP_SGL exp = pCChar->exp; 328 FIXP_DBL tmp = FX_SGL2FX_DBL(gainDb), tmp_out; 329 int e_out; 330 331 if (pCChar->flipSign == 1) { 332 tmp = -tmp; 333 } 334 if (exp < (FIXP_SGL)MAXVAL_SGL) { 335 /* x = tmp / gainDbLimit; */ 336 /* tmp = tmp / pow(1.0f - pow(x, exp), 1.0f / exp); */ 337 err = _compressorIO_sigmoid_common(tmp, FX_SGL2FX_DBL(pCChar->gain), 338 FX_SGL2FX_DBL(exp), 1, &tmp); 339 if (err) return err; 340 } 341 if (ioRatio == (FIXP_SGL)0) { 342 return DE_NOT_OK; 343 } 344 tmp_out = fDivNormSigned(tmp, FX_SGL2FX_DBL(ioRatio), &e_out); 345 e_out += 7 - 2; 346 tmp_out = fAddNorm(DRC_INPUT_LOUDNESS_TARGET, 7, -tmp_out, e_out, &e_out); 347 *inLev = scaleValueSaturate(tmp_out, e_out - 7); 348 349 return err; 350 } 351 352 static DRC_ERROR _compressorIO_nodes(const CUSTOM_DRC_CHAR_NODES* pCChar, 353 const FIXP_DBL inLevelDb, /* e = 7 */ 354 FIXP_DBL* outGainDb) /* e = 7 */ 355 { 356 int n; 357 FIXP_DBL w; 358 const FIXP_SGL* nodeLevel = pCChar->nodeLevel; 359 const FIXP_SGL* nodeGain = pCChar->nodeGain; 360 361 if (inLevelDb < DRC_INPUT_LOUDNESS_TARGET) { 362 for (n = 0; n < pCChar->characteristicNodeCount; n++) { 363 if ((inLevelDb <= FX_SGL2FX_DBL(nodeLevel[n])) && 364 (inLevelDb > FX_SGL2FX_DBL(nodeLevel[n + 1]))) { 365 w = fDivNorm(inLevelDb - FX_SGL2FX_DBL(nodeLevel[n + 1]), 366 FX_SGL2FX_DBL(nodeLevel[n] - nodeLevel[n + 1])); 367 *outGainDb = fMult(w, nodeGain[n]) + 368 fMult((FIXP_DBL)MAXVAL_DBL - w, nodeGain[n + 1]); 369 /* *outGainDb = (w * nodeGain[n] + (1.0-w) * nodeGain[n+1]); */ 370 return DE_OK; 371 } 372 } 373 } else { 374 for (n = 0; n < pCChar->characteristicNodeCount; n++) { 375 if ((inLevelDb >= FX_SGL2FX_DBL(nodeLevel[n])) && 376 (inLevelDb < FX_SGL2FX_DBL(nodeLevel[n + 1]))) { 377 w = fDivNorm(FX_SGL2FX_DBL(nodeLevel[n + 1]) - inLevelDb, 378 FX_SGL2FX_DBL(nodeLevel[n + 1] - nodeLevel[n])); 379 *outGainDb = fMult(w, nodeGain[n]) + 380 fMult((FIXP_DBL)MAXVAL_DBL - w, nodeGain[n + 1]); 381 /* *outGainDb = (w * nodeGain[n] + (1.0-w) * nodeGain[n+1]); */ 382 return DE_OK; 383 } 384 } 385 } 386 *outGainDb = FX_SGL2FX_DBL(nodeGain[pCChar->characteristicNodeCount]); 387 return DE_OK; 388 } 389 390 static DRC_ERROR _compressorIO_nodes_inverse( 391 const CUSTOM_DRC_CHAR_NODES* pCChar, const FIXP_SGL gainDb, /* e = 7 */ 392 FIXP_DBL* inLev) /* e = 7 */ 393 { 394 int n; 395 int k; 396 FIXP_DBL w; 397 int gainIsNegative = 0; 398 const FIXP_SGL* nodeLevel = pCChar->nodeLevel; 399 const FIXP_SGL* nodeGain = pCChar->nodeGain; 400 int nodeCount = pCChar->characteristicNodeCount; 401 for (k = 0; k < nodeCount; k++) { 402 if (pCChar->nodeGain[k + 1] < (FIXP_SGL)0) { 403 gainIsNegative = 1; 404 } 405 } 406 if (gainIsNegative == 1) { 407 if (gainDb <= nodeGain[nodeCount]) { 408 *inLev = FX_SGL2FX_DBL(nodeLevel[nodeCount]); 409 } else { 410 if (gainDb >= (FIXP_SGL)0) { 411 *inLev = DRC_INPUT_LOUDNESS_TARGET; 412 } else { 413 for (n = 0; n < nodeCount; n++) { 414 if ((gainDb <= nodeGain[n]) && (gainDb > nodeGain[n + 1])) { 415 FIXP_SGL gainDelta = nodeGain[n] - nodeGain[n + 1]; 416 if (gainDelta == (FIXP_SGL)0) { 417 *inLev = FX_SGL2FX_DBL(nodeLevel[n]); 418 return DE_OK; 419 } 420 w = fDivNorm(gainDb - nodeGain[n + 1], gainDelta); 421 *inLev = fMult(w, nodeLevel[n]) + 422 fMult((FIXP_DBL)MAXVAL_DBL - w, nodeLevel[n + 1]); 423 /* *inLev = (w * nodeLevel[n] + (1.0-w) * nodeLevel[n+1]); */ 424 return DE_OK; 425 } 426 } 427 *inLev = FX_SGL2FX_DBL(nodeLevel[nodeCount]); 428 } 429 } 430 } else { 431 if (gainDb >= nodeGain[nodeCount]) { 432 *inLev = FX_SGL2FX_DBL(nodeLevel[nodeCount]); 433 } else { 434 if (gainDb <= (FIXP_SGL)0) { 435 *inLev = DRC_INPUT_LOUDNESS_TARGET; 436 } else { 437 for (n = 0; n < nodeCount; n++) { 438 if ((gainDb >= nodeGain[n]) && (gainDb < nodeGain[n + 1])) { 439 FIXP_SGL gainDelta = nodeGain[n + 1] - nodeGain[n]; 440 if (gainDelta == (FIXP_SGL)0) { 441 *inLev = FX_SGL2FX_DBL(nodeLevel[n]); 442 return DE_OK; 443 } 444 w = fDivNorm(nodeGain[n + 1] - gainDb, gainDelta); 445 *inLev = fMult(w, nodeLevel[n]) + 446 fMult((FIXP_DBL)MAXVAL_DBL - w, nodeLevel[n + 1]); 447 /* *inLev = (w * nodeLevel[n] + (1.0-w) * nodeLevel[n+1]); */ 448 return DE_OK; 449 } 450 } 451 *inLev = FX_SGL2FX_DBL(nodeLevel[nodeCount]); 452 } 453 } 454 } 455 return DE_OK; 456 } 457 458 static DRC_ERROR _mapGain(const CHARACTERISTIC_FORMAT pCCharFormatSource, 459 const CUSTOM_DRC_CHAR* pCCharSource, 460 const CHARACTERISTIC_FORMAT pCCharFormatTarget, 461 const CUSTOM_DRC_CHAR* pCCharTarget, 462 const FIXP_SGL gainInDb, /* e = 7 */ 463 FIXP_DBL* gainOutDb) /* e = 7 */ 464 { 465 FIXP_DBL inLevel = (FIXP_DBL)0; 466 DRC_ERROR err = DE_OK; 467 468 switch (pCCharFormatSource) { 469 case CF_SIGMOID: 470 err = _compressorIO_sigmoid_inverse( 471 (const CUSTOM_DRC_CHAR_SIGMOID*)pCCharSource, gainInDb, &inLevel); 472 if (err) return err; 473 break; 474 case CF_NODES: 475 err = _compressorIO_nodes_inverse( 476 (const CUSTOM_DRC_CHAR_NODES*)pCCharSource, gainInDb, &inLevel); 477 if (err) return err; 478 break; 479 default: 480 return DE_NOT_OK; 481 } 482 switch (pCCharFormatTarget) { 483 case CF_SIGMOID: 484 err = _compressorIO_sigmoid((const CUSTOM_DRC_CHAR_SIGMOID*)pCCharTarget, 485 inLevel, gainOutDb); 486 if (err) return err; 487 break; 488 case CF_NODES: 489 err = _compressorIO_nodes((const CUSTOM_DRC_CHAR_NODES*)pCCharTarget, 490 inLevel, gainOutDb); 491 if (err) return err; 492 break; 493 default: 494 break; 495 } 496 return DE_OK; 497 } 498 499 static DRC_ERROR _toLinear( 500 const NODE_MODIFICATION* nodeMod, const int drcBand, 501 const FIXP_SGL gainDb, /* in: gain value in dB, e = 7 */ 502 const FIXP_SGL slopeDb, /* in: slope value in dB/deltaTmin, e = 2 */ 503 FIXP_DBL* gainLin, /* out: linear gain value, e = 7 */ 504 FIXP_DBL* slopeLin) /* out: linear slope value, e = 7 */ 505 { 506 FIXP_DBL gainRatio_m = FL2FXCONST_DBL(1.0f / (float)(1 << 1)); 507 GAIN_MODIFICATION* pGMod = NULL; 508 DUCKING_MODIFICATION* pDMod = nodeMod->pDMod; 509 FIXP_DBL tmp_dbl, gainDb_modified, gainDb_offset, gainDb_out, gainLin_m, 510 slopeLin_m; 511 int gainLin_e, gainRatio_e = 1, gainDb_out_e; 512 if (nodeMod->pGMod != NULL) { 513 pGMod = &(nodeMod->pGMod[drcBand]); 514 } 515 if (((nodeMod->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) == 0) && 516 (nodeMod->drcSetEffect != EB_FADE) && 517 (nodeMod->drcSetEffect != EB_CLIPPING)) { 518 DRC_ERROR err = DE_OK; 519 FIXP_DBL gainDbMapped; 520 521 if ((pGMod != NULL) && (nodeMod->drcCharacteristicPresent)) { 522 if (((gainDb > (FIXP_SGL)0) && nodeMod->slopeIsNegative) || 523 ((gainDb < (FIXP_SGL)0) && !nodeMod->slopeIsNegative)) { 524 /* left side */ 525 if (pGMod->targetCharacteristicLeftPresent == 1) { 526 err = _mapGain(nodeMod->characteristicFormatSource[CS_LEFT], 527 nodeMod->pCCharSource[CS_LEFT], 528 nodeMod->characteristicFormatTarget[CS_LEFT], 529 nodeMod->pCCharTarget[CS_LEFT], gainDb, &gainDbMapped); 530 if (err) return err; 531 gainRatio_m = fDivNormSigned( 532 gainDbMapped, FX_SGL2FX_DBL(gainDb), 533 &gainRatio_e); /* target characteristic in payload */ 534 } 535 } 536 537 else { /* if (((gainDb < (FIXP_SGL)0) && nodeMod->slopeIsNegative) || 538 ((gainDb > (FIXP_SGL)0) && !nodeMod->slopeIsNegative)) */ 539 540 /* right side */ 541 if (pGMod->targetCharacteristicRightPresent == 1) { 542 err = 543 _mapGain(nodeMod->characteristicFormatSource[CS_RIGHT], 544 nodeMod->pCCharSource[CS_RIGHT], 545 nodeMod->characteristicFormatTarget[CS_RIGHT], 546 nodeMod->pCCharTarget[CS_RIGHT], gainDb, &gainDbMapped); 547 if (err) return err; 548 gainRatio_m = fDivNormSigned( 549 gainDbMapped, FX_SGL2FX_DBL(gainDb), 550 &gainRatio_e); /* target characteristic in payload */ 551 } 552 } 553 } 554 if (gainDb < (FIXP_SGL)0) { 555 gainRatio_m = fMultDiv2(gainRatio_m, nodeMod->compress); 556 } else { 557 gainRatio_m = fMultDiv2(gainRatio_m, nodeMod->boost); 558 } 559 gainRatio_e += 2; 560 } 561 if ((pGMod != NULL) && (pGMod->gainScalingPresent == 1)) { 562 if (gainDb < (FIXP_SGL)0) { 563 gainRatio_m = fMultDiv2(gainRatio_m, pGMod->attenuationScaling); 564 } else { 565 gainRatio_m = fMultDiv2(gainRatio_m, pGMod->amplificationScaling); 566 } 567 gainRatio_e += 3; 568 } 569 if ((pDMod != NULL) && 570 (nodeMod->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) && 571 (pDMod->duckingScalingPresent == 1)) { 572 gainRatio_m = fMultDiv2(gainRatio_m, pDMod->duckingScaling); 573 gainRatio_e += 3; 574 } 575 576 gainDb_modified = 577 fMultDiv2(gainDb, gainRatio_m); /* resulting e: 7 + gainRatio_e + 1*/ 578 gainDb_offset = (FIXP_DBL)0; 579 580 if ((pGMod != NULL) && (pGMod->gainOffsetPresent == 1)) { 581 /* *gainLin *= (float)pow(2.0, (double)(pGMod->gainOffset/6.0f)); */ 582 gainDb_offset += FX_SGL2FX_DBL(pGMod->gainOffset) >> 4; /* resulting e: 8 */ 583 } 584 if ((nodeMod->limiterPeakTargetPresent == 1) && 585 (nodeMod->drcSetEffect == 586 EB_CLIPPING)) { /* The only drcSetEffect is "clipping prevention" */ 587 /* loudnessNormalizationGainModificationDb is included in 588 * loudnessNormalizationGainDb */ 589 /* *gainLin *= (float)pow(2.0, max(0.0, -nodeModification->limiterPeakTarget 590 * - nodeModification->loudnessNormalizationGainDb)/6.0); */ 591 gainDb_offset += fMax( 592 (FIXP_DBL)0, 593 (FX_SGL2FX_DBL(-nodeMod->limiterPeakTarget) >> 3) - 594 (nodeMod->loudnessNormalizationGainDb >> 1)); /* resulting e: 8 */ 595 } 596 if (gainDb_offset != (FIXP_DBL)0) { 597 gainDb_out = fAddNorm(gainDb_modified, 7 + gainRatio_e + 1, gainDb_offset, 598 8, &gainDb_out_e); 599 } else { 600 gainDb_out = gainDb_modified; 601 gainDb_out_e = 7 + gainRatio_e + 1; 602 } 603 604 /* *gainLin = (float)pow(2.0, (double)(gainDb_modified[1] / 6.0f)); */ 605 gainLin_m = approxDb2lin(gainDb_out, gainDb_out_e, &gainLin_e); 606 *gainLin = scaleValueSaturate(gainLin_m, gainLin_e - 7); 607 608 /* *slopeLin = SLOPE_FACTOR_DB_TO_LINEAR * gainRatio * *gainLin * slopeDb; */ 609 if (slopeDb == (FIXP_SGL)0) { 610 *slopeLin = (FIXP_DBL)0; 611 } else { 612 tmp_dbl = 613 fMult(slopeDb, SLOPE_FACTOR_DB_TO_LINEAR); /* resulting e: 2 - 3 = -1 */ 614 tmp_dbl = fMult(tmp_dbl, gainRatio_m); /* resulting e: -1 + gainRatio_e */ 615 if (gainDb_offset != 616 (FIXP_DBL)0) { /* recalculate gainLin from gainDb that wasn't modified 617 by gainOffset and limiterPeakTarget */ 618 gainLin_m = approxDb2lin(gainDb_modified, 7 + gainRatio_e, &gainLin_e); 619 } 620 slopeLin_m = fMult(tmp_dbl, gainLin_m); 621 *slopeLin = 622 scaleValueSaturate(slopeLin_m, -1 + gainRatio_e + gainLin_e - 7); 623 } 624 625 if ((nodeMod->limiterPeakTargetPresent == 1) && 626 (nodeMod->drcSetEffect == EB_CLIPPING)) { 627 if (*gainLin >= FL2FXCONST_DBL(1.0f / (float)(1 << 7))) { 628 *gainLin = FL2FXCONST_DBL(1.0f / (float)(1 << 7)); 629 *slopeLin = (FIXP_DBL)0; 630 } 631 } 632 633 return DE_OK; 634 } 635 636 /* prepare buffers containing linear nodes for each gain sequence */ 637 DRC_ERROR 638 prepareDrcGain(HANDLE_DRC_GAIN_DECODER hGainDec, 639 HANDLE_UNI_DRC_GAIN hUniDrcGain, const FIXP_SGL compress, 640 const FIXP_SGL boost, const FIXP_DBL loudnessNormalizationGainDb, 641 const int activeDrcIndex) { 642 int b, g, gainElementIndex; 643 DRC_GAIN_BUFFERS* drcGainBuffers = &(hGainDec->drcGainBuffers); 644 NODE_MODIFICATION nodeMod; 645 FDKmemclear(&nodeMod, sizeof(NODE_MODIFICATION)); 646 ACTIVE_DRC* pActiveDrc = &(hGainDec->activeDrc[activeDrcIndex]); 647 DRC_INSTRUCTIONS_UNI_DRC* pInst = pActiveDrc->pInst; 648 if (pInst == NULL) return DE_NOT_OK; 649 650 nodeMod.drcSetEffect = pInst->drcSetEffect; 651 652 nodeMod.compress = compress; 653 nodeMod.boost = boost; 654 nodeMod.loudnessNormalizationGainDb = loudnessNormalizationGainDb; 655 nodeMod.limiterPeakTargetPresent = pInst->limiterPeakTargetPresent; 656 nodeMod.limiterPeakTarget = pInst->limiterPeakTarget; 657 658 gainElementIndex = 0; 659 for (g = 0; g < pInst->nDrcChannelGroups; g++) { 660 int gainSetIndex = 0; 661 int nDrcBands = 0; 662 DRC_COEFFICIENTS_UNI_DRC* pCoef = pActiveDrc->pCoef; 663 if (pCoef == NULL) return DE_NOT_OK; 664 665 if (!pActiveDrc->channelGroupIsParametricDrc[g]) { 666 gainSetIndex = pInst->gainSetIndexForChannelGroup[g]; 667 668 if (nodeMod.drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { 669 nodeMod.pDMod = &(pActiveDrc->duckingModificationForChannelGroup[g]); 670 nodeMod.pGMod = NULL; 671 } else { 672 nodeMod.pGMod = pInst->gainModificationForChannelGroup[g]; 673 nodeMod.pDMod = NULL; 674 } 675 676 nDrcBands = pActiveDrc->bandCountForChannelGroup[g]; 677 for (b = 0; b < nDrcBands; b++) { 678 DRC_ERROR err = DE_OK; 679 GAIN_SET* pGainSet = &(pCoef->gainSet[gainSetIndex]); 680 int seq = pGainSet->gainSequenceIndex[b]; 681 DRC_CHARACTERISTIC* pDChar = &(pGainSet->drcCharacteristic[b]); 682 683 /* linearNodeBuffer contains a copy of the gain sequences (consisting of 684 nodes) that are relevant for decoding. It also contains gain 685 sequences of previous frames. */ 686 LINEAR_NODE_BUFFER* pLnb = 687 &(drcGainBuffers->linearNodeBuffer[pActiveDrc->activeDrcOffset + 688 gainElementIndex]); 689 int i, lnbp; 690 lnbp = drcGainBuffers->lnbPointer; 691 pLnb->gainInterpolationType = 692 (GAIN_INTERPOLATION_TYPE)pGainSet->gainInterpolationType; 693 694 err = _prepareDrcCharacteristic(pDChar, pCoef, b, &nodeMod); 695 if (err) return err; 696 697 /* copy a node buffer and convert from dB to linear */ 698 pLnb->nNodes[lnbp] = fMin((int)hUniDrcGain->nNodes[seq], 16); 699 for (i = 0; i < pLnb->nNodes[lnbp]; i++) { 700 FIXP_DBL gainLin, slopeLin; 701 err = _toLinear(&nodeMod, b, hUniDrcGain->gainNode[seq][i].gainDb, 702 (FIXP_SGL)0, &gainLin, &slopeLin); 703 if (err) return err; 704 pLnb->linearNode[lnbp][i].gainLin = gainLin; 705 pLnb->linearNode[lnbp][i].time = hUniDrcGain->gainNode[seq][i].time; 706 } 707 gainElementIndex++; 708 } 709 } else { 710 /* parametric DRC not supported */ 711 gainElementIndex++; 712 } 713 } 714 return DE_OK; 715 } 716