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