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 VOID 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             if (ID_FOR_BASE_LAYOUT == drc_instructions_drc_tmp->downmix_id[0]) {
308               if (drc_instructions_drc_tmp->limiter_peak_target_present) {
309                 eq_set_id[peak_count] = -1;
310                 signal_peak_level[peak_count] =
311                     drc_instructions_drc_tmp->limiter_peak_target +
312                     signal_peak_level_tmp;
313                 explicit_peak_information_present[peak_count] = 0;
314                 match_found_flag = 1;
315                 peak_count++;
316               }
317             }
318           }
319         }
320       }
321     }
322   }
323   if (peak_count > 0) {
324     *peak_info_count = peak_count;
325   } else {
326     *peak_info_count = pre_lim_count;
327   }
328   return;
329 }
330 
331 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)332 impd_extract_loudness_peak_to_average_info(
333     ia_loudness_info_struct* loudness_info, WORD32 dyn_range_measurement_type,
334     WORD32* loudness_peak_2_avg_value_present,
335     FLOAT32* loudness_peak_2_avg_value) {
336   WORD32 k;
337   WORD32 program_loudness_present = 0;
338   WORD32 peak_loudness_present = 0;
339   WORD32 match_measure_program_loudness = 0;
340   WORD32 match_measure_peak_loudness = 0;
341   FLOAT32 program_loudness = 0.0f;
342   FLOAT32 peak_loudness = 0.0f;
343   ia_loudness_measure_struct* loudness_measure = NULL;
344 
345   for (k = 0; k < loudness_info->measurement_count; k++) {
346     loudness_measure = &(loudness_info->loudness_measure[k]);
347     if (loudness_measure->method_def == METHOD_DEFINITION_PROGRAM_LOUDNESS) {
348       if (match_measure_program_loudness <
349           measurement_method_prog_loudness_tbl[loudness_measure
350                                                    ->measurement_system]) {
351         program_loudness = loudness_measure->method_val;
352         program_loudness_present = 1;
353         match_measure_program_loudness =
354             measurement_method_prog_loudness_tbl[loudness_measure
355                                                      ->measurement_system];
356       }
357     }
358     switch (dyn_range_measurement_type) {
359       case SHORT_TERM_LOUDNESS_TO_AVG:
360         if (loudness_measure->method_def ==
361             METHOD_DEFINITION_SHORT_TERM_LOUDNESS_MAX) {
362           if (match_measure_peak_loudness <
363               measurement_method_peak_loudness_tbl[loudness_measure
364                                                        ->measurement_system]) {
365             peak_loudness = loudness_measure->method_val;
366             peak_loudness_present = 1;
367             match_measure_peak_loudness =
368                 measurement_method_peak_loudness_tbl[loudness_measure
369                                                          ->measurement_system];
370           }
371         }
372         break;
373 
374       case MOMENTARY_LOUDNESS_TO_AVG:
375         if (loudness_measure->method_def ==
376             METHOD_DEFINITION_MOMENTARY_LOUDNESS_MAX) {
377           if (match_measure_peak_loudness <
378               measurement_method_peak_loudness_tbl[loudness_measure
379                                                        ->measurement_system]) {
380             peak_loudness = loudness_measure->method_val;
381             peak_loudness_present = 1;
382             match_measure_peak_loudness =
383                 measurement_method_peak_loudness_tbl[loudness_measure
384                                                          ->measurement_system];
385           }
386         }
387         break;
388 
389       case TOP_OF_LOUDNESS_RANGE_TO_AVG:
390         if (loudness_measure->method_def ==
391             METHOD_DEFINITION_MAX_OF_LOUDNESS_RANGE) {
392           if (match_measure_peak_loudness <
393               measurement_method_peak_loudness_tbl[loudness_measure
394                                                        ->measurement_system]) {
395             peak_loudness = loudness_measure->method_val;
396             peak_loudness_present = 1;
397             match_measure_peak_loudness =
398                 measurement_method_peak_loudness_tbl[loudness_measure
399                                                          ->measurement_system];
400           }
401         }
402         break;
403 
404       default:
405         return (UNEXPECTED_ERROR);
406 
407         break;
408     }
409   }
410   if ((program_loudness_present == 1) && (peak_loudness_present == 1)) {
411     *loudness_peak_2_avg_value = peak_loudness - program_loudness;
412     *loudness_peak_2_avg_value_present = 1;
413   }
414   return (0);
415 }
416 
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)417 WORD32 impd_loudness_peak_to_average_info(
418     ia_drc_loudness_info_set_struct* pstr_loudness_info,
419     ia_drc_instructions_struct* str_drc_instruction_str,
420     WORD32 requested_dwnmix_id, WORD32 dyn_range_measurement_type,
421     WORD32 album_mode, WORD32* loudness_peak_2_avg_value_present,
422     FLOAT32* loudness_peak_2_avg_value) {
423   WORD32 n, err;
424   WORD32 drc_set_id = max(0, str_drc_instruction_str->drc_set_id);
425 
426   *loudness_peak_2_avg_value_present = 0;
427 
428   if (album_mode == 1) {
429     for (n = 0; n < pstr_loudness_info->loudness_info_album_count; n++) {
430       ia_loudness_info_struct* loudness_info =
431           &(pstr_loudness_info->str_loudness_info_album[n]);
432       if (drc_set_id == loudness_info->drc_set_id) {
433         if (requested_dwnmix_id == loudness_info->downmix_id) {
434           err = impd_extract_loudness_peak_to_average_info(
435               loudness_info, dyn_range_measurement_type,
436               loudness_peak_2_avg_value_present, loudness_peak_2_avg_value);
437           if (err) return (err);
438         }
439       }
440     }
441   }
442   if (*loudness_peak_2_avg_value_present == 0) {
443     for (n = 0; n < pstr_loudness_info->loudness_info_count; n++) {
444       ia_loudness_info_struct* loudness_info =
445           &(pstr_loudness_info->loudness_info[n]);
446       if (drc_set_id == loudness_info->drc_set_id) {
447         if (requested_dwnmix_id == loudness_info->downmix_id) {
448           err = impd_extract_loudness_peak_to_average_info(
449               loudness_info, dyn_range_measurement_type,
450               loudness_peak_2_avg_value_present, loudness_peak_2_avg_value);
451           if (err) return (err);
452         }
453       }
454     }
455   }
456   return (0);
457 }
458 
impd_overall_loudness_present(ia_loudness_info_struct * loudness_info,WORD32 * loudness_info_present)459 VOID impd_overall_loudness_present(ia_loudness_info_struct* loudness_info,
460                                    WORD32* loudness_info_present) {
461   WORD32 m;
462 
463   *loudness_info_present = 0;
464   for (m = 0; m < loudness_info->measurement_count; m++) {
465     if ((loudness_info->loudness_measure[m].method_def ==
466          METHOD_DEFINITION_PROGRAM_LOUDNESS) ||
467         (loudness_info->loudness_measure[m].method_def ==
468          METHOD_DEFINITION_ANCHOR_LOUDNESS)) {
469       *loudness_info_present = 1;
470     }
471   }
472   return;
473 }
474 
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[])475 WORD32 impd_check_loud_info(WORD32 loudness_info_count,
476                             ia_loudness_info_struct* loudness_info,
477                             WORD32 requested_dwnmix_id,
478                             WORD32 drc_set_id_requested, WORD32* info_count,
479                             ia_loudness_info_struct* loudness_info_matching[]) {
480   WORD32 n;
481   WORD32 loudness_info_present;
482   for (n = 0; n < loudness_info_count; n++) {
483     if (requested_dwnmix_id == loudness_info[n].downmix_id) {
484       if (drc_set_id_requested == loudness_info[n].drc_set_id) {
485         impd_overall_loudness_present(&(loudness_info[n]),
486                                       &loudness_info_present);
487 
488         if (loudness_info_present) {
489           loudness_info_matching[*info_count] = &(loudness_info[n]);
490           (*info_count)++;
491         }
492       }
493     }
494   }
495 
496   return (0);
497 }
498 
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[])499 WORD32 impd_check_loud_payload(
500     WORD32 loudness_info_count, ia_loudness_info_struct* loudness_info,
501     WORD32 requested_dwnmix_id, WORD32 drc_set_id_requested, WORD32* info_count,
502     ia_loudness_info_struct* loudness_info_matching[]) {
503   WORD32 err = 0;
504 
505   err = impd_check_loud_info(loudness_info_count, loudness_info,
506                              requested_dwnmix_id, drc_set_id_requested,
507                              info_count, loudness_info_matching);
508   if (err || *info_count) goto matchEnd;
509   err = impd_check_loud_info(loudness_info_count, loudness_info,
510                              ID_FOR_ANY_DOWNMIX, 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                              requested_dwnmix_id, ID_FOR_ANY_DRC, info_count,
515                              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_NO_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                              ID_FOR_ANY_DOWNMIX, ID_FOR_ANY_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_NO_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_BASE_LAYOUT, drc_set_id_requested,
531                              info_count, 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, ID_FOR_ANY_DRC, info_count,
535                              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_NO_DRC, info_count,
539                              loudness_info_matching);
540   if (err || *info_count) goto matchEnd;
541 matchEnd:
542   return (err);
543 }
544 
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[])545 WORD32 impd_find_overall_loudness_info(
546     ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct,
547     ia_drc_loudness_info_set_struct* pstr_loudness_info,
548     WORD32 requested_dwnmix_id, WORD32 drc_set_id_requested,
549     WORD32* overall_loudness_info_present, WORD32* info_count,
550     ia_loudness_info_struct* loudness_info_matching[]) {
551   WORD32 err;
552   WORD32 loudness_drc_set_id_requested;
553 
554   *info_count = 0;
555   if (drc_set_id_requested < 0) {
556     loudness_drc_set_id_requested = ID_FOR_NO_DRC;
557   } else {
558     loudness_drc_set_id_requested = drc_set_id_requested;
559   }
560   if (pstr_drc_sel_proc_params_struct->album_mode == 1) {
561     err = impd_check_loud_payload(
562         pstr_loudness_info->loudness_info_album_count,
563         pstr_loudness_info->str_loudness_info_album, requested_dwnmix_id,
564         loudness_drc_set_id_requested, info_count, loudness_info_matching);
565     if (err) return (err);
566   }
567   if (*info_count == 0) {
568     err = impd_check_loud_payload(pstr_loudness_info->loudness_info_count,
569                                   pstr_loudness_info->loudness_info,
570                                   requested_dwnmix_id,
571                                   loudness_drc_set_id_requested,
572 
573                                   info_count, loudness_info_matching);
574     if (err) return (err);
575   }
576   *overall_loudness_info_present = (*info_count > 0);
577   return (0);
578 }
579 
580 WORD32
impd_high_pass_loudness_adjust_info(ia_loudness_info_struct * loudness_info,WORD32 * loudness_hp_adjust_present,FLOAT32 * loudness_hp_adjust)581 impd_high_pass_loudness_adjust_info(ia_loudness_info_struct* loudness_info,
582                                     WORD32* loudness_hp_adjust_present,
583                                     FLOAT32* loudness_hp_adjust) {
584   WORD32 m, k;
585 
586   *loudness_hp_adjust_present = 0;
587   *loudness_hp_adjust = 0.0f;
588   for (m = 0; m < loudness_info->measurement_count; m++) {
589     if (loudness_info->loudness_measure[m].measurement_system ==
590         MEASUREMENT_SYSTEM_BS_1770_4_PRE_PROCESSING) {
591       for (k = 0; k < loudness_info->measurement_count; k++) {
592         if (loudness_info->loudness_measure[k].measurement_system ==
593             MEASUREMENT_SYSTEM_BS_1770_4) {
594           if (loudness_info->loudness_measure[m].method_def ==
595               loudness_info->loudness_measure[k].method_def) {
596             *loudness_hp_adjust_present = 1;
597             *loudness_hp_adjust =
598                 loudness_info->loudness_measure[m].method_val -
599                 loudness_info->loudness_measure[k].method_val;
600           }
601         }
602       }
603     }
604   }
605   return (0);
606 }
607 
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)608 WORD32 impd_find_high_pass_loudness_adjust(
609     ia_drc_loudness_info_set_struct* pstr_loudness_info,
610     WORD32 requested_dwnmix_id, WORD32 drc_set_id_requested, WORD32 album_mode,
611     FLOAT32 device_cutoff_freq, WORD32* loudness_hp_adjust_present,
612     FLOAT32* loudness_hp_adjust) {
613   WORD32 n, err;
614   WORD32 loudness_drc_set_id_requested;
615 
616   if (drc_set_id_requested < 0) {
617     loudness_drc_set_id_requested = 0;
618   } else {
619     loudness_drc_set_id_requested = drc_set_id_requested;
620   }
621 
622   *loudness_hp_adjust_present = 0;
623 
624   if (album_mode == 1) {
625     for (n = 0; n < pstr_loudness_info->loudness_info_album_count; n++) {
626       if ((requested_dwnmix_id ==
627            pstr_loudness_info->str_loudness_info_album[n].downmix_id) ||
628           (ID_FOR_ANY_DOWNMIX ==
629            pstr_loudness_info->str_loudness_info_album[n].downmix_id)) {
630         if (loudness_drc_set_id_requested ==
631             pstr_loudness_info->str_loudness_info_album[n].drc_set_id) {
632           err = impd_high_pass_loudness_adjust_info(
633               &(pstr_loudness_info->loudness_info[n]),
634               loudness_hp_adjust_present, loudness_hp_adjust);
635           if (err) return (err);
636         }
637       }
638     }
639   }
640   if (*loudness_hp_adjust_present == 0) {
641     for (n = 0; n < pstr_loudness_info->loudness_info_count; n++) {
642       if ((requested_dwnmix_id ==
643            pstr_loudness_info->loudness_info[n].downmix_id) ||
644           (ID_FOR_ANY_DOWNMIX ==
645            pstr_loudness_info->loudness_info[n].downmix_id)) {
646         if (loudness_drc_set_id_requested ==
647             pstr_loudness_info->loudness_info[n].drc_set_id) {
648           err = impd_high_pass_loudness_adjust_info(
649               &(pstr_loudness_info->loudness_info[n]),
650               loudness_hp_adjust_present, loudness_hp_adjust);
651           if (err) return (err);
652         }
653       }
654     }
655   }
656   if (*loudness_hp_adjust_present == 0) {
657     for (n = 0; n < pstr_loudness_info->loudness_info_count; n++) {
658       if (ID_FOR_BASE_LAYOUT ==
659           pstr_loudness_info->loudness_info[n].downmix_id) /* base layout */
660       {
661         if (loudness_drc_set_id_requested ==
662             pstr_loudness_info->loudness_info[n].drc_set_id) {
663           err = impd_high_pass_loudness_adjust_info(
664               &(pstr_loudness_info->loudness_info[n]),
665               loudness_hp_adjust_present, loudness_hp_adjust);
666           if (err) return (err);
667         }
668       }
669     }
670   }
671   if (*loudness_hp_adjust_present == 0) {
672     for (n = 0; n < pstr_loudness_info->loudness_info_count; n++) {
673       if (ID_FOR_BASE_LAYOUT ==
674           pstr_loudness_info->loudness_info[n].downmix_id) /* base layout */
675       {
676         if (0 == pstr_loudness_info->loudness_info[n].drc_set_id) {
677           err = impd_high_pass_loudness_adjust_info(
678               &(pstr_loudness_info->loudness_info[n]),
679               loudness_hp_adjust_present, loudness_hp_adjust);
680           if (err) return (err);
681         }
682       }
683     }
684   }
685   if (*loudness_hp_adjust_present == 0) {
686     *loudness_hp_adjust = 0.0f;
687   } else {
688     *loudness_hp_adjust *=
689         (max(20.0f, min(500.0f, device_cutoff_freq)) - 20.0f) /
690         (500.0f - 20.0f);
691   }
692   return (0);
693 }
694 
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[])695 WORD32 impd_init_loudness_control(
696     ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct,
697     ia_drc_loudness_info_set_struct* pstr_loudness_info,
698     WORD32 requested_dwnmix_id, WORD32 drc_set_id_requested,
699     WORD32 num_compression_eq_count, WORD32* num_compression_eq_id,
700     WORD32* loudness_info_count, WORD32 eq_set_id[],
701     FLOAT32 loudness_normalization_gain_db[], FLOAT32 loudness[]) {
702   WORD32 err, k, info_count = 0, pre_lim_count;
703   WORD32 loudness_hp_adjust_present;
704   WORD32 overall_loudness_info_present;
705   FLOAT32 pre_proc_adjust;
706 
707   k = 0;
708   if (drc_set_id_requested < 0) {
709     for (k = 0; k < num_compression_eq_count; k++) {
710       eq_set_id[k] = num_compression_eq_id[k];
711       loudness[k] = UNDEFINED_LOUDNESS_VALUE;
712       loudness_normalization_gain_db[k] = 0.0f;
713     }
714   }
715   if (k >= MAX_NUM_COMPRESSION_EQ) return UNEXPECTED_ERROR;
716   eq_set_id[k] = 0;
717 
718   loudness[k] = UNDEFINED_LOUDNESS_VALUE;
719 
720   loudness_normalization_gain_db[k] = 0.0f;
721   k++;
722 
723   pre_lim_count = k;
724 
725   if (pstr_drc_sel_proc_params_struct->loudness_normalization_on == 1) {
726     WORD32 n;
727     ia_loudness_info_struct* loudness_info[16];
728     err = impd_find_overall_loudness_info(
729         pstr_drc_sel_proc_params_struct, pstr_loudness_info,
730         requested_dwnmix_id, drc_set_id_requested,
731         &overall_loudness_info_present, &info_count, loudness_info);
732     if (err) return (err);
733 
734     if (overall_loudness_info_present == 1) {
735       WORD32 requested_method_definition = METHOD_DEFINITION_PROGRAM_LOUDNESS;
736       WORD32 other_method_definition = METHOD_DEFINITION_PROGRAM_LOUDNESS;
737       WORD32 requested_measurement_system = MEASUREMENT_SYSTEM_BS_1770_4;
738       WORD32 requested_preprocessing = 0;
739 
740       const WORD32* system_bonus = measurement_system_default_tbl;
741 
742       WORD32 match_measure;
743       FLOAT32 method_val = 0;
744 
745       switch (pstr_drc_sel_proc_params_struct->loudness_measurement_method) {
746         case USER_METHOD_DEFINITION_DEFAULT:
747         case USER_METHOD_DEFINITION_PROGRAM_LOUDNESS:
748           requested_method_definition = METHOD_DEFINITION_PROGRAM_LOUDNESS;
749           other_method_definition = METHOD_DEFINITION_ANCHOR_LOUDNESS;
750           break;
751         case USER_METHOD_DEFINITION_ANCHOR_LOUDNESS:
752           requested_method_definition = METHOD_DEFINITION_ANCHOR_LOUDNESS;
753           other_method_definition = METHOD_DEFINITION_PROGRAM_LOUDNESS;
754           break;
755 
756         default:
757           return (UNEXPECTED_ERROR);
758           break;
759       }
760 
761       switch (pstr_drc_sel_proc_params_struct->loudness_measurement_system) {
762         case USER_MEASUREMENT_SYSTEM_DEFAULT:
763         case USER_MEASUREMENT_SYSTEM_BS_1770_4:
764           requested_measurement_system = MEASUREMENT_SYSTEM_BS_1770_4;
765           system_bonus = measurement_system_bs1770_3_tbl;
766           break;
767         case USER_MEASUREMENT_SYSTEM_USER:
768           requested_measurement_system = MEASUREMENT_SYSTEM_USER;
769           system_bonus = measurement_system_user_tbl;
770           break;
771         case USER_MEASUREMENT_SYSTEM_EXPERT_PANEL:
772           requested_measurement_system = MEASUREMENT_SYSTEM_EXPERT_PANEL;
773           system_bonus = measurement_system_expert_tbl;
774           break;
775         case USER_MEASUREMENT_SYSTEM_RESERVED_A:
776           requested_measurement_system = USER_MEASUREMENT_SYSTEM_RESERVED_A;
777           system_bonus = measurement_system_rms_a_tbl;
778           break;
779         case USER_MEASUREMENT_SYSTEM_RESERVED_B:
780           requested_measurement_system = USER_MEASUREMENT_SYSTEM_RESERVED_B;
781           system_bonus = measurement_system_rms_b_tbl;
782           break;
783         case USER_MEASUREMENT_SYSTEM_RESERVED_C:
784           requested_measurement_system = USER_MEASUREMENT_SYSTEM_RESERVED_C;
785           system_bonus = measurement_system_rms_c_tbl;
786           break;
787         case USER_MEASUREMENT_SYSTEM_RESERVED_D:
788           requested_measurement_system = USER_MEASUREMENT_SYSTEM_RESERVED_D;
789           system_bonus = measurement_system_rms_d_tbl;
790           break;
791         case USER_MEASUREMENT_SYSTEM_RESERVED_E:
792           requested_measurement_system = USER_MEASUREMENT_SYSTEM_RESERVED_E;
793           system_bonus = measurement_system_rms_e_tbl;
794           break;
795 
796         default:
797           return (UNEXPECTED_ERROR);
798           break;
799       }
800 
801       switch (pstr_drc_sel_proc_params_struct->loudness_measurement_pre_proc) {
802         case USER_LOUDNESS_PREPROCESSING_DEFAULT:
803         case USER_LOUDNESS_PREPROCESSING_OFF:
804           requested_preprocessing = 0;
805           break;
806         case USER_LOUDNESS_PREPROCESSING_HIGHPASS:
807           requested_preprocessing = 1;
808           break;
809 
810         default:
811           return (UNEXPECTED_ERROR);
812           break;
813       }
814 
815       for (k = 0; k < info_count; k++) {
816         match_measure = -1;
817         for (n = 0; n < loudness_info[k]->measurement_count; n++) {
818           ia_loudness_measure_struct* loudness_measure =
819               &(loudness_info[k]->loudness_measure[n]);
820           if (match_measure <
821                   system_bonus[loudness_measure->measurement_system] &&
822               requested_method_definition == loudness_measure->method_def) {
823             method_val = loudness_measure->method_val;
824             match_measure = system_bonus[loudness_measure->measurement_system];
825           }
826         }
827         if (match_measure == -1) {
828           for (n = 0; n < loudness_info[k]->measurement_count; n++) {
829             ia_loudness_measure_struct* loudness_measure =
830                 &(loudness_info[k]->loudness_measure[n]);
831             if (match_measure <
832                     system_bonus[loudness_measure->measurement_system] &&
833                 other_method_definition == loudness_measure->method_def) {
834               method_val = loudness_measure->method_val;
835               match_measure =
836                   system_bonus[loudness_measure->measurement_system];
837             }
838           }
839         }
840 
841         if (requested_preprocessing == 1) {
842           err = impd_find_high_pass_loudness_adjust(
843               pstr_loudness_info, requested_dwnmix_id, drc_set_id_requested,
844               pstr_drc_sel_proc_params_struct->album_mode,
845               (FLOAT32)
846                   pstr_drc_sel_proc_params_struct->device_cut_off_frequency,
847               &loudness_hp_adjust_present, &pre_proc_adjust);
848           if (err) return (err);
849 
850           if (loudness_hp_adjust_present == 0) {
851             pre_proc_adjust = -2.0f;
852           }
853           method_val += pre_proc_adjust;
854         }
855 
856         eq_set_id[k] = 0;
857 
858         loudness_normalization_gain_db[k] =
859             pstr_drc_sel_proc_params_struct->target_loudness - method_val;
860         loudness[k] = method_val;
861       }
862     }
863   }
864   if (info_count > 0) {
865     *loudness_info_count = info_count;
866   } else {
867     *loudness_info_count = pre_lim_count;
868   }
869 
870   return (0);
871 }
872 
873 #define MIXING_LEVEL_DEFAULT 85.0f
874 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)875 impd_mixing_level_info(
876     ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct,
877     ia_drc_loudness_info_set_struct* pstr_loudness_info,
878     WORD32 requested_dwnmix_id, WORD32 drc_set_id_requested,
879     WORD32 eq_set_id_requested, FLOAT32* mixing_level) {
880   WORD32 n, k, info_count;
881   WORD32 album_mode = pstr_drc_sel_proc_params_struct->album_mode;
882   WORD32 loudness_drc_set_id_requested;
883   ia_loudness_info_struct* loudness_info;
884 
885   *mixing_level = MIXING_LEVEL_DEFAULT;
886   if (drc_set_id_requested < 0) {
887     loudness_drc_set_id_requested = 0;
888   } else {
889     loudness_drc_set_id_requested = drc_set_id_requested;
890   }
891   if (album_mode == 1) {
892     info_count = pstr_loudness_info->loudness_info_album_count;
893     loudness_info = pstr_loudness_info->str_loudness_info_album;
894   } else {
895     info_count = pstr_loudness_info->loudness_info_count;
896     loudness_info = pstr_loudness_info->loudness_info;
897   }
898   for (n = 0; n < info_count; n++) {
899     if ((requested_dwnmix_id == loudness_info[n].downmix_id) ||
900         (ID_FOR_ANY_DOWNMIX == loudness_info[n].downmix_id)) {
901       if (loudness_drc_set_id_requested == loudness_info[n].drc_set_id) {
902         if (eq_set_id_requested == loudness_info[n].eq_set_id) {
903           for (k = 0; k < loudness_info[n].measurement_count; k++) {
904             if (loudness_info[n].loudness_measure[k].method_def ==
905                 METHOD_DEFINITION_MIXING_LEVEL) {
906               *mixing_level = loudness_info[n].loudness_measure[k].method_val;
907               break;
908             }
909           }
910         }
911       }
912     }
913   }
914   return (0);
915 }
916