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