1 /******************************************************************************
2 *
3 * Copyright (C) 2018 The Android Open Source Project
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at:
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 *****************************************************************************
18 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19 */
20 #include <stdio.h>
21 #include <math.h>
22
23 #include "impd_type_def.h"
24 #include "impd_drc_extr_delta_coded_info.h"
25 #include "impd_drc_common.h"
26 #include "impd_drc_struct.h"
27 #include "impd_drc_interface.h"
28 #include "impd_drc_selection_process.h"
29 #include "impd_drc_filter_bank.h"
30 #include "impd_drc_rom.h"
impd_signal_peak_level_info(ia_drc_config * pstr_drc_config,ia_drc_loudness_info_set_struct * pstr_loudness_info,ia_drc_instructions_struct * str_drc_instruction_str,WORD32 requested_dwnmix_id,WORD32 album_mode,WORD32 num_compression_eq_count,WORD32 * num_compression_eq_id,WORD32 * peak_info_count,WORD32 eq_set_id[],FLOAT32 signal_peak_level[],WORD32 explicit_peak_information_present[])31 WORD32 impd_signal_peak_level_info(
32 ia_drc_config* pstr_drc_config,
33 ia_drc_loudness_info_set_struct* pstr_loudness_info,
34 ia_drc_instructions_struct* str_drc_instruction_str,
35 WORD32 requested_dwnmix_id, WORD32 album_mode,
36 WORD32 num_compression_eq_count, WORD32* num_compression_eq_id,
37 WORD32* peak_info_count, WORD32 eq_set_id[], FLOAT32 signal_peak_level[],
38 WORD32 explicit_peak_information_present[]) {
39 WORD32 c, d, i, k, n, base_channel_count, mode;
40 WORD32 pre_lim_count;
41 WORD32 peak_count = 0;
42 WORD32 loudness_info_count = 0;
43 ia_loudness_info_struct* loudness_info;
44 FLOAT32 sum, max_sum;
45 WORD32 drc_set_id_requested = str_drc_instruction_str->drc_set_id;
46 WORD32 loudness_drc_set_id_requested;
47 WORD32 match_found_flag = 0;
48
49 FLOAT32 signal_peak_level_tmp;
50 eq_set_id[0] = 0;
51 signal_peak_level[0] = 0.0f;
52 explicit_peak_information_present[0] = 0;
53
54 k = 0;
55 if (drc_set_id_requested < 0) {
56 for (k = 0; k < num_compression_eq_count; k++) {
57 eq_set_id[k] = num_compression_eq_id[k];
58 signal_peak_level[k] = 0.0f;
59 explicit_peak_information_present[k] = 0;
60 }
61 }
62 eq_set_id[k] = 0;
63 signal_peak_level[k] = 0.0f;
64 explicit_peak_information_present[k] = 0;
65 k++;
66
67 pre_lim_count = k;
68
69 if (drc_set_id_requested < 0) {
70 loudness_drc_set_id_requested = 0;
71 } else {
72 loudness_drc_set_id_requested = drc_set_id_requested;
73 }
74
75 if (album_mode == 1) {
76 mode = 1;
77 loudness_info_count = pstr_loudness_info->loudness_info_album_count;
78 } else {
79 mode = 0;
80 loudness_info_count = pstr_loudness_info->loudness_info_count;
81 }
82
83 for (n = 0; n < loudness_info_count; n++) {
84 if (mode == 1) {
85 loudness_info = &(pstr_loudness_info->str_loudness_info_album[n]);
86 } else {
87 loudness_info = &(pstr_loudness_info->loudness_info[n]);
88 }
89 if (loudness_drc_set_id_requested == loudness_info->drc_set_id &&
90 requested_dwnmix_id == loudness_info->downmix_id) {
91 if (loudness_info->true_peak_level_present) {
92 eq_set_id[peak_count] = loudness_info->eq_set_id;
93
94 signal_peak_level[peak_count] = loudness_info->true_peak_level;
95 explicit_peak_information_present[peak_count] = 1;
96
97 match_found_flag = 1;
98 peak_count++;
99 }
100 if (match_found_flag == 0) {
101 if (loudness_info->sample_peak_level_present) {
102 eq_set_id[peak_count] = loudness_info->eq_set_id;
103
104 signal_peak_level[peak_count] = loudness_info->sample_peak_level;
105 explicit_peak_information_present[peak_count] = 1;
106
107 match_found_flag = 1;
108 peak_count++;
109 }
110 }
111 }
112 }
113 if (match_found_flag == 0) {
114 for (n = 0; n < loudness_info_count; n++) {
115 if (mode == 1) {
116 loudness_info = &(pstr_loudness_info->str_loudness_info_album[n]);
117 } else {
118 loudness_info = &(pstr_loudness_info->loudness_info[n]);
119 }
120 if (ID_FOR_ANY_DRC == loudness_info->drc_set_id &&
121 requested_dwnmix_id == loudness_info->downmix_id) {
122 if (loudness_info->true_peak_level_present) {
123 eq_set_id[peak_count] = loudness_info->eq_set_id;
124
125 signal_peak_level[peak_count] = loudness_info->true_peak_level;
126 explicit_peak_information_present[peak_count] = 1;
127
128 match_found_flag = 1;
129 peak_count++;
130 }
131 if (match_found_flag == 0) {
132 if (loudness_info->sample_peak_level_present) {
133 eq_set_id[peak_count] = loudness_info->eq_set_id;
134
135 signal_peak_level[peak_count] = loudness_info->sample_peak_level;
136 explicit_peak_information_present[peak_count] = 1;
137
138 match_found_flag = 1;
139 peak_count++;
140 }
141 }
142 }
143 }
144 }
145 if (match_found_flag == 0) {
146 for (i = 0; i < str_drc_instruction_str->dwnmix_id_count; i++) {
147 if (requested_dwnmix_id == str_drc_instruction_str->downmix_id[0] ||
148 ID_FOR_ANY_DOWNMIX == str_drc_instruction_str->downmix_id[0]) {
149 if (str_drc_instruction_str->limiter_peak_target_present) {
150 if (str_drc_instruction_str->requires_eq == 1) {
151 for (d = 0;
152 d < pstr_drc_config->str_drc_config_ext.eq_instructions_count;
153 d++) {
154 ia_eq_instructions_struct* eq_instructions =
155 &pstr_drc_config->str_drc_config_ext.str_eq_instructions[d];
156 for (c = 0; c < eq_instructions->drc_set_id_count; c++) {
157 if ((eq_instructions->drc_set_id[c] ==
158 loudness_drc_set_id_requested) ||
159 (eq_instructions->drc_set_id[c] == ID_FOR_ANY_DRC)) {
160 for (i = 0; i < eq_instructions->dwnmix_id_count; i++) {
161 if ((eq_instructions->downmix_id[i] ==
162 requested_dwnmix_id) ||
163 (eq_instructions->downmix_id[i] ==
164 ID_FOR_ANY_DOWNMIX)) {
165 eq_set_id[peak_count] = eq_instructions->eq_set_id;
166 signal_peak_level[peak_count] =
167 str_drc_instruction_str->limiter_peak_target;
168 explicit_peak_information_present[peak_count] = 1;
169 match_found_flag = 1;
170 peak_count++;
171 }
172 }
173 }
174 }
175 }
176 } else
177
178 {
179 eq_set_id[peak_count] = 0;
180 signal_peak_level[peak_count] =
181 str_drc_instruction_str->limiter_peak_target;
182 explicit_peak_information_present[peak_count] = 1;
183 match_found_flag = 1;
184 peak_count++;
185 }
186 }
187 }
188 }
189 }
190 if (match_found_flag == 0) {
191 for (i = 1; i < str_drc_instruction_str->dwnmix_id_count; i++) {
192 if (requested_dwnmix_id == str_drc_instruction_str->downmix_id[i]) {
193 if (str_drc_instruction_str->limiter_peak_target_present) {
194 {
195 eq_set_id[peak_count] = 0;
196 signal_peak_level[peak_count] =
197 str_drc_instruction_str->limiter_peak_target;
198 explicit_peak_information_present[peak_count] = 1;
199 match_found_flag = 1;
200 peak_count++;
201 }
202 }
203 }
204 }
205 }
206 if (match_found_flag == 0) {
207 if (requested_dwnmix_id != ID_FOR_BASE_LAYOUT) {
208 signal_peak_level_tmp = 0.f;
209 for (i = 0; i < pstr_drc_config->dwnmix_instructions_count; i++) {
210 if (pstr_drc_config->dwnmix_instructions[i].downmix_id ==
211 requested_dwnmix_id) {
212 if (pstr_drc_config->dwnmix_instructions[i]
213 .downmix_coefficients_present) {
214 base_channel_count =
215 pstr_drc_config->channel_layout.base_channel_count;
216 max_sum = 0.0f;
217 for (c = 0;
218 c <
219 pstr_drc_config->dwnmix_instructions[i].target_channel_count;
220 c++) {
221 sum = 0.0f;
222 for (d = 0; d < base_channel_count; d++) {
223 sum += pstr_drc_config->dwnmix_instructions[i]
224 .downmix_coefficient[c * base_channel_count + d];
225 }
226 if (max_sum < sum) max_sum = sum;
227 }
228 signal_peak_level_tmp = 20.0f * (FLOAT32)log10(max_sum);
229 } else {
230 }
231 break;
232 }
233 }
234 for (n = 0; n < loudness_info_count; n++) {
235 if (mode == 1) {
236 loudness_info = &(pstr_loudness_info->str_loudness_info_album[n]);
237 } else {
238 loudness_info = &(pstr_loudness_info->loudness_info[n]);
239 }
240 if (loudness_drc_set_id_requested == loudness_info->drc_set_id &&
241 ID_FOR_BASE_LAYOUT == loudness_info->downmix_id) {
242 if (loudness_info->true_peak_level_present) {
243 eq_set_id[peak_count] = loudness_info->eq_set_id;
244
245 signal_peak_level[peak_count] =
246 loudness_info->true_peak_level + signal_peak_level_tmp;
247 explicit_peak_information_present[peak_count] = 0;
248
249 match_found_flag = 1;
250 peak_count++;
251 }
252 if (match_found_flag == 0) {
253 if (loudness_info->sample_peak_level_present) {
254 eq_set_id[peak_count] = loudness_info->eq_set_id;
255
256 signal_peak_level[peak_count] =
257 loudness_info->sample_peak_level + signal_peak_level_tmp;
258 explicit_peak_information_present[peak_count] = 0;
259
260 match_found_flag = 1;
261 peak_count++;
262 }
263 }
264 }
265 }
266 if (match_found_flag == 0) {
267 for (n = 0; n < loudness_info_count; n++) {
268 if (mode == 1) {
269 loudness_info = &(pstr_loudness_info->str_loudness_info_album[n]);
270 } else {
271 loudness_info = &(pstr_loudness_info->loudness_info[n]);
272 }
273 if (ID_FOR_ANY_DRC == loudness_info->drc_set_id &&
274 ID_FOR_BASE_LAYOUT == loudness_info->downmix_id) {
275 if (loudness_info->true_peak_level_present) {
276 eq_set_id[peak_count] = loudness_info->eq_set_id;
277
278 signal_peak_level[peak_count] =
279 loudness_info->true_peak_level + signal_peak_level_tmp;
280 explicit_peak_information_present[peak_count] = 0;
281
282 match_found_flag = 1;
283 peak_count++;
284 }
285 if (match_found_flag == 0) {
286 if (loudness_info->sample_peak_level_present) {
287 eq_set_id[peak_count] = loudness_info->eq_set_id;
288
289 signal_peak_level[peak_count] =
290 loudness_info->sample_peak_level + signal_peak_level_tmp;
291 explicit_peak_information_present[peak_count] = 0;
292
293 match_found_flag = 1;
294 peak_count++;
295 }
296 }
297 }
298 }
299 }
300 if (match_found_flag == 0) {
301 ia_drc_instructions_struct* drc_instructions_drc_tmp;
302 for (n = 0; n < pstr_drc_config->drc_instructions_count_plus; n++) {
303 drc_instructions_drc_tmp =
304 &pstr_drc_config->str_drc_instruction_str[n];
305 if (loudness_drc_set_id_requested ==
306 drc_instructions_drc_tmp->drc_set_id) {
307 for (k = 0; k < drc_instructions_drc_tmp->dwnmix_id_count; k++) {
308 if (ID_FOR_BASE_LAYOUT ==
309 drc_instructions_drc_tmp->downmix_id[k]) {
310 if (drc_instructions_drc_tmp->limiter_peak_target_present) {
311 eq_set_id[peak_count] = -1;
312 signal_peak_level[peak_count] =
313 drc_instructions_drc_tmp->limiter_peak_target +
314 signal_peak_level_tmp;
315 explicit_peak_information_present[peak_count] = 0;
316 match_found_flag = 1;
317 peak_count++;
318 }
319 }
320 break;
321 }
322 }
323 }
324 }
325 }
326 }
327 if (peak_count > 0) {
328 *peak_info_count = peak_count;
329 } else {
330 *peak_info_count = pre_lim_count;
331 }
332 return (0);
333 }
334
335 WORD32
impd_extract_loudness_peak_to_average_info(ia_loudness_info_struct * loudness_info,WORD32 dyn_range_measurement_type,WORD32 * loudness_peak_2_avg_value_present,FLOAT32 * loudness_peak_2_avg_value)336 impd_extract_loudness_peak_to_average_info(
337 ia_loudness_info_struct* loudness_info, WORD32 dyn_range_measurement_type,
338 WORD32* loudness_peak_2_avg_value_present,
339 FLOAT32* loudness_peak_2_avg_value) {
340 WORD32 k;
341 WORD32 program_loudness_present = 0;
342 WORD32 peak_loudness_present = 0;
343 WORD32 match_measure_program_loudness = 0;
344 WORD32 match_measure_peak_loudness = 0;
345 FLOAT32 program_loudness = 0.0f;
346 FLOAT32 peak_loudness = 0.0f;
347 ia_loudness_measure_struct* loudness_measure = NULL;
348
349 for (k = 0; k < loudness_info->measurement_count; k++) {
350 loudness_measure = &(loudness_info->loudness_measure[k]);
351 if (loudness_measure->method_def == METHOD_DEFINITION_PROGRAM_LOUDNESS) {
352 if (match_measure_program_loudness <
353 measurement_method_prog_loudness_tbl[loudness_measure
354 ->measurement_system]) {
355 program_loudness = loudness_measure->method_val;
356 program_loudness_present = 1;
357 match_measure_program_loudness =
358 measurement_method_prog_loudness_tbl[loudness_measure
359 ->measurement_system];
360 }
361 }
362 switch (dyn_range_measurement_type) {
363 case SHORT_TERM_LOUDNESS_TO_AVG:
364 if (loudness_measure->method_def ==
365 METHOD_DEFINITION_SHORT_TERM_LOUDNESS_MAX) {
366 if (match_measure_peak_loudness <
367 measurement_method_peak_loudness_tbl[loudness_measure
368 ->measurement_system]) {
369 peak_loudness = loudness_measure->method_val;
370 peak_loudness_present = 1;
371 match_measure_peak_loudness =
372 measurement_method_peak_loudness_tbl[loudness_measure
373 ->measurement_system];
374 }
375 }
376 break;
377
378 case MOMENTARY_LOUDNESS_TO_AVG:
379 if (loudness_measure->method_def ==
380 METHOD_DEFINITION_MOMENTARY_LOUDNESS_MAX) {
381 if (match_measure_peak_loudness <
382 measurement_method_peak_loudness_tbl[loudness_measure
383 ->measurement_system]) {
384 peak_loudness = loudness_measure->method_val;
385 peak_loudness_present = 1;
386 match_measure_peak_loudness =
387 measurement_method_peak_loudness_tbl[loudness_measure
388 ->measurement_system];
389 }
390 }
391 break;
392
393 case TOP_OF_LOUDNESS_RANGE_TO_AVG:
394 if (loudness_measure->method_def ==
395 METHOD_DEFINITION_MAX_OF_LOUDNESS_RANGE) {
396 if (match_measure_peak_loudness <
397 measurement_method_peak_loudness_tbl[loudness_measure
398 ->measurement_system]) {
399 peak_loudness = loudness_measure->method_val;
400 peak_loudness_present = 1;
401 match_measure_peak_loudness =
402 measurement_method_peak_loudness_tbl[loudness_measure
403 ->measurement_system];
404 }
405 }
406 break;
407
408 default:
409 return (UNEXPECTED_ERROR);
410
411 break;
412 }
413 }
414 if ((program_loudness_present == 1) && (peak_loudness_present == 1)) {
415 *loudness_peak_2_avg_value = peak_loudness - program_loudness;
416 *loudness_peak_2_avg_value_present = 1;
417 }
418 return (0);
419 }
420
impd_loudness_peak_to_average_info(ia_drc_loudness_info_set_struct * pstr_loudness_info,ia_drc_instructions_struct * str_drc_instruction_str,WORD32 requested_dwnmix_id,WORD32 dyn_range_measurement_type,WORD32 album_mode,WORD32 * loudness_peak_2_avg_value_present,FLOAT32 * loudness_peak_2_avg_value)421 WORD32 impd_loudness_peak_to_average_info(
422 ia_drc_loudness_info_set_struct* pstr_loudness_info,
423 ia_drc_instructions_struct* str_drc_instruction_str,
424 WORD32 requested_dwnmix_id, WORD32 dyn_range_measurement_type,
425 WORD32 album_mode, WORD32* loudness_peak_2_avg_value_present,
426 FLOAT32* loudness_peak_2_avg_value) {
427 WORD32 n, err;
428 WORD32 drc_set_id = max(0, str_drc_instruction_str->drc_set_id);
429
430 *loudness_peak_2_avg_value_present = 0;
431
432 if (album_mode == 1) {
433 for (n = 0; n < pstr_loudness_info->loudness_info_album_count; n++) {
434 ia_loudness_info_struct* loudness_info =
435 &(pstr_loudness_info->str_loudness_info_album[n]);
436 if (drc_set_id == loudness_info->drc_set_id) {
437 if (requested_dwnmix_id == loudness_info->downmix_id) {
438 err = impd_extract_loudness_peak_to_average_info(
439 loudness_info, dyn_range_measurement_type,
440 loudness_peak_2_avg_value_present, loudness_peak_2_avg_value);
441 if (err) return (err);
442 }
443 }
444 }
445 }
446 if (*loudness_peak_2_avg_value_present == 0) {
447 for (n = 0; n < pstr_loudness_info->loudness_info_count; n++) {
448 ia_loudness_info_struct* loudness_info =
449 &(pstr_loudness_info->loudness_info[n]);
450 if (drc_set_id == loudness_info->drc_set_id) {
451 if (requested_dwnmix_id == loudness_info->downmix_id) {
452 err = impd_extract_loudness_peak_to_average_info(
453 loudness_info, dyn_range_measurement_type,
454 loudness_peak_2_avg_value_present, loudness_peak_2_avg_value);
455 if (err) return (err);
456 }
457 }
458 }
459 }
460 return (0);
461 }
462
impd_overall_loudness_present(ia_loudness_info_struct * loudness_info,WORD32 * loudness_info_present)463 WORD32 impd_overall_loudness_present(ia_loudness_info_struct* loudness_info,
464 WORD32* loudness_info_present) {
465 WORD32 m;
466
467 *loudness_info_present = 0;
468 for (m = 0; m < loudness_info->measurement_count; m++) {
469 if ((loudness_info->loudness_measure[m].method_def ==
470 METHOD_DEFINITION_PROGRAM_LOUDNESS) ||
471 (loudness_info->loudness_measure[m].method_def ==
472 METHOD_DEFINITION_ANCHOR_LOUDNESS)) {
473 *loudness_info_present = 1;
474 }
475 }
476 return (0);
477 }
478
impd_check_loud_info(WORD32 loudness_info_count,ia_loudness_info_struct * loudness_info,WORD32 requested_dwnmix_id,WORD32 drc_set_id_requested,WORD32 * info_count,ia_loudness_info_struct * loudness_info_matching[])479 WORD32 impd_check_loud_info(WORD32 loudness_info_count,
480 ia_loudness_info_struct* loudness_info,
481 WORD32 requested_dwnmix_id,
482 WORD32 drc_set_id_requested, WORD32* info_count,
483 ia_loudness_info_struct* loudness_info_matching[]) {
484 WORD32 n, err;
485 WORD32 loudness_info_present;
486 for (n = 0; n < loudness_info_count; n++) {
487 if (requested_dwnmix_id == loudness_info[n].downmix_id) {
488 if (drc_set_id_requested == loudness_info[n].drc_set_id) {
489 err = impd_overall_loudness_present(&(loudness_info[n]),
490 &loudness_info_present);
491 if (err) return (err);
492 if (loudness_info_present) {
493 loudness_info_matching[*info_count] = &(loudness_info[n]);
494 (*info_count)++;
495 }
496 }
497 }
498 }
499
500 return (0);
501 }
502
impd_check_loud_payload(WORD32 loudness_info_count,ia_loudness_info_struct * loudness_info,WORD32 requested_dwnmix_id,WORD32 drc_set_id_requested,WORD32 * info_count,ia_loudness_info_struct * loudness_info_matching[])503 WORD32 impd_check_loud_payload(
504 WORD32 loudness_info_count, ia_loudness_info_struct* loudness_info,
505 WORD32 requested_dwnmix_id, WORD32 drc_set_id_requested, WORD32* info_count,
506 ia_loudness_info_struct* loudness_info_matching[]) {
507 WORD32 err = 0;
508
509 err = impd_check_loud_info(loudness_info_count, loudness_info,
510 requested_dwnmix_id, drc_set_id_requested,
511 info_count, loudness_info_matching);
512 if (err || *info_count) goto matchEnd;
513 err = impd_check_loud_info(loudness_info_count, loudness_info,
514 ID_FOR_ANY_DOWNMIX, drc_set_id_requested,
515 info_count, loudness_info_matching);
516 if (err || *info_count) goto matchEnd;
517 err = impd_check_loud_info(loudness_info_count, loudness_info,
518 requested_dwnmix_id, ID_FOR_ANY_DRC, info_count,
519 loudness_info_matching);
520 if (err || *info_count) goto matchEnd;
521 err = impd_check_loud_info(loudness_info_count, loudness_info,
522 requested_dwnmix_id, ID_FOR_NO_DRC, info_count,
523 loudness_info_matching);
524 if (err || *info_count) goto matchEnd;
525 err = impd_check_loud_info(loudness_info_count, loudness_info,
526 ID_FOR_ANY_DOWNMIX, ID_FOR_ANY_DRC, info_count,
527 loudness_info_matching);
528 if (err || *info_count) goto matchEnd;
529 err = impd_check_loud_info(loudness_info_count, loudness_info,
530 ID_FOR_ANY_DOWNMIX, ID_FOR_NO_DRC, info_count,
531 loudness_info_matching);
532 if (err || *info_count) goto matchEnd;
533 err = impd_check_loud_info(loudness_info_count, loudness_info,
534 ID_FOR_BASE_LAYOUT, drc_set_id_requested,
535 info_count, loudness_info_matching);
536 if (err || *info_count) goto matchEnd;
537 err = impd_check_loud_info(loudness_info_count, loudness_info,
538 ID_FOR_BASE_LAYOUT, ID_FOR_ANY_DRC, info_count,
539 loudness_info_matching);
540 if (err || *info_count) goto matchEnd;
541 err = impd_check_loud_info(loudness_info_count, loudness_info,
542 ID_FOR_BASE_LAYOUT, ID_FOR_NO_DRC, info_count,
543 loudness_info_matching);
544 if (err || *info_count) goto matchEnd;
545 matchEnd:
546 return (err);
547 }
548
impd_find_overall_loudness_info(ia_drc_sel_proc_params_struct * pstr_drc_sel_proc_params_struct,ia_drc_loudness_info_set_struct * pstr_loudness_info,WORD32 requested_dwnmix_id,WORD32 drc_set_id_requested,WORD32 * overall_loudness_info_present,WORD32 * info_count,ia_loudness_info_struct * loudness_info_matching[])549 WORD32 impd_find_overall_loudness_info(
550 ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct,
551 ia_drc_loudness_info_set_struct* pstr_loudness_info,
552 WORD32 requested_dwnmix_id, WORD32 drc_set_id_requested,
553 WORD32* overall_loudness_info_present, WORD32* info_count,
554 ia_loudness_info_struct* loudness_info_matching[]) {
555 WORD32 err;
556 WORD32 loudness_drc_set_id_requested;
557
558 *info_count = 0;
559 if (drc_set_id_requested < 0) {
560 loudness_drc_set_id_requested = ID_FOR_NO_DRC;
561 } else {
562 loudness_drc_set_id_requested = drc_set_id_requested;
563 }
564 if (pstr_drc_sel_proc_params_struct->album_mode == 1) {
565 err = impd_check_loud_payload(
566 pstr_loudness_info->loudness_info_album_count,
567 pstr_loudness_info->str_loudness_info_album, requested_dwnmix_id,
568 loudness_drc_set_id_requested, info_count, loudness_info_matching);
569 if (err) return (err);
570 }
571 if (*info_count == 0) {
572 err = impd_check_loud_payload(pstr_loudness_info->loudness_info_count,
573 pstr_loudness_info->loudness_info,
574 requested_dwnmix_id,
575 loudness_drc_set_id_requested,
576
577 info_count, loudness_info_matching);
578 if (err) return (err);
579 }
580 *overall_loudness_info_present = (*info_count > 0);
581 return (0);
582 }
583
584 WORD32
impd_high_pass_loudness_adjust_info(ia_loudness_info_struct * loudness_info,WORD32 * loudness_hp_adjust_present,FLOAT32 * loudness_hp_adjust)585 impd_high_pass_loudness_adjust_info(ia_loudness_info_struct* loudness_info,
586 WORD32* loudness_hp_adjust_present,
587 FLOAT32* loudness_hp_adjust) {
588 WORD32 m, k;
589
590 *loudness_hp_adjust_present = 0;
591 *loudness_hp_adjust = 0.0f;
592 for (m = 0; m < loudness_info->measurement_count; m++) {
593 if (loudness_info->loudness_measure[m].measurement_system ==
594 MEASUREMENT_SYSTEM_BS_1770_4_PRE_PROCESSING) {
595 for (k = 0; k < loudness_info->measurement_count; k++) {
596 if (loudness_info->loudness_measure[k].measurement_system ==
597 MEASUREMENT_SYSTEM_BS_1770_4) {
598 if (loudness_info->loudness_measure[m].method_def ==
599 loudness_info->loudness_measure[k].method_def) {
600 *loudness_hp_adjust_present = 1;
601 *loudness_hp_adjust =
602 loudness_info->loudness_measure[m].method_val -
603 loudness_info->loudness_measure[k].method_val;
604 }
605 }
606 }
607 }
608 }
609 return (0);
610 }
611
impd_find_high_pass_loudness_adjust(ia_drc_loudness_info_set_struct * pstr_loudness_info,WORD32 requested_dwnmix_id,WORD32 drc_set_id_requested,WORD32 album_mode,FLOAT32 device_cutoff_freq,WORD32 * loudness_hp_adjust_present,FLOAT32 * loudness_hp_adjust)612 WORD32 impd_find_high_pass_loudness_adjust(
613 ia_drc_loudness_info_set_struct* pstr_loudness_info,
614 WORD32 requested_dwnmix_id, WORD32 drc_set_id_requested, WORD32 album_mode,
615 FLOAT32 device_cutoff_freq, WORD32* loudness_hp_adjust_present,
616 FLOAT32* loudness_hp_adjust) {
617 WORD32 n, err;
618 WORD32 loudness_drc_set_id_requested;
619
620 if (drc_set_id_requested < 0) {
621 loudness_drc_set_id_requested = 0;
622 } else {
623 loudness_drc_set_id_requested = drc_set_id_requested;
624 }
625
626 *loudness_hp_adjust_present = 0;
627
628 if (album_mode == 1) {
629 for (n = 0; n < pstr_loudness_info->loudness_info_album_count; n++) {
630 if ((requested_dwnmix_id ==
631 pstr_loudness_info->str_loudness_info_album[n].downmix_id) ||
632 (ID_FOR_ANY_DOWNMIX ==
633 pstr_loudness_info->str_loudness_info_album[n].downmix_id)) {
634 if (loudness_drc_set_id_requested ==
635 pstr_loudness_info->str_loudness_info_album[n].drc_set_id) {
636 err = impd_high_pass_loudness_adjust_info(
637 &(pstr_loudness_info->loudness_info[n]),
638 loudness_hp_adjust_present, loudness_hp_adjust);
639 if (err) return (err);
640 }
641 }
642 }
643 }
644 if (*loudness_hp_adjust_present == 0) {
645 for (n = 0; n < pstr_loudness_info->loudness_info_count; n++) {
646 if ((requested_dwnmix_id ==
647 pstr_loudness_info->loudness_info[n].downmix_id) ||
648 (ID_FOR_ANY_DOWNMIX ==
649 pstr_loudness_info->loudness_info[n].downmix_id)) {
650 if (loudness_drc_set_id_requested ==
651 pstr_loudness_info->loudness_info[n].drc_set_id) {
652 err = impd_high_pass_loudness_adjust_info(
653 &(pstr_loudness_info->loudness_info[n]),
654 loudness_hp_adjust_present, loudness_hp_adjust);
655 if (err) return (err);
656 }
657 }
658 }
659 }
660 if (*loudness_hp_adjust_present == 0) {
661 for (n = 0; n < pstr_loudness_info->loudness_info_count; n++) {
662 if (ID_FOR_BASE_LAYOUT ==
663 pstr_loudness_info->loudness_info[n].downmix_id) /* base layout */
664 {
665 if (loudness_drc_set_id_requested ==
666 pstr_loudness_info->loudness_info[n].drc_set_id) {
667 err = impd_high_pass_loudness_adjust_info(
668 &(pstr_loudness_info->loudness_info[n]),
669 loudness_hp_adjust_present, loudness_hp_adjust);
670 if (err) return (err);
671 }
672 }
673 }
674 }
675 if (*loudness_hp_adjust_present == 0) {
676 for (n = 0; n < pstr_loudness_info->loudness_info_count; n++) {
677 if (ID_FOR_BASE_LAYOUT ==
678 pstr_loudness_info->loudness_info[n].downmix_id) /* base layout */
679 {
680 if (0 == pstr_loudness_info->loudness_info[n].drc_set_id) {
681 err = impd_high_pass_loudness_adjust_info(
682 &(pstr_loudness_info->loudness_info[n]),
683 loudness_hp_adjust_present, loudness_hp_adjust);
684 if (err) return (err);
685 }
686 }
687 }
688 }
689 if (*loudness_hp_adjust_present == 0) {
690 *loudness_hp_adjust = 0.0f;
691 } else {
692 *loudness_hp_adjust *=
693 (max(20.0f, min(500.0f, device_cutoff_freq)) - 20.0f) /
694 (500.0f - 20.0f);
695 }
696 return (0);
697 }
698
impd_init_loudness_control(ia_drc_sel_proc_params_struct * pstr_drc_sel_proc_params_struct,ia_drc_loudness_info_set_struct * pstr_loudness_info,WORD32 requested_dwnmix_id,WORD32 drc_set_id_requested,WORD32 num_compression_eq_count,WORD32 * num_compression_eq_id,WORD32 * loudness_info_count,WORD32 eq_set_id[],FLOAT32 loudness_normalization_gain_db[],FLOAT32 loudness[])699 WORD32 impd_init_loudness_control(
700 ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct,
701 ia_drc_loudness_info_set_struct* pstr_loudness_info,
702 WORD32 requested_dwnmix_id, WORD32 drc_set_id_requested,
703 WORD32 num_compression_eq_count, WORD32* num_compression_eq_id,
704 WORD32* loudness_info_count, WORD32 eq_set_id[],
705 FLOAT32 loudness_normalization_gain_db[], FLOAT32 loudness[]) {
706 WORD32 err, k, info_count = 0, pre_lim_count;
707 WORD32 loudness_hp_adjust_present;
708 WORD32 overall_loudness_info_present;
709 FLOAT32 pre_proc_adjust;
710
711 k = 0;
712 if (drc_set_id_requested < 0) {
713 for (k = 0; k < num_compression_eq_count; k++) {
714 eq_set_id[k] = num_compression_eq_id[k];
715 loudness[k] = UNDEFINED_LOUDNESS_VALUE;
716 loudness_normalization_gain_db[k] = 0.0f;
717 }
718 }
719 if (k >= MAX_NUM_COMPRESSION_EQ) return UNEXPECTED_ERROR;
720 eq_set_id[k] = 0;
721
722 loudness[k] = UNDEFINED_LOUDNESS_VALUE;
723
724 loudness_normalization_gain_db[k] = 0.0f;
725 k++;
726
727 pre_lim_count = k;
728
729 if (pstr_drc_sel_proc_params_struct->loudness_normalization_on == 1) {
730 WORD32 n;
731 ia_loudness_info_struct* loudness_info[16];
732 err = impd_find_overall_loudness_info(
733 pstr_drc_sel_proc_params_struct, pstr_loudness_info,
734 requested_dwnmix_id, drc_set_id_requested,
735 &overall_loudness_info_present, &info_count, loudness_info);
736 if (err) return (err);
737
738 if (overall_loudness_info_present == 1) {
739 WORD32 requested_method_definition = METHOD_DEFINITION_PROGRAM_LOUDNESS;
740 WORD32 other_method_definition = METHOD_DEFINITION_PROGRAM_LOUDNESS;
741 WORD32 requested_measurement_system = MEASUREMENT_SYSTEM_BS_1770_4;
742 WORD32 requested_preprocessing = 0;
743
744 const WORD32* system_bonus = measurement_system_default_tbl;
745
746 WORD32 match_measure;
747 FLOAT32 method_val = 0;
748
749 switch (pstr_drc_sel_proc_params_struct->loudness_measurement_method) {
750 case USER_METHOD_DEFINITION_DEFAULT:
751 case USER_METHOD_DEFINITION_PROGRAM_LOUDNESS:
752 requested_method_definition = METHOD_DEFINITION_PROGRAM_LOUDNESS;
753 other_method_definition = METHOD_DEFINITION_ANCHOR_LOUDNESS;
754 break;
755 case USER_METHOD_DEFINITION_ANCHOR_LOUDNESS:
756 requested_method_definition = METHOD_DEFINITION_ANCHOR_LOUDNESS;
757 other_method_definition = METHOD_DEFINITION_PROGRAM_LOUDNESS;
758 break;
759
760 default:
761 return (UNEXPECTED_ERROR);
762 break;
763 }
764
765 switch (pstr_drc_sel_proc_params_struct->loudness_measurement_system) {
766 case USER_MEASUREMENT_SYSTEM_DEFAULT:
767 case USER_MEASUREMENT_SYSTEM_BS_1770_4:
768 requested_measurement_system = MEASUREMENT_SYSTEM_BS_1770_4;
769 system_bonus = measurement_system_bs1770_3_tbl;
770 break;
771 case USER_MEASUREMENT_SYSTEM_USER:
772 requested_measurement_system = MEASUREMENT_SYSTEM_USER;
773 system_bonus = measurement_system_user_tbl;
774 break;
775 case USER_MEASUREMENT_SYSTEM_EXPERT_PANEL:
776 requested_measurement_system = MEASUREMENT_SYSTEM_EXPERT_PANEL;
777 system_bonus = measurement_system_expert_tbl;
778 break;
779 case USER_MEASUREMENT_SYSTEM_RESERVED_A:
780 requested_measurement_system = USER_MEASUREMENT_SYSTEM_RESERVED_A;
781 system_bonus = measurement_system_rms_a_tbl;
782 break;
783 case USER_MEASUREMENT_SYSTEM_RESERVED_B:
784 requested_measurement_system = USER_MEASUREMENT_SYSTEM_RESERVED_B;
785 system_bonus = measurement_system_rms_b_tbl;
786 break;
787 case USER_MEASUREMENT_SYSTEM_RESERVED_C:
788 requested_measurement_system = USER_MEASUREMENT_SYSTEM_RESERVED_C;
789 system_bonus = measurement_system_rms_c_tbl;
790 break;
791 case USER_MEASUREMENT_SYSTEM_RESERVED_D:
792 requested_measurement_system = USER_MEASUREMENT_SYSTEM_RESERVED_D;
793 system_bonus = measurement_system_rms_d_tbl;
794 break;
795 case USER_MEASUREMENT_SYSTEM_RESERVED_E:
796 requested_measurement_system = USER_MEASUREMENT_SYSTEM_RESERVED_E;
797 system_bonus = measurement_system_rms_e_tbl;
798 break;
799
800 default:
801 return (UNEXPECTED_ERROR);
802 break;
803 }
804
805 switch (pstr_drc_sel_proc_params_struct->loudness_measurement_pre_proc) {
806 case USER_LOUDNESS_PREPROCESSING_DEFAULT:
807 case USER_LOUDNESS_PREPROCESSING_OFF:
808 requested_preprocessing = 0;
809 break;
810 case USER_LOUDNESS_PREPROCESSING_HIGHPASS:
811 requested_preprocessing = 1;
812 break;
813
814 default:
815 return (UNEXPECTED_ERROR);
816 break;
817 }
818
819 for (k = 0; k < info_count; k++) {
820 match_measure = -1;
821 for (n = 0; n < loudness_info[k]->measurement_count; n++) {
822 ia_loudness_measure_struct* loudness_measure =
823 &(loudness_info[k]->loudness_measure[n]);
824 if (match_measure <
825 system_bonus[loudness_measure->measurement_system] &&
826 requested_method_definition == loudness_measure->method_def) {
827 method_val = loudness_measure->method_val;
828 match_measure = system_bonus[loudness_measure->measurement_system];
829 }
830 }
831 if (match_measure == -1) {
832 for (n = 0; n < loudness_info[k]->measurement_count; n++) {
833 ia_loudness_measure_struct* loudness_measure =
834 &(loudness_info[k]->loudness_measure[n]);
835 if (match_measure <
836 system_bonus[loudness_measure->measurement_system] &&
837 other_method_definition == loudness_measure->method_def) {
838 method_val = loudness_measure->method_val;
839 match_measure =
840 system_bonus[loudness_measure->measurement_system];
841 }
842 }
843 }
844
845 if (requested_preprocessing == 1) {
846 err = impd_find_high_pass_loudness_adjust(
847 pstr_loudness_info, requested_dwnmix_id, drc_set_id_requested,
848 pstr_drc_sel_proc_params_struct->album_mode,
849 (FLOAT32)
850 pstr_drc_sel_proc_params_struct->device_cut_off_frequency,
851 &loudness_hp_adjust_present, &pre_proc_adjust);
852 if (err) return (err);
853
854 if (loudness_hp_adjust_present == 0) {
855 pre_proc_adjust = -2.0f;
856 }
857 method_val += pre_proc_adjust;
858 }
859
860 eq_set_id[k] = 0;
861
862 loudness_normalization_gain_db[k] =
863 pstr_drc_sel_proc_params_struct->target_loudness - method_val;
864 loudness[k] = method_val;
865 }
866 }
867 }
868 if (info_count > 0) {
869 *loudness_info_count = info_count;
870 } else {
871 *loudness_info_count = pre_lim_count;
872 }
873
874 return (0);
875 }
876
877 #define MIXING_LEVEL_DEFAULT 85.0f
878 WORD32
impd_mixing_level_info(ia_drc_sel_proc_params_struct * pstr_drc_sel_proc_params_struct,ia_drc_loudness_info_set_struct * pstr_loudness_info,WORD32 requested_dwnmix_id,WORD32 drc_set_id_requested,WORD32 eq_set_id_requested,FLOAT32 * mixing_level)879 impd_mixing_level_info(
880 ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct,
881 ia_drc_loudness_info_set_struct* pstr_loudness_info,
882 WORD32 requested_dwnmix_id, WORD32 drc_set_id_requested,
883 WORD32 eq_set_id_requested, FLOAT32* mixing_level) {
884 WORD32 n, k, info_count;
885 WORD32 album_mode = pstr_drc_sel_proc_params_struct->album_mode;
886 WORD32 loudness_drc_set_id_requested;
887 ia_loudness_info_struct* loudness_info;
888
889 *mixing_level = MIXING_LEVEL_DEFAULT;
890 if (drc_set_id_requested < 0) {
891 loudness_drc_set_id_requested = 0;
892 } else {
893 loudness_drc_set_id_requested = drc_set_id_requested;
894 }
895 if (album_mode == 1) {
896 info_count = pstr_loudness_info->loudness_info_album_count;
897 loudness_info = pstr_loudness_info->str_loudness_info_album;
898 } else {
899 info_count = pstr_loudness_info->loudness_info_count;
900 loudness_info = pstr_loudness_info->loudness_info;
901 }
902 for (n = 0; n < info_count; n++) {
903 if ((requested_dwnmix_id == loudness_info[n].downmix_id) ||
904 (ID_FOR_ANY_DOWNMIX == loudness_info[n].downmix_id)) {
905 if (loudness_drc_set_id_requested == loudness_info[n].drc_set_id) {
906 if (eq_set_id_requested == loudness_info[n].eq_set_id) {
907 for (k = 0; k < loudness_info[n].measurement_count; k++) {
908 if (loudness_info[n].loudness_measure[k].method_def ==
909 METHOD_DEFINITION_MIXING_LEVEL) {
910 *mixing_level = loudness_info[n].loudness_measure[k].method_val;
911 break;
912 }
913 }
914 }
915 }
916 }
917 }
918 return (0);
919 }
920