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