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