Coverage Report

Created: 2026-10-28 06:57

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