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): Andreas Hoelzer 98 99 Description: DRC Set Selection 100 101 *******************************************************************************/ 102 103 #include "drcDec_selectionProcess.h" 104 #include "drcDec_tools.h" 105 106 #define UNDEFINED_LOUDNESS_VALUE (FIXP_DBL) MAXVAL_DBL 107 108 typedef enum { 109 DETR_NONE = 0, 110 DETR_NIGHT = 1, 111 DETR_NOISY = 2, 112 DETR_LIMITED = 3, 113 DETR_LOWLEVEL = 4, 114 DETR_DIALOG = 5, 115 DETR_GENERAL_COMPR = 6, 116 DETR_EXPAND = 7, 117 DETR_ARTISTIC = 8, 118 DETR_COUNT 119 } DRC_EFFECT_TYPE_REQUEST; 120 121 typedef enum { 122 DFRT_EFFECT_TYPE, 123 DFRT_DYNAMIC_RANGE, 124 DFRT_DRC_CHARACTERISTIC 125 } DRC_FEATURE_REQUEST_TYPE; 126 127 typedef enum { 128 MDR_DEFAULT = 0, 129 MDR_PROGRAM_LOUDNESS = 1, 130 MDR_ANCHOR_LOUDNESS = 2 131 } METHOD_DEFINITION_REQUEST; 132 133 typedef enum { 134 MSR_DEFAULT = 0, 135 MSR_BS_1770_4 = 1, 136 MSR_USER = 2, 137 MSR_EXPERT_PANEL = 3, 138 MSR_RESERVED_A = 4, 139 MSR_RESERVED_B = 5, 140 MSR_RESERVED_C = 6, 141 MSR_RESERVED_D = 7, 142 MSR_RESERVED_E = 8 143 } MEASUREMENT_SYSTEM_REQUEST; 144 145 typedef enum { 146 LPR_DEFAULT = 0, 147 LPR_OFF = 1, 148 LPR_HIGHPASS = 2 149 } LOUDNESS_PREPROCESSING_REQUEST; 150 151 typedef enum { 152 DRMRT_SHORT_TERM_LOUDNESS_TO_AVG = 0, 153 DRMRT_MOMENTARY_LOUDNESS_TO_AVG = 1, 154 DRMRT_TOP_OF_LOUDNESS_RANGE_TO_AVG = 2 155 } DYN_RANGE_MEASUREMENT_REQUEST_TYPE; 156 157 typedef enum { 158 TCRT_DOWNMIX_ID = 0, 159 TCRT_TARGET_LAYOUT = 1, 160 TCRT_TARGET_CHANNEL_COUNT = 2 161 } TARGET_CONFIG_REQUEST_TYPE; 162 163 typedef shouldBeUnion { 164 struct { 165 UCHAR numRequests; 166 UCHAR numRequestsDesired; 167 DRC_EFFECT_TYPE_REQUEST request[MAX_REQUESTS_DRC_EFFECT_TYPE]; 168 } drcEffectType; 169 struct { 170 DYN_RANGE_MEASUREMENT_REQUEST_TYPE measurementRequestType; 171 UCHAR requestedIsRange; 172 FIXP_DBL requestValue; /* e = 7 */ 173 FIXP_DBL requestValueMin; /* e = 7 */ 174 FIXP_DBL requestValueMax; /* e = 7 */ 175 } dynamicRange; 176 UCHAR drcCharacteristic; 177 } 178 DRC_FEATURE_REQUEST; 179 180 typedef struct { 181 /* system parameters */ 182 SCHAR baseChannelCount; 183 SCHAR baseLayout; /* not supported */ 184 TARGET_CONFIG_REQUEST_TYPE targetConfigRequestType; 185 UCHAR numDownmixIdRequests; 186 UCHAR downmixIdRequested[MAX_REQUESTS_DOWNMIX_ID]; 187 UCHAR targetLayoutRequested; 188 UCHAR targetChannelCountRequested; 189 LONG audioSampleRate; /* needed for complexity estimation, currently not 190 supported */ 191 192 /* loudness normalization parameters */ 193 UCHAR loudnessNormalizationOn; 194 FIXP_DBL targetLoudness; /* e = 7 */ 195 UCHAR albumMode; 196 UCHAR peakLimiterPresent; 197 UCHAR loudnessDeviationMax; /* resolution: 1 dB */ 198 METHOD_DEFINITION_REQUEST loudnessMeasurementMethod; 199 MEASUREMENT_SYSTEM_REQUEST loudnessMeasurementSystem; 200 LOUDNESS_PREPROCESSING_REQUEST loudnessMeasurementPreProc; /* not supported */ 201 LONG deviceCutOffFrequency; /* not supported */ 202 FIXP_DBL loudnessNormalizationGainDbMax; /* e = 7 */ 203 FIXP_DBL loudnessNormalizationGainModificationDb; /* e = 7 */ 204 FIXP_DBL outputPeakLevelMax; /* e = 7 */ 205 206 /* dynamic range control parameters */ 207 UCHAR dynamicRangeControlOn; 208 UCHAR numDrcFeatureRequests; 209 DRC_FEATURE_REQUEST_TYPE drcFeatureRequestType[MAX_REQUESTS_DRC_FEATURE]; 210 DRC_FEATURE_REQUEST drcFeatureRequest[MAX_REQUESTS_DRC_FEATURE]; 211 212 /* other */ 213 FIXP_SGL boost; /* e = 1 */ 214 FIXP_SGL compress; /* e = 1 */ 215 UCHAR drcCharacteristicTarget; /* not supported */ 216 } SEL_PROC_INPUT, *HANDLE_SEL_PROC_INPUT; 217 218 /* Table E.1 of ISO/IEC DIS 23003-4: Recommended order of fallback effect type 219 * requests */ 220 static DRC_EFFECT_TYPE_REQUEST fallbackEffectTypeRequests[6][5] = { 221 /* Night */ {DETR_GENERAL_COMPR, DETR_NOISY, DETR_LIMITED, DETR_LOWLEVEL, 222 DETR_DIALOG}, 223 /* Noisy */ 224 {DETR_GENERAL_COMPR, DETR_NIGHT, DETR_LIMITED, DETR_LOWLEVEL, DETR_DIALOG}, 225 /* Limited */ 226 {DETR_GENERAL_COMPR, DETR_NIGHT, DETR_NOISY, DETR_LOWLEVEL, DETR_DIALOG}, 227 /* LowLevel */ 228 {DETR_GENERAL_COMPR, DETR_NOISY, DETR_NIGHT, DETR_LIMITED, DETR_DIALOG}, 229 /* Dialog */ 230 {DETR_GENERAL_COMPR, DETR_NIGHT, DETR_NOISY, DETR_LIMITED, DETR_LOWLEVEL}, 231 /* General */ 232 {DETR_NIGHT, DETR_NOISY, DETR_LIMITED, DETR_LOWLEVEL, DETR_DIALOG}}; 233 234 /*******************************************/ 235 typedef struct { 236 UCHAR selectionFlag; 237 UCHAR downmixIdRequestIndex; 238 FIXP_DBL outputPeakLevel; /* e = 7 */ 239 FIXP_DBL loudnessNormalizationGainDbAdjusted; /* e = 7 */ 240 FIXP_DBL outputLoudness; /* e = 7 */ 241 DRC_INSTRUCTIONS_UNI_DRC* pInst; 242 243 } DRCDEC_SELECTION_DATA; 244 245 typedef struct { 246 UCHAR numData; 247 DRCDEC_SELECTION_DATA data[(12 + 1 + 6)]; 248 249 } DRCDEC_SELECTION; 250 251 /*******************************************/ 252 /* helper functions */ 253 /*******************************************/ 254 255 static int _isError(int x) { 256 if (x < DRCDEC_SELECTION_PROCESS_WARNING) { 257 return 1; 258 } 259 260 return 0; 261 } 262 263 /* compare and assign */ 264 static inline int _compAssign(UCHAR* dest, const UCHAR src) { 265 int diff = 0; 266 if (*dest != src) diff = 1; 267 *dest = src; 268 return diff; 269 } 270 271 static inline int _compAssign(SCHAR* dest, const SCHAR src) { 272 int diff = 0; 273 if (*dest != src) diff = 1; 274 *dest = src; 275 return diff; 276 } 277 278 static inline int _compAssign(FIXP_DBL* dest, const FIXP_DBL src) { 279 int diff = 0; 280 if (*dest != src) diff = 1; 281 *dest = src; 282 return diff; 283 } 284 285 static inline int _compAssign(FIXP_SGL* dest, const FIXP_SGL src) { 286 int diff = 0; 287 if (*dest != src) diff = 1; 288 *dest = src; 289 return diff; 290 } 291 292 static inline int _compAssign(TARGET_CONFIG_REQUEST_TYPE* dest, const int src) { 293 int diff = 0; 294 if (*dest != src) diff = 1; 295 *dest = (TARGET_CONFIG_REQUEST_TYPE)src; 296 return diff; 297 } 298 299 static inline int _compAssign(METHOD_DEFINITION_REQUEST* dest, const int src) { 300 int diff = 0; 301 if (*dest != src) diff = 1; 302 *dest = (METHOD_DEFINITION_REQUEST)src; 303 return diff; 304 } 305 306 static inline int _compAssign(DRC_FEATURE_REQUEST_TYPE* dest, const int src) { 307 int diff = 0; 308 if (*dest != src) diff = 1; 309 *dest = (DRC_FEATURE_REQUEST_TYPE)src; 310 return diff; 311 } 312 313 static inline int _compAssign(DRC_EFFECT_TYPE_REQUEST* dest, const int src) { 314 int diff = 0; 315 if (*dest != src) diff = 1; 316 *dest = (DRC_EFFECT_TYPE_REQUEST)src; 317 return diff; 318 } 319 320 static DRCDEC_SELECTION_DATA* _drcdec_selection_addNew( 321 DRCDEC_SELECTION* pSelection); 322 323 static DRCDEC_SELECTION_DATA* _drcdec_selection_add( 324 DRCDEC_SELECTION* pSelection, DRCDEC_SELECTION_DATA* pDataIn); 325 326 static int _drcdec_selection_clear(DRCDEC_SELECTION* pSelection); 327 328 static int _drcdec_selection_getNumber(DRCDEC_SELECTION* pSelection); 329 330 static int _drcdec_selection_setNumber(DRCDEC_SELECTION* pSelection, int num); 331 332 static DRCDEC_SELECTION_DATA* _drcdec_selection_getAt( 333 DRCDEC_SELECTION* pSelection, int at); 334 335 static int _swapSelectionAndClear(DRCDEC_SELECTION** ppCandidatesPotential, 336 DRCDEC_SELECTION** ppCandidatesSelected); 337 338 static int _swapSelection(DRCDEC_SELECTION** ppCandidatesPotential, 339 DRCDEC_SELECTION** ppCandidatesSelected); 340 341 /*******************************************/ 342 /* declarations of static functions */ 343 /*******************************************/ 344 345 static DRCDEC_SELECTION_PROCESS_RETURN _initDefaultParams( 346 HANDLE_SEL_PROC_INPUT hSelProcInput); 347 348 static DRCDEC_SELECTION_PROCESS_RETURN _initCodecModeParams( 349 HANDLE_SEL_PROC_INPUT hSelProcInput, const SEL_PROC_CODEC_MODE codecMode); 350 351 static DRCDEC_SELECTION_PROCESS_RETURN _drcSetPreSelection( 352 SEL_PROC_INPUT* hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 353 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, 354 DRCDEC_SELECTION** ppCandidatesPotential, 355 DRCDEC_SELECTION** ppCandidatesSelected, SEL_PROC_CODEC_MODE codecMode); 356 357 static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_peakValue0( 358 DRCDEC_SELECTION* pCandidatesPotential, 359 DRCDEC_SELECTION* pCandidatesSelected); 360 361 static DRCDEC_SELECTION_PROCESS_RETURN _dynamicRangeMeasurement( 362 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, DRC_INSTRUCTIONS_UNI_DRC* pInst, 363 UCHAR downmixIdRequested, 364 DYN_RANGE_MEASUREMENT_REQUEST_TYPE dynamicRangeMeasurementType, 365 int albumMode, int* peakToAveragePresent, FIXP_DBL* peakToAverage); 366 367 static DRCDEC_SELECTION_PROCESS_RETURN _channelLayoutToDownmixIdMapping( 368 HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig); 369 370 static DRCDEC_SELECTION_PROCESS_RETURN _generateVirtualDrcSets( 371 HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 372 SEL_PROC_CODEC_MODE codecMode); 373 374 static DRCDEC_SELECTION_PROCESS_RETURN _drcSetRequestSelection( 375 SEL_PROC_INPUT* hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 376 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, 377 DRCDEC_SELECTION** ppCandidatesPotential, 378 DRCDEC_SELECTION** ppCandidatesSelected); 379 380 static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection( 381 HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 382 DRCDEC_SELECTION** ppCandidatesPotential, 383 DRCDEC_SELECTION** ppCandidatesSelected, SEL_PROC_CODEC_MODE codecMode); 384 385 static DRCDEC_SELECTION_PROCESS_RETURN _generateOutputInfo( 386 HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_SEL_PROC_OUTPUT hSelProcOutput, 387 HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 388 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, 389 DRCDEC_SELECTION_DATA* pSelectionData, SEL_PROC_CODEC_MODE codecMode); 390 391 static DRCDEC_SELECTION_PROCESS_RETURN _selectDownmixMatrix( 392 HANDLE_SEL_PROC_OUTPUT hSelProcOutput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig); 393 394 static DRCDEC_SELECTION_PROCESS_RETURN _getLoudness( 395 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int albumMode, 396 METHOD_DEFINITION_REQUEST measurementMethodRequested, 397 MEASUREMENT_SYSTEM_REQUEST measurementSystemRequested, 398 FIXP_DBL targetLoudness, int drcSetId, int downmixIdRequested, 399 FIXP_DBL* pLoudnessNormalizationGain, FIXP_DBL* pLoudness); 400 401 static DRCDEC_SELECTION_PROCESS_RETURN _getMixingLevel( 402 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int downmixIdRequested, 403 int drcSetIdRequested, int albumMode, FIXP_DBL* pMixingLevel); 404 405 static DRCDEC_SELECTION_PROCESS_RETURN _getSignalPeakLevel( 406 HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 407 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, DRC_INSTRUCTIONS_UNI_DRC* pInst, 408 int downmixIdRequested, int* explicitPeakInformationPresent, 409 FIXP_DBL* signalPeakLevelOut, /* e = 7 */ 410 SEL_PROC_CODEC_MODE codecMode); 411 412 static DRCDEC_SELECTION_PROCESS_RETURN _extractLoudnessPeakToAverageValue( 413 LOUDNESS_INFO* loudnessInfo, 414 DYN_RANGE_MEASUREMENT_REQUEST_TYPE dynamicRangeMeasurementType, 415 int* pLoudnessPeakToAverageValuePresent, 416 FIXP_DBL* pLoudnessPeakToAverageValue); 417 418 static DRCDEC_SELECTION_PROCESS_RETURN _selectAlbumLoudness( 419 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, 420 DRCDEC_SELECTION* pCandidatesPotential, 421 DRCDEC_SELECTION* pCandidatesSelected); 422 423 static int _findMethodDefinition(LOUDNESS_INFO* pLoudnessInfo, 424 int methodDefinition, int startIndex); 425 426 /*******************************************/ 427 /* public functions */ 428 /*******************************************/ 429 430 struct s_drcdec_selection_process { 431 SEL_PROC_CODEC_MODE codecMode; 432 SEL_PROC_INPUT selProcInput; 433 DRCDEC_SELECTION 434 selectionData[2]; /* 2 instances, one before and one after selection */ 435 }; 436 437 DRCDEC_SELECTION_PROCESS_RETURN 438 drcDec_SelectionProcess_Create(HANDLE_DRC_SELECTION_PROCESS* phInstance) { 439 HANDLE_DRC_SELECTION_PROCESS hInstance; 440 hInstance = (HANDLE_DRC_SELECTION_PROCESS)FDKcalloc( 441 1, sizeof(struct s_drcdec_selection_process)); 442 443 if (!hInstance) return DRCDEC_SELECTION_PROCESS_OUTOFMEMORY; 444 445 hInstance->codecMode = SEL_PROC_CODEC_MODE_UNDEFINED; 446 447 *phInstance = hInstance; 448 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 449 } 450 451 DRCDEC_SELECTION_PROCESS_RETURN 452 drcDec_SelectionProcess_Init(HANDLE_DRC_SELECTION_PROCESS hInstance) { 453 if (!hInstance) return DRCDEC_SELECTION_PROCESS_NOT_OK; 454 455 _initDefaultParams(&hInstance->selProcInput); 456 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 457 } 458 459 DRCDEC_SELECTION_PROCESS_RETURN 460 drcDec_SelectionProcess_SetCodecMode(HANDLE_DRC_SELECTION_PROCESS hInstance, 461 const SEL_PROC_CODEC_MODE codecMode) { 462 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 463 464 if (!hInstance) return DRCDEC_SELECTION_PROCESS_NOT_OK; 465 466 switch (codecMode) { 467 case SEL_PROC_MPEG_4_AAC: 468 case SEL_PROC_MPEG_D_USAC: 469 case SEL_PROC_TEST_TIME_DOMAIN: 470 case SEL_PROC_TEST_QMF_DOMAIN: 471 case SEL_PROC_TEST_STFT_DOMAIN: 472 hInstance->codecMode = codecMode; 473 break; 474 475 case SEL_PROC_CODEC_MODE_UNDEFINED: 476 default: 477 return DRCDEC_SELECTION_PROCESS_NOT_OK; 478 } 479 480 retVal = _initCodecModeParams(&(hInstance->selProcInput), 481 hInstance->codecMode = codecMode); 482 483 return retVal; 484 } 485 486 DRCDEC_SELECTION_PROCESS_RETURN 487 drcDec_SelectionProcess_SetParam(HANDLE_DRC_SELECTION_PROCESS hInstance, 488 const SEL_PROC_USER_PARAM requestType, 489 FIXP_DBL requestValue, int* pDiff) { 490 INT requestValueInt = (INT)requestValue; 491 int i, diff = 0; 492 SEL_PROC_INPUT* pSelProcInput = &(hInstance->selProcInput); 493 494 switch (requestType) { 495 case SEL_PROC_LOUDNESS_NORMALIZATION_ON: 496 if ((requestValueInt != 0) && (requestValueInt != 1)) 497 return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; 498 diff |= 499 _compAssign(&pSelProcInput->loudnessNormalizationOn, requestValueInt); 500 break; 501 case SEL_PROC_TARGET_LOUDNESS: 502 /* Lower boundary: drcSetTargetLoudnessValueLower default value. 503 Upper boundary: drcSetTargetLoudnessValueUpper default value */ 504 if ((requestValue < FL2FXCONST_DBL(-63.0f / (float)(1 << 7))) || 505 (requestValue > (FIXP_DBL)0)) 506 return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; 507 if (requestValue > 508 FL2FXCONST_DBL(-10.0f / 509 (float)(1 << 7))) /* recommended maximum value */ 510 requestValue = FL2FXCONST_DBL(-10.0f / (float)(1 << 7)); 511 diff |= _compAssign(&pSelProcInput->targetLoudness, requestValue); 512 break; 513 case SEL_PROC_EFFECT_TYPE: 514 if ((requestValueInt < -1) || (requestValueInt >= DETR_COUNT)) 515 return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; 516 /* Caution. This overrides all drcFeatureRequests requested so far! */ 517 if (requestValueInt == -1) { 518 diff |= _compAssign(&pSelProcInput->dynamicRangeControlOn, 0); 519 } else if (requestValueInt == DETR_NONE) { 520 diff |= _compAssign(&pSelProcInput->dynamicRangeControlOn, 1); 521 diff |= _compAssign(&pSelProcInput->numDrcFeatureRequests, 0); 522 } else { 523 diff |= _compAssign(&pSelProcInput->dynamicRangeControlOn, 1); 524 diff |= _compAssign(&pSelProcInput->numDrcFeatureRequests, 1); 525 diff |= _compAssign(&pSelProcInput->drcFeatureRequestType[0], 526 DFRT_EFFECT_TYPE); 527 diff |= _compAssign(&pSelProcInput->drcFeatureRequest[0] 528 .drcEffectType.numRequestsDesired, 529 1); 530 diff |= _compAssign( 531 &pSelProcInput->drcFeatureRequest[0].drcEffectType.request[0], 532 requestValueInt); 533 if ((requestValueInt > DETR_NONE) && 534 (requestValueInt <= DETR_GENERAL_COMPR)) { 535 /* use fallback effect type requests */ 536 for (i = 0; i < 5; i++) { 537 diff |= 538 _compAssign(&pSelProcInput->drcFeatureRequest[0] 539 .drcEffectType.request[i + 1], 540 fallbackEffectTypeRequests[requestValueInt - 1][i]); 541 } 542 diff |= _compAssign( 543 &pSelProcInput->drcFeatureRequest[0].drcEffectType.numRequests, 544 6); 545 } else { 546 diff |= _compAssign( 547 &pSelProcInput->drcFeatureRequest[0].drcEffectType.numRequests, 548 1); 549 } 550 } 551 break; 552 case SEL_PROC_LOUDNESS_MEASUREMENT_METHOD: 553 if ((requestValueInt < 0) || (requestValueInt > 2)) 554 return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; 555 diff |= _compAssign(&pSelProcInput->loudnessMeasurementMethod, 556 requestValueInt); 557 break; 558 case SEL_PROC_DOWNMIX_ID: 559 diff |= 560 _compAssign(&pSelProcInput->targetConfigRequestType, TCRT_DOWNMIX_ID); 561 if (requestValueInt < 0) { /* negative requests signal no downmixId */ 562 diff |= _compAssign(&pSelProcInput->numDownmixIdRequests, 0); 563 } else { 564 diff |= _compAssign(&pSelProcInput->numDownmixIdRequests, 1); 565 diff |= 566 _compAssign(&pSelProcInput->downmixIdRequested[0], requestValueInt); 567 } 568 break; 569 case SEL_PROC_TARGET_LAYOUT: 570 /* Request target layout according to ChannelConfiguration in ISO/IEC 571 * 23001-8 (CICP) */ 572 if ((requestValueInt < 1) || (requestValueInt > 63)) 573 return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; 574 diff |= _compAssign(&pSelProcInput->targetConfigRequestType, 575 TCRT_TARGET_LAYOUT); 576 diff |= 577 _compAssign(&pSelProcInput->targetLayoutRequested, requestValueInt); 578 break; 579 case SEL_PROC_TARGET_CHANNEL_COUNT: 580 if ((requestValueInt < 1) || (requestValueInt > 8)) 581 return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; 582 diff |= _compAssign(&pSelProcInput->targetConfigRequestType, 583 TCRT_TARGET_CHANNEL_COUNT); 584 diff |= _compAssign(&pSelProcInput->targetChannelCountRequested, 585 requestValueInt); 586 break; 587 case SEL_PROC_BASE_CHANNEL_COUNT: 588 if (requestValueInt < 0) 589 return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; 590 diff |= _compAssign(&pSelProcInput->baseChannelCount, requestValueInt); 591 break; 592 case SEL_PROC_SAMPLE_RATE: 593 if (requestValueInt < 0) 594 return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; 595 diff |= _compAssign(&pSelProcInput->audioSampleRate, requestValueInt); 596 break; 597 case SEL_PROC_BOOST: 598 if ((requestValue < (FIXP_DBL)0) || 599 (requestValue > FL2FXCONST_DBL(1.0f / (float)(1 << 1)))) 600 return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; 601 diff |= _compAssign(&pSelProcInput->boost, FX_DBL2FX_SGL(requestValue)); 602 break; 603 case SEL_PROC_COMPRESS: 604 if ((requestValue < (FIXP_DBL)0) || 605 (requestValue > FL2FXCONST_DBL(1.0f / (float)(1 << 1)))) 606 return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; 607 diff |= 608 _compAssign(&pSelProcInput->compress, FX_DBL2FX_SGL(requestValue)); 609 break; 610 default: 611 return DRCDEC_SELECTION_PROCESS_INVALID_PARAM; 612 } 613 614 if (pDiff != NULL) { 615 *pDiff |= diff; 616 } 617 618 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 619 } 620 621 FIXP_DBL 622 drcDec_SelectionProcess_GetParam(HANDLE_DRC_SELECTION_PROCESS hInstance, 623 const SEL_PROC_USER_PARAM requestType) { 624 SEL_PROC_INPUT* pSelProcInput = &(hInstance->selProcInput); 625 626 switch (requestType) { 627 case SEL_PROC_LOUDNESS_NORMALIZATION_ON: 628 return (FIXP_DBL)pSelProcInput->loudnessNormalizationOn; 629 case SEL_PROC_DYNAMIC_RANGE_CONTROL_ON: 630 return (FIXP_DBL)pSelProcInput->dynamicRangeControlOn; 631 default: 632 return (FIXP_DBL)0; 633 } 634 } 635 636 DRCDEC_SELECTION_PROCESS_RETURN 637 drcDec_SelectionProcess_Delete(HANDLE_DRC_SELECTION_PROCESS* phInstance) { 638 if (phInstance == NULL || *phInstance == NULL) 639 return DRCDEC_SELECTION_PROCESS_INVALID_HANDLE; 640 641 FDKfree(*phInstance); 642 *phInstance = NULL; 643 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 644 } 645 646 DRCDEC_SELECTION_PROCESS_RETURN 647 drcDec_SelectionProcess_Process(HANDLE_DRC_SELECTION_PROCESS hInstance, 648 HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 649 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, 650 HANDLE_SEL_PROC_OUTPUT hSelProcOutput) { 651 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 652 DRCDEC_SELECTION* pCandidatesSelected; 653 DRCDEC_SELECTION* pCandidatesPotential; 654 655 if (hInstance == NULL) return DRCDEC_SELECTION_PROCESS_INVALID_HANDLE; 656 657 pCandidatesSelected = &(hInstance->selectionData[0]); 658 pCandidatesPotential = &(hInstance->selectionData[1]); 659 _drcdec_selection_setNumber(pCandidatesSelected, 0); 660 _drcdec_selection_setNumber(pCandidatesPotential, 0); 661 662 retVal = _generateVirtualDrcSets(&(hInstance->selProcInput), hUniDrcConfig, 663 hInstance->codecMode); 664 if (retVal) return (retVal); 665 666 if (hInstance->selProcInput.baseChannelCount != 667 hUniDrcConfig->channelLayout.baseChannelCount) { 668 hInstance->selProcInput.baseChannelCount = 669 hUniDrcConfig->channelLayout.baseChannelCount; 670 } 671 672 if ((hInstance->selProcInput.targetConfigRequestType != 0) || 673 (hInstance->selProcInput.targetConfigRequestType == 0 && 674 hInstance->selProcInput.numDownmixIdRequests == 0)) { 675 retVal = _channelLayoutToDownmixIdMapping(&(hInstance->selProcInput), 676 hUniDrcConfig); 677 678 if (_isError(retVal)) return (retVal); 679 } 680 681 retVal = _drcSetPreSelection(&(hInstance->selProcInput), hUniDrcConfig, 682 hLoudnessInfoSet, &pCandidatesPotential, 683 &pCandidatesSelected, hInstance->codecMode); 684 if (retVal) return (retVal); 685 686 if (hInstance->selProcInput.albumMode) { 687 _swapSelectionAndClear(&pCandidatesPotential, &pCandidatesSelected); 688 689 retVal = _selectAlbumLoudness(hLoudnessInfoSet, pCandidatesPotential, 690 pCandidatesSelected); 691 if (retVal) return (retVal); 692 693 if (_drcdec_selection_getNumber(pCandidatesSelected) == 0) { 694 _swapSelection(&pCandidatesPotential, &pCandidatesSelected); 695 } 696 } 697 698 _swapSelectionAndClear(&pCandidatesPotential, &pCandidatesSelected); 699 700 retVal = _drcSetRequestSelection(&(hInstance->selProcInput), hUniDrcConfig, 701 hLoudnessInfoSet, &pCandidatesPotential, 702 &pCandidatesSelected); 703 if (retVal) return (retVal); 704 705 retVal = _drcSetFinalSelection(&(hInstance->selProcInput), hUniDrcConfig, 706 &pCandidatesPotential, &pCandidatesSelected, 707 hInstance->codecMode); 708 if (retVal) return (retVal); 709 710 retVal = _generateOutputInfo( 711 &(hInstance->selProcInput), hSelProcOutput, hUniDrcConfig, 712 hLoudnessInfoSet, &(pCandidatesSelected->data[0]), hInstance->codecMode); 713 714 if (_isError(retVal)) return (retVal); 715 716 retVal = _selectDownmixMatrix(hSelProcOutput, hUniDrcConfig); 717 if (retVal) return (retVal); 718 719 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 720 } 721 722 /*******************************************/ 723 /* static functions */ 724 /*******************************************/ 725 726 static DRCDEC_SELECTION_PROCESS_RETURN _initDefaultParams( 727 HANDLE_SEL_PROC_INPUT hSelProcInput) { 728 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 729 730 if (hSelProcInput == NULL) return DRCDEC_SELECTION_PROCESS_INVALID_HANDLE; 731 732 /* system parameters */ 733 hSelProcInput->baseChannelCount = -1; 734 hSelProcInput->baseLayout = -1; 735 hSelProcInput->targetConfigRequestType = TCRT_DOWNMIX_ID; 736 hSelProcInput->numDownmixIdRequests = 0; 737 738 /* loudness normalization parameters */ 739 hSelProcInput->albumMode = 0; 740 hSelProcInput->peakLimiterPresent = 0; 741 hSelProcInput->loudnessNormalizationOn = 1; 742 hSelProcInput->targetLoudness = FL2FXCONST_DBL(-24.0f / (float)(1 << 7)); 743 hSelProcInput->loudnessDeviationMax = DEFAULT_LOUDNESS_DEVIATION_MAX; 744 hSelProcInput->loudnessMeasurementMethod = MDR_DEFAULT; 745 hSelProcInput->loudnessMeasurementSystem = MSR_DEFAULT; 746 hSelProcInput->loudnessMeasurementPreProc = LPR_DEFAULT; 747 hSelProcInput->deviceCutOffFrequency = 500; 748 hSelProcInput->loudnessNormalizationGainDbMax = 749 (FIXP_DBL)MAXVAL_DBL; /* infinity as default */ 750 hSelProcInput->loudnessNormalizationGainModificationDb = (FIXP_DBL)0; 751 hSelProcInput->outputPeakLevelMax = (FIXP_DBL)0; 752 if (hSelProcInput->peakLimiterPresent == 1) { 753 hSelProcInput->outputPeakLevelMax = FL2FXCONST_DBL(6.0f / (float)(1 << 7)); 754 } 755 756 /* dynamic range control parameters */ 757 hSelProcInput->dynamicRangeControlOn = 1; 758 759 hSelProcInput->numDrcFeatureRequests = 0; 760 761 /* other parameters */ 762 hSelProcInput->boost = FL2FXCONST_SGL(1.f / (float)(1 << 1)); 763 hSelProcInput->compress = FL2FXCONST_SGL(1.f / (float)(1 << 1)); 764 hSelProcInput->drcCharacteristicTarget = 0; 765 766 return retVal; 767 } 768 769 static DRCDEC_SELECTION_PROCESS_RETURN _initCodecModeParams( 770 HANDLE_SEL_PROC_INPUT hSelProcInput, const SEL_PROC_CODEC_MODE codecMode) { 771 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 772 773 if (hSelProcInput == NULL) return DRCDEC_SELECTION_PROCESS_INVALID_HANDLE; 774 775 switch (codecMode) { 776 case SEL_PROC_MPEG_H_3DA: 777 hSelProcInput->loudnessDeviationMax = 0; 778 hSelProcInput->peakLimiterPresent = 1; /* peak limiter is mandatory */ 779 /* The peak limiter also has to catch overshoots due to user 780 interactivity, downmixing etc. Therefore the maximum output peak level is 781 reduced to 0 dB. */ 782 hSelProcInput->outputPeakLevelMax = (FIXP_DBL)0; 783 break; 784 case SEL_PROC_MPEG_4_AAC: 785 case SEL_PROC_MPEG_D_USAC: 786 hSelProcInput->loudnessDeviationMax = DEFAULT_LOUDNESS_DEVIATION_MAX; 787 hSelProcInput->peakLimiterPresent = 1; 788 /* A peak limiter is present at the end of the decoder, therefore we can 789 * allow for a maximum output peak level greater than full scale 790 */ 791 hSelProcInput->outputPeakLevelMax = 792 FL2FXCONST_DBL(6.0f / (float)(1 << 7)); 793 break; 794 case SEL_PROC_TEST_TIME_DOMAIN: 795 case SEL_PROC_TEST_QMF_DOMAIN: 796 case SEL_PROC_TEST_STFT_DOMAIN: 797 /* for testing, adapt to default settings in reference software */ 798 hSelProcInput->loudnessNormalizationOn = 0; 799 hSelProcInput->dynamicRangeControlOn = 0; 800 break; 801 case SEL_PROC_CODEC_MODE_UNDEFINED: 802 default: 803 hSelProcInput->loudnessDeviationMax = DEFAULT_LOUDNESS_DEVIATION_MAX; 804 hSelProcInput->peakLimiterPresent = 0; 805 } 806 807 return retVal; 808 } 809 810 static DRCDEC_SELECTION_PROCESS_RETURN _channelLayoutToDownmixIdMapping( 811 HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig) { 812 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 813 814 DOWNMIX_INSTRUCTIONS* pDown = NULL; 815 816 int i; 817 818 hSelProcInput->numDownmixIdRequests = 0; 819 820 switch (hSelProcInput->targetConfigRequestType) { 821 case TCRT_DOWNMIX_ID: 822 if (hSelProcInput->numDownmixIdRequests == 0) { 823 hSelProcInput->downmixIdRequested[0] = 0; 824 hSelProcInput->numDownmixIdRequests = 1; 825 } 826 827 break; 828 829 case TCRT_TARGET_LAYOUT: 830 if (hSelProcInput->targetLayoutRequested == hSelProcInput->baseLayout) { 831 hSelProcInput->downmixIdRequested[0] = 0; 832 hSelProcInput->numDownmixIdRequests = 1; 833 } 834 835 if (hSelProcInput->numDownmixIdRequests == 0) { 836 for (i = 0; i < hUniDrcConfig->downmixInstructionsCount; i++) { 837 pDown = &(hUniDrcConfig->downmixInstructions[i]); 838 839 if (hSelProcInput->targetLayoutRequested == pDown->targetLayout) { 840 hSelProcInput 841 ->downmixIdRequested[hSelProcInput->numDownmixIdRequests] = 842 pDown->downmixId; 843 hSelProcInput->numDownmixIdRequests++; 844 } 845 } 846 } 847 848 if (hSelProcInput->baseLayout == -1) { 849 retVal = DRCDEC_SELECTION_PROCESS_WARNING; 850 } 851 852 if (hSelProcInput->numDownmixIdRequests == 0) { 853 hSelProcInput->downmixIdRequested[0] = 0; 854 hSelProcInput->numDownmixIdRequests = 1; 855 retVal = DRCDEC_SELECTION_PROCESS_WARNING; 856 } 857 858 break; 859 860 case TCRT_TARGET_CHANNEL_COUNT: 861 if (hSelProcInput->targetChannelCountRequested == 862 hSelProcInput->baseChannelCount) { 863 hSelProcInput->downmixIdRequested[0] = 0; 864 hSelProcInput->numDownmixIdRequests = 1; 865 } 866 867 if (hSelProcInput->numDownmixIdRequests == 0) { 868 for (i = 0; i < hUniDrcConfig->downmixInstructionsCount; i++) { 869 pDown = &(hUniDrcConfig->downmixInstructions[i]); 870 871 if (hSelProcInput->targetChannelCountRequested == 872 pDown->targetChannelCount) { 873 hSelProcInput 874 ->downmixIdRequested[hSelProcInput->numDownmixIdRequests] = 875 pDown->downmixId; 876 hSelProcInput->numDownmixIdRequests++; 877 } 878 } 879 } 880 881 if (hSelProcInput->baseChannelCount == -1) { 882 retVal = DRCDEC_SELECTION_PROCESS_WARNING; 883 } 884 885 if (hSelProcInput->numDownmixIdRequests == 0) { 886 retVal = DRCDEC_SELECTION_PROCESS_WARNING; 887 hSelProcInput->downmixIdRequested[0] = 0; 888 hSelProcInput->numDownmixIdRequests = 1; 889 } 890 891 break; 892 893 default: 894 return DRCDEC_SELECTION_PROCESS_NOT_OK; 895 } 896 897 return retVal; 898 } 899 900 /*******************************************/ 901 902 /* Note: Numbering of DRC pre-selection steps according to MPEG-D Part-4 DRC 903 * Amd1 */ 904 905 /* #1: DownmixId of DRC set matches the requested downmixId. 906 #2: Output channel layout of DRC set matches the requested layout. 907 #3: Channel count of DRC set matches the requested channel count. */ 908 static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement123( 909 int nRequestedDownmixId, DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, 910 int* pMatchFound) { 911 int i; 912 *pMatchFound = 0; 913 914 for (i = 0; i < pDrcInstructionUniDrc->downmixIdCount; i++) { 915 if ((pDrcInstructionUniDrc->downmixId[i] == nRequestedDownmixId) || 916 (pDrcInstructionUniDrc->downmixId[i] == DOWNMIX_ID_ANY_DOWNMIX) || 917 ((pDrcInstructionUniDrc->downmixId[i] == DOWNMIX_ID_BASE_LAYOUT) && 918 (pDrcInstructionUniDrc->drcSetId > 0))) { 919 *pMatchFound = 1; 920 break; 921 } 922 } 923 924 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 925 } 926 927 /* #4: The DRC set is not a "Fade-" or "Ducking-" only DRC set. */ 928 static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement4( 929 DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction, int nDynamicRangeControlOn, 930 int* pMatchFound) { 931 *pMatchFound = 0; 932 933 if (nDynamicRangeControlOn == 1) { 934 if ((pDrcInstruction->drcSetEffect != EB_FADE) && 935 (pDrcInstruction->drcSetEffect != EB_DUCK_OTHER) && 936 (pDrcInstruction->drcSetEffect != EB_DUCK_SELF) && 937 (pDrcInstruction->drcSetEffect != 0 || pDrcInstruction->drcSetId < 0)) { 938 *pMatchFound = 1; 939 } 940 } else { 941 *pMatchFound = 1; 942 } 943 944 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 945 } 946 947 /* #5: The number of DRC bands is supported. */ 948 static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement5( 949 DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, 950 DRC_COEFFICIENTS_UNI_DRC* pCoef, int* pMatchFound) { 951 int i; 952 953 *pMatchFound = 1; 954 955 if (pCoef == NULL) /* check for parametricDRC */ 956 { 957 *pMatchFound = 1; 958 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 959 } 960 961 for (i = 0; i < pDrcInstructionUniDrc->nDrcChannelGroups; i++) { 962 int indexDrcCoeff = pDrcInstructionUniDrc->gainSetIndexForChannelGroup[i]; 963 int bandCount = 0; 964 965 if (indexDrcCoeff > pCoef->gainSetCount - 1) /* check for parametricDRC */ 966 { 967 *pMatchFound = 1; 968 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 969 } 970 971 GAIN_SET* gainSet = &(pCoef->gainSet[indexDrcCoeff]); 972 bandCount = gainSet->bandCount; 973 974 if (bandCount > 4) { 975 *pMatchFound = 0; 976 } 977 } 978 979 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 980 } 981 982 /* #6: Independent use of DRC set is permitted.*/ 983 static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement6( 984 DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, int* pMatchFound) { 985 *pMatchFound = 0; 986 987 if (((pDrcInstructionUniDrc->dependsOnDrcSetPresent == 0) && 988 (pDrcInstructionUniDrc->noIndependentUse == 0)) || 989 (pDrcInstructionUniDrc->dependsOnDrcSetPresent == 1)) { 990 *pMatchFound = 1; 991 } 992 993 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 994 } 995 996 /* #7: DRC sets that require EQ are only permitted if EQ is supported. */ 997 static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement7( 998 DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, int* pMatchFound) { 999 *pMatchFound = 1; 1000 1001 if (pDrcInstructionUniDrc->requiresEq) { 1002 /* EQ is not supported */ 1003 *pMatchFound = 0; 1004 } 1005 1006 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 1007 } 1008 1009 static void _setSelectionDataInfo(DRCDEC_SELECTION_DATA* pData, 1010 FIXP_DBL loudness, 1011 FIXP_DBL loudnessNormalizationGainDb, 1012 FIXP_DBL loudnessNormalizationGainDbMax, 1013 FIXP_DBL loudnessDeviationMax, 1014 FIXP_DBL signalPeakLevel, 1015 FIXP_DBL outputPeakLevelMax, 1016 int applyAdjustment) { 1017 FIXP_DBL adjustment = 0; 1018 1019 if (applyAdjustment) { 1020 adjustment = 1021 fMax((FIXP_DBL)0, signalPeakLevel + loudnessNormalizationGainDb - 1022 outputPeakLevelMax); 1023 adjustment = fMin(adjustment, fMax((FIXP_DBL)0, loudnessDeviationMax)); 1024 } 1025 1026 pData->loudnessNormalizationGainDbAdjusted = fMin( 1027 loudnessNormalizationGainDb - adjustment, loudnessNormalizationGainDbMax); 1028 pData->outputLoudness = loudness + pData->loudnessNormalizationGainDbAdjusted; 1029 pData->outputPeakLevel = 1030 signalPeakLevel + pData->loudnessNormalizationGainDbAdjusted; 1031 } 1032 1033 static int _targetLoudnessInRange( 1034 DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, FIXP_DBL targetLoudness) { 1035 int retVal = 0; 1036 1037 FIXP_DBL drcSetTargetLoudnessValueUpper = 1038 ((FIXP_DBL)pDrcInstructionUniDrc->drcSetTargetLoudnessValueUpper) 1039 << (DFRACT_BITS - 1 - 7); 1040 FIXP_DBL drcSetTargetLoudnessValueLower = 1041 ((FIXP_DBL)pDrcInstructionUniDrc->drcSetTargetLoudnessValueLower) 1042 << (DFRACT_BITS - 1 - 7); 1043 1044 if (pDrcInstructionUniDrc->drcSetTargetLoudnessPresent && 1045 drcSetTargetLoudnessValueUpper >= targetLoudness && 1046 drcSetTargetLoudnessValueLower < targetLoudness) { 1047 retVal = 1; 1048 } 1049 1050 return retVal; 1051 } 1052 1053 /* #8: The range of the target loudness specified for a DRC set has to include 1054 * the requested decoder target loudness. */ 1055 static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement8( 1056 SEL_PROC_INPUT* hSelProcInput, int downmixIdIndex, 1057 HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 1058 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, 1059 DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, 1060 DRCDEC_SELECTION* pCandidatesPotential, 1061 DRCDEC_SELECTION* pCandidatesSelected, SEL_PROC_CODEC_MODE codecMode) { 1062 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 1063 int explicitPeakInformationPresent; 1064 FIXP_DBL signalPeakLevel; 1065 int addToCandidate = 0; 1066 1067 FIXP_DBL loudnessNormalizationGainDb; 1068 FIXP_DBL loudness; 1069 1070 FIXP_DBL loudnessDeviationMax = 1071 ((FIXP_DBL)hSelProcInput->loudnessDeviationMax) << (DFRACT_BITS - 1 - 7); 1072 ; 1073 1074 if (hSelProcInput->loudnessNormalizationOn) { 1075 retVal = _getLoudness(hLoudnessInfoSet, hSelProcInput->albumMode, 1076 hSelProcInput->loudnessMeasurementMethod, 1077 hSelProcInput->loudnessMeasurementSystem, 1078 hSelProcInput->targetLoudness, 1079 pDrcInstructionUniDrc->drcSetId, 1080 hSelProcInput->downmixIdRequested[downmixIdIndex], 1081 &loudnessNormalizationGainDb, &loudness); 1082 if (retVal) return (retVal); 1083 } else { 1084 loudnessNormalizationGainDb = (FIXP_DBL)0; 1085 loudness = UNDEFINED_LOUDNESS_VALUE; 1086 } 1087 1088 retVal = _getSignalPeakLevel( 1089 hSelProcInput, hUniDrcConfig, hLoudnessInfoSet, pDrcInstructionUniDrc, 1090 hSelProcInput->downmixIdRequested[downmixIdIndex], 1091 &explicitPeakInformationPresent, &signalPeakLevel, codecMode 1092 1093 ); 1094 if (retVal) return (retVal); 1095 1096 if (hSelProcInput->dynamicRangeControlOn) { 1097 if (explicitPeakInformationPresent == 0) { 1098 if (pDrcInstructionUniDrc->drcSetTargetLoudnessPresent && 1099 ((hSelProcInput->loudnessNormalizationOn && 1100 _targetLoudnessInRange(pDrcInstructionUniDrc, 1101 hSelProcInput->targetLoudness)) || 1102 !hSelProcInput->loudnessNormalizationOn)) { 1103 DRCDEC_SELECTION_DATA* pData = 1104 _drcdec_selection_addNew(pCandidatesSelected); 1105 if (pData == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1106 1107 _setSelectionDataInfo(pData, loudness, loudnessNormalizationGainDb, 1108 hSelProcInput->loudnessNormalizationGainDbMax, 1109 loudnessDeviationMax, signalPeakLevel, 1110 hSelProcInput->outputPeakLevelMax, 0); 1111 pData->downmixIdRequestIndex = downmixIdIndex; 1112 pData->pInst = pDrcInstructionUniDrc; 1113 pData->selectionFlag = 1114 1; /* signal pre-selection step dealing with drcSetTargetLoudness */ 1115 1116 if (hSelProcInput->loudnessNormalizationOn) { 1117 pData->outputPeakLevel = 1118 hSelProcInput->targetLoudness - 1119 (((FIXP_DBL)pData->pInst->drcSetTargetLoudnessValueUpper) 1120 << (DFRACT_BITS - 1 - 7)); 1121 } else { 1122 pData->outputPeakLevel = (FIXP_DBL)0; 1123 } 1124 } else { 1125 if ((!hSelProcInput->loudnessNormalizationOn) || 1126 (!pDrcInstructionUniDrc->drcSetTargetLoudnessPresent) || 1127 (hSelProcInput->loudnessNormalizationOn && 1128 _targetLoudnessInRange(pDrcInstructionUniDrc, 1129 hSelProcInput->targetLoudness))) { 1130 addToCandidate = 1; 1131 } 1132 } 1133 } else { 1134 addToCandidate = 1; 1135 } 1136 1137 if (addToCandidate) { 1138 DRCDEC_SELECTION_DATA* pData = 1139 _drcdec_selection_addNew(pCandidatesPotential); 1140 if (pData == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1141 1142 _setSelectionDataInfo(pData, loudness, loudnessNormalizationGainDb, 1143 hSelProcInput->loudnessNormalizationGainDbMax, 1144 loudnessDeviationMax, signalPeakLevel, 1145 hSelProcInput->outputPeakLevelMax, 0); 1146 pData->downmixIdRequestIndex = downmixIdIndex; 1147 pData->pInst = pDrcInstructionUniDrc; 1148 pData->selectionFlag = 0; 1149 } 1150 } else { 1151 if (pDrcInstructionUniDrc->drcSetId < 0) { 1152 DRCDEC_SELECTION_DATA* pData = 1153 _drcdec_selection_addNew(pCandidatesSelected); 1154 if (pData == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1155 1156 _setSelectionDataInfo(pData, loudness, loudnessNormalizationGainDb, 1157 hSelProcInput->loudnessNormalizationGainDbMax, 1158 loudnessDeviationMax, signalPeakLevel, 1159 hSelProcInput->outputPeakLevelMax, 1); 1160 1161 pData->downmixIdRequestIndex = downmixIdIndex; 1162 pData->pInst = pDrcInstructionUniDrc; 1163 pData->selectionFlag = 0; 1164 } 1165 } 1166 1167 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 1168 } 1169 1170 /* #9: Clipping is minimized. */ 1171 static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement9( 1172 SEL_PROC_INPUT* hSelProcInput, DRCDEC_SELECTION* pCandidatesPotential, 1173 DRCDEC_SELECTION* pCandidatesSelected) { 1174 int i; 1175 1176 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1177 DRCDEC_SELECTION_DATA* pCandidate = 1178 _drcdec_selection_getAt(pCandidatesPotential, i); 1179 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1180 1181 if (pCandidate->outputPeakLevel <= hSelProcInput->outputPeakLevelMax) { 1182 if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) 1183 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1184 } 1185 } 1186 1187 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 1188 } 1189 1190 static DRCDEC_SELECTION_PROCESS_RETURN _drcSetPreSelectionSingleInstruction( 1191 SEL_PROC_INPUT* hSelProcInput, int downmixIdIndex, 1192 HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 1193 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, 1194 DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, 1195 DRCDEC_SELECTION* pCandidatesPotential, 1196 DRCDEC_SELECTION* pCandidatesSelected, SEL_PROC_CODEC_MODE codecMode) { 1197 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 1198 int matchFound = 0; 1199 DRC_COEFFICIENTS_UNI_DRC* pCoef = 1200 selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED); 1201 1202 retVal = _preSelectionRequirement123( 1203 hSelProcInput->downmixIdRequested[downmixIdIndex], pDrcInstructionUniDrc, 1204 &matchFound); 1205 1206 if (!retVal && matchFound) 1207 retVal = _preSelectionRequirement4(pDrcInstructionUniDrc, 1208 hSelProcInput->dynamicRangeControlOn, 1209 &matchFound); 1210 1211 if (!retVal && matchFound) 1212 retVal = 1213 _preSelectionRequirement5(pDrcInstructionUniDrc, pCoef, &matchFound); 1214 1215 if (!retVal && matchFound) 1216 retVal = _preSelectionRequirement6(pDrcInstructionUniDrc, &matchFound); 1217 1218 if (!retVal && matchFound) 1219 retVal = _preSelectionRequirement7(pDrcInstructionUniDrc, &matchFound); 1220 1221 if (!retVal && matchFound) 1222 retVal = _preSelectionRequirement8( 1223 hSelProcInput, downmixIdIndex, hUniDrcConfig, hLoudnessInfoSet, 1224 pDrcInstructionUniDrc, pCandidatesPotential, pCandidatesSelected, 1225 codecMode); 1226 1227 return retVal; 1228 } 1229 1230 static DRCDEC_SELECTION_PROCESS_RETURN _drcSetSelectionAddCandidates( 1231 SEL_PROC_INPUT* hSelProcInput, DRCDEC_SELECTION* pCandidatesPotential, 1232 DRCDEC_SELECTION* pCandidatesSelected) { 1233 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 1234 int nHitCount = 0; 1235 int i; 1236 1237 DRCDEC_SELECTION_DATA* pCandidate = NULL; 1238 DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc = NULL; 1239 1240 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1241 pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); 1242 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1243 1244 pDrcInstructionUniDrc = pCandidate->pInst; 1245 1246 if (_targetLoudnessInRange(pDrcInstructionUniDrc, 1247 hSelProcInput->targetLoudness)) { 1248 nHitCount++; 1249 } 1250 } 1251 1252 if (nHitCount != 0) { 1253 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1254 pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); 1255 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1256 1257 pDrcInstructionUniDrc = pCandidate->pInst; 1258 1259 if (_targetLoudnessInRange(pDrcInstructionUniDrc, 1260 hSelProcInput->targetLoudness)) { 1261 if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) 1262 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1263 } 1264 } 1265 } else { 1266 FIXP_DBL lowestPeakLevel = MAXVAL_DBL; /* e = 7 */ 1267 FIXP_DBL peakLevel = 0; /* e = 7 */ 1268 1269 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1270 pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); 1271 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1272 1273 peakLevel = pCandidate->outputPeakLevel; 1274 1275 if (peakLevel < lowestPeakLevel) { 1276 lowestPeakLevel = peakLevel; 1277 } 1278 } 1279 1280 /* add all with lowest peak level or max 1dB above */ 1281 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1282 FIXP_DBL loudnessDeviationMax = 1283 ((FIXP_DBL)hSelProcInput->loudnessDeviationMax) 1284 << (DFRACT_BITS - 1 - 7); /* e = 7 */ 1285 1286 pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); 1287 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1288 1289 peakLevel = pCandidate->outputPeakLevel; 1290 1291 if (peakLevel == lowestPeakLevel || 1292 peakLevel <= 1293 lowestPeakLevel + FL2FXCONST_DBL(1.0f / (float)(1 << 7))) { 1294 FIXP_DBL adjustment = 1295 fMax((FIXP_DBL)0, peakLevel - hSelProcInput->outputPeakLevelMax); 1296 adjustment = fMin(adjustment, fMax((FIXP_DBL)0, loudnessDeviationMax)); 1297 1298 pCandidate->loudnessNormalizationGainDbAdjusted -= adjustment; 1299 pCandidate->outputPeakLevel -= adjustment; 1300 pCandidate->outputLoudness -= adjustment; 1301 if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) 1302 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1303 } 1304 } 1305 } 1306 1307 return retVal; 1308 } 1309 1310 static DRCDEC_SELECTION_PROCESS_RETURN _dependentDrcInstruction( 1311 HANDLE_UNI_DRC_CONFIG hUniDrcConfig, DRC_INSTRUCTIONS_UNI_DRC* pInst, 1312 DRC_INSTRUCTIONS_UNI_DRC** ppDrcInstructionsDependent) { 1313 int i; 1314 DRC_INSTRUCTIONS_UNI_DRC* pDependentDrc = NULL; 1315 1316 for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { 1317 pDependentDrc = 1318 (DRC_INSTRUCTIONS_UNI_DRC*)&(hUniDrcConfig->drcInstructionsUniDrc[i]); 1319 1320 if (pDependentDrc->drcSetId == pInst->dependsOnDrcSet) { 1321 break; 1322 } 1323 } 1324 1325 if (i == hUniDrcConfig->drcInstructionsUniDrcCount) { 1326 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1327 } 1328 1329 if (pDependentDrc->dependsOnDrcSetPresent == 1) { 1330 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1331 } 1332 1333 *ppDrcInstructionsDependent = pDependentDrc; 1334 1335 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 1336 } 1337 1338 static DRCDEC_SELECTION_PROCESS_RETURN _selectDrcSetEffectNone( 1339 HANDLE_UNI_DRC_CONFIG hUniDrcConfig, DRCDEC_SELECTION* pCandidatesPotential, 1340 DRCDEC_SELECTION* pCandidatesSelected) { 1341 int i; 1342 1343 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1344 DRCDEC_SELECTION_DATA* pCandidate = 1345 _drcdec_selection_getAt(pCandidatesPotential, i); 1346 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1347 1348 if ((pCandidate->pInst->drcSetEffect & 0xff) == 0) { 1349 if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) 1350 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1351 } 1352 } 1353 1354 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 1355 } 1356 1357 static DRCDEC_SELECTION_PROCESS_RETURN _selectSingleEffectType( 1358 HANDLE_UNI_DRC_CONFIG hUniDrcConfig, DRC_EFFECT_TYPE_REQUEST effectType, 1359 DRCDEC_SELECTION* pCandidatesPotential, 1360 DRCDEC_SELECTION* pCandidatesSelected) { 1361 int i; 1362 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 1363 DRC_INSTRUCTIONS_UNI_DRC* pInst; 1364 DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionsDependent; 1365 1366 if (effectType == DETR_NONE) { 1367 retVal = _selectDrcSetEffectNone(hUniDrcConfig, pCandidatesPotential, 1368 pCandidatesSelected); 1369 if (retVal) return (retVal); 1370 } else { 1371 int effectBitPosition = 1 << (effectType - 1); 1372 1373 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1374 DRCDEC_SELECTION_DATA* pCandidate = 1375 _drcdec_selection_getAt(pCandidatesPotential, i); 1376 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1377 1378 pInst = pCandidate->pInst; 1379 1380 if (!pInst->dependsOnDrcSetPresent) { 1381 if ((pInst->drcSetEffect & effectBitPosition)) { 1382 if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) 1383 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1384 } 1385 } else { 1386 retVal = _dependentDrcInstruction(hUniDrcConfig, pInst, 1387 &pDrcInstructionsDependent); 1388 if (retVal) return (retVal); 1389 1390 if (((pInst->drcSetEffect & effectBitPosition)) || 1391 ((pDrcInstructionsDependent->drcSetEffect & effectBitPosition))) { 1392 if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) 1393 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1394 } 1395 } 1396 } 1397 } 1398 1399 return retVal; 1400 } 1401 1402 static DRCDEC_SELECTION_PROCESS_RETURN _selectEffectTypeFeature( 1403 HANDLE_UNI_DRC_CONFIG hUniDrcConfig, DRC_FEATURE_REQUEST drcFeatureRequest, 1404 DRCDEC_SELECTION** ppCandidatesPotential, 1405 DRCDEC_SELECTION** ppCandidatesSelected) { 1406 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 1407 int i; 1408 int desiredEffectTypeFound = 0; 1409 1410 for (i = 0; i < drcFeatureRequest.drcEffectType.numRequestsDesired; i++) { 1411 retVal = _selectSingleEffectType( 1412 hUniDrcConfig, drcFeatureRequest.drcEffectType.request[i], 1413 *ppCandidatesPotential, *ppCandidatesSelected); 1414 if (retVal) return (retVal); 1415 1416 if (_drcdec_selection_getNumber(*ppCandidatesSelected)) { 1417 desiredEffectTypeFound = 1; 1418 _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); 1419 } 1420 } 1421 1422 if (!desiredEffectTypeFound) { 1423 for (i = drcFeatureRequest.drcEffectType.numRequestsDesired; 1424 i < drcFeatureRequest.drcEffectType.numRequests; i++) { 1425 retVal = _selectSingleEffectType( 1426 hUniDrcConfig, drcFeatureRequest.drcEffectType.request[i], 1427 *ppCandidatesPotential, *ppCandidatesSelected); 1428 if (retVal) return (retVal); 1429 1430 if (_drcdec_selection_getNumber(*ppCandidatesSelected)) { 1431 _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); 1432 break; 1433 } 1434 } 1435 } 1436 1437 _swapSelection(ppCandidatesPotential, ppCandidatesSelected); 1438 1439 return retVal; 1440 } 1441 1442 static DRCDEC_SELECTION_PROCESS_RETURN _selectDynamicRange( 1443 HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 1444 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, 1445 DRC_FEATURE_REQUEST drcFeatureRequest, UCHAR* pDownmixIdRequested, 1446 int albumMode, DRCDEC_SELECTION* pCandidatesPotential, 1447 DRCDEC_SELECTION* ppCandidatesSelected) { 1448 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 1449 int i; 1450 int peakToAveragePresent; 1451 FIXP_DBL peakToAverage; 1452 1453 FIXP_DBL minVal = MAXVAL_DBL; 1454 FIXP_DBL val = 0; 1455 1456 int numSelectedCandidates = _drcdec_selection_getNumber(ppCandidatesSelected); 1457 1458 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1459 DRCDEC_SELECTION_DATA* pCandidate = 1460 _drcdec_selection_getAt(pCandidatesPotential, i); 1461 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1462 1463 retVal = _dynamicRangeMeasurement( 1464 hLoudnessInfoSet, pCandidate->pInst, 1465 pDownmixIdRequested[pCandidate->downmixIdRequestIndex], 1466 drcFeatureRequest.dynamicRange.measurementRequestType, albumMode, 1467 &peakToAveragePresent, &peakToAverage); 1468 if (retVal) return (retVal); 1469 1470 if (peakToAveragePresent) { 1471 if (!drcFeatureRequest.dynamicRange.requestedIsRange) { 1472 val = fAbs(drcFeatureRequest.dynamicRange.requestValue - peakToAverage); 1473 1474 if (minVal > val) { 1475 minVal = val; 1476 1477 _drcdec_selection_setNumber(ppCandidatesSelected, 1478 numSelectedCandidates); 1479 } 1480 if (_drcdec_selection_add(ppCandidatesSelected, pCandidate) == NULL) 1481 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1482 } else { 1483 if ((peakToAverage >= drcFeatureRequest.dynamicRange.requestValueMin) && 1484 (peakToAverage <= drcFeatureRequest.dynamicRange.requestValueMax)) { 1485 if (_drcdec_selection_add(ppCandidatesSelected, pCandidate) == NULL) 1486 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1487 } 1488 } 1489 } 1490 } 1491 1492 return retVal; 1493 } 1494 1495 static DRCDEC_SELECTION_PROCESS_RETURN _selectSingleDrcCharacteristic( 1496 HANDLE_UNI_DRC_CONFIG hUniDrcConfig, int requestedDrcCharacteristic, 1497 DRCDEC_SELECTION** ppCandidatesPotential, 1498 DRCDEC_SELECTION** ppCandidatesSelected) { 1499 int i, j, b; 1500 int hit = 0; 1501 1502 DRC_INSTRUCTIONS_UNI_DRC* pInst = NULL; 1503 DRC_COEFFICIENTS_UNI_DRC* pCoef = NULL; 1504 GAIN_SET* pGainSet = NULL; 1505 1506 if (requestedDrcCharacteristic < 1) { 1507 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1508 } 1509 1510 pCoef = selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED); 1511 1512 if (pCoef == NULL) /* check for parametricDRC */ 1513 { 1514 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 1515 } 1516 1517 for (i = 0; i < _drcdec_selection_getNumber(*ppCandidatesPotential); i++) { 1518 DRCDEC_SELECTION_DATA* pCandidate = 1519 _drcdec_selection_getAt(*ppCandidatesPotential, i); 1520 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1521 1522 pInst = pCandidate->pInst; 1523 1524 hit = 0; 1525 1526 for (j = 0; j < pInst->nDrcChannelGroups; j++) { 1527 int bandCount = 0; 1528 int indexDrcCoeff = pInst->gainSetIndexForChannelGroup[j]; 1529 1530 if (indexDrcCoeff > pCoef->gainSetCount - 1) /* check for parametricDRC */ 1531 { 1532 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 1533 } 1534 1535 pGainSet = &(pCoef->gainSet[indexDrcCoeff]); 1536 bandCount = pGainSet->bandCount; 1537 1538 for (b = 0; b < bandCount; b++) { 1539 if ((pGainSet->drcCharacteristic[b].isCICP) && 1540 (pGainSet->drcCharacteristic[b].cicpIndex == 1541 requestedDrcCharacteristic)) { 1542 hit = 1; 1543 break; 1544 } 1545 } 1546 1547 if (hit) break; 1548 } 1549 1550 if (hit) { 1551 if (_drcdec_selection_add(*ppCandidatesSelected, pCandidate) == NULL) 1552 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1553 } 1554 } 1555 1556 if (_drcdec_selection_getNumber(*ppCandidatesSelected)) { 1557 _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); 1558 } 1559 1560 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 1561 } 1562 1563 static DRCDEC_SELECTION_PROCESS_RETURN _selectDrcCharacteristic( 1564 HANDLE_UNI_DRC_CONFIG hUniDrcConfig, int drcCharacteristicRequested, 1565 DRCDEC_SELECTION** ppCandidatesPotential, 1566 DRCDEC_SELECTION** ppCandidatesSelected) { 1567 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 1568 1569 const int secondTry[12] = {0, 2, 3, 4, 5, 6, 5, 9, 10, 7, 8, 10}; 1570 1571 retVal = _selectSingleDrcCharacteristic( 1572 hUniDrcConfig, drcCharacteristicRequested, ppCandidatesPotential, 1573 ppCandidatesSelected); 1574 if (retVal) return (retVal); 1575 1576 if ((drcCharacteristicRequested <= 11) && 1577 (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0)) { 1578 retVal = _selectSingleDrcCharacteristic( 1579 hUniDrcConfig, secondTry[drcCharacteristicRequested], 1580 ppCandidatesPotential, ppCandidatesSelected); 1581 if (retVal) return (retVal); 1582 } 1583 1584 if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { 1585 if ((drcCharacteristicRequested >= 2) && 1586 (drcCharacteristicRequested <= 5)) { 1587 retVal = _selectSingleDrcCharacteristic( 1588 hUniDrcConfig, drcCharacteristicRequested - 1, ppCandidatesPotential, 1589 ppCandidatesSelected); 1590 if (retVal) return (retVal); 1591 } else if (drcCharacteristicRequested == 11) { 1592 retVal = _selectSingleDrcCharacteristic( 1593 hUniDrcConfig, 9, ppCandidatesPotential, ppCandidatesSelected); 1594 if (retVal) return (retVal); 1595 } 1596 } 1597 1598 _swapSelection(ppCandidatesPotential, ppCandidatesSelected); 1599 1600 return retVal; 1601 } 1602 1603 static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_peakValue0( 1604 DRCDEC_SELECTION* pCandidatesPotential, 1605 DRCDEC_SELECTION* pCandidatesSelected) { 1606 int i; 1607 1608 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1609 DRCDEC_SELECTION_DATA* pCandidate = 1610 _drcdec_selection_getAt(pCandidatesPotential, i); 1611 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1612 1613 if (pCandidate->outputPeakLevel <= FIXP_DBL(0)) { 1614 if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) 1615 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1616 } 1617 } 1618 1619 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 1620 } 1621 1622 static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_downmixId( 1623 HANDLE_SEL_PROC_INPUT hSelProcInput, 1624 DRCDEC_SELECTION** ppCandidatesPotential, 1625 DRCDEC_SELECTION** ppCandidatesSelected) { 1626 int i, j; 1627 DRCDEC_SELECTION_DATA* pCandidate = NULL; 1628 DRC_INSTRUCTIONS_UNI_DRC* pInst = NULL; 1629 1630 for (i = 0; i < _drcdec_selection_getNumber(*ppCandidatesPotential); i++) { 1631 pCandidate = _drcdec_selection_getAt(*ppCandidatesPotential, i); 1632 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1633 1634 pInst = pCandidate->pInst; 1635 1636 for (j = 0; j < pInst->downmixIdCount; j++) { 1637 if (DOWNMIX_ID_BASE_LAYOUT != pInst->downmixId[j] && 1638 DOWNMIX_ID_ANY_DOWNMIX != pInst->downmixId[j] && 1639 hSelProcInput 1640 ->downmixIdRequested[pCandidate->downmixIdRequestIndex] == 1641 pInst->downmixId[j]) { 1642 if (_drcdec_selection_add(*ppCandidatesSelected, pCandidate) == NULL) 1643 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1644 } 1645 } 1646 } 1647 1648 if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { 1649 _swapSelection(ppCandidatesPotential, ppCandidatesSelected); 1650 } 1651 1652 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 1653 } 1654 1655 static int _crossSum(int value) { 1656 int sum = 0; 1657 1658 while (value != 0) { 1659 if ((value & 1) == 1) { 1660 sum++; 1661 } 1662 1663 value >>= 1; 1664 } 1665 1666 return sum; 1667 } 1668 1669 static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_effectTypes( 1670 DRCDEC_SELECTION* pCandidatesPotential, 1671 DRCDEC_SELECTION* pCandidatesSelected) { 1672 int i; 1673 int minNumEffects = 1000; 1674 int numEffects = 0; 1675 int effects = 0; 1676 DRCDEC_SELECTION_DATA* pCandidate = NULL; 1677 DRC_INSTRUCTIONS_UNI_DRC* pInst = NULL; 1678 1679 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1680 pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); 1681 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1682 1683 pInst = pCandidate->pInst; 1684 1685 effects = pInst->drcSetEffect; 1686 effects &= 0xffff ^ (EB_GENERAL_COMPR); 1687 numEffects = _crossSum(effects); 1688 1689 if (numEffects < minNumEffects) { 1690 minNumEffects = numEffects; 1691 } 1692 } 1693 1694 /* add all with minimum number of effects */ 1695 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1696 pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); 1697 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1698 1699 pInst = pCandidate->pInst; 1700 1701 effects = pInst->drcSetEffect; 1702 effects &= 0xffff ^ (EB_GENERAL_COMPR); 1703 numEffects = _crossSum(effects); 1704 1705 if (numEffects == minNumEffects) { 1706 if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) 1707 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1708 } 1709 } 1710 1711 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 1712 } 1713 1714 static DRCDEC_SELECTION_PROCESS_RETURN _selectSmallestTargetLoudnessValueUpper( 1715 DRCDEC_SELECTION* pCandidatesPotential, 1716 DRCDEC_SELECTION* pCandidatesSelected) { 1717 int i; 1718 SCHAR minVal = 0x7F; 1719 SCHAR val = 0; 1720 DRCDEC_SELECTION_DATA* pCandidate = NULL; 1721 1722 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1723 pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); 1724 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1725 1726 val = pCandidate->pInst->drcSetTargetLoudnessValueUpper; 1727 1728 if (val < minVal) { 1729 minVal = val; 1730 } 1731 } 1732 1733 /* add all with same smallest drcSetTargetLoudnessValueUpper */ 1734 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1735 pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); 1736 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1737 1738 val = pCandidate->pInst->drcSetTargetLoudnessValueUpper; 1739 1740 if (val == minVal) { 1741 if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) 1742 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1743 } 1744 } 1745 1746 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 1747 } 1748 1749 static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_targetLoudness( 1750 FIXP_DBL targetLoudness, DRCDEC_SELECTION* pCandidatesPotential, 1751 DRCDEC_SELECTION* pCandidatesSelected) { 1752 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 1753 int i; 1754 DRCDEC_SELECTION_DATA* pCandidate = NULL; 1755 1756 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1757 pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); 1758 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1759 1760 if (pCandidate->selectionFlag == 0) { 1761 if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) 1762 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1763 } 1764 } 1765 1766 if (_drcdec_selection_getNumber(pCandidatesSelected) == 0) { 1767 retVal = _selectSmallestTargetLoudnessValueUpper(pCandidatesPotential, 1768 pCandidatesSelected); 1769 if (retVal) return (retVal); 1770 } 1771 1772 if (_drcdec_selection_getNumber(pCandidatesSelected) > 1) { 1773 DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc = NULL; 1774 1775 _swapSelectionAndClear(&pCandidatesPotential, &pCandidatesSelected); 1776 1777 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1778 pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); 1779 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1780 1781 pDrcInstructionUniDrc = pCandidate->pInst; 1782 1783 if (_targetLoudnessInRange(pDrcInstructionUniDrc, targetLoudness)) { 1784 if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) 1785 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1786 } 1787 } 1788 1789 if (_drcdec_selection_getNumber(pCandidatesSelected) > 1) { 1790 _swapSelectionAndClear(&pCandidatesPotential, &pCandidatesSelected); 1791 1792 retVal = _selectSmallestTargetLoudnessValueUpper(pCandidatesPotential, 1793 pCandidatesSelected); 1794 if (retVal) return (retVal); 1795 } 1796 } 1797 1798 return retVal; 1799 } 1800 1801 static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_peakValueLargest( 1802 DRCDEC_SELECTION* pCandidatesPotential, 1803 DRCDEC_SELECTION* pCandidatesSelected) { 1804 int i; 1805 FIXP_DBL largestPeakLevel = MINVAL_DBL; 1806 FIXP_DBL peakLevel = 0; 1807 DRCDEC_SELECTION_DATA* pCandidate = NULL; 1808 1809 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1810 pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); 1811 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1812 1813 peakLevel = pCandidate->outputPeakLevel; 1814 1815 if (peakLevel > largestPeakLevel) { 1816 largestPeakLevel = peakLevel; 1817 } 1818 } 1819 1820 /* add all with same largest peak level */ 1821 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1822 pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); 1823 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1824 1825 peakLevel = pCandidate->outputPeakLevel; 1826 1827 if (peakLevel == largestPeakLevel) { 1828 if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) 1829 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1830 } 1831 } 1832 1833 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 1834 } 1835 1836 static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_drcSetId( 1837 DRCDEC_SELECTION* pCandidatesPotential, 1838 DRCDEC_SELECTION* pCandidatesSelected) { 1839 int i; 1840 int largestId = -1000; 1841 int id = 0; 1842 DRCDEC_SELECTION_DATA* pCandidate = NULL; 1843 DRCDEC_SELECTION_DATA* pCandidateSelected = NULL; 1844 1845 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 1846 pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); 1847 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 1848 1849 id = pCandidate->pInst->drcSetId; 1850 1851 if (id > largestId) { 1852 largestId = id; 1853 pCandidateSelected = pCandidate; 1854 } 1855 } 1856 1857 if (pCandidateSelected != NULL) { 1858 if (_drcdec_selection_add(pCandidatesSelected, pCandidateSelected) == NULL) 1859 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1860 } else { 1861 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1862 } 1863 1864 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 1865 } 1866 1867 static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection( 1868 HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 1869 DRCDEC_SELECTION** ppCandidatesPotential, 1870 DRCDEC_SELECTION** ppCandidatesSelected, SEL_PROC_CODEC_MODE codecMode) { 1871 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 1872 1873 if (_drcdec_selection_getNumber(*ppCandidatesPotential) == 0) { 1874 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1875 } else if (_drcdec_selection_getNumber(*ppCandidatesPotential) == 1) { 1876 _swapSelection(ppCandidatesPotential, ppCandidatesSelected); 1877 /* finished */ 1878 } else /* > 1 */ 1879 { 1880 retVal = _drcSetFinalSelection_peakValue0(*ppCandidatesPotential, 1881 *ppCandidatesSelected); 1882 if (retVal) return (retVal); 1883 1884 if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { 1885 _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); 1886 retVal = _drcSetFinalSelection_downmixId( 1887 hSelProcInput, ppCandidatesPotential, ppCandidatesSelected); 1888 if (retVal) return (retVal); 1889 } 1890 1891 if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { 1892 _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); 1893 retVal = _drcSetFinalSelection_effectTypes(*ppCandidatesPotential, 1894 *ppCandidatesSelected); 1895 if (retVal) return (retVal); 1896 } 1897 1898 if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { 1899 _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); 1900 retVal = _drcSetFinalSelection_targetLoudness( 1901 hSelProcInput->targetLoudness, *ppCandidatesPotential, 1902 *ppCandidatesSelected); 1903 if (retVal) return (retVal); 1904 } 1905 1906 if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { 1907 _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); 1908 retVal = _drcSetFinalSelection_peakValueLargest(*ppCandidatesPotential, 1909 *ppCandidatesSelected); 1910 if (retVal) return (retVal); 1911 } 1912 1913 if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { 1914 _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); 1915 retVal = _drcSetFinalSelection_drcSetId(*ppCandidatesPotential, 1916 *ppCandidatesSelected); 1917 if (retVal) return (retVal); 1918 } 1919 } 1920 1921 if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { 1922 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1923 } 1924 1925 return retVal; 1926 } 1927 1928 static DRCDEC_SELECTION_PROCESS_RETURN _generateVirtualDrcSets( 1929 HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 1930 SEL_PROC_CODEC_MODE codecMode) { 1931 int i; 1932 int nMixes = hUniDrcConfig->downmixInstructionsCount + 1; 1933 int index = hUniDrcConfig->drcInstructionsUniDrcCount; 1934 int indexVirtual = -1; 1935 DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction = 1936 &(hUniDrcConfig->drcInstructionsUniDrc[index]); 1937 1938 if (codecMode == SEL_PROC_MPEG_H_3DA) { 1939 nMixes = 1; 1940 } 1941 1942 if ((index + nMixes) > (12 + 1 + 6)) { 1943 return DRCDEC_SELECTION_PROCESS_NOT_OK; 1944 } 1945 1946 FDKmemset(pDrcInstruction, 0, sizeof(DRC_INSTRUCTIONS_UNI_DRC)); 1947 1948 pDrcInstruction->drcSetId = indexVirtual; 1949 index++; 1950 indexVirtual--; 1951 pDrcInstruction->downmixIdCount = 1; 1952 1953 if ((codecMode == SEL_PROC_MPEG_H_3DA) && 1954 (hSelProcInput->numDownmixIdRequests)) { 1955 pDrcInstruction->downmixId[0] = hSelProcInput->downmixIdRequested[0]; 1956 } else { 1957 pDrcInstruction->downmixId[0] = DOWNMIX_ID_BASE_LAYOUT; 1958 } 1959 1960 for (i = 1; i < nMixes; i++) { 1961 pDrcInstruction = &(hUniDrcConfig->drcInstructionsUniDrc[index]); 1962 FDKmemset(pDrcInstruction, 0, sizeof(DRC_INSTRUCTIONS_UNI_DRC)); 1963 pDrcInstruction->drcSetId = indexVirtual; 1964 pDrcInstruction->downmixId[0] = 1965 hUniDrcConfig->downmixInstructions[i - 1].downmixId; 1966 pDrcInstruction->downmixIdCount = 1; 1967 index++; 1968 indexVirtual--; 1969 } 1970 1971 hUniDrcConfig->drcInstructionsCountInclVirtual = 1972 hUniDrcConfig->drcInstructionsUniDrcCount + nMixes; 1973 1974 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 1975 } 1976 1977 static DRCDEC_SELECTION_PROCESS_RETURN _generateOutputInfo( 1978 HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_SEL_PROC_OUTPUT hSelProcOutput, 1979 HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 1980 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, 1981 DRCDEC_SELECTION_DATA* pSelectionData, SEL_PROC_CODEC_MODE codecMode) { 1982 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 1983 1984 int i, j; 1985 int hasDependend = 0; 1986 int hasFading = 0; 1987 int hasDucking = 0; 1988 int selectedDrcSetIds; 1989 int selectedDownmixIds; 1990 FIXP_DBL mixingLevel = 0; 1991 int albumMode = hSelProcInput->albumMode; 1992 UCHAR* pDownmixIdRequested = hSelProcInput->downmixIdRequested; 1993 FIXP_SGL boost = hSelProcInput->boost; 1994 FIXP_SGL compress = hSelProcInput->compress; 1995 1996 hSelProcOutput->numSelectedDrcSets = 1; 1997 hSelProcOutput->selectedDrcSetIds[0] = pSelectionData->pInst->drcSetId; 1998 hSelProcOutput->selectedDownmixIds[0] = 1999 pSelectionData->pInst->drcApplyToDownmix == 1 2000 ? pSelectionData->pInst->downmixId[0] 2001 : 0; 2002 hSelProcOutput->loudnessNormalizationGainDb = 2003 pSelectionData->loudnessNormalizationGainDbAdjusted + 2004 hSelProcInput->loudnessNormalizationGainModificationDb; 2005 hSelProcOutput->outputPeakLevelDb = pSelectionData->outputPeakLevel; 2006 2007 hSelProcOutput->boost = boost; 2008 hSelProcOutput->compress = compress; 2009 hSelProcOutput->baseChannelCount = 2010 hUniDrcConfig->channelLayout.baseChannelCount; 2011 hSelProcOutput->targetChannelCount = 2012 hUniDrcConfig->channelLayout.baseChannelCount; 2013 hSelProcOutput->activeDownmixId = 2014 pDownmixIdRequested[pSelectionData->downmixIdRequestIndex]; 2015 2016 _getMixingLevel(hLoudnessInfoSet, *pDownmixIdRequested, 2017 hSelProcOutput->selectedDrcSetIds[0], albumMode, 2018 &mixingLevel); 2019 hSelProcOutput->mixingLevel = mixingLevel; 2020 2021 /*dependent*/ 2022 if (pSelectionData->pInst->dependsOnDrcSetPresent) { 2023 int dependsOnDrcSetID = pSelectionData->pInst->dependsOnDrcSet; 2024 2025 for (i = 0; i < hUniDrcConfig->drcInstructionsCountInclVirtual; i++) { 2026 if (hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId == 2027 dependsOnDrcSetID) { 2028 hSelProcOutput->selectedDrcSetIds[hSelProcOutput->numSelectedDrcSets] = 2029 hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId; 2030 hSelProcOutput->selectedDownmixIds[hSelProcOutput->numSelectedDrcSets] = 2031 hUniDrcConfig->drcInstructionsUniDrc[i].drcApplyToDownmix == 1 2032 ? hUniDrcConfig->drcInstructionsUniDrc[i].downmixId[0] 2033 : 0; 2034 hSelProcOutput->numSelectedDrcSets++; 2035 hasDependend = 1; 2036 break; 2037 } 2038 } 2039 } 2040 2041 /* fading */ 2042 if (hSelProcInput->albumMode == 0) { 2043 for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { 2044 DRC_INSTRUCTIONS_UNI_DRC* pInst = 2045 &(hUniDrcConfig->drcInstructionsUniDrc[i]); 2046 2047 if (pInst->drcSetEffect & EB_FADE) { 2048 if (pInst->downmixId[0] == DOWNMIX_ID_ANY_DOWNMIX) { 2049 hSelProcOutput->numSelectedDrcSets = hasDependend + 1; 2050 hSelProcOutput 2051 ->selectedDrcSetIds[hSelProcOutput->numSelectedDrcSets] = 2052 hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId; 2053 hSelProcOutput 2054 ->selectedDownmixIds[hSelProcOutput->numSelectedDrcSets] = 2055 hUniDrcConfig->drcInstructionsUniDrc[i].drcApplyToDownmix == 1 2056 ? hUniDrcConfig->drcInstructionsUniDrc[i].downmixId[0] 2057 : 0; 2058 hSelProcOutput->numSelectedDrcSets++; 2059 hasFading = 1; 2060 2061 } else { 2062 retVal = DRCDEC_SELECTION_PROCESS_NOT_OK; 2063 if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; 2064 } 2065 } 2066 } 2067 } 2068 2069 /* ducking */ 2070 for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { 2071 DRC_INSTRUCTIONS_UNI_DRC* pInst = 2072 &(hUniDrcConfig->drcInstructionsUniDrc[i]); 2073 2074 if (pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { 2075 for (j = 0; j < pInst->downmixIdCount; j++) { 2076 if (pInst->downmixId[j] == hSelProcOutput->activeDownmixId) { 2077 hSelProcOutput->numSelectedDrcSets = 2078 hasDependend + 1; /* ducking overrides fading */ 2079 2080 hSelProcOutput 2081 ->selectedDrcSetIds[hSelProcOutput->numSelectedDrcSets] = 2082 hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId; 2083 /* force ducking DRC set to be processed on base layout */ 2084 hSelProcOutput 2085 ->selectedDownmixIds[hSelProcOutput->numSelectedDrcSets] = 0; 2086 hSelProcOutput->numSelectedDrcSets++; 2087 hasDucking = 1; 2088 } 2089 } 2090 } 2091 } 2092 2093 /* repeat for DOWNMIX_ID_BASE_LAYOUT if no ducking found*/ 2094 2095 if (!hasDucking) { 2096 for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { 2097 DRC_INSTRUCTIONS_UNI_DRC* pInst = 2098 &(hUniDrcConfig->drcInstructionsUniDrc[i]); 2099 2100 if (pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { 2101 for (j = 0; j < pInst->downmixIdCount; j++) { 2102 if (pInst->downmixId[j] == DOWNMIX_ID_BASE_LAYOUT) { 2103 hSelProcOutput->numSelectedDrcSets = hasDependend + hasFading + 1; 2104 hSelProcOutput 2105 ->selectedDrcSetIds[hSelProcOutput->numSelectedDrcSets] = 2106 hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId; 2107 /* force ducking DRC set to be processed on base layout */ 2108 hSelProcOutput 2109 ->selectedDownmixIds[hSelProcOutput->numSelectedDrcSets] = 0; 2110 hSelProcOutput->numSelectedDrcSets++; 2111 } 2112 } 2113 } 2114 } 2115 } 2116 2117 if (hSelProcOutput->numSelectedDrcSets > 3) { 2118 /* maximum permitted number of applied DRC sets is 3, see section 6.3.5 of 2119 * ISO/IEC 23003-4 */ 2120 hSelProcOutput->numSelectedDrcSets = 0; 2121 return DRCDEC_SELECTION_PROCESS_NOT_OK; 2122 } 2123 2124 /* sorting: Ducking/Fading -> Dependent -> Selected */ 2125 if (hSelProcOutput->numSelectedDrcSets == 3) { 2126 selectedDrcSetIds = hSelProcOutput->selectedDrcSetIds[0]; 2127 selectedDownmixIds = hSelProcOutput->selectedDownmixIds[0]; 2128 hSelProcOutput->selectedDrcSetIds[0] = hSelProcOutput->selectedDrcSetIds[2]; 2129 hSelProcOutput->selectedDownmixIds[0] = 2130 hSelProcOutput->selectedDownmixIds[2]; 2131 hSelProcOutput->selectedDrcSetIds[2] = selectedDrcSetIds; 2132 hSelProcOutput->selectedDownmixIds[2] = selectedDownmixIds; 2133 } else if (hSelProcOutput->numSelectedDrcSets == 2) { 2134 selectedDrcSetIds = hSelProcOutput->selectedDrcSetIds[0]; 2135 selectedDownmixIds = hSelProcOutput->selectedDownmixIds[0]; 2136 hSelProcOutput->selectedDrcSetIds[0] = hSelProcOutput->selectedDrcSetIds[1]; 2137 hSelProcOutput->selectedDownmixIds[0] = 2138 hSelProcOutput->selectedDownmixIds[1]; 2139 hSelProcOutput->selectedDrcSetIds[1] = selectedDrcSetIds; 2140 hSelProcOutput->selectedDownmixIds[1] = selectedDownmixIds; 2141 } 2142 2143 return retVal; 2144 } 2145 2146 static DRCDEC_SELECTION_PROCESS_RETURN _selectDownmixMatrix( 2147 HANDLE_SEL_PROC_OUTPUT hSelProcOutput, 2148 HANDLE_UNI_DRC_CONFIG hUniDrcConfig) { 2149 int i; 2150 hSelProcOutput->baseChannelCount = 2151 hUniDrcConfig->channelLayout.baseChannelCount; 2152 hSelProcOutput->targetChannelCount = 2153 hUniDrcConfig->channelLayout.baseChannelCount; 2154 hSelProcOutput->targetLayout = -1; 2155 hSelProcOutput->downmixMatrixPresent = 0; 2156 2157 if (hSelProcOutput->activeDownmixId != 0) { 2158 for (i = 0; i < hUniDrcConfig->downmixInstructionsCount; i++) { 2159 DOWNMIX_INSTRUCTIONS* pDown = &(hUniDrcConfig->downmixInstructions[i]); 2160 2161 if (hSelProcOutput->activeDownmixId == pDown->downmixId) { 2162 hSelProcOutput->targetChannelCount = pDown->targetChannelCount; 2163 hSelProcOutput->targetLayout = pDown->targetLayout; 2164 2165 if (pDown->downmixCoefficientsPresent) { 2166 int j, k; 2167 FIXP_DBL downmixOffset = getDownmixOffset( 2168 pDown, hSelProcOutput->baseChannelCount); /* e = 1 */ 2169 2170 for (j = 0; j < hSelProcOutput->baseChannelCount; j++) { 2171 for (k = 0; k < hSelProcOutput->targetChannelCount; k++) { 2172 hSelProcOutput->downmixMatrix[j][k] = 2173 fMultDiv2( 2174 downmixOffset, 2175 pDown->downmixCoefficient[j + k * hSelProcOutput 2176 ->baseChannelCount]) 2177 << 2; 2178 } 2179 } 2180 2181 hSelProcOutput->downmixMatrixPresent = 1; 2182 } 2183 break; 2184 } 2185 } 2186 } 2187 2188 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 2189 } 2190 2191 static DRCDEC_SELECTION_PROCESS_RETURN _drcSetPreSelection( 2192 SEL_PROC_INPUT* hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 2193 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, 2194 DRCDEC_SELECTION** ppCandidatesPotential, 2195 DRCDEC_SELECTION** ppCandidatesSelected, SEL_PROC_CODEC_MODE codecMode) { 2196 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 2197 int i, j; 2198 2199 for (i = 0; i < hSelProcInput->numDownmixIdRequests; i++) { 2200 for (j = 0; j < hUniDrcConfig->drcInstructionsCountInclVirtual; j++) { 2201 DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction = 2202 &(hUniDrcConfig->drcInstructionsUniDrc[j]); 2203 retVal = _drcSetPreSelectionSingleInstruction( 2204 hSelProcInput, i, hUniDrcConfig, hLoudnessInfoSet, pDrcInstruction, 2205 *ppCandidatesPotential, *ppCandidatesSelected, codecMode); 2206 if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; 2207 } 2208 } 2209 2210 retVal = _preSelectionRequirement9(hSelProcInput, *ppCandidatesPotential, 2211 *ppCandidatesSelected); 2212 if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; 2213 2214 if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { 2215 retVal = _drcSetSelectionAddCandidates( 2216 hSelProcInput, *ppCandidatesPotential, *ppCandidatesSelected); 2217 if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; 2218 } 2219 2220 return retVal; 2221 } 2222 2223 static DRCDEC_SELECTION_PROCESS_RETURN _drcSetRequestSelection( 2224 SEL_PROC_INPUT* hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 2225 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, 2226 DRCDEC_SELECTION** ppCandidatesPotential, 2227 DRCDEC_SELECTION** ppCandidatesSelected) { 2228 DRCDEC_SELECTION_PROCESS_RETURN retVal; 2229 int i; 2230 2231 if (_drcdec_selection_getNumber(*ppCandidatesPotential) == 0) { 2232 retVal = DRCDEC_SELECTION_PROCESS_NOT_OK; 2233 if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; 2234 } 2235 2236 if (hSelProcInput->dynamicRangeControlOn) { 2237 if (hSelProcInput->numDrcFeatureRequests == 0) { 2238 retVal = _selectDrcSetEffectNone(hUniDrcConfig, *ppCandidatesPotential, 2239 *ppCandidatesSelected); 2240 if (retVal) return (retVal); 2241 2242 if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { 2243 DRC_FEATURE_REQUEST fallbackRequest; 2244 fallbackRequest.drcEffectType.numRequests = 5; 2245 fallbackRequest.drcEffectType.numRequestsDesired = 5; 2246 fallbackRequest.drcEffectType.request[0] = DETR_GENERAL_COMPR; 2247 fallbackRequest.drcEffectType.request[1] = DETR_NIGHT; 2248 fallbackRequest.drcEffectType.request[2] = DETR_NOISY; 2249 fallbackRequest.drcEffectType.request[3] = DETR_LIMITED; 2250 fallbackRequest.drcEffectType.request[4] = DETR_LOWLEVEL; 2251 2252 retVal = _selectEffectTypeFeature(hUniDrcConfig, fallbackRequest, 2253 ppCandidatesPotential, 2254 ppCandidatesSelected); 2255 if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; 2256 } 2257 2258 _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); 2259 } else { 2260 for (i = 0; i < hSelProcInput->numDrcFeatureRequests; i++) { 2261 if (hSelProcInput->drcFeatureRequestType[i] == DFRT_EFFECT_TYPE) { 2262 retVal = _selectEffectTypeFeature( 2263 hUniDrcConfig, hSelProcInput->drcFeatureRequest[i], 2264 ppCandidatesPotential, ppCandidatesSelected); 2265 2266 _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); 2267 if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; 2268 } 2269 2270 else if (hSelProcInput->drcFeatureRequestType[i] == 2271 DFRT_DYNAMIC_RANGE) { 2272 retVal = _selectDynamicRange( 2273 hUniDrcConfig, hLoudnessInfoSet, 2274 hSelProcInput->drcFeatureRequest[i], 2275 hSelProcInput->downmixIdRequested, hSelProcInput->albumMode, 2276 *ppCandidatesPotential, *ppCandidatesSelected); 2277 2278 if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 0) { 2279 _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); 2280 } 2281 if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; 2282 } else if (hSelProcInput->drcFeatureRequestType[i] == 2283 DFRT_DRC_CHARACTERISTIC) { 2284 retVal = _selectDrcCharacteristic( 2285 hUniDrcConfig, 2286 hSelProcInput->drcFeatureRequest[i].drcCharacteristic, 2287 ppCandidatesPotential, ppCandidatesSelected); 2288 2289 if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 0) { 2290 _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); 2291 } 2292 if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; 2293 } 2294 } 2295 } 2296 } 2297 2298 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 2299 } 2300 2301 /*******************************************/ 2302 static DRCDEC_SELECTION_PROCESS_RETURN _dynamicRangeMeasurement( 2303 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, DRC_INSTRUCTIONS_UNI_DRC* pInst, 2304 UCHAR downmixIdRequested, 2305 DYN_RANGE_MEASUREMENT_REQUEST_TYPE dynamicRangeMeasurementType, 2306 int albumMode, int* pPeakToAveragePresent, FIXP_DBL* pPeakToAverage) { 2307 int i; 2308 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 2309 int drcSetId = fMax(0, pInst->drcSetId); 2310 2311 *pPeakToAveragePresent = 0; 2312 2313 if (albumMode) { 2314 for (i = 0; i < hLoudnessInfoSet->loudnessInfoAlbumCount; i++) { 2315 LOUDNESS_INFO* pLoudnessInfo = &(hLoudnessInfoSet->loudnessInfoAlbum[i]); 2316 2317 if (drcSetId == pLoudnessInfo->drcSetId) { 2318 if (downmixIdRequested == pLoudnessInfo->downmixId) { 2319 retVal = _extractLoudnessPeakToAverageValue( 2320 pLoudnessInfo, dynamicRangeMeasurementType, pPeakToAveragePresent, 2321 pPeakToAverage); 2322 if (retVal) return (retVal); 2323 } 2324 } 2325 } 2326 } 2327 2328 if (*pPeakToAveragePresent == 0) { 2329 for (i = 0; i < hLoudnessInfoSet->loudnessInfoCount; i++) { 2330 LOUDNESS_INFO* pLoudnessInfo = &(hLoudnessInfoSet->loudnessInfo[i]); 2331 2332 if (drcSetId == pLoudnessInfo->drcSetId) { 2333 if (downmixIdRequested == pLoudnessInfo->downmixId) { 2334 retVal = _extractLoudnessPeakToAverageValue( 2335 pLoudnessInfo, dynamicRangeMeasurementType, pPeakToAveragePresent, 2336 pPeakToAverage); 2337 if (retVal) return (retVal); 2338 } 2339 } 2340 } 2341 } 2342 2343 return retVal; 2344 } 2345 /*******************************************/ 2346 2347 static DRCDEC_SELECTION_DATA* _drcdec_selection_addNew( 2348 DRCDEC_SELECTION* pSelection) { 2349 if (pSelection->numData < (12 + 1 + 6)) { 2350 DRCDEC_SELECTION_DATA* pData = &(pSelection->data[pSelection->numData]); 2351 FDKmemset(pData, 0, sizeof(DRCDEC_SELECTION_DATA)); 2352 pSelection->numData++; 2353 2354 return pData; 2355 } else { 2356 return NULL; 2357 } 2358 } 2359 2360 static DRCDEC_SELECTION_DATA* _drcdec_selection_add( 2361 DRCDEC_SELECTION* pSelection, DRCDEC_SELECTION_DATA* pDataIn) { 2362 if (pSelection->numData < (12 + 1 + 6)) { 2363 DRCDEC_SELECTION_DATA* pData = &(pSelection->data[pSelection->numData]); 2364 FDKmemcpy(pData, pDataIn, sizeof(DRCDEC_SELECTION_DATA)); 2365 pSelection->numData++; 2366 return pData; 2367 } else { 2368 return NULL; 2369 } 2370 } 2371 2372 static int _drcdec_selection_clear(DRCDEC_SELECTION* pSelection) { 2373 return pSelection->numData = 0; 2374 } 2375 2376 static int _drcdec_selection_getNumber(DRCDEC_SELECTION* pSelection) { 2377 return pSelection->numData; 2378 } 2379 2380 static int _drcdec_selection_setNumber(DRCDEC_SELECTION* pSelection, int num) { 2381 if (num >= 0 && num < pSelection->numData) { 2382 return pSelection->numData = num; 2383 } else { 2384 return pSelection->numData; 2385 } 2386 } 2387 2388 static DRCDEC_SELECTION_DATA* _drcdec_selection_getAt( 2389 DRCDEC_SELECTION* pSelection, int at) { 2390 if (at >= 0 && at < (12 + 1 + 6)) { 2391 return &(pSelection->data[at]); 2392 } else { 2393 return NULL; 2394 } 2395 } 2396 2397 static int _swapSelectionAndClear(DRCDEC_SELECTION** ppCandidatesPotential, 2398 DRCDEC_SELECTION** ppCandidatesSelected) { 2399 DRCDEC_SELECTION* pTmp = *ppCandidatesPotential; 2400 *ppCandidatesPotential = *ppCandidatesSelected; 2401 *ppCandidatesSelected = pTmp; 2402 _drcdec_selection_clear(*ppCandidatesSelected); 2403 return 0; 2404 } 2405 2406 static int _swapSelection(DRCDEC_SELECTION** ppCandidatesPotential, 2407 DRCDEC_SELECTION** ppCandidatesSelected) { 2408 DRCDEC_SELECTION* pTmp = *ppCandidatesPotential; 2409 *ppCandidatesPotential = *ppCandidatesSelected; 2410 *ppCandidatesSelected = pTmp; 2411 return 0; 2412 } 2413 2414 /*******************************************/ 2415 2416 static LOUDNESS_INFO* _getLoudnessInfoStructure( 2417 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int drcSetId, int downmixId, 2418 int albumMode) { 2419 int i, j; 2420 int count; 2421 2422 LOUDNESS_INFO* pLoudnessInfo = NULL; 2423 2424 if (albumMode) { 2425 count = hLoudnessInfoSet->loudnessInfoAlbumCount; 2426 pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; 2427 } else { 2428 count = hLoudnessInfoSet->loudnessInfoCount; 2429 pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; 2430 } 2431 2432 for (i = 0; i < count; i++) { 2433 if ((pLoudnessInfo[i].drcSetId == drcSetId) && 2434 (pLoudnessInfo[i].downmixId == downmixId)) { 2435 for (j = 0; j < pLoudnessInfo[i].measurementCount; j++) { 2436 if ((pLoudnessInfo[i].loudnessMeasurement[j].methodDefinition == 1) || 2437 (pLoudnessInfo[i].loudnessMeasurement[j].methodDefinition == 2)) { 2438 return &pLoudnessInfo[i]; 2439 } 2440 } 2441 } 2442 } 2443 2444 return NULL; 2445 } 2446 2447 static LOUDNESS_INFO* _getApplicableLoudnessInfoStructure( 2448 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int drcSetId, 2449 int downmixIdRequested, int albumMode) { 2450 LOUDNESS_INFO* pLoudnessInfo = NULL; 2451 2452 /* default value */ 2453 pLoudnessInfo = _getLoudnessInfoStructure(hLoudnessInfoSet, drcSetId, 2454 downmixIdRequested, albumMode); 2455 2456 /* fallback values */ 2457 if (pLoudnessInfo == NULL) { 2458 pLoudnessInfo = 2459 _getLoudnessInfoStructure(hLoudnessInfoSet, drcSetId, 0x7F, albumMode); 2460 } 2461 2462 if (pLoudnessInfo == NULL) { 2463 pLoudnessInfo = _getLoudnessInfoStructure(hLoudnessInfoSet, 0x3F, 2464 downmixIdRequested, albumMode); 2465 } 2466 2467 if (pLoudnessInfo == NULL) { 2468 pLoudnessInfo = _getLoudnessInfoStructure(hLoudnessInfoSet, 0, 2469 downmixIdRequested, albumMode); 2470 } 2471 2472 if (pLoudnessInfo == NULL) { 2473 pLoudnessInfo = 2474 _getLoudnessInfoStructure(hLoudnessInfoSet, 0x3F, 0x7F, albumMode); 2475 } 2476 2477 if (pLoudnessInfo == NULL) { 2478 pLoudnessInfo = 2479 _getLoudnessInfoStructure(hLoudnessInfoSet, 0, 0x7F, albumMode); 2480 } 2481 2482 if (pLoudnessInfo == NULL) { 2483 pLoudnessInfo = 2484 _getLoudnessInfoStructure(hLoudnessInfoSet, drcSetId, 0, albumMode); 2485 } 2486 2487 if (pLoudnessInfo == NULL) { 2488 pLoudnessInfo = 2489 _getLoudnessInfoStructure(hLoudnessInfoSet, 0x3F, 0, albumMode); 2490 } 2491 2492 if (pLoudnessInfo == NULL) { 2493 pLoudnessInfo = 2494 _getLoudnessInfoStructure(hLoudnessInfoSet, 0, 0, albumMode); 2495 } 2496 2497 return pLoudnessInfo; 2498 } 2499 2500 /*******************************************/ 2501 2502 typedef struct { 2503 FIXP_DBL value; 2504 int order; 2505 } VALUE_ORDER; 2506 2507 void _initValueOrder(VALUE_ORDER* pValue) { 2508 pValue->value = (FIXP_DBL)0; 2509 pValue->order = -1; 2510 } 2511 2512 enum { 2513 MS_BONUS0 = 0, 2514 MS_BONUS1770, 2515 MS_BONUSUSER, 2516 MS_BONUSEXPERT, 2517 MS_RESA, 2518 MS_RESB, 2519 MS_RESC, 2520 MS_RESD, 2521 MS_RESE, 2522 MS_PROGRAMLOUDNESS, 2523 MS_PEAKLOUDNESS 2524 }; 2525 2526 static DRCDEC_SELECTION_PROCESS_RETURN _getMethodValue( 2527 VALUE_ORDER* pValueOrder, FIXP_DBL value, int measurementSystem, 2528 int measurementSystemRequested) { 2529 const int rows = 11; 2530 const int columns = 12; 2531 const int pOrdering[rows][columns] = { 2532 {0, 0, 8, 0, 1, 3, 0, 5, 6, 7, 4, 2}, /* default = bonus1770 */ 2533 {0, 0, 8, 0, 1, 3, 0, 5, 6, 7, 4, 2}, /* bonus1770 */ 2534 {0, 0, 1, 0, 8, 5, 0, 2, 3, 4, 6, 7}, /* bonusUser */ 2535 {0, 0, 3, 0, 1, 8, 0, 4, 5, 6, 7, 2}, /* bonusExpert */ 2536 {0, 0, 5, 0, 1, 3, 0, 8, 6, 7, 4, 2}, /* ResA */ 2537 {0, 0, 5, 0, 1, 3, 0, 6, 8, 7, 4, 2}, /* ResB */ 2538 {0, 0, 5, 0, 1, 3, 0, 6, 7, 8, 4, 2}, /* ResC */ 2539 {0, 0, 3, 0, 1, 7, 0, 4, 5, 6, 8, 2}, /* ResD */ 2540 {0, 0, 1, 0, 7, 5, 0, 2, 3, 4, 6, 8}, /* ResE */ 2541 {0, 0, 1, 0, 0, 0, 0, 2, 3, 4, 0, 0}, /* ProgramLoudness */ 2542 {0, 7, 0, 0, 0, 0, 6, 5, 4, 3, 2, 1} /* PeakLoudness */ 2543 }; 2544 2545 if (measurementSystemRequested < 0 || measurementSystemRequested >= rows || 2546 measurementSystem < 0 || measurementSystem >= columns) { 2547 return DRCDEC_SELECTION_PROCESS_NOT_OK; 2548 } 2549 2550 if (pOrdering[measurementSystemRequested][measurementSystem] > 2551 pValueOrder->order) { 2552 pValueOrder->order = 2553 pOrdering[measurementSystemRequested][measurementSystem]; 2554 pValueOrder->value = value; 2555 } 2556 2557 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 2558 } 2559 2560 /*******************************************/ 2561 2562 static DRCDEC_SELECTION_PROCESS_RETURN _getLoudness( 2563 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int albumMode, 2564 METHOD_DEFINITION_REQUEST measurementMethodRequested, 2565 MEASUREMENT_SYSTEM_REQUEST measurementSystemRequested, 2566 FIXP_DBL targetLoudness, /* e = 7 */ 2567 int drcSetId, int downmixIdRequested, 2568 FIXP_DBL* pLoudnessNormalizationGain, /* e = 7 */ 2569 FIXP_DBL* pLoudness) /* e = 7 */ 2570 { 2571 int index; 2572 2573 LOUDNESS_INFO* pLoudnessInfo = NULL; 2574 VALUE_ORDER valueOrder; 2575 2576 /* map MDR_DEFAULT to MDR_PROGRAM_LOUDNESS */ 2577 METHOD_DEFINITION_REQUEST requestedMethodDefinition = 2578 measurementMethodRequested < MDR_ANCHOR_LOUDNESS ? MDR_PROGRAM_LOUDNESS 2579 : MDR_ANCHOR_LOUDNESS; 2580 2581 if (measurementMethodRequested > MDR_ANCHOR_LOUDNESS) { 2582 return DRCDEC_SELECTION_PROCESS_NOT_OK; 2583 } 2584 2585 _initValueOrder(&valueOrder); 2586 2587 *pLoudness = UNDEFINED_LOUDNESS_VALUE; 2588 *pLoudnessNormalizationGain = (FIXP_DBL)0; 2589 2590 if (drcSetId < 0) { 2591 drcSetId = 0; 2592 } 2593 2594 pLoudnessInfo = _getApplicableLoudnessInfoStructure( 2595 hLoudnessInfoSet, drcSetId, downmixIdRequested, albumMode); 2596 2597 if (albumMode && (pLoudnessInfo == NULL)) { 2598 pLoudnessInfo = _getApplicableLoudnessInfoStructure( 2599 hLoudnessInfoSet, drcSetId, downmixIdRequested, 0); 2600 } 2601 2602 if (pLoudnessInfo == NULL) { 2603 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 2604 } 2605 2606 index = -1; 2607 2608 do { 2609 index = _findMethodDefinition(pLoudnessInfo, requestedMethodDefinition, 2610 index + 1); 2611 2612 if (index >= 0) { 2613 _getMethodValue( 2614 &valueOrder, pLoudnessInfo->loudnessMeasurement[index].methodValue, 2615 pLoudnessInfo->loudnessMeasurement[index].measurementSystem, 2616 measurementSystemRequested); 2617 } 2618 } while (index >= 0); 2619 2620 /* repeat with other method definition */ 2621 if (valueOrder.order == -1) { 2622 index = -1; 2623 2624 do { 2625 index = _findMethodDefinition( 2626 pLoudnessInfo, 2627 requestedMethodDefinition == MDR_PROGRAM_LOUDNESS 2628 ? MDR_ANCHOR_LOUDNESS 2629 : MDR_PROGRAM_LOUDNESS, 2630 index + 1); 2631 2632 if (index >= 0) { 2633 _getMethodValue( 2634 &valueOrder, pLoudnessInfo->loudnessMeasurement[index].methodValue, 2635 pLoudnessInfo->loudnessMeasurement[index].measurementSystem, 2636 measurementSystemRequested); 2637 } 2638 } while (index >= 0); 2639 } 2640 2641 if (valueOrder.order == -1) { 2642 return DRCDEC_SELECTION_PROCESS_NOT_OK; 2643 } else { 2644 *pLoudnessNormalizationGain = targetLoudness - valueOrder.value; 2645 *pLoudness = valueOrder.value; 2646 } 2647 2648 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 2649 } 2650 2651 /*******************************************/ 2652 2653 static int _truePeakLevelIsPresent(HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, 2654 int drcSetId, int downmixId, int albumMode) { 2655 int i; 2656 int count; 2657 LOUDNESS_INFO* pLoudnessInfo = NULL; 2658 2659 if (albumMode) { 2660 count = hLoudnessInfoSet->loudnessInfoAlbumCount; 2661 pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; 2662 } else { 2663 count = hLoudnessInfoSet->loudnessInfoCount; 2664 pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; 2665 } 2666 2667 for (i = 0; i < count; i++) { 2668 if ((pLoudnessInfo[i].drcSetId == drcSetId) && 2669 (pLoudnessInfo[i].downmixId == downmixId)) { 2670 if (pLoudnessInfo[i].truePeakLevelPresent) return 1; 2671 } 2672 } 2673 2674 return 0; 2675 } 2676 2677 static DRCDEC_SELECTION_PROCESS_RETURN _getTruePeakLevel( 2678 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int drcSetId, int downmixId, 2679 int albumMode, FIXP_DBL* pTruePeakLevel) { 2680 int i; 2681 int count; 2682 LOUDNESS_INFO* pLoudnessInfo = NULL; 2683 2684 if (albumMode) { 2685 count = hLoudnessInfoSet->loudnessInfoAlbumCount; 2686 pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; 2687 } else { 2688 count = hLoudnessInfoSet->loudnessInfoCount; 2689 pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; 2690 } 2691 2692 for (i = 0; i < count; i++) { 2693 if ((pLoudnessInfo[i].drcSetId == drcSetId) && 2694 (pLoudnessInfo[i].downmixId == downmixId)) { 2695 if (pLoudnessInfo[i].truePeakLevelPresent) { 2696 *pTruePeakLevel = pLoudnessInfo[i].truePeakLevel; 2697 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 2698 } 2699 } 2700 } 2701 2702 return DRCDEC_SELECTION_PROCESS_NOT_OK; 2703 } 2704 2705 static int _samplePeakLevelIsPresent(HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, 2706 int drcSetId, int downmixId, 2707 int albumMode) { 2708 int i; 2709 int count; 2710 LOUDNESS_INFO* pLoudnessInfo = NULL; 2711 2712 if (albumMode) { 2713 count = hLoudnessInfoSet->loudnessInfoAlbumCount; 2714 pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; 2715 } else { 2716 count = hLoudnessInfoSet->loudnessInfoCount; 2717 pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; 2718 } 2719 2720 for (i = 0; i < count; i++) { 2721 if ((pLoudnessInfo[i].drcSetId == drcSetId) && 2722 (pLoudnessInfo[i].downmixId == downmixId)) { 2723 if (pLoudnessInfo[i].samplePeakLevelPresent) return 1; 2724 } 2725 } 2726 2727 return 0; 2728 } 2729 2730 static DRCDEC_SELECTION_PROCESS_RETURN _getSamplePeakLevel( 2731 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int drcSetId, int downmixId, 2732 int albumMode, FIXP_DBL* pSamplePeakLevel /* e = 7 */ 2733 ) { 2734 int i; 2735 int count; 2736 LOUDNESS_INFO* pLoudnessInfo = NULL; 2737 2738 if (albumMode) { 2739 count = hLoudnessInfoSet->loudnessInfoAlbumCount; 2740 pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; 2741 } else { 2742 count = hLoudnessInfoSet->loudnessInfoCount; 2743 pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; 2744 } 2745 2746 for (i = 0; i < count; i++) { 2747 if ((pLoudnessInfo[i].drcSetId == drcSetId) && 2748 (pLoudnessInfo[i].downmixId == downmixId)) { 2749 if (pLoudnessInfo[i].samplePeakLevelPresent) { 2750 *pSamplePeakLevel = pLoudnessInfo[i].samplePeakLevel; 2751 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 2752 } 2753 } 2754 } 2755 2756 return DRCDEC_SELECTION_PROCESS_NOT_OK; 2757 } 2758 2759 static int _limiterPeakTargetIsPresent( 2760 DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction, int drcSetId, int downmixId) { 2761 int i; 2762 2763 if (pDrcInstruction->limiterPeakTargetPresent) { 2764 if ((pDrcInstruction->downmixId[0] == downmixId) || 2765 (pDrcInstruction->downmixId[0] == 0x7F)) { 2766 return 1; 2767 } 2768 2769 for (i = 0; i < pDrcInstruction->downmixIdCount; i++) { 2770 if (pDrcInstruction->downmixId[i] == downmixId) { 2771 return 1; 2772 } 2773 } 2774 } 2775 2776 return 0; 2777 } 2778 2779 static DRCDEC_SELECTION_PROCESS_RETURN _getLimiterPeakTarget( 2780 DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction, int drcSetId, int downmixId, 2781 FIXP_DBL* pLimiterPeakTarget) { 2782 int i; 2783 2784 if (pDrcInstruction->limiterPeakTargetPresent) { 2785 if ((pDrcInstruction->downmixId[0] == downmixId) || 2786 (pDrcInstruction->downmixId[0] == 0x7F)) { 2787 *pLimiterPeakTarget = 2788 ((FX_SGL2FX_DBL(pDrcInstruction->limiterPeakTarget) >> 2)); 2789 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 2790 } 2791 2792 for (i = 0; i < pDrcInstruction->downmixIdCount; i++) { 2793 if (pDrcInstruction->downmixId[i] == downmixId) { 2794 *pLimiterPeakTarget = 2795 ((FX_SGL2FX_DBL(pDrcInstruction->limiterPeakTarget) >> 2)); 2796 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 2797 } 2798 } 2799 } 2800 2801 return DRCDEC_SELECTION_PROCESS_NOT_OK; 2802 } 2803 2804 static int _downmixCoefficientsArePresent(HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 2805 int downmixId, int* pIndex) { 2806 int i; 2807 *pIndex = -1; 2808 2809 for (i = 0; i < hUniDrcConfig->downmixInstructionsCount; i++) { 2810 if (hUniDrcConfig->downmixInstructions[i].downmixId == downmixId) { 2811 if (hUniDrcConfig->downmixInstructions[i].downmixCoefficientsPresent) { 2812 *pIndex = i; 2813 return 1; 2814 } 2815 } 2816 } 2817 2818 return 0; 2819 } 2820 2821 static DRCDEC_SELECTION_PROCESS_RETURN _getSignalPeakLevel( 2822 HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, 2823 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, DRC_INSTRUCTIONS_UNI_DRC* pInst, 2824 int downmixIdRequested, int* explicitPeakInformationPresent, 2825 FIXP_DBL* signalPeakLevelOut, /* e = 7 */ 2826 SEL_PROC_CODEC_MODE codecMode 2827 2828 ) { 2829 DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; 2830 2831 int albumMode = hSelProcInput->albumMode; 2832 2833 FIXP_DBL signalPeakLevelTmp = (FIXP_DBL)0; 2834 FIXP_DBL signalPeakLevel = FIXP_DBL(0); 2835 2836 int dmxId = downmixIdRequested; 2837 2838 int drcSetId = pInst->drcSetId; 2839 2840 if (drcSetId < 0) { 2841 drcSetId = 0; 2842 } 2843 2844 *explicitPeakInformationPresent = 1; 2845 2846 if (_truePeakLevelIsPresent(hLoudnessInfoSet, drcSetId, dmxId, albumMode)) { 2847 retVal = _getTruePeakLevel(hLoudnessInfoSet, drcSetId, dmxId, albumMode, 2848 &signalPeakLevel); 2849 if (retVal) return (retVal); 2850 } else if (_samplePeakLevelIsPresent(hLoudnessInfoSet, drcSetId, dmxId, 2851 albumMode)) { 2852 retVal = _getSamplePeakLevel(hLoudnessInfoSet, drcSetId, dmxId, albumMode, 2853 &signalPeakLevel); 2854 if (retVal) return (retVal); 2855 } else if (_truePeakLevelIsPresent(hLoudnessInfoSet, 0x3F, dmxId, 2856 albumMode)) { 2857 retVal = _getTruePeakLevel(hLoudnessInfoSet, 0x3F, dmxId, albumMode, 2858 &signalPeakLevel); 2859 if (retVal) return (retVal); 2860 } else if (_samplePeakLevelIsPresent(hLoudnessInfoSet, 0x3F, dmxId, 2861 albumMode)) { 2862 retVal = _getSamplePeakLevel(hLoudnessInfoSet, 0x3F, dmxId, albumMode, 2863 &signalPeakLevel); 2864 if (retVal) return (retVal); 2865 } else if (_limiterPeakTargetIsPresent(pInst, drcSetId, dmxId)) { 2866 retVal = _getLimiterPeakTarget(pInst, drcSetId, dmxId, &signalPeakLevel); 2867 if (retVal) return (retVal); 2868 } else if (dmxId != 0) { 2869 int downmixInstructionIndex = 0; 2870 FIXP_DBL downmixPeakLevelDB = 0; 2871 2872 *explicitPeakInformationPresent = 0; 2873 2874 signalPeakLevelTmp = FIXP_DBL(0); 2875 2876 if (_downmixCoefficientsArePresent(hUniDrcConfig, dmxId, 2877 &downmixInstructionIndex)) { 2878 FIXP_DBL dB_m; 2879 int dB_e; 2880 FIXP_DBL coeff; 2881 FIXP_DBL sum, maxSum; /* e = 7, so it is possible to sum up up to 32 2882 downmix coefficients (with e = 2) */ 2883 int i, j; 2884 DOWNMIX_INSTRUCTIONS* pDown = 2885 &(hUniDrcConfig->downmixInstructions[downmixInstructionIndex]); 2886 FIXP_DBL downmixOffset = getDownmixOffset( 2887 pDown, hUniDrcConfig->channelLayout.baseChannelCount); /* e = 1 */ 2888 maxSum = (FIXP_DBL)0; 2889 2890 for (i = 0; i < pDown->targetChannelCount; i++) { 2891 sum = (FIXP_DBL)0; 2892 for (j = 0; j < hUniDrcConfig->channelLayout.baseChannelCount; j++) { 2893 coeff = pDown->downmixCoefficient[j + i * hUniDrcConfig->channelLayout 2894 .baseChannelCount]; 2895 sum += coeff >> 5; 2896 } 2897 if (maxSum < sum) maxSum = sum; 2898 } 2899 2900 maxSum = fMultDiv2(maxSum, downmixOffset) << 2; 2901 2902 if (maxSum == FL2FXCONST_DBL(1.0f / (float)(1 << 7))) { 2903 downmixPeakLevelDB = (FIXP_DBL)0; 2904 } else { 2905 dB_m = lin2dB(maxSum, 7, &dB_e); /* e_maxSum = 7 */ 2906 downmixPeakLevelDB = 2907 scaleValue(dB_m, dB_e - 7); /* e_downmixPeakLevelDB = 7 */ 2908 } 2909 } 2910 2911 if (_truePeakLevelIsPresent(hLoudnessInfoSet, drcSetId, 0, albumMode)) { 2912 retVal = _getTruePeakLevel(hLoudnessInfoSet, drcSetId, 0, albumMode, 2913 &signalPeakLevelTmp); 2914 if (retVal) return (retVal); 2915 } else if (_samplePeakLevelIsPresent(hLoudnessInfoSet, drcSetId, 0, 2916 albumMode)) { 2917 retVal = _getSamplePeakLevel(hLoudnessInfoSet, drcSetId, 0, albumMode, 2918 &signalPeakLevelTmp); 2919 if (retVal) return (retVal); 2920 } else if (_truePeakLevelIsPresent(hLoudnessInfoSet, 0x3F, 0, albumMode)) { 2921 retVal = _getTruePeakLevel(hLoudnessInfoSet, 0x3F, 0, albumMode, 2922 &signalPeakLevelTmp); 2923 if (retVal) return (retVal); 2924 } else if (_samplePeakLevelIsPresent(hLoudnessInfoSet, 0x3F, 0, 2925 albumMode)) { 2926 retVal = _getSamplePeakLevel(hLoudnessInfoSet, 0x3F, 0, albumMode, 2927 &signalPeakLevelTmp); 2928 if (retVal) return (retVal); 2929 } else if (_limiterPeakTargetIsPresent(pInst, drcSetId, 0)) { 2930 retVal = _getLimiterPeakTarget(pInst, drcSetId, 0, &signalPeakLevelTmp); 2931 if (retVal) return (retVal); 2932 } 2933 2934 signalPeakLevel = signalPeakLevelTmp + downmixPeakLevelDB; 2935 } else { 2936 signalPeakLevel = FIXP_DBL(0); /* worst case estimate */ 2937 *explicitPeakInformationPresent = FIXP_DBL(0); 2938 } 2939 2940 *signalPeakLevelOut = signalPeakLevel; 2941 2942 return retVal; 2943 } 2944 2945 static DRCDEC_SELECTION_PROCESS_RETURN _extractLoudnessPeakToAverageValue( 2946 LOUDNESS_INFO* loudnessInfo, 2947 DYN_RANGE_MEASUREMENT_REQUEST_TYPE dynamicRangeMeasurementType, 2948 int* pLoudnessPeakToAverageValuePresent, 2949 FIXP_DBL* pLoudnessPeakToAverageValue) { 2950 int i; 2951 2952 VALUE_ORDER valueOrderLoudness; 2953 VALUE_ORDER valueOrderPeakLoudness; 2954 2955 _initValueOrder(&valueOrderLoudness); 2956 _initValueOrder(&valueOrderPeakLoudness); 2957 2958 LOUDNESS_MEASUREMENT* pLoudnessMeasure = NULL; 2959 2960 *pLoudnessPeakToAverageValuePresent = 0; 2961 2962 for (i = 0; i < loudnessInfo->measurementCount; i++) { 2963 pLoudnessMeasure = &(loudnessInfo->loudnessMeasurement[i]); 2964 2965 if (pLoudnessMeasure->methodDefinition == MD_PROGRAM_LOUDNESS) { 2966 _getMethodValue(&valueOrderLoudness, pLoudnessMeasure->methodValue, 2967 pLoudnessMeasure->measurementSystem, MS_PROGRAMLOUDNESS); 2968 } 2969 2970 if ((dynamicRangeMeasurementType == DRMRT_SHORT_TERM_LOUDNESS_TO_AVG) && 2971 (pLoudnessMeasure->methodDefinition == MD_SHORT_TERM_LOUDNESS_MAX)) { 2972 _getMethodValue(&valueOrderPeakLoudness, pLoudnessMeasure->methodValue, 2973 pLoudnessMeasure->measurementSystem, MS_PEAKLOUDNESS); 2974 } 2975 2976 if ((dynamicRangeMeasurementType == DRMRT_MOMENTARY_LOUDNESS_TO_AVG) && 2977 (pLoudnessMeasure->methodDefinition == MD_MOMENTARY_LOUDNESS_MAX)) { 2978 _getMethodValue(&valueOrderPeakLoudness, pLoudnessMeasure->methodValue, 2979 pLoudnessMeasure->measurementSystem, MS_PEAKLOUDNESS); 2980 } 2981 2982 if ((dynamicRangeMeasurementType == DRMRT_TOP_OF_LOUDNESS_RANGE_TO_AVG) && 2983 (pLoudnessMeasure->methodDefinition == MD_MAX_OF_LOUDNESS_RANGE)) { 2984 _getMethodValue(&valueOrderPeakLoudness, pLoudnessMeasure->methodValue, 2985 pLoudnessMeasure->measurementSystem, MS_PEAKLOUDNESS); 2986 } 2987 } 2988 2989 if ((valueOrderLoudness.order > -1) && (valueOrderPeakLoudness.order > -1)) { 2990 *pLoudnessPeakToAverageValue = 2991 valueOrderPeakLoudness.value - valueOrderLoudness.value; 2992 *pLoudnessPeakToAverageValuePresent = 1; 2993 } 2994 2995 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 2996 } 2997 2998 /*******************************************/ 2999 3000 static DRCDEC_SELECTION_PROCESS_RETURN _selectAlbumLoudness( 3001 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, 3002 DRCDEC_SELECTION* pCandidatesPotential, 3003 DRCDEC_SELECTION* pCandidatesSelected) { 3004 int i, j; 3005 3006 for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { 3007 DRCDEC_SELECTION_DATA* pCandidate = 3008 _drcdec_selection_getAt(pCandidatesPotential, i); 3009 if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; 3010 3011 for (j = 0; j < hLoudnessInfoSet->loudnessInfoAlbumCount; j++) { 3012 if (pCandidate->pInst->drcSetId == 3013 hLoudnessInfoSet->loudnessInfoAlbum[j].drcSetId) { 3014 if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) 3015 return DRCDEC_SELECTION_PROCESS_NOT_OK; 3016 } 3017 } 3018 } 3019 3020 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 3021 } 3022 3023 /*******************************************/ 3024 3025 static int _findMethodDefinition(LOUDNESS_INFO* pLoudnessInfo, 3026 int methodDefinition, int startIndex) { 3027 int i; 3028 int index = -1; 3029 3030 for (i = startIndex; i < pLoudnessInfo->measurementCount; i++) { 3031 if (pLoudnessInfo->loudnessMeasurement[i].methodDefinition == 3032 methodDefinition) { 3033 index = i; 3034 break; 3035 } 3036 } 3037 3038 return index; 3039 } 3040 3041 /*******************************************/ 3042 3043 static DRCDEC_SELECTION_PROCESS_RETURN _getMixingLevel( 3044 HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int downmixIdRequested, 3045 int drcSetIdRequested, int albumMode, FIXP_DBL* pMixingLevel) { 3046 const FIXP_DBL mixingLevelDefault = FL2FXCONST_DBL(85.0f / (float)(1 << 7)); 3047 3048 int i; 3049 int count; 3050 3051 LOUDNESS_INFO* pLoudnessInfo = NULL; 3052 3053 *pMixingLevel = mixingLevelDefault; 3054 3055 if (drcSetIdRequested < 0) { 3056 drcSetIdRequested = 0; 3057 } 3058 3059 if (albumMode) { 3060 count = hLoudnessInfoSet->loudnessInfoAlbumCount; 3061 pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; 3062 } else { 3063 count = hLoudnessInfoSet->loudnessInfoCount; 3064 pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; 3065 } 3066 3067 for (i = 0; i < count; i++) { 3068 if ((drcSetIdRequested == pLoudnessInfo[i].drcSetId) && 3069 ((downmixIdRequested == pLoudnessInfo[i].downmixId) || 3070 (DOWNMIX_ID_ANY_DOWNMIX == pLoudnessInfo[i].downmixId))) { 3071 int index = _findMethodDefinition(&pLoudnessInfo[i], MD_MIXING_LEVEL, 0); 3072 3073 if (index >= 0) { 3074 *pMixingLevel = pLoudnessInfo[i].loudnessMeasurement[index].methodValue; 3075 break; 3076 } 3077 } 3078 } 3079 3080 return DRCDEC_SELECTION_PROCESS_NO_ERROR; 3081 } 3082 3083 /*******************************************/ 3084