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 <string.h>
     22 #include <math.h>
     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_sel_proc_drc_set_sel.h"
     30 #include "impd_drc_loudness_control.h"
     31 #include "impd_drc_filter_bank.h"
     32 #include "impd_drc_rom.h"
     33 
     34 static WORD32 effect_types_request_table[] = {
     35     EFFECT_BIT_NIGHT,    EFFECT_BIT_NOISY,   EFFECT_BIT_LIMITED,
     36     EFFECT_BIT_LOWLEVEL, EFFECT_BIT_DIALOG,  EFFECT_BIT_GENERAL_COMPR,
     37     EFFECT_BIT_EXPAND,   EFFECT_BIT_ARTISTIC};
     38 
     39 WORD32 impd_validate_requested_drc_feature(
     40     ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct) {
     41   WORD32 i, j;
     42 
     43   for (i = 0; i < pstr_drc_sel_proc_params_struct->num_drc_feature_requests;
     44        i++) {
     45     switch (pstr_drc_sel_proc_params_struct->drc_feature_req_type[i]) {
     46       case MATCH_EFFECT_TYPE:
     47         for (j = 0; j < pstr_drc_sel_proc_params_struct
     48                             ->desired_num_drc_effects_of_requested[i];
     49              j++) {
     50           if (pstr_drc_sel_proc_params_struct
     51                   ->requested_drc_effect_type[i][j] ==
     52               EFFECT_TYPE_REQUESTED_NONE) {
     53             if (pstr_drc_sel_proc_params_struct
     54                     ->desired_num_drc_effects_of_requested[i] > 1) {
     55               return (UNEXPECTED_ERROR);
     56             }
     57           }
     58         }
     59         break;
     60       case MATCH_DYNAMIC_RANGE:
     61         break;
     62       case MATCH_DRC_CHARACTERISTIC:
     63         break;
     64       default:
     65         return (UNEXPECTED_ERROR);
     66         break;
     67     }
     68   }
     69   return (0);
     70 }
     71 
     72 WORD32 impd_find_drc_instructions_uni_drc(
     73     ia_drc_config* drc_config, WORD32 drc_set_id_requested,
     74     ia_drc_instructions_struct** str_drc_instruction_str) {
     75   WORD32 i;
     76   for (i = 0; i < drc_config->drc_instructions_uni_drc_count; i++) {
     77     if (drc_set_id_requested ==
     78         drc_config->str_drc_instruction_str[i].drc_set_id)
     79       break;
     80   }
     81   if (i == drc_config->drc_instructions_uni_drc_count) {
     82     return (UNEXPECTED_ERROR);
     83   }
     84   *str_drc_instruction_str = &drc_config->str_drc_instruction_str[i];
     85   return (0);
     86 }
     87 
     88 WORD32 impd_map_requested_effect_bit_idx(WORD32 requested_effect_type,
     89                                          WORD32* effect_bit_idx) {
     90   switch (requested_effect_type) {
     91     case EFFECT_TYPE_REQUESTED_NONE:
     92       *effect_bit_idx = EFFECT_BIT_NONE;
     93       break;
     94     case EFFECT_TYPE_REQUESTED_NIGHT:
     95       *effect_bit_idx = EFFECT_BIT_NIGHT;
     96       break;
     97     case EFFECT_TYPE_REQUESTED_NOISY:
     98       *effect_bit_idx = EFFECT_BIT_NOISY;
     99       break;
    100     case EFFECT_TYPE_REQUESTED_LIMITED:
    101       *effect_bit_idx = EFFECT_BIT_LIMITED;
    102       break;
    103     case EFFECT_TYPE_REQUESTED_LOWLEVEL:
    104       *effect_bit_idx = EFFECT_BIT_LOWLEVEL;
    105       break;
    106     case EFFECT_TYPE_REQUESTED_DIALOG:
    107       *effect_bit_idx = EFFECT_BIT_DIALOG;
    108       break;
    109     case EFFECT_TYPE_REQUESTED_GENERAL_COMPR:
    110       *effect_bit_idx = EFFECT_BIT_GENERAL_COMPR;
    111       break;
    112     case EFFECT_TYPE_REQUESTED_EXPAND:
    113       *effect_bit_idx = EFFECT_BIT_EXPAND;
    114       break;
    115     case EFFECT_TYPE_REQUESTED_ARTISTIC:
    116       *effect_bit_idx = EFFECT_BIT_ARTISTIC;
    117       break;
    118 
    119     default:
    120       return (UNEXPECTED_ERROR);
    121 
    122       break;
    123   }
    124   return (0);
    125 }
    126 
    127 WORD32 impd_get_fading_drc_set(ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc) {
    128   pstr_drc_uni_sel_proc->drc_instructions_index[2] = -1;
    129   if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.album_mode == 0) {
    130     WORD32 n;
    131     ia_drc_instructions_struct* str_drc_instruction_str = NULL;
    132     for (n = 0;
    133          n < pstr_drc_uni_sel_proc->drc_config.drc_instructions_uni_drc_count;
    134          n++) {
    135       str_drc_instruction_str =
    136           &(pstr_drc_uni_sel_proc->drc_config.str_drc_instruction_str[n]);
    137 
    138       if (str_drc_instruction_str->drc_set_effect & EFFECT_BIT_FADE) {
    139         if (str_drc_instruction_str->downmix_id[0] == ID_FOR_ANY_DOWNMIX) {
    140           pstr_drc_uni_sel_proc->drc_instructions_index[2] = n;
    141 
    142         } else {
    143           return (UNEXPECTED_ERROR);
    144         }
    145       }
    146     }
    147   }
    148   return (0);
    149 }
    150 
    151 WORD32 impd_get_ducking_drc_set(ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc) {
    152   WORD32 drc_instructions_index;
    153   WORD32 n, k;
    154   ia_drc_instructions_struct* str_drc_instruction_str;
    155 
    156   WORD32 requested_dwnmix_id =
    157       pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.active_downmix_id;
    158 
    159   pstr_drc_uni_sel_proc->drc_instructions_index[3] = -1;
    160   drc_instructions_index = -1;
    161   str_drc_instruction_str = NULL;
    162 
    163   for (n = 0;
    164        n < pstr_drc_uni_sel_proc->drc_config.drc_instructions_uni_drc_count;
    165        n++) {
    166     str_drc_instruction_str =
    167         &(pstr_drc_uni_sel_proc->drc_config.str_drc_instruction_str[n]);
    168 
    169     if (str_drc_instruction_str->drc_set_effect &
    170         (EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) {
    171       for (k = 0; k < str_drc_instruction_str->dwnmix_id_count; k++) {
    172         if (str_drc_instruction_str->downmix_id[k] == requested_dwnmix_id) {
    173           drc_instructions_index = n;
    174         }
    175       }
    176     }
    177   }
    178   if (drc_instructions_index == -1) {
    179     for (n = 0;
    180          n < pstr_drc_uni_sel_proc->drc_config.drc_instructions_uni_drc_count;
    181          n++) {
    182       str_drc_instruction_str =
    183           &(pstr_drc_uni_sel_proc->drc_config.str_drc_instruction_str[n]);
    184 
    185       if (str_drc_instruction_str->drc_set_effect &
    186           (EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) {
    187         for (k = 0; k < str_drc_instruction_str->dwnmix_id_count; k++) {
    188           if (str_drc_instruction_str->downmix_id[k] == ID_FOR_BASE_LAYOUT) {
    189             drc_instructions_index = n;
    190           }
    191         }
    192       }
    193     }
    194   }
    195   if (drc_instructions_index > -1) {
    196     pstr_drc_uni_sel_proc->drc_instructions_index[2] = -1;
    197     pstr_drc_uni_sel_proc->drc_instructions_index[3] = drc_instructions_index;
    198   }
    199   return (0);
    200 }
    201 
    202 WORD32 impd_get_selected_drc_set(ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc,
    203                                  WORD32 drc_set_id_selected) {
    204   WORD32 n;
    205 
    206   ia_drc_instructions_struct* str_drc_instruction_str = NULL;
    207 
    208   for (n = 0; n < pstr_drc_uni_sel_proc->drc_config.drc_instructions_count_plus;
    209        n++) {
    210     if (pstr_drc_uni_sel_proc->drc_config.str_drc_instruction_str[n]
    211             .drc_set_id == drc_set_id_selected)
    212       break;
    213   }
    214   if (n == pstr_drc_uni_sel_proc->drc_config.drc_instructions_count_plus) {
    215     return (EXTERNAL_ERROR);
    216   }
    217   pstr_drc_uni_sel_proc->drc_inst_index_sel = n;
    218   str_drc_instruction_str = &(
    219       pstr_drc_uni_sel_proc->drc_config
    220           .str_drc_instruction_str[pstr_drc_uni_sel_proc->drc_inst_index_sel]);
    221 
    222   pstr_drc_uni_sel_proc->drc_instructions_index[0] =
    223       pstr_drc_uni_sel_proc->drc_inst_index_sel;
    224   return (0);
    225 }
    226 
    227 WORD32 impd_get_dependent_drc_set(
    228     ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc) {
    229   ia_drc_instructions_struct* str_drc_instruction_str = NULL;
    230   str_drc_instruction_str = &(
    231       pstr_drc_uni_sel_proc->drc_config
    232           .str_drc_instruction_str[pstr_drc_uni_sel_proc->drc_inst_index_sel]);
    233 
    234   if (str_drc_instruction_str->depends_on_drc_set_present == 1) {
    235     WORD32 n;
    236     WORD32 drc_dependent_set_id = str_drc_instruction_str->depends_on_drc_set;
    237 
    238     for (n = 0;
    239          n < pstr_drc_uni_sel_proc->drc_config.drc_instructions_count_plus;
    240          n++) {
    241       if (pstr_drc_uni_sel_proc->drc_config.str_drc_instruction_str[n]
    242               .drc_set_id == drc_dependent_set_id)
    243         break;
    244     }
    245     if (n == pstr_drc_uni_sel_proc->drc_config.drc_instructions_count_plus) {
    246       return (UNEXPECTED_ERROR);
    247     }
    248     pstr_drc_uni_sel_proc->drc_instructions_index[1] = n;
    249   } else {
    250     pstr_drc_uni_sel_proc->drc_instructions_index[1] = -1;
    251   }
    252   return (0);
    253 }
    254 
    255 WORD32 impd_get_dependent_drc_instructions(
    256     const ia_drc_config* drc_config,
    257     const ia_drc_instructions_struct* str_drc_instruction_str,
    258     ia_drc_instructions_struct** drc_instructions_dependent) {
    259   WORD32 j;
    260   ia_drc_instructions_struct* dependent_drc = NULL;
    261   for (j = 0; j < drc_config->drc_instructions_uni_drc_count; j++) {
    262     dependent_drc =
    263         (ia_drc_instructions_struct*)&(drc_config->str_drc_instruction_str[j]);
    264     if (dependent_drc->drc_set_id ==
    265         str_drc_instruction_str->depends_on_drc_set) {
    266       break;
    267     }
    268   }
    269   if (j == drc_config->drc_instructions_uni_drc_count) {
    270     return (UNEXPECTED_ERROR);
    271   }
    272   if (dependent_drc->depends_on_drc_set_present == 1) {
    273     return (UNEXPECTED_ERROR);
    274   }
    275   *drc_instructions_dependent = dependent_drc;
    276   return (0);
    277 }
    278 
    279 WORD32 impd_select_drcs_without_compr_effects(
    280     ia_drc_config* pstr_drc_config, WORD32* match_found_flag,
    281     WORD32* selection_candidate_count,
    282     ia_selection_candidate_info_struct* selection_candidate_info) {
    283   WORD32 i, k, n;
    284   WORD32 selection_candidate_step_2_count = 0;
    285   ia_selection_candidate_info_struct
    286       selection_candidate_info_step_2[SELECTION_CANDIDATE_COUNT_MAX];
    287   WORD32 effect_types_request_table_size;
    288   WORD32 match;
    289   ia_drc_instructions_struct* str_drc_instruction_str;
    290 
    291   effect_types_request_table_size =
    292       sizeof(effect_types_request_table) / sizeof(WORD32);
    293 
    294   k = 0;
    295   for (i = 0; i < *selection_candidate_count; i++) {
    296     str_drc_instruction_str = &(
    297         pstr_drc_config->str_drc_instruction_str[selection_candidate_info[i]
    298                                                      .drc_instructions_index]);
    299 
    300     match = 1;
    301     for (n = 0; n < effect_types_request_table_size; n++) {
    302       if ((str_drc_instruction_str->drc_set_effect &
    303            effect_types_request_table[n]) != 0x0) {
    304         match = 0;
    305       }
    306     }
    307     if (match == 1) {
    308       memcpy(&selection_candidate_info_step_2[k], &selection_candidate_info[i],
    309              sizeof(ia_selection_candidate_info_struct));
    310       k++;
    311     }
    312   }
    313   selection_candidate_step_2_count = k;
    314 
    315   if (selection_candidate_step_2_count > 0) {
    316     *match_found_flag = 1;
    317     for (i = 0; i < selection_candidate_step_2_count; i++) {
    318       memcpy(&selection_candidate_info[i], &selection_candidate_info_step_2[i],
    319              sizeof(ia_selection_candidate_info_struct));
    320       *selection_candidate_count = selection_candidate_step_2_count;
    321     }
    322   } else {
    323     *match_found_flag = 0;
    324   }
    325 
    326   return (0);
    327 }
    328 
    329 WORD32 impd_match_effect_type_attempt(
    330     ia_drc_config* pstr_drc_config, WORD32 requested_effect_type,
    331     WORD32 state_requested, WORD32* match_found_flag,
    332     WORD32* selection_candidate_count,
    333     ia_selection_candidate_info_struct* selection_candidate_info) {
    334   WORD32 i, k, err;
    335   WORD32 selection_candidate_step_2_count = 0;
    336   ia_selection_candidate_info_struct
    337       selection_candidate_info_step_2[SELECTION_CANDIDATE_COUNT_MAX];
    338   ia_drc_instructions_struct* str_drc_instruction_str;
    339   ia_drc_instructions_struct* drc_instructions_dependent;
    340   WORD32 effect_bit_idx;
    341 
    342   err =
    343       impd_map_requested_effect_bit_idx(requested_effect_type, &effect_bit_idx);
    344   if (err) return (err);
    345 
    346   if (effect_bit_idx == EFFECT_BIT_NONE) {
    347     err = impd_select_drcs_without_compr_effects(
    348         pstr_drc_config, match_found_flag, selection_candidate_count,
    349         selection_candidate_info);
    350     if (err) return (err);
    351   } else {
    352     k = 0;
    353     for (i = 0; i < *selection_candidate_count; i++) {
    354       str_drc_instruction_str =
    355           &(pstr_drc_config->str_drc_instruction_str
    356                 [selection_candidate_info[i].drc_instructions_index]);
    357       if (str_drc_instruction_str->depends_on_drc_set_present == 1) {
    358         err = impd_get_dependent_drc_instructions(pstr_drc_config,
    359                                                   str_drc_instruction_str,
    360                                                   &drc_instructions_dependent);
    361         if (err) return (err);
    362 
    363         if (state_requested == 1) {
    364           if (((str_drc_instruction_str->drc_set_effect & effect_bit_idx) !=
    365                0x0) ||
    366               ((drc_instructions_dependent->drc_set_effect & effect_bit_idx) !=
    367                0x0)) {
    368             memcpy(&selection_candidate_info_step_2[k],
    369                    &selection_candidate_info[i],
    370                    sizeof(ia_selection_candidate_info_struct));
    371             k++;
    372           }
    373         } else {
    374           if (((str_drc_instruction_str->drc_set_effect & effect_bit_idx) ==
    375                0x0) &&
    376               ((drc_instructions_dependent->drc_set_effect & effect_bit_idx) ==
    377                0x0)) {
    378             memcpy(&selection_candidate_info_step_2[k],
    379                    &selection_candidate_info[i],
    380                    sizeof(ia_selection_candidate_info_struct));
    381             k++;
    382           }
    383         }
    384       } else {
    385         if (state_requested == 1) {
    386           if ((str_drc_instruction_str->drc_set_effect & effect_bit_idx) !=
    387               0x0) {
    388             memcpy(&selection_candidate_info_step_2[k],
    389                    &selection_candidate_info[i],
    390                    sizeof(ia_selection_candidate_info_struct));
    391             k++;
    392           }
    393         } else {
    394           if ((str_drc_instruction_str->drc_set_effect & effect_bit_idx) ==
    395               0x0) {
    396             memcpy(&selection_candidate_info_step_2[k],
    397                    &selection_candidate_info[i],
    398                    sizeof(ia_selection_candidate_info_struct));
    399             k++;
    400           }
    401         }
    402       }
    403     }
    404     selection_candidate_step_2_count = k;
    405 
    406     if (selection_candidate_step_2_count > 0) {
    407       *match_found_flag = 1;
    408       for (i = 0; i < selection_candidate_step_2_count; i++) {
    409         *selection_candidate_count = selection_candidate_step_2_count;
    410         memcpy(&selection_candidate_info[i],
    411                &selection_candidate_info_step_2[i],
    412                sizeof(ia_selection_candidate_info_struct));
    413       }
    414     } else {
    415       *match_found_flag = 0;
    416     }
    417   }
    418   return (0);
    419 }
    420 
    421 WORD32 impd_match_effect_types(
    422     ia_drc_config* pstr_drc_config, WORD32 effect_type_requested_total_count,
    423     WORD32 effect_type_requested_desired_count, WORD32* requested_effect_type,
    424     WORD32* selection_candidate_count,
    425     ia_selection_candidate_info_struct* selection_candidate_info) {
    426   WORD32 k, err;
    427   WORD32 match_found_flag = 0;
    428   WORD32 state_requested;
    429   WORD32 desired_effect_type_found, fallback_effect_type_found;
    430 
    431   desired_effect_type_found = 0;
    432   fallback_effect_type_found = 0;
    433   k = 0;
    434   while (k < effect_type_requested_desired_count) {
    435     state_requested = 1;
    436     err = impd_match_effect_type_attempt(
    437         pstr_drc_config, requested_effect_type[k], state_requested,
    438         &match_found_flag, selection_candidate_count, selection_candidate_info);
    439     if (err) return (err);
    440     if (match_found_flag) desired_effect_type_found = 1;
    441     k++;
    442   }
    443   if (desired_effect_type_found == 0) {
    444     while ((k < effect_type_requested_total_count) && (match_found_flag == 0)) {
    445       state_requested = 1;
    446       err = impd_match_effect_type_attempt(
    447           pstr_drc_config, requested_effect_type[k], state_requested,
    448           &match_found_flag, selection_candidate_count,
    449           selection_candidate_info);
    450       if (err) return (err);
    451       if (match_found_flag) fallback_effect_type_found = 1;
    452       k++;
    453     }
    454   }
    455 
    456   return (0);
    457 }
    458 
    459 WORD32 impd_match_dynamic_range(
    460     ia_drc_config* pstr_drc_config,
    461     ia_drc_loudness_info_set_struct* pstr_loudness_info,
    462     ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct,
    463     WORD32 num_drc_requests, WORD32* selection_candidate_count,
    464     ia_selection_candidate_info_struct* selection_candidate_info) {
    465   ia_drc_instructions_struct* str_drc_instruction_str;
    466   WORD32 err, i, k;
    467   WORD32 lp_avg_present_val;
    468   FLOAT32 lp_avg_val;
    469   FLOAT32 deviation_min = 1000.0f;
    470   WORD32 selected[DRC_INSTRUCTIONS_COUNT_MAX];
    471   WORD32 dynamic_range_measurement_type =
    472       pstr_drc_sel_proc_params_struct
    473           ->requested_dyn_range_measur_type[num_drc_requests];
    474 
    475   WORD32 requested_dyn_range_range_flag =
    476       pstr_drc_sel_proc_params_struct
    477           ->requested_dyn_range_range_flag[num_drc_requests];
    478 
    479   FLOAT32 dynamic_range_requested =
    480       pstr_drc_sel_proc_params_struct
    481           ->requested_dyn_range_value[num_drc_requests];
    482 
    483   FLOAT32 dynamic_range_min_requested =
    484       pstr_drc_sel_proc_params_struct
    485           ->requested_dyn_range_min_val[num_drc_requests];
    486 
    487   FLOAT32 dynamic_range_max_requested =
    488       pstr_drc_sel_proc_params_struct
    489           ->requested_dyn_range_max_val[num_drc_requests];
    490 
    491   WORD32* requested_dwnmix_id =
    492       pstr_drc_sel_proc_params_struct->requested_dwnmix_id;
    493 
    494   WORD32 album_mode = pstr_drc_sel_proc_params_struct->album_mode;
    495 
    496   k = 0;
    497   for (i = 0; i < *selection_candidate_count; i++) {
    498     str_drc_instruction_str = &(
    499         pstr_drc_config->str_drc_instruction_str[selection_candidate_info[i]
    500                                                      .drc_instructions_index]);
    501 
    502     err = impd_loudness_peak_to_average_info(
    503         pstr_loudness_info, str_drc_instruction_str,
    504         requested_dwnmix_id[selection_candidate_info[i]
    505                                 .downmix_id_request_index],
    506         dynamic_range_measurement_type, album_mode, &lp_avg_present_val,
    507         &lp_avg_val);
    508     if (err) return (err);
    509 
    510     if (lp_avg_present_val == 1) {
    511       if (requested_dyn_range_range_flag == 1) {
    512         if ((lp_avg_val >= dynamic_range_min_requested) &&
    513             (lp_avg_val <= dynamic_range_max_requested)) {
    514           selected[k] = i;
    515           k++;
    516         }
    517       } else {
    518         FLOAT32 deviation =
    519             (FLOAT32)fabs((FLOAT64)(dynamic_range_requested - lp_avg_val));
    520         if (deviation_min >= deviation) {
    521           if (deviation_min > deviation) {
    522             deviation_min = deviation;
    523             k = 0;
    524           }
    525           selected[k] = i;
    526           k++;
    527         }
    528       }
    529     }
    530   }
    531   if (k > 0) {
    532     for (i = 0; i < k; i++) {
    533       memcpy(&selection_candidate_info[i],
    534              &selection_candidate_info[selected[i]],
    535              sizeof(ia_selection_candidate_info_struct));
    536     }
    537     *selection_candidate_count = k;
    538   }
    539 
    540   return (0);
    541 }
    542 
    543 WORD32 impd_match_drc_characteristic_attempt(
    544     ia_drc_config* pstr_drc_config, WORD32 requested_drc_characteristic,
    545     WORD32* match_found_flag, WORD32* selection_candidate_count,
    546     ia_selection_candidate_info_struct* selection_candidate_info) {
    547   WORD32 i, k, n, b, m;
    548   WORD32 ref_count;
    549   WORD32 drc_characteristic;
    550   FLOAT32 match_count;
    551   WORD32 drc_characteristic_request_1;
    552   WORD32 drc_characteristic_request_2;
    553   WORD32 drc_characteristic_request_3;
    554 
    555   ia_drc_instructions_struct* str_drc_instruction_str = NULL;
    556   ia_uni_drc_coeffs_struct* str_p_loc_drc_coefficients_uni_drc = NULL;
    557   ia_gain_set_params_struct* gain_set_params = NULL;
    558   *match_found_flag = 0;
    559 
    560   if (requested_drc_characteristic < 1) {
    561     return (UNEXPECTED_ERROR);
    562   }
    563   if (requested_drc_characteristic < 12) {
    564     drc_characteristic_request_1 =
    565         drc_characteristic_order_default[requested_drc_characteristic - 1][0];
    566     drc_characteristic_request_2 =
    567         drc_characteristic_order_default[requested_drc_characteristic - 1][1];
    568     drc_characteristic_request_3 =
    569         drc_characteristic_order_default[requested_drc_characteristic - 1][2];
    570   } else {
    571     drc_characteristic_request_1 = requested_drc_characteristic;
    572     drc_characteristic_request_2 = -1;
    573     drc_characteristic_request_3 = -1;
    574   }
    575 
    576   if (pstr_drc_config->drc_coefficients_drc_count) {
    577     for (i = 0; i < pstr_drc_config->drc_coefficients_drc_count; i++) {
    578       str_p_loc_drc_coefficients_uni_drc =
    579           &(pstr_drc_config->str_p_loc_drc_coefficients_uni_drc[i]);
    580       if (str_p_loc_drc_coefficients_uni_drc->drc_location == LOCATION_SELECTED)
    581         break;
    582     }
    583 
    584     if (i == pstr_drc_config->drc_coefficients_drc_count) {
    585       return (UNEXPECTED_ERROR);
    586     }
    587   }
    588 
    589   n = 0;
    590   for (i = 0; i < *selection_candidate_count; i++) {
    591     ref_count = 0;
    592     match_count = 0;
    593 
    594     str_drc_instruction_str = &(
    595         pstr_drc_config->str_drc_instruction_str[selection_candidate_info[i]
    596                                                      .drc_instructions_index]);
    597     for (k = 0; k < str_drc_instruction_str->num_drc_ch_groups; k++) {
    598       gain_set_params =
    599           &(str_p_loc_drc_coefficients_uni_drc->gain_set_params
    600                 [str_drc_instruction_str->gain_set_index_for_channel_group[k]]);
    601       for (b = 0; b < gain_set_params->band_count; b++) {
    602         ref_count++;
    603         drc_characteristic = gain_set_params->gain_params[b].drc_characteristic;
    604         if (drc_characteristic == drc_characteristic_request_1)
    605           match_count += 1.0f;
    606         else if (drc_characteristic == drc_characteristic_request_2)
    607           match_count += 0.75f;
    608         else if (drc_characteristic == drc_characteristic_request_3)
    609           match_count += 0.5f;
    610       }
    611     }
    612     if (str_drc_instruction_str->depends_on_drc_set_present == 1) {
    613       WORD32 depends_on_drc_set = str_drc_instruction_str->depends_on_drc_set;
    614       for (m = 0; m < pstr_drc_config->drc_instructions_uni_drc_count; m++) {
    615         if (pstr_drc_config->str_drc_instruction_str[m].drc_set_id ==
    616             depends_on_drc_set)
    617           break;
    618       }
    619       if (m == pstr_drc_config->drc_instructions_uni_drc_count) {
    620         return (UNEXPECTED_ERROR);
    621       }
    622       str_drc_instruction_str = &(pstr_drc_config->str_drc_instruction_str[m]);
    623       if ((str_drc_instruction_str->drc_set_effect &
    624            (EFFECT_BIT_FADE | EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) ==
    625           0) {
    626         if (str_drc_instruction_str->drc_set_effect != EFFECT_BIT_CLIPPING) {
    627           for (k = 0; k < str_drc_instruction_str->num_drc_ch_groups; k++) {
    628             gain_set_params =
    629                 &(str_p_loc_drc_coefficients_uni_drc->gain_set_params
    630                       [str_drc_instruction_str
    631                            ->gain_set_index_for_channel_group[k]]);
    632             for (b = 0; b < gain_set_params->band_count; b++) {
    633               ref_count++;
    634               drc_characteristic =
    635                   gain_set_params->gain_params[b].drc_characteristic;
    636               if (drc_characteristic == drc_characteristic_request_1)
    637                 match_count += 1.0f;
    638               else if (drc_characteristic == drc_characteristic_request_2)
    639                 match_count += 0.75f;
    640               else if (drc_characteristic == drc_characteristic_request_3)
    641                 match_count += 0.5;
    642             }
    643           }
    644         }
    645       }
    646     }
    647     if ((ref_count > 0) && (((FLOAT32)match_count) > 0.5f * ref_count)) {
    648       memcpy(&selection_candidate_info[n], &selection_candidate_info[i],
    649              sizeof(ia_selection_candidate_info_struct));
    650       n++;
    651     }
    652   }
    653   if (n > 0) {
    654     *selection_candidate_count = n;
    655     *match_found_flag = 1;
    656   }
    657 
    658   return (0);
    659 }
    660 
    661 WORD32 impd_match_drc_characteristic(
    662     ia_drc_config* pstr_drc_config, WORD32 requested_drc_characteristic,
    663     WORD32* selection_candidate_count,
    664     ia_selection_candidate_info_struct* selection_candidate_info) {
    665   WORD32 k, err;
    666   WORD32 match_found_flag = 0;
    667 
    668   WORD32* drc_characteristic_order =
    669       drc_characteristic_order_default[requested_drc_characteristic - 1];
    670   WORD32 drc_characteristic_order_count =
    671       sizeof(drc_characteristic_order_default[requested_drc_characteristic]) /
    672       sizeof(WORD32);
    673   k = 0;
    674   while ((k < drc_characteristic_order_count) && (match_found_flag == 0) &&
    675          (drc_characteristic_order[k] > 0)) {
    676     err = impd_match_drc_characteristic_attempt(
    677         pstr_drc_config, drc_characteristic_order[k], &match_found_flag,
    678         selection_candidate_count, selection_candidate_info);
    679     if (err) return (err);
    680     k++;
    681   }
    682   return (0);
    683 }
    684 
    685 WORD32 impd_drc_set_preselection(
    686     ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct,
    687     ia_drc_config* pstr_drc_config,
    688     ia_drc_loudness_info_set_struct* pstr_loudness_info,
    689     WORD32 restrict_to_drc_with_album_loudness,
    690     ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc,
    691     WORD32* selection_candidate_count,
    692     ia_selection_candidate_info_struct* selection_candidate_info) {
    693   WORD32 i, j, k, l, d, n, err;
    694   WORD32 downmix_id_match = 0;
    695 
    696   WORD32 selection_candidate_step_2_count;
    697   ia_selection_candidate_info_struct
    698       selection_candidate_info_step_2[SELECTION_CANDIDATE_COUNT_MAX];
    699 
    700   WORD32 num_downmix_id_requests =
    701       pstr_drc_sel_proc_params_struct->num_downmix_id_requests;
    702   WORD32* requested_dwnmix_id =
    703       pstr_drc_sel_proc_params_struct->requested_dwnmix_id;
    704   FLOAT32 output_peak_level_max =
    705       pstr_drc_sel_proc_params_struct->output_peak_level_max;
    706   WORD32 loudness_deviation_max =
    707       pstr_drc_sel_proc_params_struct->loudness_deviation_max;
    708   WORD32* drc_set_id_valid_flag = pstr_drc_uni_sel_proc->drc_set_id_valid_flag;
    709   WORD32* eq_set_id_valid_flag = pstr_drc_uni_sel_proc->eq_set_id_valid_flag;
    710 
    711   FLOAT32 output_peak_level_min = 1000.0f;
    712   FLOAT32 adjustment;
    713   WORD32 loudness_drc_set_id_requested;
    714 
    715   WORD32 num_compression_eq_count = 0;
    716   WORD32 num_compression_eq_id[16];
    717 
    718   WORD32 loudness_info_count = 0;
    719   WORD32 eq_set_id_loudness[16];
    720   FLOAT32 loudness_normalization_gain_db[16];
    721   FLOAT32 loudness[16];
    722   WORD32 peak_info_count;
    723   WORD32 eq_set_id_Peak[16];
    724   FLOAT32 signal_peak_level[16];
    725   WORD32 explicit_peak_information_present[16];
    726 
    727   ia_uni_drc_coeffs_struct* str_p_loc_drc_coefficients_uni_drc = NULL;
    728   ia_drc_instructions_struct* str_drc_instruction_str = NULL;
    729 
    730   impd_select_drc_coeff3(pstr_drc_config, &str_p_loc_drc_coefficients_uni_drc);
    731 
    732   k = 0;
    733   for (d = 0; d < num_downmix_id_requests; d++) {
    734     err = impd_find_eq_set_no_compression(
    735         pstr_drc_config, requested_dwnmix_id[d], &num_compression_eq_count,
    736         num_compression_eq_id);
    737     if (err) return (err);
    738     for (i = 0; i < pstr_drc_config->drc_instructions_count_plus; i++) {
    739       downmix_id_match = 0;
    740       str_drc_instruction_str = &(pstr_drc_config->str_drc_instruction_str[i]);
    741 
    742       for (j = 0; j < str_drc_instruction_str->dwnmix_id_count; j++) {
    743         if ((str_drc_instruction_str->downmix_id[j] ==
    744              requested_dwnmix_id[d]) ||
    745             ((str_drc_instruction_str->downmix_id[j] == ID_FOR_BASE_LAYOUT) &&
    746              (str_drc_instruction_str->drc_set_id > 0)) ||
    747             (str_drc_instruction_str->downmix_id[j] == ID_FOR_ANY_DOWNMIX)) {
    748           downmix_id_match = 1;
    749         }
    750       }
    751       if (downmix_id_match == 1) {
    752         if (pstr_drc_sel_proc_params_struct->dynamic_range_control_on == 1) {
    753           if ((str_drc_instruction_str->drc_set_effect != EFFECT_BIT_FADE) &&
    754               (str_drc_instruction_str->drc_set_effect !=
    755                EFFECT_BIT_DUCK_OTHER) &&
    756               (str_drc_instruction_str->drc_set_effect !=
    757                EFFECT_BIT_DUCK_SELF) &&
    758               (str_drc_instruction_str->drc_set_effect != 0 ||
    759                str_drc_instruction_str->drc_set_id < 0) &&
    760               (((str_drc_instruction_str->depends_on_drc_set_present == 0) &&
    761                 (str_drc_instruction_str->no_independent_use == 0)) ||
    762                (str_drc_instruction_str->depends_on_drc_set_present == 1))) {
    763             WORD32 drc_is_permitted = 1;
    764             if (str_drc_instruction_str->drc_set_id > 0) {
    765               drc_is_permitted =
    766                   drc_set_id_valid_flag[str_drc_instruction_str->drc_set_id];
    767             }
    768             if (drc_is_permitted == 1) {
    769               err = impd_init_loudness_control(
    770                   pstr_drc_sel_proc_params_struct, pstr_loudness_info,
    771                   requested_dwnmix_id[d], str_drc_instruction_str->drc_set_id,
    772 
    773                   num_compression_eq_count, num_compression_eq_id,
    774                   &loudness_info_count, eq_set_id_loudness,
    775                   loudness_normalization_gain_db, loudness);
    776               if (err) return (err);
    777 
    778               err = impd_signal_peak_level_info(
    779                   pstr_drc_config, pstr_loudness_info, str_drc_instruction_str,
    780                   requested_dwnmix_id[d],
    781                   pstr_drc_sel_proc_params_struct->album_mode,
    782                   num_compression_eq_count, num_compression_eq_id,
    783                   &peak_info_count, eq_set_id_Peak, signal_peak_level,
    784                   explicit_peak_information_present);
    785               if (err) return (err);
    786 
    787               for (l = 0; l < loudness_info_count; l++) {
    788                 WORD32 match_found_flag = 0;
    789                 WORD32 p;
    790                 selection_candidate_info[k].loudness_norm_db_gain_adjusted =
    791                     loudness_normalization_gain_db[l];
    792 
    793                 selection_candidate_info[k]
    794                     .loudness_norm_db_gain_adjusted = min(
    795                     selection_candidate_info[k].loudness_norm_db_gain_adjusted,
    796                     pstr_drc_sel_proc_params_struct->loudness_norm_gain_db_max);
    797 
    798                 if (loudness[l] != UNDEFINED_LOUDNESS_VALUE) {
    799                   selection_candidate_info[k].output_loudness =
    800                       loudness[l] +
    801                       selection_candidate_info[k]
    802                           .loudness_norm_db_gain_adjusted;
    803                 } else {
    804                   selection_candidate_info[k].output_loudness =
    805                       UNDEFINED_LOUDNESS_VALUE;
    806                 }
    807 
    808                 for (p = 0; p < peak_info_count; p++) {
    809                   if (eq_set_id_Peak[p] == eq_set_id_loudness[l]) {
    810                     if (eq_set_id_valid_flag[eq_set_id_Peak[p]] == 1)
    811 
    812                     {
    813                       match_found_flag = 1;
    814                       break;
    815                     }
    816                   }
    817                 }
    818                 if (match_found_flag == 1) {
    819                   selection_candidate_info[k].output_peak_level =
    820                       signal_peak_level[p] +
    821                       selection_candidate_info[k]
    822                           .loudness_norm_db_gain_adjusted;
    823                 } else {
    824                   selection_candidate_info[k].output_peak_level =
    825                       selection_candidate_info[k]
    826                           .loudness_norm_db_gain_adjusted;
    827                 }
    828                 if ((str_drc_instruction_str->requires_eq == 1) &&
    829                     (eq_set_id_valid_flag[eq_set_id_loudness[l]] == 0))
    830                   continue;
    831                 selection_candidate_info[k].drc_instructions_index = i;
    832                 selection_candidate_info[k].downmix_id_request_index = d;
    833                 selection_candidate_info[k].eq_set_id = eq_set_id_loudness[l];
    834                 if (explicit_peak_information_present[p] == 1) {
    835                   selection_candidate_info[k].selection_flags =
    836                       SELECTION_FLAG_EXPLICIT_PEAK_INFO_PRESENT;
    837                 } else {
    838                   selection_candidate_info[k].selection_flags = 0;
    839                 }
    840                 impd_mixing_level_info(
    841                     pstr_drc_sel_proc_params_struct, pstr_loudness_info,
    842                     requested_dwnmix_id[d], str_drc_instruction_str->drc_set_id,
    843                     eq_set_id_loudness[l],
    844                     &selection_candidate_info[k].mixing_level);
    845                 if (str_drc_instruction_str->drc_set_target_loudness_present &&
    846                     ((pstr_drc_sel_proc_params_struct
    847                           ->loudness_normalization_on &&
    848                       str_drc_instruction_str
    849                               ->drc_set_target_loudness_value_upper >=
    850                           pstr_drc_sel_proc_params_struct->target_loudness &&
    851                       str_drc_instruction_str
    852                               ->drc_set_target_loudness_value_lower <
    853                           pstr_drc_sel_proc_params_struct->target_loudness) ||
    854                      !pstr_drc_sel_proc_params_struct
    855                           ->loudness_normalization_on)) {
    856                   selection_candidate_info[k].selection_flags |=
    857                       SELECTION_FLAG_DRC_TARGET_LOUDNESS_MATCH;
    858                   if (!explicit_peak_information_present[p]) {
    859                     if (pstr_drc_sel_proc_params_struct
    860                             ->loudness_normalization_on) {
    861                       selection_candidate_info[k].output_peak_level =
    862                           pstr_drc_sel_proc_params_struct->target_loudness -
    863                           str_drc_instruction_str
    864                               ->drc_set_target_loudness_value_upper;
    865                     } else {
    866                       selection_candidate_info[k].output_peak_level = 0.0f;
    867                     }
    868                   }
    869                 }
    870                 if ((selection_candidate_info[k].selection_flags &
    871                          (SELECTION_FLAG_DRC_TARGET_LOUDNESS_MATCH |
    872                           SELECTION_FLAG_EXPLICIT_PEAK_INFO_PRESENT) ||
    873                      !str_drc_instruction_str
    874                           ->drc_set_target_loudness_present)) {
    875                   k++;
    876                 } else {
    877                 }
    878               }
    879             }
    880           }
    881         } else {
    882           if (str_drc_instruction_str->drc_set_id < 0) {
    883             err = impd_init_loudness_control(
    884                 pstr_drc_sel_proc_params_struct, pstr_loudness_info,
    885                 requested_dwnmix_id[d], str_drc_instruction_str->drc_set_id,
    886                 num_compression_eq_count, num_compression_eq_id,
    887                 &loudness_info_count, eq_set_id_loudness,
    888                 loudness_normalization_gain_db, loudness);
    889             if (err) return (err);
    890 
    891             err = impd_signal_peak_level_info(
    892                 pstr_drc_config, pstr_loudness_info, str_drc_instruction_str,
    893                 requested_dwnmix_id[d],
    894                 pstr_drc_sel_proc_params_struct->album_mode,
    895                 num_compression_eq_count, num_compression_eq_id,
    896                 &peak_info_count, eq_set_id_Peak, signal_peak_level,
    897                 explicit_peak_information_present);
    898             if (err) return (err);
    899             for (l = 0; l < loudness_info_count; l++) {
    900               WORD32 match_found_flag = 0;
    901               WORD32 p;
    902               for (p = 0; p < peak_info_count; p++) {
    903                 if (eq_set_id_Peak[p] == eq_set_id_loudness[l]) {
    904                   if (eq_set_id_valid_flag[eq_set_id_Peak[p]] == 1) {
    905                     match_found_flag = 1;
    906                     break;
    907                   }
    908                 }
    909               }
    910               if (match_found_flag == 1) {
    911                 adjustment = max(
    912                     0.0f,
    913                     signal_peak_level[p] + loudness_normalization_gain_db[l] -
    914                         pstr_drc_sel_proc_params_struct->output_peak_level_max);
    915                 adjustment = min(adjustment, max(0.0f, loudness_deviation_max));
    916                 selection_candidate_info[k].loudness_norm_db_gain_adjusted =
    917                     loudness_normalization_gain_db[l] - adjustment;
    918 
    919                 selection_candidate_info[k]
    920                     .loudness_norm_db_gain_adjusted = min(
    921                     selection_candidate_info[k].loudness_norm_db_gain_adjusted,
    922                     pstr_drc_sel_proc_params_struct->loudness_norm_gain_db_max);
    923 
    924                 selection_candidate_info[k].output_peak_level =
    925                     signal_peak_level[p] +
    926                     selection_candidate_info[k].loudness_norm_db_gain_adjusted;
    927                 if (loudness[l] != UNDEFINED_LOUDNESS_VALUE) {
    928                   selection_candidate_info[k].output_loudness =
    929                       loudness[l] +
    930                       selection_candidate_info[k]
    931                           .loudness_norm_db_gain_adjusted;
    932                 } else {
    933                   selection_candidate_info[k].output_loudness =
    934                       UNDEFINED_LOUDNESS_VALUE;
    935                 }
    936                 selection_candidate_info[k].drc_instructions_index = i;
    937                 selection_candidate_info[k].downmix_id_request_index = d;
    938                 selection_candidate_info[k].eq_set_id = eq_set_id_loudness[l];
    939                 if (explicit_peak_information_present[p] == 1) {
    940                   selection_candidate_info[k].selection_flags =
    941                       SELECTION_FLAG_EXPLICIT_PEAK_INFO_PRESENT;
    942                 } else {
    943                   selection_candidate_info[k].selection_flags = 0;
    944                 }
    945                 impd_mixing_level_info(
    946                     pstr_drc_sel_proc_params_struct, pstr_loudness_info,
    947                     requested_dwnmix_id[d], str_drc_instruction_str->drc_set_id,
    948                     eq_set_id_loudness[l],
    949                     &selection_candidate_info[k].mixing_level);
    950                 k++;
    951               }
    952             }
    953           }
    954         }
    955       }
    956     }
    957   }
    958   *selection_candidate_count = k;
    959 
    960   if (*selection_candidate_count > SELECTION_CANDIDATE_COUNT_MAX) {
    961     return UNEXPECTED_ERROR;
    962   } else if (pstr_drc_sel_proc_params_struct->dynamic_range_control_on == 1) {
    963     n = 0;
    964     for (k = 0; k < *selection_candidate_count; k++) {
    965       str_drc_instruction_str =
    966           &(pstr_drc_config->str_drc_instruction_str
    967                 [selection_candidate_info[k].drc_instructions_index]);
    968 
    969       if (pstr_drc_sel_proc_params_struct->eq_set_purpose_request !=
    970           EQ_PURPOSE_EQ_OFF) {
    971         WORD32 matching_eq_set_count = 0;
    972         WORD32 matching_eq_instrucions_index[64];
    973         err = impd_match_eq_set(
    974             pstr_drc_config, requested_dwnmix_id[selection_candidate_info[k]
    975                                                      .downmix_id_request_index],
    976             str_drc_instruction_str->drc_set_id, eq_set_id_valid_flag,
    977             &matching_eq_set_count, matching_eq_instrucions_index);
    978         if (err) return (err);
    979         for (j = 0; j < matching_eq_set_count; j++) {
    980           memcpy(&selection_candidate_info_step_2[n],
    981                  &selection_candidate_info[k],
    982                  sizeof(ia_selection_candidate_info_struct));
    983           selection_candidate_info_step_2[n].eq_set_id =
    984               pstr_drc_config->str_drc_config_ext
    985                   .str_eq_instructions[matching_eq_instrucions_index[j]]
    986                   .eq_set_id;
    987           n++;
    988         }
    989       }
    990       if (str_drc_instruction_str->requires_eq == 0) {
    991         memcpy(&selection_candidate_info_step_2[n],
    992                &selection_candidate_info[k],
    993                sizeof(ia_selection_candidate_info_struct));
    994         selection_candidate_info_step_2[n].eq_set_id = 0;
    995         n++;
    996       }
    997     }
    998     for (k = 0; k < n; k++) {
    999       memcpy(&selection_candidate_info[k], &selection_candidate_info_step_2[k],
   1000              sizeof(ia_selection_candidate_info_struct));
   1001     }
   1002     *selection_candidate_count = n;
   1003     n = 0;
   1004     for (k = 0; k < *selection_candidate_count; k++) {
   1005       if ((selection_candidate_info[k].selection_flags &
   1006            SELECTION_FLAG_DRC_TARGET_LOUDNESS_MATCH) &&
   1007           !(selection_candidate_info[k].selection_flags &
   1008             SELECTION_FLAG_EXPLICIT_PEAK_INFO_PRESENT)) {
   1009         memcpy(&selection_candidate_info_step_2[n],
   1010                &selection_candidate_info[k],
   1011                sizeof(ia_selection_candidate_info_struct));
   1012         n++;
   1013       } else {
   1014         if (selection_candidate_info[k].output_peak_level <=
   1015             output_peak_level_max) {
   1016           memcpy(&selection_candidate_info_step_2[n],
   1017                  &selection_candidate_info[k],
   1018                  sizeof(ia_selection_candidate_info_struct));
   1019           n++;
   1020         }
   1021         if (selection_candidate_info[k].output_peak_level <
   1022             output_peak_level_min) {
   1023           output_peak_level_min = selection_candidate_info[k].output_peak_level;
   1024         }
   1025       }
   1026     }
   1027     selection_candidate_step_2_count = n;
   1028     if (selection_candidate_step_2_count == 0) {
   1029       n = 0;
   1030       for (k = 0; k < *selection_candidate_count; k++) {
   1031         if ((selection_candidate_info[k].selection_flags &
   1032              SELECTION_FLAG_DRC_TARGET_LOUDNESS_MATCH) &&
   1033             (selection_candidate_info[k].selection_flags &
   1034              SELECTION_FLAG_EXPLICIT_PEAK_INFO_PRESENT)) {
   1035           memcpy(&selection_candidate_info_step_2[n],
   1036                  &selection_candidate_info[k],
   1037                  sizeof(ia_selection_candidate_info_struct));
   1038           n++;
   1039         }
   1040       }
   1041       selection_candidate_step_2_count = n;
   1042     }
   1043     if (selection_candidate_step_2_count == 0) {
   1044       n = 0;
   1045       for (k = 0; k < *selection_candidate_count; k++) {
   1046         if (selection_candidate_info_step_2[k].output_peak_level <
   1047             output_peak_level_min + 1.0f) {
   1048           memcpy(&selection_candidate_info_step_2[n],
   1049                  &selection_candidate_info[k],
   1050                  sizeof(ia_selection_candidate_info_struct));
   1051           adjustment =
   1052               max(0.0f, selection_candidate_info_step_2[n].output_peak_level -
   1053                             output_peak_level_max);
   1054           adjustment = min(adjustment, max(0.0f, loudness_deviation_max));
   1055           selection_candidate_info_step_2[n].loudness_norm_db_gain_adjusted -=
   1056               adjustment;
   1057           selection_candidate_info_step_2[n].output_peak_level -= adjustment;
   1058           selection_candidate_info_step_2[n].output_loudness -= adjustment;
   1059           n++;
   1060         }
   1061       }
   1062       selection_candidate_step_2_count = n;
   1063     }
   1064 
   1065     for (n = 0; n < selection_candidate_step_2_count; n++) {
   1066       memcpy(&selection_candidate_info[n], &selection_candidate_info_step_2[n],
   1067              sizeof(ia_selection_candidate_info_struct));
   1068     }
   1069     *selection_candidate_count = selection_candidate_step_2_count;
   1070   }
   1071 
   1072   if (restrict_to_drc_with_album_loudness == 1) {
   1073     j = 0;
   1074     for (k = 0; k < *selection_candidate_count; k++) {
   1075       loudness_drc_set_id_requested =
   1076           max(0, pstr_drc_config
   1077                      ->str_drc_instruction_str[selection_candidate_info[k]
   1078                                                    .drc_instructions_index]
   1079                      .drc_set_id);
   1080       for (n = 0; n < pstr_loudness_info->loudness_info_album_count; n++) {
   1081         if (loudness_drc_set_id_requested ==
   1082             pstr_loudness_info->str_loudness_info_album[n].drc_set_id) {
   1083           memcpy(&selection_candidate_info[j], &selection_candidate_info[k],
   1084                  sizeof(ia_selection_candidate_info_struct));
   1085           j++;
   1086           break;
   1087         }
   1088       }
   1089     }
   1090     *selection_candidate_count = j;
   1091   }
   1092   return (0);
   1093 }
   1094 
   1095 WORD32 impd_drc_set_final_selection(
   1096     ia_drc_config* pstr_drc_config,
   1097     ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct,
   1098     WORD32* selection_candidate_count,
   1099     ia_selection_candidate_info_struct* selection_candidate_info,
   1100     WORD32* eq_set_id_valid_flag) {
   1101   WORD32 k, i, n, err;
   1102   WORD32 selection_candidate_step_2_count;
   1103   ia_selection_candidate_info_struct
   1104       selection_candidate_info_step_2[SELECTION_CANDIDATE_COUNT_MAX];
   1105   WORD32 drc_set_id_max;
   1106   FLOAT32 output_level_max;
   1107   FLOAT32 output_level_min;
   1108   WORD32 effect_count, effect_count_min;
   1109   WORD32 effect_types_request_table_size;
   1110   WORD32 drc_set_target_loudness_val_upper_min;
   1111   ia_drc_instructions_struct* str_drc_instruction_str;
   1112   ia_drc_instructions_struct* drc_instructions_dependent;
   1113 
   1114   if (pstr_drc_sel_proc_params_struct->eq_set_purpose_request > 0) {
   1115     WORD32 eq_purpose_requested =
   1116         pstr_drc_sel_proc_params_struct->eq_set_purpose_request;
   1117 
   1118     impd_match_eq_set_purpose(pstr_drc_config, eq_purpose_requested,
   1119                               eq_set_id_valid_flag, selection_candidate_count,
   1120                               selection_candidate_info,
   1121                               selection_candidate_info_step_2);
   1122   }
   1123 
   1124   output_level_min = 10000.0f;
   1125   k = 0;
   1126   for (i = 0; i < *selection_candidate_count; i++) {
   1127     if (output_level_min >= selection_candidate_info[i].output_peak_level) {
   1128       if (output_level_min > selection_candidate_info[i].output_peak_level) {
   1129         output_level_min = selection_candidate_info[i].output_peak_level;
   1130         k = 0;
   1131       }
   1132       memcpy(&selection_candidate_info_step_2[k], &selection_candidate_info[i],
   1133              sizeof(ia_selection_candidate_info_struct));
   1134       k++;
   1135     }
   1136   }
   1137   selection_candidate_step_2_count = k;
   1138 
   1139   if (output_level_min <= 0.0f) {
   1140     selection_candidate_step_2_count = *selection_candidate_count;
   1141     k = 0;
   1142     for (i = 0; i < selection_candidate_step_2_count; i++) {
   1143       if (selection_candidate_info[i].output_peak_level <= 0.0f) {
   1144         memcpy(&selection_candidate_info_step_2[k],
   1145                &selection_candidate_info[i],
   1146                sizeof(ia_selection_candidate_info_struct));
   1147         k++;
   1148       }
   1149     }
   1150     selection_candidate_step_2_count = k;
   1151 
   1152     k = 0;
   1153     for (i = 0; i < selection_candidate_step_2_count; i++) {
   1154       str_drc_instruction_str =
   1155           &(pstr_drc_config->str_drc_instruction_str
   1156                 [selection_candidate_info_step_2[i].drc_instructions_index]);
   1157       for (n = 0; n < str_drc_instruction_str->dwnmix_id_count; n++) {
   1158         if (pstr_drc_sel_proc_params_struct->requested_dwnmix_id
   1159                 [selection_candidate_info_step_2[i].downmix_id_request_index] ==
   1160             str_drc_instruction_str->downmix_id[n]) {
   1161           memcpy(&selection_candidate_info_step_2[k],
   1162                  &selection_candidate_info_step_2[i],
   1163                  sizeof(ia_selection_candidate_info_struct));
   1164           k++;
   1165         }
   1166       }
   1167     }
   1168     if (k > 0) {
   1169       selection_candidate_step_2_count = k;
   1170     }
   1171 
   1172     effect_types_request_table_size =
   1173         sizeof(effect_types_request_table) / sizeof(WORD32);
   1174     effect_count_min = 100;
   1175     k = 0;
   1176     for (i = 0; i < selection_candidate_step_2_count; i++) {
   1177       str_drc_instruction_str =
   1178           &(pstr_drc_config->str_drc_instruction_str
   1179                 [selection_candidate_info_step_2[i].drc_instructions_index]);
   1180       effect_count = 0;
   1181       if (str_drc_instruction_str->depends_on_drc_set_present == 1) {
   1182         err = impd_get_dependent_drc_instructions(pstr_drc_config,
   1183                                                   str_drc_instruction_str,
   1184                                                   &drc_instructions_dependent);
   1185         if (err) return (err);
   1186 
   1187         for (n = 0; n < effect_types_request_table_size; n++) {
   1188           if (effect_types_request_table[n] != EFFECT_BIT_GENERAL_COMPR) {
   1189             if (((str_drc_instruction_str->drc_set_effect &
   1190                   effect_types_request_table[n]) != 0x0) ||
   1191                 ((drc_instructions_dependent->drc_set_effect &
   1192                   effect_types_request_table[n]) != 0x0)) {
   1193               effect_count++;
   1194             }
   1195           }
   1196         }
   1197       } else {
   1198         for (n = 0; n < effect_types_request_table_size; n++) {
   1199           if (effect_types_request_table[n] != EFFECT_BIT_GENERAL_COMPR) {
   1200             if ((str_drc_instruction_str->drc_set_effect &
   1201                  effect_types_request_table[n]) != 0x0) {
   1202               effect_count++;
   1203             }
   1204           }
   1205         }
   1206       }
   1207       if (effect_count_min >= effect_count) {
   1208         if (effect_count_min > effect_count) {
   1209           effect_count_min = effect_count;
   1210           k = 0;
   1211         }
   1212         memcpy(&selection_candidate_info_step_2[k],
   1213                &selection_candidate_info_step_2[i],
   1214                sizeof(ia_selection_candidate_info_struct));
   1215         k++;
   1216       }
   1217     }
   1218     selection_candidate_step_2_count = k;
   1219 
   1220     drc_set_target_loudness_val_upper_min = 100;
   1221     k = 0;
   1222     for (i = 0; i < selection_candidate_step_2_count; i++) {
   1223       if (selection_candidate_info_step_2[i].selection_flags &
   1224           SELECTION_FLAG_DRC_TARGET_LOUDNESS_MATCH) {
   1225         k++;
   1226       }
   1227     }
   1228     if (k != 0 && k != selection_candidate_step_2_count) {
   1229       k = 0;
   1230       for (i = 0; i < selection_candidate_step_2_count; i++) {
   1231         if (!(selection_candidate_info_step_2[i].selection_flags &
   1232               SELECTION_FLAG_DRC_TARGET_LOUDNESS_MATCH)) {
   1233           memcpy(&selection_candidate_info_step_2[k],
   1234                  &selection_candidate_info_step_2[i],
   1235                  sizeof(ia_selection_candidate_info_struct));
   1236           k++;
   1237         }
   1238       }
   1239       selection_candidate_step_2_count = k;
   1240     } else if (k == selection_candidate_step_2_count) {
   1241       k = 0;
   1242       for (i = 0; i < selection_candidate_step_2_count; i++) {
   1243         str_drc_instruction_str =
   1244             &(pstr_drc_config->str_drc_instruction_str
   1245                   [selection_candidate_info_step_2[i].drc_instructions_index]);
   1246         if (str_drc_instruction_str->drc_set_target_loudness_present != 1) {
   1247           return UNEXPECTED_ERROR;
   1248         }
   1249         if (drc_set_target_loudness_val_upper_min >=
   1250             str_drc_instruction_str->drc_set_target_loudness_value_upper) {
   1251           if (drc_set_target_loudness_val_upper_min >
   1252               str_drc_instruction_str->drc_set_target_loudness_value_upper) {
   1253             drc_set_target_loudness_val_upper_min =
   1254                 str_drc_instruction_str->drc_set_target_loudness_value_upper;
   1255             k = 0;
   1256           }
   1257           memcpy(&selection_candidate_info_step_2[k],
   1258                  &selection_candidate_info_step_2[i],
   1259                  sizeof(ia_selection_candidate_info_struct));
   1260           k++;
   1261         }
   1262       }
   1263       selection_candidate_step_2_count = k;
   1264     }
   1265 
   1266     k = 0;
   1267     for (i = 0; i < selection_candidate_step_2_count; i++) {
   1268       str_drc_instruction_str =
   1269           &(pstr_drc_config->str_drc_instruction_str
   1270                 [selection_candidate_info_step_2[i].drc_instructions_index]);
   1271       if (str_drc_instruction_str->drc_set_target_loudness_present &&
   1272           pstr_drc_sel_proc_params_struct->loudness_normalization_on &&
   1273           str_drc_instruction_str->drc_set_target_loudness_value_upper >=
   1274               pstr_drc_sel_proc_params_struct->target_loudness &&
   1275           str_drc_instruction_str->drc_set_target_loudness_value_lower <
   1276               pstr_drc_sel_proc_params_struct->target_loudness) {
   1277         k++;
   1278       }
   1279     }
   1280     if (k != 0 && k != selection_candidate_step_2_count) {
   1281       k = 0;
   1282       for (i = 0; i < selection_candidate_step_2_count; i++) {
   1283         str_drc_instruction_str =
   1284             &(pstr_drc_config->str_drc_instruction_str
   1285                   [selection_candidate_info_step_2[i].drc_instructions_index]);
   1286         if (str_drc_instruction_str->drc_set_target_loudness_present &&
   1287             pstr_drc_sel_proc_params_struct->loudness_normalization_on &&
   1288             str_drc_instruction_str->drc_set_target_loudness_value_upper >=
   1289                 pstr_drc_sel_proc_params_struct->target_loudness &&
   1290             str_drc_instruction_str->drc_set_target_loudness_value_lower <
   1291                 pstr_drc_sel_proc_params_struct->target_loudness) {
   1292           memcpy(&selection_candidate_info_step_2[k],
   1293                  &selection_candidate_info_step_2[i],
   1294                  sizeof(ia_selection_candidate_info_struct));
   1295           k++;
   1296         }
   1297       }
   1298       selection_candidate_step_2_count = k;
   1299       drc_set_target_loudness_val_upper_min = 100;
   1300       k = 0;
   1301       for (i = 0; i < selection_candidate_step_2_count; i++) {
   1302         str_drc_instruction_str =
   1303             &(pstr_drc_config->str_drc_instruction_str
   1304                   [selection_candidate_info_step_2[i].drc_instructions_index]);
   1305         if (str_drc_instruction_str->drc_set_target_loudness_present != 1) {
   1306           return UNEXPECTED_ERROR;
   1307         }
   1308         if (drc_set_target_loudness_val_upper_min >=
   1309             str_drc_instruction_str->drc_set_target_loudness_value_upper) {
   1310           if (drc_set_target_loudness_val_upper_min >
   1311               str_drc_instruction_str->drc_set_target_loudness_value_upper) {
   1312             drc_set_target_loudness_val_upper_min =
   1313                 str_drc_instruction_str->drc_set_target_loudness_value_upper;
   1314             k = 0;
   1315           }
   1316           memcpy(&selection_candidate_info_step_2[k],
   1317                  &selection_candidate_info_step_2[i],
   1318                  sizeof(ia_selection_candidate_info_struct));
   1319           k++;
   1320         }
   1321       }
   1322       selection_candidate_step_2_count = k;
   1323     } else if (k == selection_candidate_step_2_count) {
   1324       drc_set_target_loudness_val_upper_min = 100;
   1325       k = 0;
   1326       for (i = 0; i < selection_candidate_step_2_count; i++) {
   1327         str_drc_instruction_str =
   1328             &(pstr_drc_config->str_drc_instruction_str
   1329                   [selection_candidate_info_step_2[i].drc_instructions_index]);
   1330         if (str_drc_instruction_str->drc_set_target_loudness_present != 1) {
   1331           return UNEXPECTED_ERROR;
   1332         }
   1333         if (drc_set_target_loudness_val_upper_min >=
   1334             str_drc_instruction_str->drc_set_target_loudness_value_upper) {
   1335           if (drc_set_target_loudness_val_upper_min >
   1336               str_drc_instruction_str->drc_set_target_loudness_value_upper) {
   1337             drc_set_target_loudness_val_upper_min =
   1338                 str_drc_instruction_str->drc_set_target_loudness_value_upper;
   1339             k = 0;
   1340           }
   1341           memcpy(&selection_candidate_info_step_2[k],
   1342                  &selection_candidate_info_step_2[i],
   1343                  sizeof(ia_selection_candidate_info_struct));
   1344           k++;
   1345         }
   1346       }
   1347       selection_candidate_step_2_count = k;
   1348     }
   1349     k = 0;
   1350     output_level_max = -1000.0f;
   1351     for (i = 0; i < selection_candidate_step_2_count; i++) {
   1352       if ((selection_candidate_info_step_2[i].output_peak_level <= 0.0f) &&
   1353           (output_level_max <=
   1354            selection_candidate_info_step_2[i].output_peak_level)) {
   1355         if (output_level_max <
   1356             selection_candidate_info_step_2[i].output_peak_level) {
   1357           output_level_max =
   1358               selection_candidate_info_step_2[i].output_peak_level;
   1359           k = 0;
   1360         }
   1361         memcpy(&selection_candidate_info_step_2[k],
   1362                &selection_candidate_info_step_2[i],
   1363                sizeof(ia_selection_candidate_info_struct));
   1364         k++;
   1365         output_level_max = selection_candidate_info_step_2[i].output_peak_level;
   1366       }
   1367     }
   1368     selection_candidate_step_2_count = k;
   1369   }
   1370 
   1371   drc_set_id_max = -1000;
   1372   for (i = 0; i < selection_candidate_step_2_count; i++) {
   1373     str_drc_instruction_str =
   1374         &(pstr_drc_config->str_drc_instruction_str
   1375               [selection_candidate_info_step_2[i].drc_instructions_index]);
   1376     if (drc_set_id_max < str_drc_instruction_str->drc_set_id) {
   1377       drc_set_id_max = str_drc_instruction_str->drc_set_id;
   1378       memcpy(&selection_candidate_info_step_2[0],
   1379              &selection_candidate_info_step_2[i],
   1380              sizeof(ia_selection_candidate_info_struct));
   1381     }
   1382   }
   1383   memcpy(&selection_candidate_info[0], &selection_candidate_info_step_2[0],
   1384          sizeof(ia_selection_candidate_info_struct));
   1385   *selection_candidate_count = 1;
   1386 
   1387   return 0;
   1388 }
   1389 
   1390 WORD32 impd_select_drc_set(ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc,
   1391                            WORD32* drc_set_id_selected,
   1392                            WORD32* eq_set_id_selected, WORD32* loud_eq_id_sel) {
   1393   WORD32 i, err;
   1394 
   1395   ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct =
   1396       &pstr_drc_uni_sel_proc->uni_drc_sel_proc_params;
   1397   ia_drc_config* pstr_drc_config = &pstr_drc_uni_sel_proc->drc_config;
   1398   ia_drc_loudness_info_set_struct* pstr_loudness_info =
   1399       &pstr_drc_uni_sel_proc->loudness_info_set;
   1400 
   1401   WORD32 selection_candidate_count = 0;
   1402   WORD32 restrict_to_drc_with_album_loudness = 0;
   1403   ia_selection_candidate_info_struct
   1404       selection_candidate_info[SELECTION_CANDIDATE_COUNT_MAX];
   1405 
   1406   //    WORD32 selected_eq_set_count = 0;
   1407 
   1408   if (pstr_drc_sel_proc_params_struct->album_mode == 1) {
   1409     restrict_to_drc_with_album_loudness = 1;
   1410   }
   1411 
   1412   while (!selection_candidate_count) {
   1413     impd_drc_set_preselection(
   1414         pstr_drc_sel_proc_params_struct, pstr_drc_config, pstr_loudness_info,
   1415         restrict_to_drc_with_album_loudness, pstr_drc_uni_sel_proc,
   1416         &selection_candidate_count, selection_candidate_info);
   1417 
   1418     if (selection_candidate_count == 0) {
   1419       if (restrict_to_drc_with_album_loudness == 1) {
   1420         restrict_to_drc_with_album_loudness = 0;
   1421         continue;
   1422       } else {
   1423         return (UNEXPECTED_ERROR);
   1424       }
   1425     }
   1426 
   1427     err = impd_validate_requested_drc_feature(pstr_drc_sel_proc_params_struct);
   1428     if (err) return (err);
   1429 
   1430     if (pstr_drc_sel_proc_params_struct->dynamic_range_control_on == 1) {
   1431       if (pstr_drc_sel_proc_params_struct->num_drc_feature_requests > 0) {
   1432         for (i = 0;
   1433              i < pstr_drc_sel_proc_params_struct->num_drc_feature_requests;
   1434              i++) {
   1435           switch (pstr_drc_sel_proc_params_struct->drc_feature_req_type[i]) {
   1436             case MATCH_EFFECT_TYPE:
   1437               err = impd_match_effect_types(
   1438                   pstr_drc_config,
   1439                   pstr_drc_sel_proc_params_struct->requested_num_drc_effects[i],
   1440                   pstr_drc_sel_proc_params_struct
   1441                       ->desired_num_drc_effects_of_requested[i],
   1442                   pstr_drc_sel_proc_params_struct->requested_drc_effect_type[i],
   1443                   &selection_candidate_count, selection_candidate_info);
   1444               if (err) return (err);
   1445               break;
   1446             case MATCH_DYNAMIC_RANGE:
   1447               err = impd_match_dynamic_range(
   1448                   pstr_drc_config, pstr_loudness_info,
   1449                   pstr_drc_sel_proc_params_struct, i,
   1450                   &selection_candidate_count, selection_candidate_info);
   1451               if (err) return (err);
   1452               break;
   1453             case MATCH_DRC_CHARACTERISTIC:
   1454               err = impd_match_drc_characteristic(
   1455                   pstr_drc_config, pstr_drc_sel_proc_params_struct
   1456                                        ->requested_drc_characteristic[i],
   1457                   &selection_candidate_count, selection_candidate_info);
   1458               if (err) return (err);
   1459               break;
   1460 
   1461             default:
   1462               return (UNEXPECTED_ERROR);
   1463               break;
   1464           }
   1465         }
   1466       } else {
   1467         WORD32 match_found_flag = 0;
   1468 
   1469         err = impd_select_drcs_without_compr_effects(
   1470             pstr_drc_config, &match_found_flag, &selection_candidate_count,
   1471             selection_candidate_info);
   1472         if (err) return (err);
   1473 
   1474         if (match_found_flag == 0) {
   1475           WORD32 requested_num_drc_effects = 5;
   1476           WORD32 desired_num_drc_effects_of_requested = 1;
   1477           WORD32 requested_drc_effect_type[5] = {
   1478               EFFECT_TYPE_REQUESTED_GENERAL_COMPR, EFFECT_TYPE_REQUESTED_NIGHT,
   1479               EFFECT_TYPE_REQUESTED_NOISY, EFFECT_TYPE_REQUESTED_LIMITED,
   1480               EFFECT_TYPE_REQUESTED_LOWLEVEL};
   1481 
   1482           err = impd_match_effect_types(
   1483               pstr_drc_config, requested_num_drc_effects,
   1484               desired_num_drc_effects_of_requested, requested_drc_effect_type,
   1485               &selection_candidate_count, selection_candidate_info);
   1486           if (err) return (err);
   1487         }
   1488       }
   1489 
   1490       if (selection_candidate_count > 0) {
   1491         err = impd_drc_set_final_selection(
   1492             pstr_drc_config, pstr_drc_sel_proc_params_struct,
   1493             &selection_candidate_count, selection_candidate_info,
   1494             pstr_drc_uni_sel_proc->eq_set_id_valid_flag);
   1495         if (err) return (err);
   1496       } else {
   1497         selection_candidate_count = 0;
   1498         return (UNEXPECTED_ERROR);
   1499       }
   1500     }
   1501 
   1502     if (selection_candidate_count == 0) {
   1503       if (restrict_to_drc_with_album_loudness == 1) {
   1504         restrict_to_drc_with_album_loudness = 0;
   1505       } else {
   1506         return (UNEXPECTED_ERROR);
   1507       }
   1508     }
   1509   }
   1510   *drc_set_id_selected =
   1511       pstr_drc_config
   1512           ->str_drc_instruction_str[selection_candidate_info[0]
   1513                                         .drc_instructions_index]
   1514           .drc_set_id;
   1515   *eq_set_id_selected = selection_candidate_info[0].eq_set_id;
   1516 
   1517   impd_select_loud_eq(
   1518       pstr_drc_config,
   1519       pstr_drc_sel_proc_params_struct->requested_dwnmix_id
   1520           [selection_candidate_info[0].downmix_id_request_index],
   1521       *drc_set_id_selected, *eq_set_id_selected, loud_eq_id_sel);
   1522   if (selection_candidate_count > 0) {
   1523     pstr_drc_uni_sel_proc->uni_drc_sel_proc_output
   1524         .loudness_normalization_gain_db =
   1525         selection_candidate_info[0].loudness_norm_db_gain_adjusted;
   1526     pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.output_peak_level_db =
   1527         selection_candidate_info[0].output_peak_level;
   1528     pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.output_loudness =
   1529         selection_candidate_info[0].output_loudness;
   1530     pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.active_downmix_id =
   1531         pstr_drc_sel_proc_params_struct->requested_dwnmix_id
   1532             [selection_candidate_info[0].downmix_id_request_index];
   1533     pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.mixing_level =
   1534         selection_candidate_info[0].mixing_level;
   1535   }
   1536   return (0);
   1537 }
   1538