Home | History | Annotate | Download | only in drc_src
      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 
     32 WORD32 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 
    336 WORD32
    337 impd_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 
    422 WORD32 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 
    464 WORD32 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 
    480 WORD32 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 
    504 WORD32 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;
    546 matchEnd:
    547   return (err);
    548 }
    549 
    550 WORD32 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 
    585 WORD32
    586 impd_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 
    613 WORD32 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 
    700 WORD32 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
    876 WORD32
    877 impd_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