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 <stdlib.h>
     22 #include <math.h>
     23 #include <string.h>
     24 #include "impd_type_def.h"
     25 #include "impd_drc_extr_delta_coded_info.h"
     26 #include "impd_drc_common.h"
     27 #include "impd_drc_struct.h"
     28 #include "impd_drc_interface.h"
     29 #include "impd_drc_selection_process.h"
     30 #include "impd_drc_sel_proc_drc_set_sel.h"
     31 
     32 WORD32 impd_drc_uni_selction_proc_init(
     33     ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc,
     34     ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct,
     35     ia_drc_interface_struct* pstr_drc_interface, WORD32 subband_domain_mode) {
     36   WORD32 err = 0;
     37 
     38   if (pstr_drc_uni_sel_proc == NULL) {
     39     return 1;
     40   }
     41 
     42   if (pstr_drc_uni_sel_proc->first_frame == 1) {
     43     err = impd_drc_sel_proc_init_dflt(pstr_drc_uni_sel_proc);
     44     if (err) return (err);
     45   }
     46 
     47   err = impd_drc_sel_proc_init_sel_proc_params(pstr_drc_uni_sel_proc,
     48                                                pstr_drc_sel_proc_params_struct);
     49   if (err) return (err);
     50   {
     51     WORD32 i;
     52     pstr_drc_uni_sel_proc->drc_set_id_valid_flag[0] = 1;
     53     for (i = 1; i < DRC_INSTRUCTIONS_COUNT_MAX; i++) {
     54       pstr_drc_uni_sel_proc->drc_set_id_valid_flag[i] = 0;
     55     }
     56 
     57     pstr_drc_uni_sel_proc->eq_set_id_valid_flag[0] = 1;
     58     for (i = 1; i < EQ_INSTRUCTIONS_COUNT_MAX; i++) {
     59       pstr_drc_uni_sel_proc->eq_set_id_valid_flag[i] = 0;
     60     }
     61   }
     62   err = impd_drc_sel_proc_init_interface_params(pstr_drc_uni_sel_proc,
     63                                                 pstr_drc_interface);
     64   if (err) return (err);
     65 
     66   pstr_drc_uni_sel_proc->subband_domain_mode = subband_domain_mode;
     67 
     68   return 0;
     69 }
     70 
     71 WORD32
     72 impd_drc_uni_sel_proc_process(
     73     ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc,
     74     ia_drc_config* pstr_drc_config,
     75     ia_drc_loudness_info_set_struct* pstr_loudness_info,
     76     ia_drc_sel_proc_output_struct* hia_drc_sel_proc_output_struct) {
     77   WORD32 i, err, drc_set_id_selected, activeDrcSetIndex;
     78   WORD32 eq_set_id_selected;
     79   WORD32 loudEqSetIdSelected;
     80 
     81   if (pstr_drc_config != NULL) {
     82     if (memcmp(&pstr_drc_uni_sel_proc->drc_config, pstr_drc_config,
     83                sizeof(ia_drc_config))) {
     84       pstr_drc_uni_sel_proc->drc_config = *pstr_drc_config;
     85       pstr_drc_uni_sel_proc->drc_config_flag = 1;
     86 
     87       if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.base_channel_count !=
     88           pstr_drc_uni_sel_proc->drc_config.channel_layout.base_channel_count) {
     89         pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.base_channel_count =
     90             pstr_drc_uni_sel_proc->drc_config.channel_layout.base_channel_count;
     91       }
     92       if (pstr_drc_uni_sel_proc->drc_config.channel_layout
     93                   .layout_signaling_present == 1 &&
     94           pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.base_layout !=
     95               pstr_drc_uni_sel_proc->drc_config.channel_layout.defined_layout) {
     96         pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.base_layout =
     97             pstr_drc_uni_sel_proc->drc_config.channel_layout.defined_layout;
     98       }
     99     } else {
    100       pstr_drc_uni_sel_proc->drc_config_flag = 0;
    101     }
    102   }
    103   if (pstr_loudness_info != NULL) {
    104     if (memcmp(&pstr_drc_uni_sel_proc->loudness_info_set, pstr_loudness_info,
    105                sizeof(ia_drc_loudness_info_set_struct))) {
    106       pstr_drc_uni_sel_proc->loudness_info_set = *pstr_loudness_info;
    107       pstr_drc_uni_sel_proc->loudness_info_set_flag = 1;
    108     } else {
    109       pstr_drc_uni_sel_proc->loudness_info_set_flag = 0;
    110     }
    111   }
    112 
    113   if ((pstr_drc_uni_sel_proc->drc_config_flag &&
    114        pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    115                .target_config_request_type != 0) ||
    116       (pstr_drc_uni_sel_proc->sel_proc_request_flag &&
    117        pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    118                .target_config_request_type != 0) ||
    119       (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    120                .target_config_request_type == 0 &&
    121        pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.num_downmix_id_requests ==
    122            0)) {
    123     err = impd_map_target_config_req_downmix_id(
    124         pstr_drc_uni_sel_proc, &pstr_drc_uni_sel_proc->drc_config);
    125     if (err) return (err);
    126   }
    127 
    128   if (pstr_drc_uni_sel_proc->drc_config_flag ||
    129       pstr_drc_uni_sel_proc->loudness_info_set_flag ||
    130       pstr_drc_uni_sel_proc->sel_proc_request_flag) {
    131     WORD32 repeat_selection = 1;
    132     WORD32 loop_cnt = 0;
    133 
    134     err = impd_manage_drc_complexity(pstr_drc_uni_sel_proc, pstr_drc_config);
    135     if (err) return (err);
    136     err = impd_manage_eq_complexity(pstr_drc_uni_sel_proc, pstr_drc_config);
    137     if (err) return (err);
    138     while (repeat_selection == 1) {
    139       err = impd_select_drc_set(pstr_drc_uni_sel_proc, &drc_set_id_selected,
    140                                 &eq_set_id_selected, &loudEqSetIdSelected);
    141       if (err) return (err);
    142 
    143       err =
    144           impd_get_selected_drc_set(pstr_drc_uni_sel_proc, drc_set_id_selected);
    145       if (err) return (err);
    146 
    147       err = impd_get_dependent_drc_set(pstr_drc_uni_sel_proc);
    148       if (err) return (err);
    149 
    150       err = impd_get_fading_drc_set(pstr_drc_uni_sel_proc);
    151       if (err) return (err);
    152 
    153       err = impd_get_ducking_drc_set(pstr_drc_uni_sel_proc);
    154       if (err) return (err);
    155 
    156       pstr_drc_uni_sel_proc->eq_inst_index[0] = -1;
    157       pstr_drc_uni_sel_proc->eq_inst_index[1] = -1;
    158 
    159       err = impd_get_selected_eq_set(pstr_drc_uni_sel_proc, eq_set_id_selected);
    160       if (err) return (err);
    161 
    162       err = impd_get_dependent_eq_set(pstr_drc_uni_sel_proc);
    163       if (err) return (err);
    164 
    165       err = impd_get_selected_loud_eq_set(pstr_drc_uni_sel_proc,
    166                                           loudEqSetIdSelected);
    167       if (err) return (err);
    168 
    169       activeDrcSetIndex = 0;
    170       for (i = SUB_DRC_COUNT - 1; i >= 0; i--) {
    171         WORD32 drc_instructions_index =
    172             pstr_drc_uni_sel_proc->drc_instructions_index[i];
    173         if (drc_instructions_index < 0) continue;
    174 
    175         ia_drc_instructions_struct* str_drc_instruction_str =
    176             &(pstr_drc_uni_sel_proc->drc_config
    177                   .str_drc_instruction_str[drc_instructions_index]);
    178 
    179         if (str_drc_instruction_str->drc_set_id > 0) {
    180           pstr_drc_uni_sel_proc->uni_drc_sel_proc_output
    181               .sel_drc_set_ids[activeDrcSetIndex] =
    182               str_drc_instruction_str->drc_set_id;
    183 
    184           if ((i == 3) && (str_drc_instruction_str->drc_set_effect &
    185                            (EFFECT_BIT_DUCK_SELF | EFFECT_BIT_DUCK_OTHER))) {
    186             pstr_drc_uni_sel_proc->uni_drc_sel_proc_output
    187                 .sel_downmix_ids[activeDrcSetIndex] = 0;
    188           } else {
    189             if (str_drc_instruction_str->drc_apply_to_dwnmix == 1) {
    190               pstr_drc_uni_sel_proc->uni_drc_sel_proc_output
    191                   .sel_downmix_ids[activeDrcSetIndex] =
    192                   str_drc_instruction_str->downmix_id[0];
    193             } else {
    194               pstr_drc_uni_sel_proc->uni_drc_sel_proc_output
    195                   .sel_downmix_ids[activeDrcSetIndex] = 0;
    196             }
    197           }
    198 
    199           activeDrcSetIndex++;
    200         }
    201       }
    202       if (activeDrcSetIndex <= 3) {
    203         pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.num_sel_drc_sets =
    204             activeDrcSetIndex;
    205       } else {
    206         pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.num_sel_drc_sets = -1;
    207         return (UNEXPECTED_ERROR);
    208       }
    209 
    210       impd_sel_downmix_matrix(pstr_drc_uni_sel_proc,
    211                               &pstr_drc_uni_sel_proc->drc_config);
    212 
    213       err = impd_manage_complexity(pstr_drc_uni_sel_proc, pstr_drc_config,
    214                                    &repeat_selection);
    215       if (err) return (err);
    216 
    217       loop_cnt++;
    218       if (loop_cnt > 100) {
    219         return (UNEXPECTED_ERROR);
    220       }
    221     }
    222 
    223     pstr_drc_uni_sel_proc->sel_proc_request_flag = 0;
    224     pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.boost =
    225         pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.boost;
    226     pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.compress =
    227         pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.compress;
    228     pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.drc_characteristic_target =
    229         pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    230             .drc_characteristic_target;
    231     pstr_drc_uni_sel_proc->uni_drc_sel_proc_output
    232         .loudness_normalization_gain_db +=
    233         pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    234             .loudness_norm_gain_modification_db;
    235   }
    236   for (i = 0; i < 2; i++) {
    237     if (pstr_drc_uni_sel_proc->eq_inst_index[i] >= 0) {
    238       pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.sel_eq_set_ids[i] =
    239           pstr_drc_uni_sel_proc->drc_config.str_drc_config_ext
    240               .str_eq_instructions[pstr_drc_uni_sel_proc->eq_inst_index[i]]
    241               .eq_set_id;
    242     }
    243   }
    244   if (pstr_drc_uni_sel_proc->loud_eq_inst_index_sel >= 0) {
    245     pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.sel_loud_eq_id =
    246         pstr_drc_uni_sel_proc->drc_config.str_drc_config_ext
    247             .loud_eq_instructions[pstr_drc_uni_sel_proc->loud_eq_inst_index_sel]
    248             .loud_eq_set_id;
    249   } else {
    250     pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.sel_loud_eq_id = 0;
    251   }
    252   *hia_drc_sel_proc_output_struct =
    253       pstr_drc_uni_sel_proc->uni_drc_sel_proc_output;
    254 
    255   return 0;
    256 }
    257 
    258 WORD32 impd_map_target_config_req_downmix_id(
    259     ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc,
    260     ia_drc_config* pstr_drc_config) {
    261   WORD32 i, dwnmix_instructions_count;
    262   WORD32 target_ch_count_prelim =
    263       pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.base_channel_count;
    264 
    265   pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.num_downmix_id_requests = 0;
    266   switch (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    267               .target_config_request_type) {
    268     case 0:
    269       if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    270               .num_downmix_id_requests == 0) {
    271         pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.requested_dwnmix_id[0] =
    272             0;
    273         pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.num_downmix_id_requests =
    274             1;
    275       }
    276       break;
    277     case 1:
    278       if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    279               .requested_target_layout ==
    280           pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.base_layout) {
    281         pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.requested_dwnmix_id[0] =
    282             0;
    283         pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.num_downmix_id_requests =
    284             1;
    285       }
    286       if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    287               .num_downmix_id_requests == 0) {
    288         dwnmix_instructions_count =
    289             pstr_drc_uni_sel_proc->drc_config.dwnmix_instructions_count;
    290         for (i = 0; i < dwnmix_instructions_count; i++) {
    291           ia_downmix_instructions_struct* dwnmix_instructions =
    292               &(pstr_drc_config->dwnmix_instructions[i]);
    293           if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    294                   .requested_target_layout ==
    295               dwnmix_instructions->target_layout) {
    296             pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.requested_dwnmix_id
    297                 [pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    298                      .num_downmix_id_requests] =
    299                 dwnmix_instructions->downmix_id;
    300             pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    301                 .num_downmix_id_requests += 1;
    302             target_ch_count_prelim = dwnmix_instructions->target_channel_count;
    303           }
    304         }
    305       }
    306 
    307       if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    308               .num_downmix_id_requests == 0) {
    309         pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.requested_dwnmix_id[0] =
    310             0;
    311         pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.num_downmix_id_requests =
    312             1;
    313       }
    314       break;
    315     case 2:
    316       if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    317               .requested_target_ch_count ==
    318           pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.base_channel_count) {
    319         pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.requested_dwnmix_id[0] =
    320             0;
    321         pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.num_downmix_id_requests =
    322             1;
    323       }
    324       if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    325               .num_downmix_id_requests == 0) {
    326         dwnmix_instructions_count =
    327             pstr_drc_uni_sel_proc->drc_config.dwnmix_instructions_count;
    328         for (i = 0; i < dwnmix_instructions_count; i++) {
    329           ia_downmix_instructions_struct* dwnmix_instructions =
    330               &(pstr_drc_config->dwnmix_instructions[i]);
    331           if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    332                   .requested_target_ch_count ==
    333               dwnmix_instructions->target_channel_count) {
    334             pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.requested_dwnmix_id
    335                 [pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    336                      .num_downmix_id_requests] =
    337                 dwnmix_instructions->downmix_id;
    338             pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    339                 .num_downmix_id_requests += 1;
    340             target_ch_count_prelim = dwnmix_instructions->target_channel_count;
    341           }
    342         }
    343       }
    344 
    345       if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params
    346               .num_downmix_id_requests == 0) {
    347         pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.requested_dwnmix_id[0] =
    348             0;
    349         pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.num_downmix_id_requests =
    350             1;
    351       }
    352       break;
    353     default:
    354       return UNEXPECTED_ERROR;
    355       break;
    356   }
    357   pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.target_ch_count_prelim =
    358       target_ch_count_prelim;
    359 
    360   return 0;
    361 }
    362 
    363 VOID impd_sel_downmix_matrix(ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc,
    364                              ia_drc_config* pstr_drc_config) {
    365   WORD32 i, j, n;
    366 
    367   pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.base_channel_count =
    368       pstr_drc_config->channel_layout.base_channel_count;
    369   pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.target_channel_count =
    370       pstr_drc_config->channel_layout.base_channel_count;
    371   pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.target_layout = -1;
    372   pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.downmix_matrix_present = 0;
    373   pstr_drc_uni_sel_proc->downmix_inst_index_sel = -1;
    374 
    375   if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.active_downmix_id != 0) {
    376     for (n = 0; n < pstr_drc_config->dwnmix_instructions_count; n++) {
    377       ia_downmix_instructions_struct* dwnmix_instructions =
    378           &(pstr_drc_config->dwnmix_instructions[n]);
    379 
    380       if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.active_downmix_id ==
    381           dwnmix_instructions->downmix_id) {
    382         pstr_drc_uni_sel_proc->downmix_inst_index_sel = n;
    383         pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.target_channel_count =
    384             dwnmix_instructions->target_channel_count;
    385         pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.target_layout =
    386             dwnmix_instructions->target_layout;
    387         if (dwnmix_instructions->downmix_coefficients_present) {
    388           for (i = 0; i < pstr_drc_uni_sel_proc->uni_drc_sel_proc_output
    389                               .base_channel_count;
    390                i++) {
    391             for (j = 0; j < pstr_drc_uni_sel_proc->uni_drc_sel_proc_output
    392                                 .target_channel_count;
    393                  j++) {
    394               pstr_drc_uni_sel_proc->uni_drc_sel_proc_output
    395                   .downmix_matrix[i][j] =
    396                   dwnmix_instructions->downmix_coefficient
    397                       [i +
    398                        j *
    399                            pstr_drc_uni_sel_proc->uni_drc_sel_proc_output
    400                                .base_channel_count];
    401             }
    402           }
    403           pstr_drc_uni_sel_proc->uni_drc_sel_proc_output
    404               .downmix_matrix_present = 1;
    405         }
    406         break;
    407       }
    408     }
    409   }
    410   return;
    411 }
    412 
    413 WORD32 impd_get_selected_eq_set(ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc,
    414                                 WORD32 eq_set_id_selected) {
    415   WORD32 n;
    416 
    417   pstr_drc_uni_sel_proc->eq_inst_index_sel = -1;
    418 
    419   if (eq_set_id_selected > 0) {
    420     for (n = 0; n < pstr_drc_uni_sel_proc->drc_config.str_drc_config_ext
    421                         .eq_instructions_count;
    422          n++) {
    423       if (pstr_drc_uni_sel_proc->drc_config.str_drc_config_ext
    424               .str_eq_instructions[n]
    425               .eq_set_id == eq_set_id_selected)
    426         break;
    427     }
    428     if (n ==
    429         pstr_drc_uni_sel_proc->drc_config.str_drc_config_ext
    430             .eq_instructions_count) {
    431       return (EXTERNAL_ERROR);
    432     }
    433     pstr_drc_uni_sel_proc->eq_inst_index_sel = n;
    434     if (pstr_drc_uni_sel_proc->drc_config.str_drc_config_ext
    435             .str_eq_instructions[n]
    436             .eq_apply_to_downmix == 1) {
    437       pstr_drc_uni_sel_proc->eq_inst_index[1] =
    438           pstr_drc_uni_sel_proc->eq_inst_index_sel;
    439     } else {
    440       pstr_drc_uni_sel_proc->eq_inst_index[0] =
    441           pstr_drc_uni_sel_proc->eq_inst_index_sel;
    442     }
    443   }
    444   return (0);
    445 }
    446 
    447 WORD32 impd_get_dependent_eq_set(ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc) {
    448   ia_eq_instructions_struct* str_eq_instructions = NULL;
    449 
    450   if (pstr_drc_uni_sel_proc->eq_inst_index_sel >= 0) {
    451     str_eq_instructions =
    452         &(pstr_drc_uni_sel_proc->drc_config.str_drc_config_ext
    453               .str_eq_instructions[pstr_drc_uni_sel_proc->eq_inst_index_sel]);
    454 
    455     if (str_eq_instructions->depends_on_eq_set_present == 1) {
    456       WORD32 n;
    457       WORD32 dependsOnEqSetID = str_eq_instructions->depends_on_eq_set;
    458 
    459       for (n = 0; n < pstr_drc_uni_sel_proc->drc_config.str_drc_config_ext
    460                           .eq_instructions_count;
    461            n++) {
    462         if (pstr_drc_uni_sel_proc->drc_config.str_drc_config_ext
    463                 .str_eq_instructions[n]
    464                 .eq_set_id == dependsOnEqSetID)
    465           break;
    466       }
    467       if (n ==
    468           pstr_drc_uni_sel_proc->drc_config.str_drc_config_ext
    469               .eq_instructions_count) {
    470         return (UNEXPECTED_ERROR);
    471       }
    472       if (pstr_drc_uni_sel_proc->drc_config.str_drc_config_ext
    473               .str_eq_instructions[n]
    474               .eq_apply_to_downmix == 1) {
    475         pstr_drc_uni_sel_proc->eq_inst_index[1] = n;
    476       } else {
    477         pstr_drc_uni_sel_proc->eq_inst_index[0] = n;
    478       }
    479     }
    480   }
    481   return (0);
    482 }
    483 
    484 WORD32 impd_get_selected_loud_eq_set(
    485     ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc, WORD32 loudEqSetIdSelected) {
    486   WORD32 n;
    487 
    488   pstr_drc_uni_sel_proc->loud_eq_inst_index_sel = -1;
    489 
    490   if (loudEqSetIdSelected > 0) {
    491     for (n = 0; n < pstr_drc_uni_sel_proc->drc_config.str_drc_config_ext
    492                         .loud_eq_instructions_count;
    493          n++) {
    494       if (pstr_drc_uni_sel_proc->drc_config.str_drc_config_ext
    495               .loud_eq_instructions[n]
    496               .loud_eq_set_id == loudEqSetIdSelected)
    497         break;
    498     }
    499     if (n ==
    500         pstr_drc_uni_sel_proc->drc_config.str_drc_config_ext
    501             .loud_eq_instructions_count) {
    502       return (EXTERNAL_ERROR);
    503     }
    504     pstr_drc_uni_sel_proc->loud_eq_inst_index_sel = n;
    505   }
    506   return (0);
    507 }
    508 
    509 WORD32 impd_select_loud_eq(ia_drc_config* pstr_drc_config,
    510                            WORD32 requested_dwnmix_id,
    511                            WORD32 drc_set_id_requested,
    512                            WORD32 eq_set_id_requested, WORD32* loud_eq_id_sel) {
    513   WORD32 i, c, d, e;
    514 
    515   *loud_eq_id_sel = 0;
    516   for (i = 0;
    517        i < pstr_drc_config->str_drc_config_ext.loud_eq_instructions_count;
    518        i++) {
    519     ia_loud_eq_instructions_struct* loud_eq_instructions =
    520         &pstr_drc_config->str_drc_config_ext.loud_eq_instructions[i];
    521     if (loud_eq_instructions->drc_location == LOCATION_SELECTED) {
    522       for (d = 0; d < loud_eq_instructions->dwnmix_id_count; d++) {
    523         if ((loud_eq_instructions->downmix_id[d] == requested_dwnmix_id) ||
    524             (loud_eq_instructions->downmix_id[d] == ID_FOR_ANY_DOWNMIX)) {
    525           for (c = 0; c < loud_eq_instructions->drc_set_id_count; c++) {
    526             if ((loud_eq_instructions->drc_set_id[c] == drc_set_id_requested) ||
    527                 (loud_eq_instructions->drc_set_id[c] == ID_FOR_ANY_DRC)) {
    528               for (e = 0; e < loud_eq_instructions->eq_set_id_count; e++) {
    529                 if ((loud_eq_instructions->eq_set_id[e] ==
    530                      eq_set_id_requested) ||
    531                     (loud_eq_instructions->eq_set_id[e] == ID_FOR_ANY_EQ)) {
    532                   *loud_eq_id_sel = loud_eq_instructions->loud_eq_set_id;
    533                 }
    534               }
    535             }
    536           }
    537         }
    538       }
    539     }
    540   }
    541   return (0);
    542 }
    543 
    544 WORD32 impd_match_eq_set(ia_drc_config* drc_config, WORD32 downmix_id,
    545                          WORD32 drc_set_id, WORD32* eq_set_id_valid_flag,
    546                          WORD32* matching_eq_set_count,
    547                          WORD32* matching_eq_set_idx) {
    548   ia_eq_instructions_struct* str_eq_instructions = NULL;
    549   WORD32 i, k, n;
    550   WORD32 match = 0;
    551   *matching_eq_set_count = 0;
    552   for (i = 0; i < drc_config->str_drc_config_ext.eq_instructions_count; i++) {
    553     str_eq_instructions =
    554         &drc_config->str_drc_config_ext.str_eq_instructions[i];
    555 
    556     if (str_eq_instructions->depends_on_eq_set_present == 0) {
    557       if (str_eq_instructions->no_independent_eq_use == 1) continue;
    558     }
    559     if (eq_set_id_valid_flag[str_eq_instructions->eq_set_id] == 0) continue;
    560     for (k = 0; k < str_eq_instructions->dwnmix_id_count; k++) {
    561       if ((str_eq_instructions->downmix_id[k] == ID_FOR_ANY_DOWNMIX) ||
    562           (downmix_id == str_eq_instructions->downmix_id[k])) {
    563         for (n = 0; n < str_eq_instructions->drc_set_id_count; n++) {
    564           if ((str_eq_instructions->drc_set_id[n] == ID_FOR_ANY_DRC) ||
    565               (drc_set_id == str_eq_instructions->drc_set_id[n])) {
    566             match = 1;
    567             matching_eq_set_idx[*matching_eq_set_count] = i;
    568             (*matching_eq_set_count)++;
    569           }
    570         }
    571       }
    572     }
    573   }
    574   return (0);
    575 }
    576 
    577 WORD32 impd_match_eq_set_purpose(
    578     ia_drc_config* drc_config, WORD32 eq_set_purpose_requested,
    579     WORD32* eq_set_id_valid_flag, WORD32* selection_candidate_count,
    580     ia_selection_candidate_info_struct* selection_candidate_info,
    581     ia_selection_candidate_info_struct* selection_candidate_info_step_2) {
    582   WORD32 i, j, k;
    583   WORD32 match_found_flag;
    584   WORD32 loop_cnt = 0;
    585   ia_eq_instructions_struct* str_eq_instructions = NULL;
    586   match_found_flag = 0;
    587 
    588   k = 0;
    589   while ((k == 0) && (loop_cnt < 2)) {
    590     for (j = 0; j < *selection_candidate_count; j++) {
    591       WORD32 eq_set_id_requested = selection_candidate_info[j].eq_set_id;
    592 
    593       for (i = 0; i < drc_config->str_drc_config_ext.eq_instructions_count;
    594            i++) {
    595         str_eq_instructions =
    596             &drc_config->str_drc_config_ext.str_eq_instructions[i];
    597 
    598         if (str_eq_instructions->depends_on_eq_set_present == 0) {
    599           if (eq_set_id_valid_flag[str_eq_instructions->eq_set_id] == 0)
    600             continue;
    601         }
    602         if (eq_set_id_valid_flag[str_eq_instructions->eq_set_id] == 0) continue;
    603         if ((str_eq_instructions->eq_set_id == eq_set_id_requested) &&
    604             (str_eq_instructions->eq_set_purpose & eq_set_purpose_requested)) {
    605           match_found_flag = 1;
    606         }
    607       }
    608 
    609       if (match_found_flag > 0) {
    610         memcpy(&selection_candidate_info_step_2[k],
    611                &selection_candidate_info[j],
    612                sizeof(ia_selection_candidate_info_struct));
    613         k++;
    614       }
    615     }
    616     eq_set_purpose_requested = EQ_PURPOSE_DEFAULT;
    617     loop_cnt++;
    618   }
    619 
    620   if (k > 0) {
    621     memcpy(&selection_candidate_info[0], &selection_candidate_info_step_2[0],
    622            k * sizeof(ia_selection_candidate_info_struct));
    623     *selection_candidate_count = k;
    624   }
    625 
    626   return (0);
    627 }
    628 
    629 WORD32 impd_find_eq_set_no_compression(ia_drc_config* pstr_drc_config,
    630                                        WORD32 requested_dwnmix_id,
    631                                        WORD32* num_compression_eq_count,
    632                                        WORD32* num_compression_eq_id) {
    633   WORD32 i, d, k, c;
    634   k = 0;
    635   for (i = 0; i < pstr_drc_config->str_drc_config_ext.eq_instructions_count;
    636        i++) {
    637     ia_eq_instructions_struct* str_eq_instructions =
    638         &pstr_drc_config->str_drc_config_ext.str_eq_instructions[i];
    639     for (d = 0; d < str_eq_instructions->dwnmix_id_count; d++) {
    640       if (requested_dwnmix_id == str_eq_instructions->downmix_id[d]) {
    641         for (c = 0; c < str_eq_instructions->drc_set_id_count; c++) {
    642           if ((str_eq_instructions->drc_set_id[c] == ID_FOR_ANY_DRC) ||
    643               (str_eq_instructions->drc_set_id[c] == 0)) {
    644             if (k >= MAX_NUM_COMPRESSION_EQ) return UNEXPECTED_ERROR;
    645             num_compression_eq_id[k] = str_eq_instructions->eq_set_id;
    646             k++;
    647           }
    648         }
    649       }
    650     }
    651   }
    652   *num_compression_eq_count = k;
    653   return (0);
    654 }
    655 
    656 VOID impd_select_drc_coeff3(
    657     ia_drc_config* drc_config,
    658     ia_uni_drc_coeffs_struct** str_p_loc_drc_coefficients_uni_drc) {
    659   WORD32 n;
    660   WORD32 cV1 = -1;
    661   WORD32 cV0 = -1;
    662   for (n = 0; n < drc_config->drc_coefficients_drc_count; n++) {
    663     if (drc_config->str_p_loc_drc_coefficients_uni_drc[n].drc_location == 1) {
    664       if (drc_config->str_p_loc_drc_coefficients_uni_drc[n].version == 0) {
    665         cV0 = n;
    666       } else {
    667         cV1 = n;
    668       }
    669     }
    670   }
    671   if (cV1 >= 0) {
    672     *str_p_loc_drc_coefficients_uni_drc =
    673         &(drc_config->str_p_loc_drc_coefficients_uni_drc[cV1]);
    674   } else if (cV0 >= 0) {
    675     *str_p_loc_drc_coefficients_uni_drc =
    676         &(drc_config->str_p_loc_drc_coefficients_uni_drc[cV0]);
    677   } else {
    678     *str_p_loc_drc_coefficients_uni_drc = NULL;
    679   }
    680   return;
    681 }
    682 
    683 WORD32 impd_manage_drc_complexity(ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc,
    684                                   ia_drc_config* pstr_drc_config) {
    685   WORD32 i, j, err, channel_count;
    686   WORD32 numBandsTooLarge = 0;
    687   FLOAT32 complexityDrcPrelim;
    688   ia_uni_drc_coeffs_struct* str_p_loc_drc_coefficients_uni_drc;
    689   FLOAT32 complexitySupportedTotal =
    690       (FLOAT32)(pow(2.0f, pstr_drc_uni_sel_proc->compl_level_supported_total));
    691   ia_drc_instructions_struct* str_drc_instruction_str;
    692   ia_drc_instructions_struct* drc_inst_uni_drc_dependent;
    693   ia_drc_sel_proc_output_struct* uni_drc_sel_proc_output =
    694       &pstr_drc_uni_sel_proc->uni_drc_sel_proc_output;
    695   ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct =
    696       &pstr_drc_uni_sel_proc->uni_drc_sel_proc_params;
    697 
    698   impd_select_drc_coeff3(pstr_drc_config, &str_p_loc_drc_coefficients_uni_drc);
    699   if (str_p_loc_drc_coefficients_uni_drc == NULL) return UNEXPECTED_ERROR;
    700   for (i = 0; i < pstr_drc_config->drc_instructions_uni_drc_count; i++) {
    701     str_drc_instruction_str = &pstr_drc_config->str_drc_instruction_str[i];
    702     if (str_drc_instruction_str->no_independent_use) continue;
    703 
    704     numBandsTooLarge = 0;
    705     if (str_drc_instruction_str->drc_apply_to_dwnmix == 1) {
    706       channel_count = uni_drc_sel_proc_output->target_channel_count;
    707     } else {
    708       channel_count = uni_drc_sel_proc_output->base_channel_count;
    709     }
    710     if (pstr_drc_uni_sel_proc->subband_domain_mode == SUBBAND_DOMAIN_MODE_OFF) {
    711       for (j = 0; j < str_drc_instruction_str->num_drc_ch_groups; j++) {
    712         ia_gain_set_params_struct* gain_set_params = &(
    713             str_p_loc_drc_coefficients_uni_drc->gain_set_params
    714                 [str_drc_instruction_str->gain_set_index_for_channel_group[j]]);
    715         if (gain_set_params->band_count >
    716             pstr_drc_sel_proc_params_struct->num_bands_supported) {
    717           numBandsTooLarge = 1;
    718         } else {
    719           if (gain_set_params->band_count > 4) {
    720             /* Add complexity for analysis and synthesis QMF bank here, if
    721              * supported */
    722           }
    723         }
    724       }
    725     }
    726     complexityDrcPrelim =
    727         (FLOAT32)(channel_count *
    728                   (1 << str_drc_instruction_str->drc_set_complexity_level));
    729 
    730     if (str_drc_instruction_str->depends_on_drc_set > 0) {
    731       err = impd_find_drc_instructions_uni_drc(
    732           pstr_drc_config, str_drc_instruction_str->depends_on_drc_set,
    733           &drc_inst_uni_drc_dependent);
    734       if (err) return (err);
    735       if (drc_inst_uni_drc_dependent->drc_apply_to_dwnmix == 1) {
    736         channel_count = uni_drc_sel_proc_output->target_channel_count;
    737       } else {
    738         channel_count = uni_drc_sel_proc_output->base_channel_count;
    739       }
    740       if (pstr_drc_uni_sel_proc->subband_domain_mode ==
    741           SUBBAND_DOMAIN_MODE_OFF) {
    742         for (j = 0; j < str_drc_instruction_str->num_drc_ch_groups; j++) {
    743           ia_gain_set_params_struct* gain_set_params = &(
    744               str_p_loc_drc_coefficients_uni_drc
    745                   ->gain_set_params[drc_inst_uni_drc_dependent
    746                                         ->gain_set_index_for_channel_group[j]]);
    747           if (gain_set_params->band_count >
    748               pstr_drc_sel_proc_params_struct->num_bands_supported) {
    749             numBandsTooLarge = 1;
    750           } else {
    751             if (gain_set_params->band_count > 4) {
    752               /* Add complexity for analysis and synthesis QMF bank here, if
    753                * supported */
    754             }
    755           }
    756         }
    757       }
    758       complexityDrcPrelim +=
    759           channel_count *
    760           (1 << drc_inst_uni_drc_dependent->drc_set_complexity_level);
    761     }
    762 
    763     complexityDrcPrelim *= pstr_drc_config->sampling_rate / 48000.0f;
    764 
    765     if ((complexityDrcPrelim <= complexitySupportedTotal) &&
    766         (numBandsTooLarge == 0)) {
    767       pstr_drc_uni_sel_proc
    768           ->drc_set_id_valid_flag[str_drc_instruction_str->drc_set_id] = 1;
    769     }
    770   }
    771   return (0);
    772 }
    773 
    774 WORD32 impd_manage_eq_complexity(ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc,
    775                                  ia_drc_config* pstr_drc_config) {
    776   WORD32 k, n, m, err;
    777   WORD32 eqComplexityPrimary = 0;
    778   WORD32 eqComplexityDependent = 0;
    779   WORD32 eqChannelCountPrimary = 0, eqChannelCountDependent = 0;
    780   FLOAT32 complexityTotalEq;
    781   ia_drc_config* drc_config = &pstr_drc_uni_sel_proc->drc_config;
    782   ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct =
    783       &pstr_drc_uni_sel_proc->uni_drc_sel_proc_params;
    784   FLOAT32 complexitySupportedTotal =
    785       (FLOAT32)(pow(2.0f, pstr_drc_uni_sel_proc->compl_level_supported_total));
    786 
    787   for (n = 0; n < drc_config->str_drc_config_ext.eq_instructions_count; n++) {
    788     ia_eq_instructions_struct* str_eq_instructions =
    789         &pstr_drc_config->str_drc_config_ext.str_eq_instructions[n];
    790 
    791     eqChannelCountPrimary = pstr_drc_sel_proc_params_struct->base_channel_count;
    792     eqChannelCountDependent =
    793         pstr_drc_sel_proc_params_struct->base_channel_count;
    794 
    795     eqComplexityPrimary = 1 << str_eq_instructions->eq_set_complexity_level;
    796     if (pstr_drc_uni_sel_proc->subband_domain_mode == SUBBAND_DOMAIN_MODE_OFF) {
    797       if (str_eq_instructions->td_filter_cascade_present == 0) {
    798         eqComplexityPrimary = 0;
    799       }
    800     } else {
    801       if (str_eq_instructions->td_filter_cascade_present == 1) {
    802         eqComplexityPrimary = (WORD32)2.5f;
    803       }
    804     }
    805     if (str_eq_instructions->eq_apply_to_downmix == 1) {
    806       if (str_eq_instructions->downmix_id[0] == ID_FOR_ANY_DOWNMIX) {
    807         eqChannelCountPrimary =
    808             pstr_drc_sel_proc_params_struct->target_ch_count_prelim;
    809       } else {
    810         for (k = 0; k < pstr_drc_config->dwnmix_instructions_count; k++) {
    811           for (m = 0; m < str_eq_instructions->dwnmix_id_count; m++) {
    812             if (pstr_drc_config->dwnmix_instructions[k].downmix_id ==
    813                 str_eq_instructions->downmix_id[m]) {
    814               if (eqChannelCountPrimary >
    815                   pstr_drc_config->dwnmix_instructions[k]
    816                       .target_channel_count) {
    817                 eqChannelCountPrimary = pstr_drc_config->dwnmix_instructions[k]
    818                                             .target_channel_count;
    819               }
    820             }
    821           }
    822         }
    823       }
    824     }
    825     complexityTotalEq = (FLOAT32)(eqChannelCountPrimary * eqComplexityPrimary);
    826 
    827     if (str_eq_instructions->depends_on_eq_set_present > 0) {
    828       ia_eq_instructions_struct* eq_instructionsDependent;
    829       err = impd_find_eq_instructions(drc_config,
    830                                       str_eq_instructions->depends_on_eq_set,
    831                                       &eq_instructionsDependent);
    832       if (err) return (err);
    833       eqComplexityDependent =
    834           1 << eq_instructionsDependent->eq_set_complexity_level;
    835       if (pstr_drc_uni_sel_proc->subband_domain_mode ==
    836           SUBBAND_DOMAIN_MODE_OFF) {
    837         if (str_eq_instructions->td_filter_cascade_present == 0) {
    838           eqComplexityDependent = 0;
    839         }
    840       } else {
    841         if (str_eq_instructions->td_filter_cascade_present == 1) {
    842           eqComplexityDependent = (WORD32)2.5f;
    843         }
    844       }
    845       if (eq_instructionsDependent->eq_apply_to_downmix == 1) {
    846         if (eq_instructionsDependent->downmix_id[0] == ID_FOR_ANY_DOWNMIX) {
    847           eqChannelCountDependent =
    848               pstr_drc_sel_proc_params_struct->target_ch_count_prelim;
    849         } else {
    850           for (k = 0; k < pstr_drc_config->dwnmix_instructions_count; k++) {
    851             for (m = 0; m < str_eq_instructions->dwnmix_id_count; m++) {
    852               if (pstr_drc_config->dwnmix_instructions[k].downmix_id ==
    853                   eq_instructionsDependent->downmix_id[m]) {
    854                 if (eqChannelCountDependent >
    855                     pstr_drc_config->dwnmix_instructions[k]
    856                         .target_channel_count) {
    857                   eqChannelCountDependent =
    858                       pstr_drc_config->dwnmix_instructions[k]
    859                           .target_channel_count;
    860                 }
    861               }
    862             }
    863           }
    864         }
    865       }
    866       complexityTotalEq += eqChannelCountDependent * eqComplexityDependent;
    867     }
    868 
    869     pstr_drc_uni_sel_proc
    870         ->eq_set_id_valid_flag[str_eq_instructions->eq_set_id] = 0;
    871     complexityTotalEq *= pstr_drc_config->sampling_rate / 48000.0f;
    872 
    873     if (complexityTotalEq <= complexitySupportedTotal) {
    874       pstr_drc_uni_sel_proc
    875           ->eq_set_id_valid_flag[str_eq_instructions->eq_set_id] = 1;
    876     }
    877   }
    878   return 0;
    879 }
    880 
    881 WORD32 impd_manage_complexity(ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc,
    882                               ia_drc_config* pstr_drc_config,
    883                               WORD32* repeat_selection) {
    884   WORD32 i, j, p, err;
    885   WORD32 channel_count;
    886   WORD32 numBandsTooLarge = 0;
    887   WORD32 drcRequiresEq;
    888   FLOAT32 complexityEq;
    889   FLOAT32 complexityDrcTotal = 0.0f;
    890   FLOAT32 complexityEqTotal = 0.0f;
    891   FLOAT32 freqNorm = pstr_drc_config->sampling_rate / 48000.0f;
    892   ia_uni_drc_coeffs_struct* str_p_loc_drc_coefficients_uni_drc;
    893   ia_drc_instructions_struct* str_drc_instruction_str =
    894       &pstr_drc_config->str_drc_instruction_str[0];
    895   ia_drc_sel_proc_output_struct* uni_drc_sel_proc_output =
    896       &pstr_drc_uni_sel_proc->uni_drc_sel_proc_output;
    897   ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct =
    898       &pstr_drc_uni_sel_proc->uni_drc_sel_proc_params;
    899   FLOAT32 complexitySupportedTotal =
    900       (FLOAT32)(pow(2.0f, pstr_drc_uni_sel_proc->compl_level_supported_total));
    901 
    902   impd_select_drc_coeff3(pstr_drc_config, &str_p_loc_drc_coefficients_uni_drc);
    903 
    904   if (str_p_loc_drc_coefficients_uni_drc == NULL) return UNEXPECTED_ERROR;
    905 
    906   for (p = 0; p < 4; p++) {
    907     if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.sel_drc_set_ids[p] <= 0)
    908       continue;
    909     err = impd_find_drc_instructions_uni_drc(
    910         pstr_drc_config,
    911         pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.sel_drc_set_ids[p],
    912         &str_drc_instruction_str);
    913     if (err) return (err);
    914 
    915     if (str_drc_instruction_str->drc_apply_to_dwnmix == 1) {
    916       channel_count = uni_drc_sel_proc_output->target_channel_count;
    917     } else {
    918       channel_count = uni_drc_sel_proc_output->base_channel_count;
    919     }
    920     if (pstr_drc_uni_sel_proc->subband_domain_mode == SUBBAND_DOMAIN_MODE_OFF) {
    921       for (j = 0; j < str_drc_instruction_str->num_drc_ch_groups; j++) {
    922         ia_gain_set_params_struct* gain_set_params = &(
    923             str_p_loc_drc_coefficients_uni_drc->gain_set_params
    924                 [str_drc_instruction_str->gain_set_index_for_channel_group[j]]);
    925         if (gain_set_params->band_count >
    926             pstr_drc_sel_proc_params_struct->num_bands_supported) {
    927           if (p < 2) {
    928             numBandsTooLarge = 1;
    929           } else {
    930             pstr_drc_uni_sel_proc
    931                 ->drc_set_id_valid_flag[str_drc_instruction_str->drc_set_id] =
    932                 0;
    933             pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.sel_drc_set_ids[p] =
    934                 0;
    935           }
    936         } else {
    937           if (gain_set_params->band_count > 4) {
    938             /* Add complexity for analysis and synthesis QMF bank here, if
    939              * supported */
    940           }
    941         }
    942       }
    943     }
    944     complexityDrcTotal +=
    945         channel_count *
    946         (1 << str_drc_instruction_str->drc_set_complexity_level);
    947   }
    948 
    949   if (uni_drc_sel_proc_output->active_downmix_id > 0) {
    950     FLOAT32 complexityPerCoeff;
    951     ia_downmix_instructions_struct* dwnmix_instructions;
    952 
    953     if (pstr_drc_uni_sel_proc->subband_domain_mode == SUBBAND_DOMAIN_MODE_OFF) {
    954       complexityPerCoeff = 1.0f;
    955     } else {
    956       complexityPerCoeff = 2.0f;
    957     }
    958     impd_find_downmix(pstr_drc_config,
    959                       uni_drc_sel_proc_output->active_downmix_id,
    960                       &dwnmix_instructions);
    961     if (dwnmix_instructions->downmix_coefficients_present == 1) {
    962       for (i = 0; i < uni_drc_sel_proc_output->base_channel_count; i++) {
    963         for (j = 0; j < uni_drc_sel_proc_output->target_channel_count; j++) {
    964           if (uni_drc_sel_proc_output->downmix_matrix[i][j] != 0.0f) {
    965             complexityDrcTotal += complexityPerCoeff;
    966           }
    967         }
    968       }
    969     } else {
    970       /* add standard downmix here */
    971     }
    972   }
    973 
    974   for (p = 0; p < 2; p++) {
    975     if (pstr_drc_uni_sel_proc->eq_inst_index[p] >= 0) {
    976       ia_eq_instructions_struct* str_eq_instructions =
    977           &pstr_drc_config->str_drc_config_ext
    978                .str_eq_instructions[pstr_drc_uni_sel_proc->eq_inst_index[p]];
    979       if (p == 0) {
    980         channel_count = uni_drc_sel_proc_output->base_channel_count;
    981       } else {
    982         channel_count = uni_drc_sel_proc_output->target_channel_count;
    983       }
    984 
    985       complexityEq =
    986           (FLOAT32)(1 << str_eq_instructions->eq_set_complexity_level);
    987       if (pstr_drc_uni_sel_proc->subband_domain_mode ==
    988           SUBBAND_DOMAIN_MODE_OFF) {
    989         if (str_eq_instructions->td_filter_cascade_present == 0) {
    990           complexityEq = 0.0;
    991         }
    992       } else {
    993         if (str_eq_instructions->td_filter_cascade_present == 1) {
    994           complexityEq = 2.5;
    995         }
    996       }
    997 
    998       complexityEqTotal += channel_count * complexityEq;
    999     }
   1000   }
   1001 
   1002   complexityDrcTotal *= freqNorm;
   1003   complexityEqTotal *= freqNorm;
   1004 
   1005   if (numBandsTooLarge == 1) {
   1006     if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.sel_drc_set_ids[0] > 0) {
   1007       err = impd_find_drc_instructions_uni_drc(
   1008           pstr_drc_config,
   1009           pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.sel_drc_set_ids[0],
   1010           &str_drc_instruction_str);
   1011       if (err) return (err);
   1012 
   1013       pstr_drc_uni_sel_proc
   1014           ->drc_set_id_valid_flag[str_drc_instruction_str->drc_set_id] = 0;
   1015     }
   1016     *repeat_selection = 1;
   1017   } else {
   1018     if (complexityDrcTotal + complexityEqTotal <= complexitySupportedTotal) {
   1019       *repeat_selection = 0;
   1020     } else {
   1021       drcRequiresEq = 0;
   1022       for (p = 0; p < 2; p++) {
   1023         if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.sel_drc_set_ids[p] <=
   1024             0)
   1025           continue;
   1026         err = impd_find_drc_instructions_uni_drc(
   1027             pstr_drc_config,
   1028             pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.sel_drc_set_ids[p],
   1029             &str_drc_instruction_str);
   1030         if (err) return (err);
   1031         if (str_drc_instruction_str->requires_eq == 1) {
   1032           drcRequiresEq = 1;
   1033         }
   1034       }
   1035       if ((drcRequiresEq == 0) &&
   1036           (complexityDrcTotal <= complexitySupportedTotal)) {
   1037         for (p = 0; p < 2; p++) {
   1038           pstr_drc_uni_sel_proc->eq_inst_index[p] = 0;
   1039         }
   1040         *repeat_selection = 0;
   1041       } else {
   1042         if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.sel_drc_set_ids[0] >
   1043             0) {
   1044           err = impd_find_drc_instructions_uni_drc(
   1045               pstr_drc_config,
   1046               pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.sel_drc_set_ids[0],
   1047               &str_drc_instruction_str);
   1048           if (err) return (err);
   1049 
   1050           pstr_drc_uni_sel_proc
   1051               ->drc_set_id_valid_flag[str_drc_instruction_str->drc_set_id] = 0;
   1052         } else {
   1053           for (p = 2; p < 4; p++) {
   1054             pstr_drc_uni_sel_proc
   1055                 ->drc_set_id_valid_flag[str_drc_instruction_str->drc_set_id] =
   1056                 0;
   1057             pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.sel_drc_set_ids[p] =
   1058                 0;
   1059           }
   1060         }
   1061         *repeat_selection = 1;
   1062       }
   1063     }
   1064   }
   1065 
   1066   if (*repeat_selection == 1) {
   1067     memset(&pstr_drc_uni_sel_proc->uni_drc_sel_proc_output, 0,
   1068            sizeof(ia_drc_sel_proc_output_struct));
   1069   }
   1070   return (0);
   1071 }
   1072 
   1073 WORD32 impd_find_loud_eq_instructions_idx_for_id(
   1074     ia_drc_config* drc_config, WORD32 loud_eq_set_id_requested,
   1075     WORD32* instructions_idx) {
   1076   WORD32 i;
   1077   if (loud_eq_set_id_requested > 0) {
   1078     for (i = 0; i < drc_config->str_drc_config_ext.loud_eq_instructions_count;
   1079          i++) {
   1080       if (drc_config->str_drc_config_ext.loud_eq_instructions[i]
   1081               .loud_eq_set_id == loud_eq_set_id_requested)
   1082         break;
   1083     }
   1084     if (i == drc_config->str_drc_config_ext.loud_eq_instructions_count) {
   1085       return (UNEXPECTED_ERROR);
   1086     }
   1087     *instructions_idx = i;
   1088   } else {
   1089     *instructions_idx = -1;
   1090   }
   1091   return (0);
   1092 }
   1093 
   1094 WORD32 impd_find_eq_instructions(
   1095     ia_drc_config* drc_config, WORD32 eq_set_id_requested,
   1096     ia_eq_instructions_struct** str_eq_instructions) {
   1097   WORD32 i;
   1098   for (i = 0; i < drc_config->str_drc_config_ext.eq_instructions_count; i++) {
   1099     if (eq_set_id_requested ==
   1100         drc_config->str_drc_config_ext.str_eq_instructions[i].eq_set_id)
   1101       break;
   1102   }
   1103   if (i == drc_config->str_drc_config_ext.eq_instructions_count) {
   1104     return (UNEXPECTED_ERROR);
   1105   }
   1106   *str_eq_instructions = &drc_config->str_drc_config_ext.str_eq_instructions[i];
   1107   return (0);
   1108 }
   1109 
   1110 WORD32 impd_find_downmix(ia_drc_config* drc_config, WORD32 requested_dwnmix_id,
   1111                          ia_downmix_instructions_struct** dwnmix_instructions) {
   1112   WORD32 i;
   1113   for (i = 0; i < drc_config->dwnmix_instructions_count; i++) {
   1114     if (requested_dwnmix_id == drc_config->dwnmix_instructions[i].downmix_id)
   1115       break;
   1116   }
   1117   if (i == drc_config->dwnmix_instructions_count) {
   1118     return (UNEXPECTED_ERROR);
   1119   }
   1120   *dwnmix_instructions = &drc_config->dwnmix_instructions[i];
   1121   return (0);
   1122 }
   1123