/src/aac/libDRCdec/src/drcDec_selectionProcess.cpp
Line | Count | Source (jump to first uncovered line) |
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 | 230k | static int _isError(int x) { |
254 | 230k | if (x < DRCDEC_SELECTION_PROCESS_WARNING) { |
255 | 5.36k | return 1; |
256 | 5.36k | } |
257 | | |
258 | 225k | return 0; |
259 | 230k | } |
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 | 101k | static inline int _compAssign(SCHAR* dest, const SCHAR src) { |
270 | 101k | int diff = 0; |
271 | 101k | if (*dest != src) diff = 1; |
272 | 101k | *dest = src; |
273 | 101k | return diff; |
274 | 101k | } |
275 | | |
276 | 111k | static inline int _compAssign(FIXP_DBL* dest, const FIXP_DBL src) { |
277 | 111k | int diff = 0; |
278 | 111k | if (*dest != src) diff = 1; |
279 | 111k | *dest = src; |
280 | 111k | return diff; |
281 | 111k | } |
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 | 27.3k | drcDec_SelectionProcess_Create(HANDLE_DRC_SELECTION_PROCESS* phInstance) { |
437 | 27.3k | HANDLE_DRC_SELECTION_PROCESS hInstance; |
438 | 27.3k | hInstance = (HANDLE_DRC_SELECTION_PROCESS)FDKcalloc( |
439 | 27.3k | 1, sizeof(struct s_drcdec_selection_process)); |
440 | | |
441 | 27.3k | if (!hInstance) return DRCDEC_SELECTION_PROCESS_OUTOFMEMORY; |
442 | | |
443 | 27.3k | hInstance->codecMode = SEL_PROC_CODEC_MODE_UNDEFINED; |
444 | | |
445 | 27.3k | *phInstance = hInstance; |
446 | 27.3k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
447 | 27.3k | } |
448 | | |
449 | | DRCDEC_SELECTION_PROCESS_RETURN |
450 | 27.3k | drcDec_SelectionProcess_Init(HANDLE_DRC_SELECTION_PROCESS hInstance) { |
451 | 27.3k | if (!hInstance) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
452 | | |
453 | 27.3k | _initDefaultParams(&hInstance->selProcInput); |
454 | 27.3k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
455 | 27.3k | } |
456 | | |
457 | | DRCDEC_SELECTION_PROCESS_RETURN |
458 | | drcDec_SelectionProcess_SetCodecMode(HANDLE_DRC_SELECTION_PROCESS hInstance, |
459 | 16.5k | const SEL_PROC_CODEC_MODE codecMode) { |
460 | 16.5k | DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
461 | | |
462 | 16.5k | if (!hInstance) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
463 | | |
464 | 16.5k | switch (codecMode) { |
465 | 0 | case SEL_PROC_MPEG_4_AAC: |
466 | 16.5k | case SEL_PROC_MPEG_D_USAC: |
467 | 16.5k | case SEL_PROC_TEST_TIME_DOMAIN: |
468 | 16.5k | case SEL_PROC_TEST_QMF_DOMAIN: |
469 | 16.5k | case SEL_PROC_TEST_STFT_DOMAIN: |
470 | 16.5k | hInstance->codecMode = codecMode; |
471 | 16.5k | break; |
472 | | |
473 | 0 | case SEL_PROC_CODEC_MODE_UNDEFINED: |
474 | 0 | default: |
475 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
476 | 16.5k | } |
477 | | |
478 | 16.5k | retVal = _initCodecModeParams(&(hInstance->selProcInput), |
479 | 16.5k | hInstance->codecMode = codecMode); |
480 | | |
481 | 16.5k | return retVal; |
482 | 16.5k | } |
483 | | |
484 | | DRCDEC_SELECTION_PROCESS_RETURN |
485 | | drcDec_SelectionProcess_SetParam(HANDLE_DRC_SELECTION_PROCESS hInstance, |
486 | | const SEL_PROC_USER_PARAM requestType, |
487 | 212k | FIXP_DBL requestValue, int* pDiff) { |
488 | 212k | INT requestValueInt = (INT)requestValue; |
489 | 212k | int i, diff = 0; |
490 | 212k | SEL_PROC_INPUT* pSelProcInput = &(hInstance->selProcInput); |
491 | | |
492 | 212k | 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 | 9.86k | case SEL_PROC_TARGET_LOUDNESS: |
500 | | /* Lower boundary: drcSetTargetLoudnessValueLower default value. |
501 | | Upper boundary: drcSetTargetLoudnessValueUpper default value */ |
502 | 9.86k | if ((requestValue < FL2FXCONST_DBL(-63.0f / (float)(1 << 7))) || |
503 | 9.86k | (requestValue > (FIXP_DBL)0)) |
504 | 0 | return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; |
505 | 9.86k | if (requestValue > |
506 | 9.86k | FL2FXCONST_DBL(-10.0f / |
507 | 9.86k | (float)(1 << 7))) /* recommended maximum value */ |
508 | 0 | requestValue = FL2FXCONST_DBL(-10.0f / (float)(1 << 7)); |
509 | 9.86k | diff |= _compAssign(&pSelProcInput->targetLoudness, requestValue); |
510 | 9.86k | 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 | 101k | case SEL_PROC_BASE_CHANNEL_COUNT: |
591 | 101k | if (requestValueInt < 0) |
592 | 0 | return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; |
593 | 101k | diff |= _compAssign(&pSelProcInput->baseChannelCount, requestValueInt); |
594 | 101k | break; |
595 | 101k | case SEL_PROC_SAMPLE_RATE: |
596 | 101k | if (requestValueInt < 0) |
597 | 0 | return DRCDEC_SELECTION_PROCESS_PARAM_OUT_OF_RANGE; |
598 | 101k | diff |= _compAssign(&pSelProcInput->audioSampleRate, requestValueInt); |
599 | 101k | 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 | 212k | } |
623 | | |
624 | 212k | if (pDiff != NULL) { |
625 | 212k | *pDiff |= diff; |
626 | 212k | } |
627 | | |
628 | 212k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
629 | 212k | } |
630 | | |
631 | | FIXP_DBL |
632 | | drcDec_SelectionProcess_GetParam(HANDLE_DRC_SELECTION_PROCESS hInstance, |
633 | 1.73M | const SEL_PROC_USER_PARAM requestType) { |
634 | 1.73M | SEL_PROC_INPUT* pSelProcInput = &(hInstance->selProcInput); |
635 | | |
636 | 1.73M | switch (requestType) { |
637 | 869k | case SEL_PROC_LOUDNESS_NORMALIZATION_ON: |
638 | 869k | return (FIXP_DBL)pSelProcInput->loudnessNormalizationOn; |
639 | 869k | case SEL_PROC_DYNAMIC_RANGE_CONTROL_ON: |
640 | 869k | return (FIXP_DBL)pSelProcInput->dynamicRangeControlOn; |
641 | 0 | default: |
642 | 0 | return (FIXP_DBL)0; |
643 | 1.73M | } |
644 | 1.73M | } |
645 | | |
646 | | DRCDEC_SELECTION_PROCESS_RETURN |
647 | 27.3k | drcDec_SelectionProcess_Delete(HANDLE_DRC_SELECTION_PROCESS* phInstance) { |
648 | 27.3k | if (phInstance == NULL || *phInstance == NULL) |
649 | 0 | return DRCDEC_SELECTION_PROCESS_INVALID_HANDLE; |
650 | | |
651 | 27.3k | FDKfree(*phInstance); |
652 | 27.3k | *phInstance = NULL; |
653 | 27.3k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
654 | 27.3k | } |
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 | 213k | HANDLE_SEL_PROC_OUTPUT hSelProcOutput) { |
661 | 213k | DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
662 | 213k | DRCDEC_SELECTION* pCandidatesSelected; |
663 | 213k | DRCDEC_SELECTION* pCandidatesPotential; |
664 | | |
665 | 213k | if (hInstance == NULL) return DRCDEC_SELECTION_PROCESS_INVALID_HANDLE; |
666 | | |
667 | 213k | pCandidatesSelected = &(hInstance->selectionData[0]); |
668 | 213k | pCandidatesPotential = &(hInstance->selectionData[1]); |
669 | 213k | _drcdec_selection_setNumber(pCandidatesSelected, 0); |
670 | 213k | _drcdec_selection_setNumber(pCandidatesPotential, 0); |
671 | | |
672 | 213k | retVal = _generateVirtualDrcSets(&(hInstance->selProcInput), hUniDrcConfig, |
673 | 213k | hInstance->codecMode); |
674 | 213k | if (retVal) return (retVal); |
675 | | |
676 | 213k | if (hInstance->selProcInput.baseChannelCount != |
677 | 213k | hUniDrcConfig->channelLayout.baseChannelCount) { |
678 | 117k | hInstance->selProcInput.baseChannelCount = |
679 | 117k | hUniDrcConfig->channelLayout.baseChannelCount; |
680 | 117k | } |
681 | | |
682 | 213k | if ((hInstance->selProcInput.targetConfigRequestType != 0) || |
683 | 213k | (hInstance->selProcInput.targetConfigRequestType == 0 && |
684 | 213k | hInstance->selProcInput.numDownmixIdRequests == 0)) { |
685 | 23.1k | retVal = _channelLayoutToDownmixIdMapping(&(hInstance->selProcInput), |
686 | 23.1k | hUniDrcConfig); |
687 | | |
688 | 23.1k | if (_isError(retVal)) return (retVal); |
689 | 23.1k | } |
690 | | |
691 | 213k | retVal = _drcSetPreSelection(&(hInstance->selProcInput), hUniDrcConfig, |
692 | 213k | hLoudnessInfoSet, &pCandidatesPotential, |
693 | 213k | &pCandidatesSelected, hInstance->codecMode); |
694 | 213k | if (retVal) return (retVal); |
695 | | |
696 | 213k | 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 | 213k | _swapSelectionAndClear(&pCandidatesPotential, &pCandidatesSelected); |
709 | | |
710 | 213k | retVal = _drcSetRequestSelection(&(hInstance->selProcInput), hUniDrcConfig, |
711 | 213k | hLoudnessInfoSet, &pCandidatesPotential, |
712 | 213k | &pCandidatesSelected); |
713 | 213k | if (retVal) return (retVal); |
714 | | |
715 | 211k | retVal = _drcSetFinalSelection(&(hInstance->selProcInput), hUniDrcConfig, |
716 | 211k | &pCandidatesPotential, &pCandidatesSelected, |
717 | 211k | hInstance->codecMode); |
718 | 211k | if (retVal) return (retVal); |
719 | | |
720 | 207k | retVal = _generateOutputInfo( |
721 | 207k | &(hInstance->selProcInput), hSelProcOutput, hUniDrcConfig, |
722 | 207k | hLoudnessInfoSet, &(pCandidatesSelected->data[0]), hInstance->codecMode); |
723 | | |
724 | 207k | if (_isError(retVal)) return (retVal); |
725 | | |
726 | 201k | retVal = _selectDownmixMatrix(hSelProcOutput, hUniDrcConfig); |
727 | 201k | if (retVal) return (retVal); |
728 | | |
729 | 201k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
730 | 201k | } |
731 | | |
732 | | /*******************************************/ |
733 | | /* static functions */ |
734 | | /*******************************************/ |
735 | | |
736 | | static DRCDEC_SELECTION_PROCESS_RETURN _initDefaultParams( |
737 | 27.3k | HANDLE_SEL_PROC_INPUT hSelProcInput) { |
738 | 27.3k | DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
739 | | |
740 | 27.3k | if (hSelProcInput == NULL) return DRCDEC_SELECTION_PROCESS_INVALID_HANDLE; |
741 | | |
742 | | /* system parameters */ |
743 | 27.3k | hSelProcInput->baseChannelCount = -1; |
744 | 27.3k | hSelProcInput->baseLayout = -1; |
745 | 27.3k | hSelProcInput->targetConfigRequestType = TCRT_DOWNMIX_ID; |
746 | 27.3k | hSelProcInput->numDownmixIdRequests = 0; |
747 | | |
748 | | /* loudness normalization parameters */ |
749 | 27.3k | hSelProcInput->albumMode = 0; |
750 | 27.3k | hSelProcInput->peakLimiterPresent = 0; |
751 | 27.3k | hSelProcInput->loudnessNormalizationOn = 1; |
752 | 27.3k | hSelProcInput->targetLoudness = FL2FXCONST_DBL(-24.0f / (float)(1 << 7)); |
753 | 27.3k | hSelProcInput->loudnessDeviationMax = DEFAULT_LOUDNESS_DEVIATION_MAX; |
754 | 27.3k | hSelProcInput->loudnessMeasurementMethod = MDR_ANCHOR_LOUDNESS; |
755 | 27.3k | hSelProcInput->loudnessMeasurementSystem = MSR_EXPERT_PANEL; |
756 | 27.3k | hSelProcInput->loudnessMeasurementPreProc = LPR_DEFAULT; |
757 | 27.3k | hSelProcInput->deviceCutOffFrequency = 500; |
758 | 27.3k | hSelProcInput->loudnessNormalizationGainDbMax = |
759 | 27.3k | (FIXP_DBL)MAXVAL_DBL; /* infinity as default */ |
760 | 27.3k | hSelProcInput->loudnessNormalizationGainModificationDb = (FIXP_DBL)0; |
761 | 27.3k | hSelProcInput->outputPeakLevelMax = (FIXP_DBL)0; |
762 | 27.3k | if (hSelProcInput->peakLimiterPresent == 1) { |
763 | 0 | hSelProcInput->outputPeakLevelMax = FL2FXCONST_DBL(6.0f / (float)(1 << 7)); |
764 | 0 | } |
765 | | |
766 | | /* dynamic range control parameters */ |
767 | 27.3k | hSelProcInput->dynamicRangeControlOn = 1; |
768 | | |
769 | 27.3k | hSelProcInput->numDrcFeatureRequests = 0; |
770 | | |
771 | | /* other parameters */ |
772 | 27.3k | hSelProcInput->boost = FL2FXCONST_SGL(1.f / (float)(1 << 1)); |
773 | 27.3k | hSelProcInput->compress = FL2FXCONST_SGL(1.f / (float)(1 << 1)); |
774 | 27.3k | hSelProcInput->drcCharacteristicTarget = 0; |
775 | | |
776 | 27.3k | return retVal; |
777 | 27.3k | } |
778 | | |
779 | | static DRCDEC_SELECTION_PROCESS_RETURN _initCodecModeParams( |
780 | 16.5k | HANDLE_SEL_PROC_INPUT hSelProcInput, const SEL_PROC_CODEC_MODE codecMode) { |
781 | 16.5k | DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
782 | | |
783 | 16.5k | if (hSelProcInput == NULL) return DRCDEC_SELECTION_PROCESS_INVALID_HANDLE; |
784 | | |
785 | 16.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 | 16.5k | case SEL_PROC_MPEG_D_USAC: |
796 | 16.5k | hSelProcInput->loudnessDeviationMax = DEFAULT_LOUDNESS_DEVIATION_MAX; |
797 | 16.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 | 16.5k | hSelProcInput->outputPeakLevelMax = |
802 | 16.5k | FL2FXCONST_DBL(6.0f / (float)(1 << 7)); |
803 | 16.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 | 16.5k | } |
816 | | |
817 | 16.5k | return retVal; |
818 | 16.5k | } |
819 | | |
820 | | static DRCDEC_SELECTION_PROCESS_RETURN _channelLayoutToDownmixIdMapping( |
821 | 23.1k | HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig) { |
822 | 23.1k | DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
823 | | |
824 | 23.1k | DOWNMIX_INSTRUCTIONS* pDown = NULL; |
825 | | |
826 | 23.1k | int i; |
827 | | |
828 | 23.1k | hSelProcInput->numDownmixIdRequests = 0; |
829 | | |
830 | 23.1k | switch (hSelProcInput->targetConfigRequestType) { |
831 | 23.1k | case TCRT_DOWNMIX_ID: |
832 | 23.1k | if (hSelProcInput->numDownmixIdRequests == 0) { |
833 | 23.1k | hSelProcInput->downmixIdRequested[0] = 0; |
834 | 23.1k | hSelProcInput->numDownmixIdRequests = 1; |
835 | 23.1k | } |
836 | | |
837 | 23.1k | 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 | 23.1k | } |
906 | | |
907 | 23.1k | return retVal; |
908 | 23.1k | } |
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 | 322k | int* pMatchFound) { |
921 | 322k | int i; |
922 | 322k | *pMatchFound = 0; |
923 | | |
924 | 398k | for (i = 0; i < pDrcInstructionUniDrc->downmixIdCount; i++) { |
925 | 366k | if ((pDrcInstructionUniDrc->downmixId[i] == nRequestedDownmixId) || |
926 | 366k | (pDrcInstructionUniDrc->downmixId[i] == DOWNMIX_ID_ANY_DOWNMIX) || |
927 | 366k | ((pDrcInstructionUniDrc->downmixId[i] == DOWNMIX_ID_BASE_LAYOUT) && |
928 | 290k | (pDrcInstructionUniDrc->drcSetId > 0))) { |
929 | 290k | *pMatchFound = 1; |
930 | 290k | break; |
931 | 290k | } |
932 | 366k | } |
933 | | |
934 | 322k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
935 | 322k | } |
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 | 290k | int* pMatchFound) { |
941 | 290k | *pMatchFound = 0; |
942 | | |
943 | 290k | if (nDynamicRangeControlOn == 1) { |
944 | 290k | if ((pDrcInstruction->drcSetEffect != EB_FADE) && |
945 | 290k | (pDrcInstruction->drcSetEffect != EB_DUCK_OTHER) && |
946 | 290k | (pDrcInstruction->drcSetEffect != EB_DUCK_SELF) && |
947 | 290k | (pDrcInstruction->drcSetEffect != 0 || pDrcInstruction->drcSetId < 0)) { |
948 | 280k | *pMatchFound = 1; |
949 | 280k | } |
950 | 290k | } else { |
951 | 0 | *pMatchFound = 1; |
952 | 0 | } |
953 | | |
954 | 290k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
955 | 290k | } |
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 | 466k | DRC_COEFFICIENTS_UNI_DRC* pCoef, int* pMatchFound) { |
962 | 466k | int b, i; |
963 | | |
964 | 466k | *pMatchFound = 1; |
965 | | |
966 | 466k | if (pDrcInstructionUniDrc->drcSetId < 0) /* virtual DRC sets are okay */ |
967 | 221k | { |
968 | 221k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
969 | 221k | } |
970 | | |
971 | 245k | if (pCoef == NULL) /* check for parametricDRC */ |
972 | 10.8k | { |
973 | 10.8k | *pMatchFound = 0; /* parametricDRC not supported */ |
974 | 10.8k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
975 | 10.8k | } |
976 | | |
977 | 234k | if (pCoef->drcLocation != |
978 | 234k | pDrcInstructionUniDrc |
979 | 234k | ->drcLocation) /* drcLocation must be LOCATION_SELECTED */ |
980 | 118k | { |
981 | 118k | *pMatchFound = 0; |
982 | 118k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
983 | 118k | } |
984 | | |
985 | 170k | for (i = 0; i < pDrcInstructionUniDrc->nDrcChannelGroups; i++) { |
986 | 63.3k | int indexDrcCoeff = pDrcInstructionUniDrc->gainSetIndexForChannelGroup[i]; |
987 | 63.3k | int bandCount = 0; |
988 | | |
989 | 63.3k | if (indexDrcCoeff >= 12) { |
990 | 7.80k | *pMatchFound = 0; |
991 | 7.80k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
992 | 7.80k | } |
993 | | |
994 | 55.5k | if (indexDrcCoeff > pCoef->gainSetCount - 1) /* check for parametricDRC */ |
995 | 42.7k | { |
996 | 42.7k | continue; |
997 | 42.7k | } |
998 | | |
999 | 12.7k | GAIN_SET* gainSet = &(pCoef->gainSet[indexDrcCoeff]); |
1000 | 12.7k | bandCount = gainSet->bandCount; |
1001 | | |
1002 | 12.7k | if (bandCount > 4) { |
1003 | 0 | *pMatchFound = 0; |
1004 | 0 | } |
1005 | | |
1006 | 44.4k | for (b = 0; b < bandCount; b++) { |
1007 | 32.7k | if ((gainSet->gainSequenceIndex[b] >= 12) || |
1008 | 32.7k | (gainSet->gainSequenceIndex[b] >= pCoef->gainSequenceCount)) { |
1009 | 1.05k | *pMatchFound = 0; |
1010 | 1.05k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1011 | 1.05k | } |
1012 | 32.7k | } |
1013 | 12.7k | } |
1014 | | |
1015 | 107k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1016 | 116k | } |
1017 | | |
1018 | | /* #6: Independent use of DRC set is permitted.*/ |
1019 | | static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement6( |
1020 | 255k | DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, int* pMatchFound) { |
1021 | 255k | *pMatchFound = 0; |
1022 | | |
1023 | 255k | if (((pDrcInstructionUniDrc->dependsOnDrcSetPresent == 0) && |
1024 | 255k | (pDrcInstructionUniDrc->noIndependentUse == 0)) || |
1025 | 255k | (pDrcInstructionUniDrc->dependsOnDrcSetPresent == 1)) { |
1026 | 254k | *pMatchFound = 1; |
1027 | 254k | } |
1028 | | |
1029 | 255k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1030 | 255k | } |
1031 | | |
1032 | | /* #7: DRC sets that require EQ are only permitted if EQ is supported. */ |
1033 | | static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement7( |
1034 | 254k | DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, int* pMatchFound) { |
1035 | 254k | *pMatchFound = 1; |
1036 | | |
1037 | 254k | if (pDrcInstructionUniDrc->requiresEq) { |
1038 | | /* EQ is not supported */ |
1039 | 0 | *pMatchFound = 0; |
1040 | 0 | } |
1041 | | |
1042 | 254k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1043 | 254k | } |
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 | 250k | int applyAdjustment) { |
1053 | 250k | FIXP_DBL adjustment = 0; /* e = 8 */ |
1054 | | |
1055 | | /* use e = 8 for all function parameters to prevent overflow */ |
1056 | 250k | loudness >>= 1; |
1057 | 250k | loudnessNormalizationGainDb >>= 1; |
1058 | 250k | loudnessNormalizationGainDbMax >>= 1; |
1059 | 250k | loudnessDeviationMax >>= 1; |
1060 | 250k | signalPeakLevel >>= 1; |
1061 | 250k | outputPeakLevelMax >>= 1; |
1062 | | |
1063 | 250k | 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 | 250k | pData->loudnessNormalizationGainDbAdjusted = fMin( |
1071 | 250k | loudnessNormalizationGainDb - adjustment, loudnessNormalizationGainDbMax); |
1072 | 250k | pData->outputLoudness = loudness + pData->loudnessNormalizationGainDbAdjusted; |
1073 | 250k | pData->outputPeakLevel = |
1074 | 250k | signalPeakLevel + pData->loudnessNormalizationGainDbAdjusted; |
1075 | | |
1076 | | /* shift back to e = 7 using saturation */ |
1077 | 250k | pData->loudnessNormalizationGainDbAdjusted = SATURATE_LEFT_SHIFT( |
1078 | 250k | pData->loudnessNormalizationGainDbAdjusted, 1, DFRACT_BITS); |
1079 | 250k | pData->outputLoudness = |
1080 | 250k | SATURATE_LEFT_SHIFT(pData->outputLoudness, 1, DFRACT_BITS); |
1081 | 250k | pData->outputPeakLevel = |
1082 | 250k | SATURATE_LEFT_SHIFT(pData->outputPeakLevel, 1, DFRACT_BITS); |
1083 | 250k | } |
1084 | | |
1085 | | static int _targetLoudnessInRange( |
1086 | 62.5k | DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc, FIXP_DBL targetLoudness) { |
1087 | 62.5k | int retVal = 0; |
1088 | | |
1089 | 62.5k | FIXP_DBL drcSetTargetLoudnessValueUpper = |
1090 | 62.5k | ((FIXP_DBL)pDrcInstructionUniDrc->drcSetTargetLoudnessValueUpper) |
1091 | 62.5k | << (DFRACT_BITS - 1 - 7); |
1092 | 62.5k | FIXP_DBL drcSetTargetLoudnessValueLower = |
1093 | 62.5k | ((FIXP_DBL)pDrcInstructionUniDrc->drcSetTargetLoudnessValueLower) |
1094 | 62.5k | << (DFRACT_BITS - 1 - 7); |
1095 | | |
1096 | 62.5k | if (pDrcInstructionUniDrc->drcSetTargetLoudnessPresent && |
1097 | 62.5k | drcSetTargetLoudnessValueUpper >= targetLoudness && |
1098 | 62.5k | drcSetTargetLoudnessValueLower < targetLoudness) { |
1099 | 11.8k | retVal = 1; |
1100 | 11.8k | } |
1101 | | |
1102 | 62.5k | return retVal; |
1103 | 62.5k | } |
1104 | | |
1105 | | static int _drcSetIsUsable(HANDLE_UNI_DRC_CONFIG hUniDrcConfig, |
1106 | 212k | DRC_INSTRUCTIONS_UNI_DRC* pInst) { |
1107 | 212k | int usable = 0; |
1108 | 212k | DRC_COEFFICIENTS_UNI_DRC* pCoef = |
1109 | 212k | selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED); |
1110 | | |
1111 | | /* check if ID is unique */ |
1112 | 212k | if (selectDrcInstructions(hUniDrcConfig, pInst->drcSetId) != pInst) return 0; |
1113 | | /* sanity check on drcInstructions */ |
1114 | 185k | _preSelectionRequirement5(pInst, pCoef, &usable); |
1115 | 185k | return usable; |
1116 | 212k | } |
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 | 254k | DRCDEC_SELECTION* pCandidatesSelected, SEL_PROC_CODEC_MODE codecMode) { |
1127 | 254k | DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1128 | 254k | int explicitPeakInformationPresent; |
1129 | 254k | FIXP_DBL signalPeakLevel; |
1130 | 254k | int addToCandidate = 0; |
1131 | | |
1132 | 254k | FIXP_DBL loudnessNormalizationGainDb; |
1133 | 254k | FIXP_DBL loudness; |
1134 | | |
1135 | 254k | FIXP_DBL loudnessDeviationMax = |
1136 | 254k | ((FIXP_DBL)hSelProcInput->loudnessDeviationMax) << (DFRACT_BITS - 1 - 7); |
1137 | | |
1138 | 254k | { |
1139 | 254k | retVal = _getLoudness(hLoudnessInfoSet, hSelProcInput->albumMode, |
1140 | 254k | hSelProcInput->loudnessMeasurementMethod, |
1141 | 254k | hSelProcInput->loudnessMeasurementSystem, |
1142 | 254k | hSelProcInput->targetLoudness, |
1143 | 254k | pDrcInstructionUniDrc->drcSetId, |
1144 | 254k | hSelProcInput->downmixIdRequested[downmixIdIndex], |
1145 | 254k | &loudnessNormalizationGainDb, &loudness); |
1146 | 254k | if (retVal) return (retVal); |
1147 | 254k | } |
1148 | | |
1149 | 254k | if (!hSelProcInput->loudnessNormalizationOn) { |
1150 | 0 | loudnessNormalizationGainDb = (FIXP_DBL)0; |
1151 | 0 | } |
1152 | | |
1153 | 254k | retVal = _getSignalPeakLevel( |
1154 | 254k | hSelProcInput, hUniDrcConfig, hLoudnessInfoSet, pDrcInstructionUniDrc, |
1155 | 254k | hSelProcInput->downmixIdRequested[downmixIdIndex], |
1156 | 254k | &explicitPeakInformationPresent, &signalPeakLevel, codecMode |
1157 | | |
1158 | 254k | ); |
1159 | 254k | if (retVal) return (retVal); |
1160 | | |
1161 | 254k | if (hSelProcInput->dynamicRangeControlOn) { |
1162 | 254k | if (explicitPeakInformationPresent == 0) { |
1163 | 210k | if (pDrcInstructionUniDrc->drcSetTargetLoudnessPresent && |
1164 | 210k | ((hSelProcInput->loudnessNormalizationOn && |
1165 | 8.36k | _targetLoudnessInRange(pDrcInstructionUniDrc, |
1166 | 8.36k | hSelProcInput->targetLoudness)) || |
1167 | 8.36k | !hSelProcInput->loudnessNormalizationOn)) { |
1168 | 4.46k | DRCDEC_SELECTION_DATA* pData = |
1169 | 4.46k | _drcdec_selection_addNew(pCandidatesSelected); |
1170 | 4.46k | if (pData == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1171 | | |
1172 | 4.46k | _setSelectionDataInfo(pData, loudness, loudnessNormalizationGainDb, |
1173 | 4.46k | hSelProcInput->loudnessNormalizationGainDbMax, |
1174 | 4.46k | loudnessDeviationMax, signalPeakLevel, |
1175 | 4.46k | hSelProcInput->outputPeakLevelMax, 0); |
1176 | 4.46k | pData->downmixIdRequestIndex = downmixIdIndex; |
1177 | 4.46k | pData->pInst = pDrcInstructionUniDrc; |
1178 | 4.46k | pData->selectionFlag = |
1179 | 4.46k | 1; /* signal pre-selection step dealing with drcSetTargetLoudness */ |
1180 | | |
1181 | 4.46k | if (hSelProcInput->loudnessNormalizationOn) { |
1182 | 4.46k | pData->outputPeakLevel = |
1183 | 4.46k | hSelProcInput->targetLoudness - |
1184 | 4.46k | (((FIXP_DBL)pData->pInst->drcSetTargetLoudnessValueUpper) |
1185 | 4.46k | << (DFRACT_BITS - 1 - 7)); |
1186 | 4.46k | } else { |
1187 | 0 | pData->outputPeakLevel = (FIXP_DBL)0; |
1188 | 0 | } |
1189 | 206k | } else { |
1190 | 206k | if ((!hSelProcInput->loudnessNormalizationOn) || |
1191 | 206k | (!pDrcInstructionUniDrc->drcSetTargetLoudnessPresent) || |
1192 | 206k | (hSelProcInput->loudnessNormalizationOn && |
1193 | 3.89k | _targetLoudnessInRange(pDrcInstructionUniDrc, |
1194 | 202k | hSelProcInput->targetLoudness))) { |
1195 | 202k | addToCandidate = 1; |
1196 | 202k | } |
1197 | 206k | } |
1198 | 210k | } else { |
1199 | 43.7k | addToCandidate = 1; |
1200 | 43.7k | } |
1201 | | |
1202 | 254k | if (addToCandidate) { |
1203 | 246k | DRCDEC_SELECTION_DATA* pData = |
1204 | 246k | _drcdec_selection_addNew(pCandidatesPotential); |
1205 | 246k | if (pData == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1206 | | |
1207 | 246k | _setSelectionDataInfo(pData, loudness, loudnessNormalizationGainDb, |
1208 | 246k | hSelProcInput->loudnessNormalizationGainDbMax, |
1209 | 246k | loudnessDeviationMax, signalPeakLevel, |
1210 | 246k | hSelProcInput->outputPeakLevelMax, 0); |
1211 | 246k | pData->downmixIdRequestIndex = downmixIdIndex; |
1212 | 246k | pData->pInst = pDrcInstructionUniDrc; |
1213 | 246k | pData->selectionFlag = 0; |
1214 | 246k | } |
1215 | 254k | } 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 | 254k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1233 | 254k | } |
1234 | | |
1235 | | /* #9: Clipping is minimized. */ |
1236 | | static DRCDEC_SELECTION_PROCESS_RETURN _preSelectionRequirement9( |
1237 | | SEL_PROC_INPUT* hSelProcInput, DRCDEC_SELECTION* pCandidatesPotential, |
1238 | 213k | DRCDEC_SELECTION* pCandidatesSelected) { |
1239 | 213k | int i; |
1240 | | |
1241 | 459k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1242 | 246k | DRCDEC_SELECTION_DATA* pCandidate = |
1243 | 246k | _drcdec_selection_getAt(pCandidatesPotential, i); |
1244 | 246k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1245 | | |
1246 | 246k | if (pCandidate->outputPeakLevel <= hSelProcInput->outputPeakLevelMax) { |
1247 | 206k | if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) |
1248 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1249 | 206k | } |
1250 | 246k | } |
1251 | | |
1252 | 213k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1253 | 213k | } |
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 | 322k | DRCDEC_SELECTION* pCandidatesSelected, SEL_PROC_CODEC_MODE codecMode) { |
1262 | 322k | DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1263 | 322k | int matchFound = 0; |
1264 | 322k | DRC_COEFFICIENTS_UNI_DRC* pCoef = |
1265 | 322k | selectDrcCoefficients(hUniDrcConfig, LOCATION_SELECTED); |
1266 | | |
1267 | 322k | retVal = _preSelectionRequirement123( |
1268 | 322k | hSelProcInput->downmixIdRequested[downmixIdIndex], pDrcInstructionUniDrc, |
1269 | 322k | &matchFound); |
1270 | | |
1271 | 322k | if (!retVal && matchFound) |
1272 | 290k | retVal = _preSelectionRequirement4(pDrcInstructionUniDrc, |
1273 | 290k | hSelProcInput->dynamicRangeControlOn, |
1274 | 290k | &matchFound); |
1275 | | |
1276 | 322k | if (!retVal && matchFound) |
1277 | 280k | retVal = |
1278 | 280k | _preSelectionRequirement5(pDrcInstructionUniDrc, pCoef, &matchFound); |
1279 | | |
1280 | 322k | if (!retVal && matchFound) |
1281 | 255k | retVal = _preSelectionRequirement6(pDrcInstructionUniDrc, &matchFound); |
1282 | | |
1283 | 322k | if (!retVal && matchFound) |
1284 | 254k | retVal = _preSelectionRequirement7(pDrcInstructionUniDrc, &matchFound); |
1285 | | |
1286 | 322k | if (!retVal && matchFound) |
1287 | 254k | retVal = _preSelectionRequirement8( |
1288 | 254k | hSelProcInput, downmixIdIndex, hUniDrcConfig, hLoudnessInfoSet, |
1289 | 254k | pDrcInstructionUniDrc, pCandidatesPotential, pCandidatesSelected, |
1290 | 254k | codecMode); |
1291 | | |
1292 | 322k | return retVal; |
1293 | 322k | } |
1294 | | |
1295 | | static DRCDEC_SELECTION_PROCESS_RETURN _drcSetSelectionAddCandidates( |
1296 | | SEL_PROC_INPUT* hSelProcInput, DRCDEC_SELECTION* pCandidatesPotential, |
1297 | 24.4k | DRCDEC_SELECTION* pCandidatesSelected) { |
1298 | 24.4k | DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1299 | 24.4k | int nHitCount = 0; |
1300 | 24.4k | int i; |
1301 | | |
1302 | 24.4k | DRCDEC_SELECTION_DATA* pCandidate = NULL; |
1303 | 24.4k | DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc = NULL; |
1304 | | |
1305 | 59.5k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1306 | 35.0k | pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); |
1307 | 35.0k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1308 | | |
1309 | 35.0k | pDrcInstructionUniDrc = pCandidate->pInst; |
1310 | | |
1311 | 35.0k | if (_targetLoudnessInRange(pDrcInstructionUniDrc, |
1312 | 35.0k | hSelProcInput->targetLoudness)) { |
1313 | 3.05k | nHitCount++; |
1314 | 3.05k | } |
1315 | 35.0k | } |
1316 | | |
1317 | 24.4k | if (nHitCount != 0) { |
1318 | 9.10k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1319 | 6.57k | pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); |
1320 | 6.57k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1321 | | |
1322 | 6.57k | pDrcInstructionUniDrc = pCandidate->pInst; |
1323 | | |
1324 | 6.57k | if (_targetLoudnessInRange(pDrcInstructionUniDrc, |
1325 | 6.57k | hSelProcInput->targetLoudness)) { |
1326 | 3.05k | if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) |
1327 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1328 | 3.05k | } |
1329 | 6.57k | } |
1330 | 21.9k | } else { |
1331 | 21.9k | FIXP_DBL lowestPeakLevel = MAXVAL_DBL; /* e = 7 */ |
1332 | 21.9k | FIXP_DBL peakLevel = 0; /* e = 7 */ |
1333 | | |
1334 | 50.4k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1335 | 28.4k | pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); |
1336 | 28.4k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1337 | | |
1338 | 28.4k | peakLevel = pCandidate->outputPeakLevel; |
1339 | | |
1340 | 28.4k | if (peakLevel < lowestPeakLevel) { |
1341 | 23.3k | lowestPeakLevel = peakLevel; |
1342 | 23.3k | } |
1343 | 28.4k | } |
1344 | | |
1345 | | /* add all with lowest peak level or max 1dB above */ |
1346 | 50.4k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1347 | 28.4k | FIXP_DBL loudnessDeviationMax = |
1348 | 28.4k | ((FIXP_DBL)hSelProcInput->loudnessDeviationMax) |
1349 | 28.4k | << (DFRACT_BITS - 1 - 7); /* e = 7 */ |
1350 | | |
1351 | 28.4k | pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); |
1352 | 28.4k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1353 | | |
1354 | 28.4k | peakLevel = pCandidate->outputPeakLevel; |
1355 | | |
1356 | 28.4k | if (peakLevel == lowestPeakLevel || |
1357 | 28.4k | peakLevel <= |
1358 | 24.0k | lowestPeakLevel + FL2FXCONST_DBL(1.0f / (float)(1 << 7))) { |
1359 | 24.0k | FIXP_DBL adjustment = |
1360 | 24.0k | fMax((FIXP_DBL)0, peakLevel - hSelProcInput->outputPeakLevelMax); |
1361 | 24.0k | adjustment = fMin(adjustment, fMax((FIXP_DBL)0, loudnessDeviationMax)); |
1362 | | |
1363 | 24.0k | pCandidate->loudnessNormalizationGainDbAdjusted -= adjustment; |
1364 | 24.0k | pCandidate->outputPeakLevel -= adjustment; |
1365 | 24.0k | pCandidate->outputLoudness -= adjustment; |
1366 | 24.0k | if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) |
1367 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1368 | 24.0k | } |
1369 | 28.4k | } |
1370 | 21.9k | } |
1371 | | |
1372 | 24.4k | return retVal; |
1373 | 24.4k | } |
1374 | | |
1375 | | static DRCDEC_SELECTION_PROCESS_RETURN _dependentDrcInstruction( |
1376 | | HANDLE_UNI_DRC_CONFIG hUniDrcConfig, DRC_INSTRUCTIONS_UNI_DRC* pInst, |
1377 | 10.8k | DRC_INSTRUCTIONS_UNI_DRC** ppDrcInstructionsDependent) { |
1378 | 10.8k | int i; |
1379 | 10.8k | DRC_INSTRUCTIONS_UNI_DRC* pDependentDrc = NULL; |
1380 | | |
1381 | 36.7k | for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { |
1382 | 35.1k | pDependentDrc = |
1383 | 35.1k | (DRC_INSTRUCTIONS_UNI_DRC*)&(hUniDrcConfig->drcInstructionsUniDrc[i]); |
1384 | | |
1385 | 35.1k | if (pDependentDrc->drcSetId == pInst->dependsOnDrcSet) { |
1386 | 9.25k | break; |
1387 | 9.25k | } |
1388 | 35.1k | } |
1389 | | |
1390 | 10.8k | if (i == hUniDrcConfig->drcInstructionsUniDrcCount) { |
1391 | 1.60k | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1392 | 1.60k | } |
1393 | | |
1394 | 9.25k | if (pDependentDrc->dependsOnDrcSetPresent == 1) { |
1395 | 318 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1396 | 318 | } |
1397 | | |
1398 | 8.93k | *ppDrcInstructionsDependent = pDependentDrc; |
1399 | | |
1400 | 8.93k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1401 | 9.25k | } |
1402 | | |
1403 | | static DRCDEC_SELECTION_PROCESS_RETURN _selectDrcSetEffectNone( |
1404 | | HANDLE_UNI_DRC_CONFIG hUniDrcConfig, DRCDEC_SELECTION* pCandidatesPotential, |
1405 | 213k | DRCDEC_SELECTION* pCandidatesSelected) { |
1406 | 213k | int i; |
1407 | | |
1408 | 451k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1409 | 237k | DRCDEC_SELECTION_DATA* pCandidate = |
1410 | 237k | _drcdec_selection_getAt(pCandidatesPotential, i); |
1411 | 237k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1412 | | |
1413 | 237k | if ((pCandidate->pInst->drcSetEffect & 0xff) == 0) { |
1414 | 223k | if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) |
1415 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1416 | 223k | } |
1417 | 237k | } |
1418 | | |
1419 | 213k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1420 | 213k | } |
1421 | | |
1422 | | static DRCDEC_SELECTION_PROCESS_RETURN _selectSingleEffectType( |
1423 | | HANDLE_UNI_DRC_CONFIG hUniDrcConfig, DRC_EFFECT_TYPE_REQUEST effectType, |
1424 | | DRCDEC_SELECTION* pCandidatesPotential, |
1425 | 21.8k | DRCDEC_SELECTION* pCandidatesSelected) { |
1426 | 21.8k | int i; |
1427 | 21.8k | DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1428 | 21.8k | DRC_INSTRUCTIONS_UNI_DRC* pInst; |
1429 | 21.8k | DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionsDependent; |
1430 | | |
1431 | 21.8k | if (effectType == DETR_NONE) { |
1432 | 0 | retVal = _selectDrcSetEffectNone(hUniDrcConfig, pCandidatesPotential, |
1433 | 0 | pCandidatesSelected); |
1434 | 0 | if (retVal) return (retVal); |
1435 | 21.8k | } else { |
1436 | 21.8k | int effectBitPosition = 1 << (effectType - 1); |
1437 | | |
1438 | 52.0k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1439 | 32.1k | DRCDEC_SELECTION_DATA* pCandidate = |
1440 | 32.1k | _drcdec_selection_getAt(pCandidatesPotential, i); |
1441 | 32.1k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1442 | | |
1443 | 32.1k | pInst = pCandidate->pInst; |
1444 | | |
1445 | 32.1k | if (!pInst->dependsOnDrcSetPresent) { |
1446 | 21.2k | if ((pInst->drcSetEffect & effectBitPosition)) { |
1447 | 6.89k | if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) |
1448 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1449 | 6.89k | } |
1450 | 21.2k | } else { |
1451 | 10.8k | retVal = _dependentDrcInstruction(hUniDrcConfig, pInst, |
1452 | 10.8k | &pDrcInstructionsDependent); |
1453 | 10.8k | if (retVal) return (retVal); |
1454 | | |
1455 | 8.93k | if (((pInst->drcSetEffect & effectBitPosition)) || |
1456 | 8.93k | ((pDrcInstructionsDependent->drcSetEffect & effectBitPosition))) { |
1457 | 3.66k | if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) |
1458 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1459 | 3.66k | } |
1460 | 8.93k | } |
1461 | 32.1k | } |
1462 | 21.8k | } |
1463 | | |
1464 | 19.9k | return retVal; |
1465 | 21.8k | } |
1466 | | |
1467 | | static DRCDEC_SELECTION_PROCESS_RETURN _selectEffectTypeFeature( |
1468 | | HANDLE_UNI_DRC_CONFIG hUniDrcConfig, DRC_FEATURE_REQUEST drcFeatureRequest, |
1469 | | DRCDEC_SELECTION** ppCandidatesPotential, |
1470 | 5.90k | DRCDEC_SELECTION** ppCandidatesSelected) { |
1471 | 5.90k | DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1472 | 5.90k | int i; |
1473 | 5.90k | int desiredEffectTypeFound = 0; |
1474 | | |
1475 | 25.8k | for (i = 0; i < drcFeatureRequest.drcEffectType.numRequestsDesired; i++) { |
1476 | 21.8k | retVal = _selectSingleEffectType( |
1477 | 21.8k | hUniDrcConfig, drcFeatureRequest.drcEffectType.request[i], |
1478 | 21.8k | *ppCandidatesPotential, *ppCandidatesSelected); |
1479 | 21.8k | if (retVal) return (retVal); |
1480 | | |
1481 | 19.9k | if (_drcdec_selection_getNumber(*ppCandidatesSelected)) { |
1482 | 7.94k | desiredEffectTypeFound = 1; |
1483 | 7.94k | _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); |
1484 | 7.94k | } |
1485 | 19.9k | } |
1486 | | |
1487 | 3.98k | if (!desiredEffectTypeFound) { |
1488 | 415 | for (i = drcFeatureRequest.drcEffectType.numRequestsDesired; |
1489 | 415 | 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 | 415 | } |
1501 | | |
1502 | 3.98k | _swapSelection(ppCandidatesPotential, ppCandidatesSelected); |
1503 | | |
1504 | 3.98k | return retVal; |
1505 | 3.98k | } |
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 | 12.0k | DRCDEC_SELECTION* pCandidatesSelected) { |
1671 | 12.0k | int i; |
1672 | | |
1673 | 42.2k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1674 | 30.2k | DRCDEC_SELECTION_DATA* pCandidate = |
1675 | 30.2k | _drcdec_selection_getAt(pCandidatesPotential, i); |
1676 | 30.2k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1677 | | |
1678 | 30.2k | if (pCandidate->outputPeakLevel <= FIXP_DBL(0)) { |
1679 | 20.5k | if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) |
1680 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1681 | 20.5k | } |
1682 | 30.2k | } |
1683 | | |
1684 | 12.0k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1685 | 12.0k | } |
1686 | | |
1687 | | static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_downmixId( |
1688 | | HANDLE_SEL_PROC_INPUT hSelProcInput, |
1689 | | DRCDEC_SELECTION** ppCandidatesPotential, |
1690 | 7.99k | DRCDEC_SELECTION** ppCandidatesSelected) { |
1691 | 7.99k | int i, j; |
1692 | 7.99k | DRCDEC_SELECTION_DATA* pCandidate = NULL; |
1693 | 7.99k | DRC_INSTRUCTIONS_UNI_DRC* pInst = NULL; |
1694 | | |
1695 | 28.4k | for (i = 0; i < _drcdec_selection_getNumber(*ppCandidatesPotential); i++) { |
1696 | 20.4k | pCandidate = _drcdec_selection_getAt(*ppCandidatesPotential, i); |
1697 | 20.4k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1698 | | |
1699 | 20.4k | pInst = pCandidate->pInst; |
1700 | | |
1701 | 48.5k | for (j = 0; j < pInst->downmixIdCount; j++) { |
1702 | 28.1k | if (DOWNMIX_ID_BASE_LAYOUT != pInst->downmixId[j] && |
1703 | 28.1k | DOWNMIX_ID_ANY_DOWNMIX != pInst->downmixId[j] && |
1704 | 28.1k | hSelProcInput |
1705 | 6.21k | ->downmixIdRequested[pCandidate->downmixIdRequestIndex] == |
1706 | 6.21k | pInst->downmixId[j]) { |
1707 | 0 | if (_drcdec_selection_add(*ppCandidatesSelected, pCandidate) == NULL) |
1708 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1709 | 0 | } |
1710 | 28.1k | } |
1711 | 20.4k | } |
1712 | | |
1713 | 7.99k | if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { |
1714 | 7.99k | _swapSelection(ppCandidatesPotential, ppCandidatesSelected); |
1715 | 7.99k | } |
1716 | | |
1717 | 7.99k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1718 | 7.99k | } |
1719 | | |
1720 | 40.9k | static int _crossSum(int value) { |
1721 | 40.9k | int sum = 0; |
1722 | | |
1723 | 293k | while (value != 0) { |
1724 | 252k | if ((value & 1) == 1) { |
1725 | 60.2k | sum++; |
1726 | 60.2k | } |
1727 | | |
1728 | 252k | value >>= 1; |
1729 | 252k | } |
1730 | | |
1731 | 40.9k | return sum; |
1732 | 40.9k | } |
1733 | | |
1734 | | static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_effectTypes( |
1735 | | DRCDEC_SELECTION* pCandidatesPotential, |
1736 | 7.99k | DRCDEC_SELECTION* pCandidatesSelected) { |
1737 | 7.99k | int i; |
1738 | 7.99k | int minNumEffects = 1000; |
1739 | 7.99k | int numEffects = 0; |
1740 | 7.99k | int effects = 0; |
1741 | 7.99k | DRCDEC_SELECTION_DATA* pCandidate = NULL; |
1742 | 7.99k | DRC_INSTRUCTIONS_UNI_DRC* pInst = NULL; |
1743 | | |
1744 | 28.4k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1745 | 20.4k | pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); |
1746 | 20.4k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1747 | | |
1748 | 20.4k | pInst = pCandidate->pInst; |
1749 | | |
1750 | 20.4k | effects = pInst->drcSetEffect; |
1751 | 20.4k | effects &= 0xffff ^ (EB_GENERAL_COMPR); |
1752 | 20.4k | numEffects = _crossSum(effects); |
1753 | | |
1754 | 20.4k | if (numEffects < minNumEffects) { |
1755 | 13.7k | minNumEffects = numEffects; |
1756 | 13.7k | } |
1757 | 20.4k | } |
1758 | | |
1759 | | /* add all with minimum number of effects */ |
1760 | 28.4k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1761 | 20.4k | pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); |
1762 | 20.4k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1763 | | |
1764 | 20.4k | pInst = pCandidate->pInst; |
1765 | | |
1766 | 20.4k | effects = pInst->drcSetEffect; |
1767 | 20.4k | effects &= 0xffff ^ (EB_GENERAL_COMPR); |
1768 | 20.4k | numEffects = _crossSum(effects); |
1769 | | |
1770 | 20.4k | if (numEffects == minNumEffects) { |
1771 | 14.6k | if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) |
1772 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1773 | 14.6k | } |
1774 | 20.4k | } |
1775 | | |
1776 | 7.99k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1777 | 7.99k | } |
1778 | | |
1779 | | static DRCDEC_SELECTION_PROCESS_RETURN _selectSmallestTargetLoudnessValueUpper( |
1780 | | DRCDEC_SELECTION* pCandidatesPotential, |
1781 | 1.39k | DRCDEC_SELECTION* pCandidatesSelected) { |
1782 | 1.39k | int i; |
1783 | 1.39k | SCHAR minVal = 0x7F; |
1784 | 1.39k | SCHAR val = 0; |
1785 | 1.39k | DRCDEC_SELECTION_DATA* pCandidate = NULL; |
1786 | | |
1787 | 4.68k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1788 | 3.28k | pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); |
1789 | 3.28k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1790 | | |
1791 | 3.28k | val = pCandidate->pInst->drcSetTargetLoudnessValueUpper; |
1792 | | |
1793 | 3.28k | if (val < minVal) { |
1794 | 1.56k | minVal = val; |
1795 | 1.56k | } |
1796 | 3.28k | } |
1797 | | |
1798 | | /* add all with same smallest drcSetTargetLoudnessValueUpper */ |
1799 | 4.68k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1800 | 3.28k | pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); |
1801 | 3.28k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1802 | | |
1803 | 3.28k | val = pCandidate->pInst->drcSetTargetLoudnessValueUpper; |
1804 | | |
1805 | 3.28k | if (val == minVal) { |
1806 | 2.24k | if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) |
1807 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1808 | 2.24k | } |
1809 | 3.28k | } |
1810 | | |
1811 | 1.39k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1812 | 1.39k | } |
1813 | | |
1814 | | static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_targetLoudness( |
1815 | | FIXP_DBL targetLoudness, DRCDEC_SELECTION* pCandidatesPotential, |
1816 | 3.21k | DRCDEC_SELECTION* pCandidatesSelected) { |
1817 | 3.21k | DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1818 | 3.21k | int i; |
1819 | 3.21k | DRCDEC_SELECTION_DATA* pCandidate = NULL; |
1820 | | |
1821 | 13.1k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1822 | 9.90k | pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); |
1823 | 9.90k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1824 | | |
1825 | 9.90k | if (pCandidate->selectionFlag == 0) { |
1826 | 7.83k | if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) |
1827 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1828 | 7.83k | } |
1829 | 9.90k | } |
1830 | | |
1831 | 3.21k | if (_drcdec_selection_getNumber(pCandidatesSelected) == 0) { |
1832 | 789 | retVal = _selectSmallestTargetLoudnessValueUpper(pCandidatesPotential, |
1833 | 789 | pCandidatesSelected); |
1834 | 789 | if (retVal) return (retVal); |
1835 | 789 | } |
1836 | | |
1837 | 3.21k | if (_drcdec_selection_getNumber(pCandidatesSelected) > 1) { |
1838 | 2.80k | DRC_INSTRUCTIONS_UNI_DRC* pDrcInstructionUniDrc = NULL; |
1839 | | |
1840 | 2.80k | _swapSelectionAndClear(&pCandidatesPotential, &pCandidatesSelected); |
1841 | | |
1842 | 11.4k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1843 | 8.64k | pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); |
1844 | 8.64k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1845 | | |
1846 | 8.64k | pDrcInstructionUniDrc = pCandidate->pInst; |
1847 | | |
1848 | 8.64k | 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 | 8.64k | } |
1853 | | |
1854 | 2.80k | if (_drcdec_selection_getNumber(pCandidatesSelected) > 1) { |
1855 | 606 | _swapSelectionAndClear(&pCandidatesPotential, &pCandidatesSelected); |
1856 | | |
1857 | 606 | retVal = _selectSmallestTargetLoudnessValueUpper(pCandidatesPotential, |
1858 | 606 | pCandidatesSelected); |
1859 | 606 | if (retVal) return (retVal); |
1860 | 606 | } |
1861 | 2.80k | } |
1862 | | |
1863 | 3.21k | return retVal; |
1864 | 3.21k | } |
1865 | | |
1866 | | static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_peakValueLargest( |
1867 | | DRCDEC_SELECTION* pCandidatesPotential, |
1868 | 2.60k | DRCDEC_SELECTION* pCandidatesSelected) { |
1869 | 2.60k | int i; |
1870 | 2.60k | FIXP_DBL largestPeakLevel = MINVAL_DBL; |
1871 | 2.60k | FIXP_DBL peakLevel = 0; |
1872 | 2.60k | DRCDEC_SELECTION_DATA* pCandidate = NULL; |
1873 | | |
1874 | 10.8k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1875 | 8.23k | pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); |
1876 | 8.23k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1877 | | |
1878 | 8.23k | peakLevel = pCandidate->outputPeakLevel; |
1879 | | |
1880 | 8.23k | if (peakLevel > largestPeakLevel) { |
1881 | 2.42k | largestPeakLevel = peakLevel; |
1882 | 2.42k | } |
1883 | 8.23k | } |
1884 | | |
1885 | | /* add all with same largest peak level */ |
1886 | 10.8k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1887 | 8.23k | pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); |
1888 | 8.23k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1889 | | |
1890 | 8.23k | peakLevel = pCandidate->outputPeakLevel; |
1891 | | |
1892 | 8.23k | if (peakLevel == largestPeakLevel) { |
1893 | 7.96k | if (_drcdec_selection_add(pCandidatesSelected, pCandidate) == NULL) |
1894 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1895 | 7.96k | } |
1896 | 8.23k | } |
1897 | | |
1898 | 2.60k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1899 | 2.60k | } |
1900 | | |
1901 | | static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection_drcSetId( |
1902 | | DRCDEC_SELECTION* pCandidatesPotential, |
1903 | 2.33k | DRCDEC_SELECTION* pCandidatesSelected) { |
1904 | 2.33k | int i; |
1905 | 2.33k | int largestId = -1000; |
1906 | 2.33k | int id = 0; |
1907 | 2.33k | DRCDEC_SELECTION_DATA* pCandidate = NULL; |
1908 | 2.33k | DRCDEC_SELECTION_DATA* pCandidateSelected = NULL; |
1909 | | |
1910 | 10.0k | for (i = 0; i < _drcdec_selection_getNumber(pCandidatesPotential); i++) { |
1911 | 7.69k | pCandidate = _drcdec_selection_getAt(pCandidatesPotential, i); |
1912 | 7.69k | if (pCandidate == NULL) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1913 | | |
1914 | 7.69k | id = pCandidate->pInst->drcSetId; |
1915 | | |
1916 | 7.69k | if (id > largestId) { |
1917 | 2.36k | largestId = id; |
1918 | 2.36k | pCandidateSelected = pCandidate; |
1919 | 2.36k | } |
1920 | 7.69k | } |
1921 | | |
1922 | 2.33k | if (pCandidateSelected != NULL) { |
1923 | 2.33k | if (_drcdec_selection_add(pCandidatesSelected, pCandidateSelected) == NULL) |
1924 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1925 | 2.33k | } else { |
1926 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1927 | 0 | } |
1928 | | |
1929 | 2.33k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1930 | 2.33k | } |
1931 | | |
1932 | | static DRCDEC_SELECTION_PROCESS_RETURN _drcSetFinalSelection( |
1933 | | HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, |
1934 | | DRCDEC_SELECTION** ppCandidatesPotential, |
1935 | 211k | DRCDEC_SELECTION** ppCandidatesSelected, SEL_PROC_CODEC_MODE codecMode) { |
1936 | 211k | DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
1937 | | |
1938 | 211k | if (_drcdec_selection_getNumber(*ppCandidatesPotential) == 0) { |
1939 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1940 | 211k | } else if (_drcdec_selection_getNumber(*ppCandidatesPotential) == 1) { |
1941 | 199k | _swapSelection(ppCandidatesPotential, ppCandidatesSelected); |
1942 | | /* finished */ |
1943 | 199k | } else /* > 1 */ |
1944 | 12.0k | { |
1945 | 12.0k | retVal = _drcSetFinalSelection_peakValue0(*ppCandidatesPotential, |
1946 | 12.0k | *ppCandidatesSelected); |
1947 | 12.0k | if (retVal) return (retVal); |
1948 | | |
1949 | 12.0k | if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { |
1950 | 7.99k | _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); |
1951 | 7.99k | retVal = _drcSetFinalSelection_downmixId( |
1952 | 7.99k | hSelProcInput, ppCandidatesPotential, ppCandidatesSelected); |
1953 | 7.99k | if (retVal) return (retVal); |
1954 | 7.99k | } |
1955 | | |
1956 | 12.0k | if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { |
1957 | 7.99k | _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); |
1958 | 7.99k | retVal = _drcSetFinalSelection_effectTypes(*ppCandidatesPotential, |
1959 | 7.99k | *ppCandidatesSelected); |
1960 | 7.99k | if (retVal) return (retVal); |
1961 | 7.99k | } |
1962 | | |
1963 | 12.0k | if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { |
1964 | 3.21k | _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); |
1965 | 3.21k | retVal = _drcSetFinalSelection_targetLoudness( |
1966 | 3.21k | hSelProcInput->targetLoudness, *ppCandidatesPotential, |
1967 | 3.21k | *ppCandidatesSelected); |
1968 | 3.21k | if (retVal) return (retVal); |
1969 | 3.21k | } |
1970 | | |
1971 | 12.0k | if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { |
1972 | 2.60k | _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); |
1973 | 2.60k | retVal = _drcSetFinalSelection_peakValueLargest(*ppCandidatesPotential, |
1974 | 2.60k | *ppCandidatesSelected); |
1975 | 2.60k | if (retVal) return (retVal); |
1976 | 2.60k | } |
1977 | | |
1978 | 12.0k | if (_drcdec_selection_getNumber(*ppCandidatesSelected) > 1) { |
1979 | 2.33k | _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); |
1980 | 2.33k | retVal = _drcSetFinalSelection_drcSetId(*ppCandidatesPotential, |
1981 | 2.33k | *ppCandidatesSelected); |
1982 | 2.33k | if (retVal) return (retVal); |
1983 | 2.33k | } |
1984 | 12.0k | } |
1985 | | |
1986 | 211k | if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { |
1987 | 3.99k | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
1988 | 3.99k | } |
1989 | | |
1990 | 207k | return retVal; |
1991 | 211k | } |
1992 | | |
1993 | | static DRCDEC_SELECTION_PROCESS_RETURN _generateVirtualDrcSets( |
1994 | | HANDLE_SEL_PROC_INPUT hSelProcInput, HANDLE_UNI_DRC_CONFIG hUniDrcConfig, |
1995 | 213k | SEL_PROC_CODEC_MODE codecMode) { |
1996 | 213k | int i; |
1997 | 213k | int nMixes = hUniDrcConfig->downmixInstructionsCount + 1; |
1998 | 213k | int index = hUniDrcConfig->drcInstructionsUniDrcCount; |
1999 | 213k | int indexVirtual = -1; |
2000 | 213k | DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction = |
2001 | 213k | &(hUniDrcConfig->drcInstructionsUniDrc[index]); |
2002 | | |
2003 | 213k | if (codecMode == SEL_PROC_MPEG_H_3DA) { |
2004 | 0 | nMixes = 1; |
2005 | 0 | } |
2006 | | |
2007 | 213k | if ((index + nMixes) > (12 + 1 + 6)) { |
2008 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
2009 | 0 | } |
2010 | | |
2011 | 213k | FDKmemset(pDrcInstruction, 0, sizeof(DRC_INSTRUCTIONS_UNI_DRC)); |
2012 | | |
2013 | 213k | pDrcInstruction->drcSetId = indexVirtual; |
2014 | 213k | index++; |
2015 | 213k | indexVirtual--; |
2016 | 213k | pDrcInstruction->downmixIdCount = 1; |
2017 | | |
2018 | 213k | if ((codecMode == SEL_PROC_MPEG_H_3DA) && |
2019 | 213k | (hSelProcInput->numDownmixIdRequests)) { |
2020 | 0 | pDrcInstruction->downmixId[0] = hSelProcInput->downmixIdRequested[0]; |
2021 | 213k | } else { |
2022 | 213k | pDrcInstruction->downmixId[0] = DOWNMIX_ID_BASE_LAYOUT; |
2023 | 213k | } |
2024 | | |
2025 | 227k | for (i = 1; i < nMixes; i++) { |
2026 | 13.4k | pDrcInstruction = &(hUniDrcConfig->drcInstructionsUniDrc[index]); |
2027 | 13.4k | FDKmemset(pDrcInstruction, 0, sizeof(DRC_INSTRUCTIONS_UNI_DRC)); |
2028 | 13.4k | pDrcInstruction->drcSetId = indexVirtual; |
2029 | 13.4k | pDrcInstruction->downmixId[0] = |
2030 | 13.4k | hUniDrcConfig->downmixInstructions[i - 1].downmixId; |
2031 | 13.4k | pDrcInstruction->downmixIdCount = 1; |
2032 | 13.4k | index++; |
2033 | 13.4k | indexVirtual--; |
2034 | 13.4k | } |
2035 | | |
2036 | 213k | hUniDrcConfig->drcInstructionsCountInclVirtual = |
2037 | 213k | hUniDrcConfig->drcInstructionsUniDrcCount + nMixes; |
2038 | | |
2039 | 213k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
2040 | 213k | } |
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 | 207k | DRCDEC_SELECTION_DATA* pSelectionData, SEL_PROC_CODEC_MODE codecMode) { |
2047 | 207k | DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
2048 | | |
2049 | 207k | int i, j; |
2050 | 207k | int hasDependend = 0; |
2051 | 207k | int hasFading = 0; |
2052 | 207k | int hasDucking = 0; |
2053 | 207k | int selectedDrcSetIds; |
2054 | 207k | int selectedDownmixIds; |
2055 | 207k | FIXP_DBL mixingLevel = 0; |
2056 | 207k | int albumMode = hSelProcInput->albumMode; |
2057 | 207k | UCHAR* pDownmixIdRequested = hSelProcInput->downmixIdRequested; |
2058 | 207k | FIXP_SGL boost = hSelProcInput->boost; |
2059 | 207k | FIXP_SGL compress = hSelProcInput->compress; |
2060 | | |
2061 | 207k | hSelProcOutput->numSelectedDrcSets = 1; |
2062 | 207k | hSelProcOutput->selectedDrcSetIds[0] = pSelectionData->pInst->drcSetId; |
2063 | 207k | hSelProcOutput->selectedDownmixIds[0] = |
2064 | 207k | pSelectionData->pInst->drcApplyToDownmix == 1 |
2065 | 207k | ? pSelectionData->pInst->downmixId[0] |
2066 | 207k | : 0; |
2067 | 207k | hSelProcOutput->loudnessNormalizationGainDb = |
2068 | 207k | pSelectionData->loudnessNormalizationGainDbAdjusted + |
2069 | 207k | hSelProcInput->loudnessNormalizationGainModificationDb; |
2070 | 207k | hSelProcOutput->outputPeakLevelDb = pSelectionData->outputPeakLevel; |
2071 | 207k | hSelProcOutput->outputLoudness = pSelectionData->outputLoudness; |
2072 | | |
2073 | 207k | hSelProcOutput->boost = boost; |
2074 | 207k | hSelProcOutput->compress = compress; |
2075 | 207k | hSelProcOutput->baseChannelCount = |
2076 | 207k | hUniDrcConfig->channelLayout.baseChannelCount; |
2077 | 207k | hSelProcOutput->targetChannelCount = |
2078 | 207k | hUniDrcConfig->channelLayout.baseChannelCount; |
2079 | 207k | hSelProcOutput->activeDownmixId = |
2080 | 207k | pDownmixIdRequested[pSelectionData->downmixIdRequestIndex]; |
2081 | | |
2082 | 207k | _getMixingLevel(hLoudnessInfoSet, *pDownmixIdRequested, |
2083 | 207k | hSelProcOutput->selectedDrcSetIds[0], albumMode, |
2084 | 207k | &mixingLevel); |
2085 | 207k | hSelProcOutput->mixingLevel = mixingLevel; |
2086 | | |
2087 | | /*dependent*/ |
2088 | 207k | if (pSelectionData->pInst->dependsOnDrcSetPresent) { |
2089 | 3.39k | int dependsOnDrcSetID = pSelectionData->pInst->dependsOnDrcSet; |
2090 | | |
2091 | 14.9k | for (i = 0; i < hUniDrcConfig->drcInstructionsCountInclVirtual; i++) { |
2092 | 13.3k | DRC_INSTRUCTIONS_UNI_DRC* pInst = |
2093 | 13.3k | &(hUniDrcConfig->drcInstructionsUniDrc[i]); |
2094 | 13.3k | if (!_drcSetIsUsable(hUniDrcConfig, pInst)) continue; |
2095 | | |
2096 | 7.70k | if (pInst->drcSetId == dependsOnDrcSetID) { |
2097 | 1.83k | hSelProcOutput->selectedDrcSetIds[hSelProcOutput->numSelectedDrcSets] = |
2098 | 1.83k | hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId; |
2099 | 1.83k | hSelProcOutput->selectedDownmixIds[hSelProcOutput->numSelectedDrcSets] = |
2100 | 1.83k | hUniDrcConfig->drcInstructionsUniDrc[i].drcApplyToDownmix == 1 |
2101 | 1.83k | ? hUniDrcConfig->drcInstructionsUniDrc[i].downmixId[0] |
2102 | 1.83k | : 0; |
2103 | 1.83k | hSelProcOutput->numSelectedDrcSets++; |
2104 | 1.83k | hasDependend = 1; |
2105 | 1.83k | break; |
2106 | 1.83k | } |
2107 | 7.70k | } |
2108 | 3.39k | } |
2109 | | |
2110 | | /* fading */ |
2111 | 207k | if (hSelProcInput->albumMode == 0) { |
2112 | 280k | for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { |
2113 | 78.8k | DRC_INSTRUCTIONS_UNI_DRC* pInst = |
2114 | 78.8k | &(hUniDrcConfig->drcInstructionsUniDrc[i]); |
2115 | 78.8k | if (!_drcSetIsUsable(hUniDrcConfig, pInst)) continue; |
2116 | | |
2117 | 29.1k | if (pInst->drcSetEffect & EB_FADE) { |
2118 | 12.0k | if (pInst->downmixId[0] == DOWNMIX_ID_ANY_DOWNMIX) { |
2119 | 6.67k | hSelProcOutput->numSelectedDrcSets = hasDependend + 1; |
2120 | 6.67k | hSelProcOutput |
2121 | 6.67k | ->selectedDrcSetIds[hSelProcOutput->numSelectedDrcSets] = |
2122 | 6.67k | hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId; |
2123 | 6.67k | hSelProcOutput |
2124 | 6.67k | ->selectedDownmixIds[hSelProcOutput->numSelectedDrcSets] = |
2125 | 6.67k | hUniDrcConfig->drcInstructionsUniDrc[i].drcApplyToDownmix == 1 |
2126 | 6.67k | ? hUniDrcConfig->drcInstructionsUniDrc[i].downmixId[0] |
2127 | 6.67k | : 0; |
2128 | 6.67k | hSelProcOutput->numSelectedDrcSets++; |
2129 | 6.67k | hasFading = 1; |
2130 | | |
2131 | 6.67k | } else { |
2132 | 5.36k | retVal = DRCDEC_SELECTION_PROCESS_NOT_OK; |
2133 | 5.36k | if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
2134 | 5.36k | } |
2135 | 12.0k | } |
2136 | 29.1k | } |
2137 | 207k | } |
2138 | | |
2139 | | /* ducking */ |
2140 | 267k | for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { |
2141 | 65.3k | DRC_INSTRUCTIONS_UNI_DRC* pInst = |
2142 | 65.3k | &(hUniDrcConfig->drcInstructionsUniDrc[i]); |
2143 | 65.3k | if (!_drcSetIsUsable(hUniDrcConfig, pInst)) continue; |
2144 | | |
2145 | 20.2k | if (pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { |
2146 | 22.7k | for (j = 0; j < pInst->downmixIdCount; j++) { |
2147 | 15.7k | if (pInst->downmixId[j] == hSelProcOutput->activeDownmixId) { |
2148 | 3.30k | hSelProcOutput->numSelectedDrcSets = |
2149 | 3.30k | hasDependend + 1; /* ducking overrides fading */ |
2150 | | |
2151 | 3.30k | hSelProcOutput |
2152 | 3.30k | ->selectedDrcSetIds[hSelProcOutput->numSelectedDrcSets] = |
2153 | 3.30k | hUniDrcConfig->drcInstructionsUniDrc[i].drcSetId; |
2154 | | /* force ducking DRC set to be processed on base layout */ |
2155 | 3.30k | hSelProcOutput |
2156 | 3.30k | ->selectedDownmixIds[hSelProcOutput->numSelectedDrcSets] = 0; |
2157 | 3.30k | hSelProcOutput->numSelectedDrcSets++; |
2158 | 3.30k | hasDucking = 1; |
2159 | 3.30k | } |
2160 | 15.7k | } |
2161 | 7.03k | } |
2162 | 20.2k | } |
2163 | | |
2164 | | /* repeat for DOWNMIX_ID_BASE_LAYOUT if no ducking found*/ |
2165 | | |
2166 | 201k | if (!hasDucking) { |
2167 | 253k | for (i = 0; i < hUniDrcConfig->drcInstructionsUniDrcCount; i++) { |
2168 | 54.6k | DRC_INSTRUCTIONS_UNI_DRC* pInst = |
2169 | 54.6k | &(hUniDrcConfig->drcInstructionsUniDrc[i]); |
2170 | 54.6k | if (!_drcSetIsUsable(hUniDrcConfig, pInst)) continue; |
2171 | | |
2172 | 15.9k | if (pInst->drcSetEffect & (EB_DUCK_OTHER | EB_DUCK_SELF)) { |
2173 | 11.1k | for (j = 0; j < pInst->downmixIdCount; j++) { |
2174 | 7.25k | 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 | 7.25k | } |
2185 | 3.84k | } |
2186 | 15.9k | } |
2187 | 198k | } |
2188 | | |
2189 | 201k | 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 | 201k | if (hSelProcOutput->numSelectedDrcSets == 3) { |
2198 | 429 | selectedDrcSetIds = hSelProcOutput->selectedDrcSetIds[0]; |
2199 | 429 | selectedDownmixIds = hSelProcOutput->selectedDownmixIds[0]; |
2200 | 429 | hSelProcOutput->selectedDrcSetIds[0] = hSelProcOutput->selectedDrcSetIds[2]; |
2201 | 429 | hSelProcOutput->selectedDownmixIds[0] = |
2202 | 429 | hSelProcOutput->selectedDownmixIds[2]; |
2203 | 429 | hSelProcOutput->selectedDrcSetIds[2] = selectedDrcSetIds; |
2204 | 429 | hSelProcOutput->selectedDownmixIds[2] = selectedDownmixIds; |
2205 | 201k | } else if (hSelProcOutput->numSelectedDrcSets == 2) { |
2206 | 8.92k | selectedDrcSetIds = hSelProcOutput->selectedDrcSetIds[0]; |
2207 | 8.92k | selectedDownmixIds = hSelProcOutput->selectedDownmixIds[0]; |
2208 | 8.92k | hSelProcOutput->selectedDrcSetIds[0] = hSelProcOutput->selectedDrcSetIds[1]; |
2209 | 8.92k | hSelProcOutput->selectedDownmixIds[0] = |
2210 | 8.92k | hSelProcOutput->selectedDownmixIds[1]; |
2211 | 8.92k | hSelProcOutput->selectedDrcSetIds[1] = selectedDrcSetIds; |
2212 | 8.92k | hSelProcOutput->selectedDownmixIds[1] = selectedDownmixIds; |
2213 | 8.92k | } |
2214 | | |
2215 | 201k | return retVal; |
2216 | 201k | } |
2217 | | |
2218 | | static DRCDEC_SELECTION_PROCESS_RETURN _selectDownmixMatrix( |
2219 | | HANDLE_SEL_PROC_OUTPUT hSelProcOutput, |
2220 | 201k | HANDLE_UNI_DRC_CONFIG hUniDrcConfig) { |
2221 | 201k | int i; |
2222 | 201k | hSelProcOutput->baseChannelCount = |
2223 | 201k | hUniDrcConfig->channelLayout.baseChannelCount; |
2224 | 201k | hSelProcOutput->targetChannelCount = |
2225 | 201k | hUniDrcConfig->channelLayout.baseChannelCount; |
2226 | 201k | hSelProcOutput->targetLayout = -1; |
2227 | 201k | hSelProcOutput->downmixMatrixPresent = 0; |
2228 | | |
2229 | 201k | 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 | 201k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
2264 | 201k | } |
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 | 213k | DRCDEC_SELECTION** ppCandidatesSelected, SEL_PROC_CODEC_MODE codecMode) { |
2271 | 213k | DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
2272 | 213k | int i, j; |
2273 | | |
2274 | 426k | for (i = 0; i < hSelProcInput->numDownmixIdRequests; i++) { |
2275 | 550k | for (j = 0; j < hUniDrcConfig->drcInstructionsCountInclVirtual; j++) { |
2276 | 337k | DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction = |
2277 | 337k | &(hUniDrcConfig->drcInstructionsUniDrc[j]); |
2278 | | /* check if ID is unique */ |
2279 | 337k | if (selectDrcInstructions(hUniDrcConfig, pDrcInstruction->drcSetId) != |
2280 | 337k | pDrcInstruction) |
2281 | 14.7k | continue; |
2282 | | |
2283 | 322k | retVal = _drcSetPreSelectionSingleInstruction( |
2284 | 322k | hSelProcInput, i, hUniDrcConfig, hLoudnessInfoSet, pDrcInstruction, |
2285 | 322k | *ppCandidatesPotential, *ppCandidatesSelected, codecMode); |
2286 | 322k | if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
2287 | 322k | } |
2288 | 213k | } |
2289 | | |
2290 | 213k | retVal = _preSelectionRequirement9(hSelProcInput, *ppCandidatesPotential, |
2291 | 213k | *ppCandidatesSelected); |
2292 | 213k | if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
2293 | | |
2294 | 213k | if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { |
2295 | 24.4k | retVal = _drcSetSelectionAddCandidates( |
2296 | 24.4k | hSelProcInput, *ppCandidatesPotential, *ppCandidatesSelected); |
2297 | 24.4k | if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
2298 | 24.4k | } |
2299 | | |
2300 | 213k | return retVal; |
2301 | 213k | } |
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 | 213k | DRCDEC_SELECTION** ppCandidatesSelected) { |
2308 | 213k | DRCDEC_SELECTION_PROCESS_RETURN retVal; |
2309 | 213k | int i; |
2310 | | |
2311 | 213k | 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 | 213k | if (hSelProcInput->dynamicRangeControlOn) { |
2317 | 213k | if (hSelProcInput->numDrcFeatureRequests == 0) { |
2318 | 213k | retVal = _selectDrcSetEffectNone(hUniDrcConfig, *ppCandidatesPotential, |
2319 | 213k | *ppCandidatesSelected); |
2320 | 213k | if (retVal) return (retVal); |
2321 | | |
2322 | 213k | if (_drcdec_selection_getNumber(*ppCandidatesSelected) == 0) { |
2323 | 5.90k | DRC_FEATURE_REQUEST fallbackRequest; |
2324 | 5.90k | fallbackRequest.drcEffectType.numRequests = 5; |
2325 | 5.90k | fallbackRequest.drcEffectType.numRequestsDesired = 5; |
2326 | 5.90k | fallbackRequest.drcEffectType.request[0] = DETR_GENERAL_COMPR; |
2327 | 5.90k | fallbackRequest.drcEffectType.request[1] = DETR_NIGHT; |
2328 | 5.90k | fallbackRequest.drcEffectType.request[2] = DETR_NOISY; |
2329 | 5.90k | fallbackRequest.drcEffectType.request[3] = DETR_LIMITED; |
2330 | 5.90k | fallbackRequest.drcEffectType.request[4] = DETR_LOWLEVEL; |
2331 | | |
2332 | 5.90k | retVal = _selectEffectTypeFeature(hUniDrcConfig, fallbackRequest, |
2333 | 5.90k | ppCandidatesPotential, |
2334 | 5.90k | ppCandidatesSelected); |
2335 | 5.90k | if (retVal) return DRCDEC_SELECTION_PROCESS_NOT_OK; |
2336 | 5.90k | } |
2337 | | |
2338 | 211k | _swapSelectionAndClear(ppCandidatesPotential, ppCandidatesSelected); |
2339 | 211k | } 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 | 213k | } |
2377 | | |
2378 | 211k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
2379 | 213k | } |
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 | 250k | DRCDEC_SELECTION* pSelection) { |
2429 | 250k | if (pSelection->numData < (12 + 1 + 6)) { |
2430 | 250k | DRCDEC_SELECTION_DATA* pData = &(pSelection->data[pSelection->numData]); |
2431 | 250k | FDKmemset(pData, 0, sizeof(DRCDEC_SELECTION_DATA)); |
2432 | 250k | pSelection->numData++; |
2433 | | |
2434 | 250k | return pData; |
2435 | 250k | } else { |
2436 | 0 | return NULL; |
2437 | 0 | } |
2438 | 250k | } |
2439 | | |
2440 | | static DRCDEC_SELECTION_DATA* _drcdec_selection_add( |
2441 | 524k | DRCDEC_SELECTION* pSelection, DRCDEC_SELECTION_DATA* pDataIn) { |
2442 | 524k | if (pSelection->numData < (12 + 1 + 6)) { |
2443 | 524k | DRCDEC_SELECTION_DATA* pData = &(pSelection->data[pSelection->numData]); |
2444 | 524k | FDKmemcpy(pData, pDataIn, sizeof(DRCDEC_SELECTION_DATA)); |
2445 | 524k | pSelection->numData++; |
2446 | 524k | return pData; |
2447 | 524k | } else { |
2448 | 0 | return NULL; |
2449 | 0 | } |
2450 | 524k | } |
2451 | | |
2452 | 460k | static int _drcdec_selection_clear(DRCDEC_SELECTION* pSelection) { |
2453 | 460k | return pSelection->numData = 0; |
2454 | 460k | } |
2455 | | |
2456 | 2.69M | static int _drcdec_selection_getNumber(DRCDEC_SELECTION* pSelection) { |
2457 | 2.69M | return pSelection->numData; |
2458 | 2.69M | } |
2459 | | |
2460 | 427k | static int _drcdec_selection_setNumber(DRCDEC_SELECTION* pSelection, int num) { |
2461 | 427k | if (num >= 0 && num < pSelection->numData) { |
2462 | 197k | return pSelection->numData = num; |
2463 | 229k | } else { |
2464 | 229k | return pSelection->numData; |
2465 | 229k | } |
2466 | 427k | } |
2467 | | |
2468 | | static DRCDEC_SELECTION_DATA* _drcdec_selection_getAt( |
2469 | 755k | DRCDEC_SELECTION* pSelection, int at) { |
2470 | 755k | if (at >= 0 && at < (12 + 1 + 6)) { |
2471 | 755k | return &(pSelection->data[at]); |
2472 | 755k | } else { |
2473 | 0 | return NULL; |
2474 | 0 | } |
2475 | 755k | } |
2476 | | |
2477 | | static int _swapSelectionAndClear(DRCDEC_SELECTION** ppCandidatesPotential, |
2478 | 460k | DRCDEC_SELECTION** ppCandidatesSelected) { |
2479 | 460k | DRCDEC_SELECTION* pTmp = *ppCandidatesPotential; |
2480 | 460k | *ppCandidatesPotential = *ppCandidatesSelected; |
2481 | 460k | *ppCandidatesSelected = pTmp; |
2482 | 460k | _drcdec_selection_clear(*ppCandidatesSelected); |
2483 | 460k | return 0; |
2484 | 460k | } |
2485 | | |
2486 | | static int _swapSelection(DRCDEC_SELECTION** ppCandidatesPotential, |
2487 | 211k | DRCDEC_SELECTION** ppCandidatesSelected) { |
2488 | 211k | DRCDEC_SELECTION* pTmp = *ppCandidatesPotential; |
2489 | 211k | *ppCandidatesPotential = *ppCandidatesSelected; |
2490 | 211k | *ppCandidatesSelected = pTmp; |
2491 | 211k | return 0; |
2492 | 211k | } |
2493 | | |
2494 | | /*******************************************/ |
2495 | | |
2496 | | static LOUDNESS_INFO* _getLoudnessInfoStructure( |
2497 | | HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int drcSetId, int downmixId, |
2498 | 1.99M | int albumMode) { |
2499 | 1.99M | int i, j; |
2500 | 1.99M | int count; |
2501 | | |
2502 | 1.99M | LOUDNESS_INFO* pLoudnessInfo = NULL; |
2503 | | |
2504 | 1.99M | if (albumMode) { |
2505 | 0 | count = hLoudnessInfoSet->loudnessInfoAlbumCount; |
2506 | 0 | pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; |
2507 | 1.99M | } else { |
2508 | 1.99M | count = hLoudnessInfoSet->loudnessInfoCount; |
2509 | 1.99M | pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; |
2510 | 1.99M | } |
2511 | | |
2512 | 3.07M | for (i = 0; i < count; i++) { |
2513 | 1.12M | if ((pLoudnessInfo[i].drcSetId == drcSetId) && |
2514 | 1.12M | (pLoudnessInfo[i].downmixId == downmixId)) { |
2515 | 391k | for (j = 0; j < pLoudnessInfo[i].measurementCount; j++) { |
2516 | 247k | if ((pLoudnessInfo[i].loudnessMeasurement[j].methodDefinition == 1) || |
2517 | 247k | (pLoudnessInfo[i].loudnessMeasurement[j].methodDefinition == 2)) { |
2518 | 50.5k | return &pLoudnessInfo[i]; |
2519 | 50.5k | } |
2520 | 247k | } |
2521 | 194k | } |
2522 | 1.12M | } |
2523 | | |
2524 | 1.94M | return NULL; |
2525 | 1.99M | } |
2526 | | |
2527 | | static LOUDNESS_INFO* _getApplicableLoudnessInfoStructure( |
2528 | | HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int drcSetId, |
2529 | 254k | int downmixIdRequested, int albumMode) { |
2530 | 254k | LOUDNESS_INFO* pLoudnessInfo = NULL; |
2531 | | |
2532 | | /* default value */ |
2533 | 254k | pLoudnessInfo = _getLoudnessInfoStructure(hLoudnessInfoSet, drcSetId, |
2534 | 254k | downmixIdRequested, albumMode); |
2535 | | |
2536 | | /* fallback values */ |
2537 | 254k | if (pLoudnessInfo == NULL) { |
2538 | 249k | pLoudnessInfo = |
2539 | 249k | _getLoudnessInfoStructure(hLoudnessInfoSet, drcSetId, 0x7F, albumMode); |
2540 | 249k | } |
2541 | | |
2542 | 254k | if (pLoudnessInfo == NULL) { |
2543 | 226k | pLoudnessInfo = _getLoudnessInfoStructure(hLoudnessInfoSet, 0x3F, |
2544 | 226k | downmixIdRequested, albumMode); |
2545 | 226k | } |
2546 | | |
2547 | 254k | if (pLoudnessInfo == NULL) { |
2548 | 220k | pLoudnessInfo = _getLoudnessInfoStructure(hLoudnessInfoSet, 0, |
2549 | 220k | downmixIdRequested, albumMode); |
2550 | 220k | } |
2551 | | |
2552 | 254k | if (pLoudnessInfo == NULL) { |
2553 | 218k | pLoudnessInfo = |
2554 | 218k | _getLoudnessInfoStructure(hLoudnessInfoSet, 0x3F, 0x7F, albumMode); |
2555 | 218k | } |
2556 | | |
2557 | 254k | if (pLoudnessInfo == NULL) { |
2558 | 216k | pLoudnessInfo = |
2559 | 216k | _getLoudnessInfoStructure(hLoudnessInfoSet, 0, 0x7F, albumMode); |
2560 | 216k | } |
2561 | | |
2562 | 254k | if (pLoudnessInfo == NULL) { |
2563 | 204k | pLoudnessInfo = |
2564 | 204k | _getLoudnessInfoStructure(hLoudnessInfoSet, drcSetId, 0, albumMode); |
2565 | 204k | } |
2566 | | |
2567 | 254k | if (pLoudnessInfo == NULL) { |
2568 | 204k | pLoudnessInfo = |
2569 | 204k | _getLoudnessInfoStructure(hLoudnessInfoSet, 0x3F, 0, albumMode); |
2570 | 204k | } |
2571 | | |
2572 | 254k | if (pLoudnessInfo == NULL) { |
2573 | 204k | pLoudnessInfo = |
2574 | 204k | _getLoudnessInfoStructure(hLoudnessInfoSet, 0, 0, albumMode); |
2575 | 204k | } |
2576 | | |
2577 | 254k | return pLoudnessInfo; |
2578 | 254k | } |
2579 | | |
2580 | | /*******************************************/ |
2581 | | |
2582 | | typedef struct { |
2583 | | FIXP_DBL value; |
2584 | | int order; |
2585 | | } VALUE_ORDER; |
2586 | | |
2587 | 254k | void _initValueOrder(VALUE_ORDER* pValue) { |
2588 | 254k | pValue->value = (FIXP_DBL)0; |
2589 | 254k | pValue->order = -1; |
2590 | 254k | } |
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 | 74.3k | int measurementSystemRequested) { |
2609 | 74.3k | const int rows = 11; |
2610 | 74.3k | const int columns = 12; |
2611 | 74.3k | const int pOrdering[rows][columns] = { |
2612 | 74.3k | {0, 0, 8, 0, 1, 3, 0, 5, 6, 7, 4, 2}, /* default = bonus1770 */ |
2613 | 74.3k | {0, 0, 8, 0, 1, 3, 0, 5, 6, 7, 4, 2}, /* bonus1770 */ |
2614 | 74.3k | {0, 0, 1, 0, 8, 5, 0, 2, 3, 4, 6, 7}, /* bonusUser */ |
2615 | 74.3k | {0, 0, 3, 0, 1, 8, 0, 4, 5, 6, 7, 2}, /* bonusExpert */ |
2616 | 74.3k | {0, 0, 5, 0, 1, 3, 0, 8, 6, 7, 4, 2}, /* ResA */ |
2617 | 74.3k | {0, 0, 5, 0, 1, 3, 0, 6, 8, 7, 4, 2}, /* ResB */ |
2618 | 74.3k | {0, 0, 5, 0, 1, 3, 0, 6, 7, 8, 4, 2}, /* ResC */ |
2619 | 74.3k | {0, 0, 3, 0, 1, 7, 0, 4, 5, 6, 8, 2}, /* ResD */ |
2620 | 74.3k | {0, 0, 1, 0, 7, 5, 0, 2, 3, 4, 6, 8}, /* ResE */ |
2621 | 74.3k | {0, 0, 1, 0, 0, 0, 0, 2, 3, 4, 0, 0}, /* ProgramLoudness */ |
2622 | 74.3k | {0, 7, 0, 0, 0, 0, 6, 5, 4, 3, 2, 1} /* PeakLoudness */ |
2623 | 74.3k | }; |
2624 | | |
2625 | 74.3k | if (measurementSystemRequested < 0 || measurementSystemRequested >= rows || |
2626 | 74.3k | measurementSystem < 0 || measurementSystem >= columns) { |
2627 | 17.8k | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
2628 | 17.8k | } |
2629 | | |
2630 | 56.5k | if (pOrdering[measurementSystemRequested][measurementSystem] > |
2631 | 56.5k | pValueOrder->order) { |
2632 | 50.4k | pValueOrder->order = |
2633 | 50.4k | pOrdering[measurementSystemRequested][measurementSystem]; |
2634 | 50.4k | pValueOrder->value = value; |
2635 | 50.4k | } |
2636 | | |
2637 | 56.5k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
2638 | 74.3k | } |
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 | 254k | { |
2651 | 254k | int index; |
2652 | | |
2653 | 254k | LOUDNESS_INFO* pLoudnessInfo = NULL; |
2654 | 254k | VALUE_ORDER valueOrder; |
2655 | | |
2656 | | /* map MDR_DEFAULT to MDR_PROGRAM_LOUDNESS */ |
2657 | 254k | METHOD_DEFINITION_REQUEST requestedMethodDefinition = |
2658 | 254k | measurementMethodRequested < MDR_ANCHOR_LOUDNESS ? MDR_PROGRAM_LOUDNESS |
2659 | 254k | : MDR_ANCHOR_LOUDNESS; |
2660 | | |
2661 | 254k | if (measurementMethodRequested > MDR_ANCHOR_LOUDNESS) { |
2662 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
2663 | 0 | } |
2664 | | |
2665 | 254k | _initValueOrder(&valueOrder); |
2666 | | |
2667 | 254k | *pLoudness = UNDEFINED_LOUDNESS_VALUE; |
2668 | 254k | *pLoudnessNormalizationGain = (FIXP_DBL)0; |
2669 | | |
2670 | 254k | if (drcSetId < 0) { |
2671 | 219k | drcSetId = 0; |
2672 | 219k | } |
2673 | | |
2674 | 254k | pLoudnessInfo = _getApplicableLoudnessInfoStructure( |
2675 | 254k | hLoudnessInfoSet, drcSetId, downmixIdRequested, albumMode); |
2676 | | |
2677 | 254k | if (albumMode && (pLoudnessInfo == NULL)) { |
2678 | 0 | pLoudnessInfo = _getApplicableLoudnessInfoStructure( |
2679 | 0 | hLoudnessInfoSet, drcSetId, downmixIdRequested, 0); |
2680 | 0 | } |
2681 | | |
2682 | 254k | if (pLoudnessInfo == NULL) { |
2683 | 204k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
2684 | 204k | } |
2685 | | |
2686 | 50.5k | index = -1; |
2687 | | |
2688 | 61.9k | do { |
2689 | 61.9k | index = _findMethodDefinition(pLoudnessInfo, requestedMethodDefinition, |
2690 | 61.9k | index + 1); |
2691 | | |
2692 | 61.9k | if (index >= 0) { |
2693 | 11.3k | _getMethodValue( |
2694 | 11.3k | &valueOrder, pLoudnessInfo->loudnessMeasurement[index].methodValue, |
2695 | 11.3k | pLoudnessInfo->loudnessMeasurement[index].measurementSystem, |
2696 | 11.3k | measurementSystemRequested); |
2697 | 11.3k | } |
2698 | 61.9k | } while (index >= 0); |
2699 | | |
2700 | | /* repeat with other method definition */ |
2701 | 50.5k | if (valueOrder.order == -1) { |
2702 | 40.6k | index = -1; |
2703 | | |
2704 | 103k | do { |
2705 | 103k | index = _findMethodDefinition( |
2706 | 103k | pLoudnessInfo, |
2707 | 103k | requestedMethodDefinition == MDR_PROGRAM_LOUDNESS |
2708 | 103k | ? MDR_ANCHOR_LOUDNESS |
2709 | 103k | : MDR_PROGRAM_LOUDNESS, |
2710 | 103k | index + 1); |
2711 | | |
2712 | 103k | if (index >= 0) { |
2713 | 62.9k | _getMethodValue( |
2714 | 62.9k | &valueOrder, pLoudnessInfo->loudnessMeasurement[index].methodValue, |
2715 | 62.9k | pLoudnessInfo->loudnessMeasurement[index].measurementSystem, |
2716 | 62.9k | measurementSystemRequested); |
2717 | 62.9k | } |
2718 | 103k | } while (index >= 0); |
2719 | 40.6k | } |
2720 | | |
2721 | 50.5k | if (valueOrder.order == -1) { |
2722 | 495 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
2723 | 50.0k | } else { |
2724 | 50.0k | *pLoudnessNormalizationGain = targetLoudness - valueOrder.value; |
2725 | 50.0k | *pLoudness = valueOrder.value; |
2726 | 50.0k | } |
2727 | | |
2728 | 50.0k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
2729 | 50.5k | } |
2730 | | |
2731 | | /*******************************************/ |
2732 | | |
2733 | | static int _truePeakLevelIsPresent(HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, |
2734 | 493k | int drcSetId, int downmixId, int albumMode) { |
2735 | 493k | int i; |
2736 | 493k | int count; |
2737 | 493k | LOUDNESS_INFO* pLoudnessInfo = NULL; |
2738 | | |
2739 | 493k | if (albumMode) { |
2740 | 0 | count = hLoudnessInfoSet->loudnessInfoAlbumCount; |
2741 | 0 | pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; |
2742 | 493k | } else { |
2743 | 493k | count = hLoudnessInfoSet->loudnessInfoCount; |
2744 | 493k | pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; |
2745 | 493k | } |
2746 | | |
2747 | 855k | for (i = 0; i < count; i++) { |
2748 | 373k | if ((pLoudnessInfo[i].drcSetId == drcSetId) && |
2749 | 373k | (pLoudnessInfo[i].downmixId == downmixId)) { |
2750 | 52.4k | if (pLoudnessInfo[i].truePeakLevelPresent) return 1; |
2751 | 52.4k | } |
2752 | 373k | } |
2753 | | |
2754 | 481k | return 0; |
2755 | 493k | } |
2756 | | |
2757 | | static DRCDEC_SELECTION_PROCESS_RETURN _getTruePeakLevel( |
2758 | | HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int drcSetId, int downmixId, |
2759 | 11.9k | int albumMode, FIXP_DBL* pTruePeakLevel) { |
2760 | 11.9k | int i; |
2761 | 11.9k | int count; |
2762 | 11.9k | LOUDNESS_INFO* pLoudnessInfo = NULL; |
2763 | | |
2764 | 11.9k | if (albumMode) { |
2765 | 0 | count = hLoudnessInfoSet->loudnessInfoAlbumCount; |
2766 | 0 | pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; |
2767 | 11.9k | } else { |
2768 | 11.9k | count = hLoudnessInfoSet->loudnessInfoCount; |
2769 | 11.9k | pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; |
2770 | 11.9k | } |
2771 | | |
2772 | 29.9k | for (i = 0; i < count; i++) { |
2773 | 29.9k | if ((pLoudnessInfo[i].drcSetId == drcSetId) && |
2774 | 29.9k | (pLoudnessInfo[i].downmixId == downmixId)) { |
2775 | 17.8k | if (pLoudnessInfo[i].truePeakLevelPresent) { |
2776 | 11.9k | *pTruePeakLevel = pLoudnessInfo[i].truePeakLevel; |
2777 | 11.9k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
2778 | 11.9k | } |
2779 | 17.8k | } |
2780 | 29.9k | } |
2781 | | |
2782 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
2783 | 11.9k | } |
2784 | | |
2785 | | static int _samplePeakLevelIsPresent(HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, |
2786 | | int drcSetId, int downmixId, |
2787 | 481k | int albumMode) { |
2788 | 481k | int i; |
2789 | 481k | int count; |
2790 | 481k | LOUDNESS_INFO* pLoudnessInfo = NULL; |
2791 | | |
2792 | 481k | if (albumMode) { |
2793 | 0 | count = hLoudnessInfoSet->loudnessInfoAlbumCount; |
2794 | 0 | pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; |
2795 | 481k | } else { |
2796 | 481k | count = hLoudnessInfoSet->loudnessInfoCount; |
2797 | 481k | pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; |
2798 | 481k | } |
2799 | | |
2800 | 808k | for (i = 0; i < count; i++) { |
2801 | 340k | if ((pLoudnessInfo[i].drcSetId == drcSetId) && |
2802 | 340k | (pLoudnessInfo[i].downmixId == downmixId)) { |
2803 | 33.1k | if (pLoudnessInfo[i].samplePeakLevelPresent) return 1; |
2804 | 33.1k | } |
2805 | 340k | } |
2806 | | |
2807 | 467k | return 0; |
2808 | 481k | } |
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 | 14.0k | ) { |
2814 | 14.0k | int i; |
2815 | 14.0k | int count; |
2816 | 14.0k | LOUDNESS_INFO* pLoudnessInfo = NULL; |
2817 | | |
2818 | 14.0k | if (albumMode) { |
2819 | 0 | count = hLoudnessInfoSet->loudnessInfoAlbumCount; |
2820 | 0 | pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; |
2821 | 14.0k | } else { |
2822 | 14.0k | count = hLoudnessInfoSet->loudnessInfoCount; |
2823 | 14.0k | pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; |
2824 | 14.0k | } |
2825 | | |
2826 | 35.3k | for (i = 0; i < count; i++) { |
2827 | 35.3k | if ((pLoudnessInfo[i].drcSetId == drcSetId) && |
2828 | 35.3k | (pLoudnessInfo[i].downmixId == downmixId)) { |
2829 | 16.1k | if (pLoudnessInfo[i].samplePeakLevelPresent) { |
2830 | 14.0k | *pSamplePeakLevel = pLoudnessInfo[i].samplePeakLevel; |
2831 | 14.0k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
2832 | 14.0k | } |
2833 | 16.1k | } |
2834 | 35.3k | } |
2835 | | |
2836 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
2837 | 14.0k | } |
2838 | | |
2839 | | static int _limiterPeakTargetIsPresent( |
2840 | 228k | DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction, int drcSetId, int downmixId) { |
2841 | 228k | int i; |
2842 | | |
2843 | 228k | if (pDrcInstruction->limiterPeakTargetPresent) { |
2844 | 18.3k | if ((pDrcInstruction->downmixId[0] == downmixId) || |
2845 | 18.3k | (pDrcInstruction->downmixId[0] == 0x7F)) { |
2846 | 17.0k | return 1; |
2847 | 17.0k | } |
2848 | | |
2849 | 7.48k | for (i = 0; i < pDrcInstruction->downmixIdCount; i++) { |
2850 | 6.90k | if (pDrcInstruction->downmixId[i] == downmixId) { |
2851 | 668 | return 1; |
2852 | 668 | } |
2853 | 6.90k | } |
2854 | 1.24k | } |
2855 | | |
2856 | 210k | return 0; |
2857 | 228k | } |
2858 | | |
2859 | | static DRCDEC_SELECTION_PROCESS_RETURN _getLimiterPeakTarget( |
2860 | | DRC_INSTRUCTIONS_UNI_DRC* pDrcInstruction, int drcSetId, int downmixId, |
2861 | 17.7k | FIXP_DBL* pLimiterPeakTarget) { |
2862 | 17.7k | int i; |
2863 | | |
2864 | 17.7k | if (pDrcInstruction->limiterPeakTargetPresent) { |
2865 | 17.7k | if ((pDrcInstruction->downmixId[0] == downmixId) || |
2866 | 17.7k | (pDrcInstruction->downmixId[0] == 0x7F)) { |
2867 | 17.0k | *pLimiterPeakTarget = |
2868 | 17.0k | ((FX_SGL2FX_DBL(pDrcInstruction->limiterPeakTarget) >> 2)); |
2869 | 17.0k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
2870 | 17.0k | } |
2871 | | |
2872 | 2.40k | for (i = 0; i < pDrcInstruction->downmixIdCount; i++) { |
2873 | 2.40k | if (pDrcInstruction->downmixId[i] == downmixId) { |
2874 | 668 | *pLimiterPeakTarget = |
2875 | 668 | ((FX_SGL2FX_DBL(pDrcInstruction->limiterPeakTarget) >> 2)); |
2876 | 668 | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
2877 | 668 | } |
2878 | 2.40k | } |
2879 | 668 | } |
2880 | | |
2881 | 0 | return DRCDEC_SELECTION_PROCESS_NOT_OK; |
2882 | 17.7k | } |
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 | 254k | ) { |
2911 | 254k | DRCDEC_SELECTION_PROCESS_RETURN retVal = DRCDEC_SELECTION_PROCESS_NO_ERROR; |
2912 | | |
2913 | 254k | int albumMode = hSelProcInput->albumMode; |
2914 | | |
2915 | 254k | FIXP_DBL signalPeakLevelTmp = (FIXP_DBL)0; |
2916 | 254k | FIXP_DBL signalPeakLevel = FIXP_DBL(0); |
2917 | | |
2918 | 254k | int dmxId = downmixIdRequested; |
2919 | | |
2920 | 254k | int drcSetId = pInst->drcSetId; |
2921 | | |
2922 | 254k | if (drcSetId < 0) { |
2923 | 219k | drcSetId = 0; |
2924 | 219k | } |
2925 | | |
2926 | 254k | *explicitPeakInformationPresent = 1; |
2927 | | |
2928 | 254k | if (_truePeakLevelIsPresent(hLoudnessInfoSet, drcSetId, dmxId, albumMode)) { |
2929 | 2.86k | retVal = _getTruePeakLevel(hLoudnessInfoSet, drcSetId, dmxId, albumMode, |
2930 | 2.86k | &signalPeakLevel); |
2931 | 2.86k | if (retVal) return (retVal); |
2932 | 251k | } else if (_samplePeakLevelIsPresent(hLoudnessInfoSet, drcSetId, dmxId, |
2933 | 251k | albumMode)) { |
2934 | 12.2k | retVal = _getSamplePeakLevel(hLoudnessInfoSet, drcSetId, dmxId, albumMode, |
2935 | 12.2k | &signalPeakLevel); |
2936 | 12.2k | if (retVal) return (retVal); |
2937 | 239k | } else if (_truePeakLevelIsPresent(hLoudnessInfoSet, 0x3F, dmxId, |
2938 | 239k | albumMode)) { |
2939 | 9.05k | retVal = _getTruePeakLevel(hLoudnessInfoSet, 0x3F, dmxId, albumMode, |
2940 | 9.05k | &signalPeakLevel); |
2941 | 9.05k | if (retVal) return (retVal); |
2942 | 230k | } else if (_samplePeakLevelIsPresent(hLoudnessInfoSet, 0x3F, dmxId, |
2943 | 230k | albumMode)) { |
2944 | 1.79k | retVal = _getSamplePeakLevel(hLoudnessInfoSet, 0x3F, dmxId, albumMode, |
2945 | 1.79k | &signalPeakLevel); |
2946 | 1.79k | if (retVal) return (retVal); |
2947 | 228k | } else if (_limiterPeakTargetIsPresent(pInst, drcSetId, dmxId)) { |
2948 | 17.7k | retVal = _getLimiterPeakTarget(pInst, drcSetId, dmxId, &signalPeakLevel); |
2949 | 17.7k | if (retVal) return (retVal); |
2950 | 210k | } 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 | 210k | } else { |
3018 | 210k | signalPeakLevel = FIXP_DBL(0); /* worst case estimate */ |
3019 | 210k | *explicitPeakInformationPresent = FIXP_DBL(0); |
3020 | 210k | } |
3021 | | |
3022 | 254k | *signalPeakLevelOut = signalPeakLevel; |
3023 | | |
3024 | 254k | return retVal; |
3025 | 254k | } |
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 | 211k | int methodDefinition, int startIndex) { |
3109 | 211k | int i; |
3110 | 211k | int index = -1; |
3111 | | |
3112 | 805k | for (i = startIndex; i < pLoudnessInfo->measurementCount; i++) { |
3113 | 683k | if (pLoudnessInfo->loudnessMeasurement[i].methodDefinition == |
3114 | 683k | methodDefinition) { |
3115 | 89.4k | index = i; |
3116 | 89.4k | break; |
3117 | 89.4k | } |
3118 | 683k | } |
3119 | | |
3120 | 211k | return index; |
3121 | 211k | } |
3122 | | |
3123 | | /*******************************************/ |
3124 | | |
3125 | | static DRCDEC_SELECTION_PROCESS_RETURN _getMixingLevel( |
3126 | | HANDLE_LOUDNESS_INFO_SET hLoudnessInfoSet, int downmixIdRequested, |
3127 | 207k | int drcSetIdRequested, int albumMode, FIXP_DBL* pMixingLevel) { |
3128 | 207k | const FIXP_DBL mixingLevelDefault = FL2FXCONST_DBL(85.0f / (float)(1 << 7)); |
3129 | | |
3130 | 207k | int i; |
3131 | 207k | int count; |
3132 | | |
3133 | 207k | LOUDNESS_INFO* pLoudnessInfo = NULL; |
3134 | | |
3135 | 207k | *pMixingLevel = mixingLevelDefault; |
3136 | | |
3137 | 207k | if (drcSetIdRequested < 0) { |
3138 | 200k | drcSetIdRequested = 0; |
3139 | 200k | } |
3140 | | |
3141 | 207k | if (albumMode) { |
3142 | 0 | count = hLoudnessInfoSet->loudnessInfoAlbumCount; |
3143 | 0 | pLoudnessInfo = hLoudnessInfoSet->loudnessInfoAlbum; |
3144 | 207k | } else { |
3145 | 207k | count = hLoudnessInfoSet->loudnessInfoCount; |
3146 | 207k | pLoudnessInfo = hLoudnessInfoSet->loudnessInfo; |
3147 | 207k | } |
3148 | | |
3149 | 316k | for (i = 0; i < count; i++) { |
3150 | 123k | if ((drcSetIdRequested == pLoudnessInfo[i].drcSetId) && |
3151 | 123k | ((downmixIdRequested == pLoudnessInfo[i].downmixId) || |
3152 | 63.0k | (DOWNMIX_ID_ANY_DOWNMIX == pLoudnessInfo[i].downmixId))) { |
3153 | 45.7k | int index = _findMethodDefinition(&pLoudnessInfo[i], MD_MIXING_LEVEL, 0); |
3154 | | |
3155 | 45.7k | if (index >= 0) { |
3156 | 15.0k | *pMixingLevel = pLoudnessInfo[i].loudnessMeasurement[index].methodValue; |
3157 | 15.0k | break; |
3158 | 15.0k | } |
3159 | 45.7k | } |
3160 | 123k | } |
3161 | | |
3162 | 207k | return DRCDEC_SELECTION_PROCESS_NO_ERROR; |
3163 | 207k | } |
3164 | | |
3165 | | /*******************************************/ |