| /****************************************************************************** |
| * |
| * Copyright (C) 2018 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at: |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| ***************************************************************************** |
| * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore |
| */ |
| #include <stdio.h> |
| #include <string.h> |
| #include <math.h> |
| #include "impd_type_def.h" |
| #include "impd_drc_extr_delta_coded_info.h" |
| #include "impd_drc_common.h" |
| #include "impd_drc_struct.h" |
| #include "impd_drc_interface.h" |
| #include "impd_drc_selection_process.h" |
| #include "impd_drc_sel_proc_drc_set_sel.h" |
| #include "impd_drc_loudness_control.h" |
| #include "impd_drc_filter_bank.h" |
| #include "impd_drc_rom.h" |
| |
| static WORD32 effect_types_request_table[] = { |
| EFFECT_BIT_NIGHT, EFFECT_BIT_NOISY, EFFECT_BIT_LIMITED, |
| EFFECT_BIT_LOWLEVEL, EFFECT_BIT_DIALOG, EFFECT_BIT_GENERAL_COMPR, |
| EFFECT_BIT_EXPAND, EFFECT_BIT_ARTISTIC}; |
| |
| WORD32 impd_validate_requested_drc_feature( |
| ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct) { |
| WORD32 i, j; |
| |
| for (i = 0; i < pstr_drc_sel_proc_params_struct->num_drc_feature_requests; |
| i++) { |
| switch (pstr_drc_sel_proc_params_struct->drc_feature_req_type[i]) { |
| case MATCH_EFFECT_TYPE: |
| for (j = 0; j < pstr_drc_sel_proc_params_struct |
| ->desired_num_drc_effects_of_requested[i]; |
| j++) { |
| if (pstr_drc_sel_proc_params_struct |
| ->requested_drc_effect_type[i][j] == |
| EFFECT_TYPE_REQUESTED_NONE) { |
| if (pstr_drc_sel_proc_params_struct |
| ->desired_num_drc_effects_of_requested[i] > 1) { |
| return (UNEXPECTED_ERROR); |
| } |
| } |
| } |
| break; |
| case MATCH_DYNAMIC_RANGE: |
| break; |
| case MATCH_DRC_CHARACTERISTIC: |
| break; |
| default: |
| return (UNEXPECTED_ERROR); |
| break; |
| } |
| } |
| return (0); |
| } |
| |
| WORD32 impd_find_drc_instructions_uni_drc( |
| ia_drc_config* drc_config, WORD32 drc_set_id_requested, |
| ia_drc_instructions_struct** str_drc_instruction_str) { |
| WORD32 i; |
| for (i = 0; i < drc_config->drc_instructions_uni_drc_count; i++) { |
| if (drc_set_id_requested == |
| drc_config->str_drc_instruction_str[i].drc_set_id) |
| break; |
| } |
| if (i == drc_config->drc_instructions_uni_drc_count) { |
| return (UNEXPECTED_ERROR); |
| } |
| *str_drc_instruction_str = &drc_config->str_drc_instruction_str[i]; |
| return (0); |
| } |
| |
| WORD32 impd_map_requested_effect_bit_idx(WORD32 requested_effect_type, |
| WORD32* effect_bit_idx) { |
| switch (requested_effect_type) { |
| case EFFECT_TYPE_REQUESTED_NONE: |
| *effect_bit_idx = EFFECT_BIT_NONE; |
| break; |
| case EFFECT_TYPE_REQUESTED_NIGHT: |
| *effect_bit_idx = EFFECT_BIT_NIGHT; |
| break; |
| case EFFECT_TYPE_REQUESTED_NOISY: |
| *effect_bit_idx = EFFECT_BIT_NOISY; |
| break; |
| case EFFECT_TYPE_REQUESTED_LIMITED: |
| *effect_bit_idx = EFFECT_BIT_LIMITED; |
| break; |
| case EFFECT_TYPE_REQUESTED_LOWLEVEL: |
| *effect_bit_idx = EFFECT_BIT_LOWLEVEL; |
| break; |
| case EFFECT_TYPE_REQUESTED_DIALOG: |
| *effect_bit_idx = EFFECT_BIT_DIALOG; |
| break; |
| case EFFECT_TYPE_REQUESTED_GENERAL_COMPR: |
| *effect_bit_idx = EFFECT_BIT_GENERAL_COMPR; |
| break; |
| case EFFECT_TYPE_REQUESTED_EXPAND: |
| *effect_bit_idx = EFFECT_BIT_EXPAND; |
| break; |
| case EFFECT_TYPE_REQUESTED_ARTISTIC: |
| *effect_bit_idx = EFFECT_BIT_ARTISTIC; |
| break; |
| |
| default: |
| return (UNEXPECTED_ERROR); |
| |
| break; |
| } |
| return (0); |
| } |
| |
| WORD32 impd_get_fading_drc_set(ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc) { |
| pstr_drc_uni_sel_proc->drc_instructions_index[2] = -1; |
| if (pstr_drc_uni_sel_proc->uni_drc_sel_proc_params.album_mode == 0) { |
| WORD32 n; |
| ia_drc_instructions_struct* str_drc_instruction_str = NULL; |
| for (n = 0; |
| n < pstr_drc_uni_sel_proc->drc_config.drc_instructions_uni_drc_count; |
| n++) { |
| str_drc_instruction_str = |
| &(pstr_drc_uni_sel_proc->drc_config.str_drc_instruction_str[n]); |
| |
| if (str_drc_instruction_str->drc_set_effect & EFFECT_BIT_FADE) { |
| if (str_drc_instruction_str->downmix_id[0] == ID_FOR_ANY_DOWNMIX) { |
| pstr_drc_uni_sel_proc->drc_instructions_index[2] = n; |
| |
| } else { |
| return (UNEXPECTED_ERROR); |
| } |
| } |
| } |
| } |
| return (0); |
| } |
| |
| WORD32 impd_get_ducking_drc_set(ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc) { |
| WORD32 drc_instructions_index; |
| WORD32 n, k; |
| ia_drc_instructions_struct* str_drc_instruction_str; |
| |
| WORD32 requested_dwnmix_id = |
| pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.active_downmix_id; |
| |
| pstr_drc_uni_sel_proc->drc_instructions_index[3] = -1; |
| drc_instructions_index = -1; |
| str_drc_instruction_str = NULL; |
| |
| for (n = 0; |
| n < pstr_drc_uni_sel_proc->drc_config.drc_instructions_uni_drc_count; |
| n++) { |
| str_drc_instruction_str = |
| &(pstr_drc_uni_sel_proc->drc_config.str_drc_instruction_str[n]); |
| |
| if (str_drc_instruction_str->drc_set_effect & |
| (EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) { |
| for (k = 0; k < str_drc_instruction_str->dwnmix_id_count; k++) { |
| if (str_drc_instruction_str->downmix_id[k] == requested_dwnmix_id) { |
| drc_instructions_index = n; |
| } |
| } |
| } |
| } |
| if (drc_instructions_index == -1) { |
| for (n = 0; |
| n < pstr_drc_uni_sel_proc->drc_config.drc_instructions_uni_drc_count; |
| n++) { |
| str_drc_instruction_str = |
| &(pstr_drc_uni_sel_proc->drc_config.str_drc_instruction_str[n]); |
| |
| if (str_drc_instruction_str->drc_set_effect & |
| (EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) { |
| for (k = 0; k < str_drc_instruction_str->dwnmix_id_count; k++) { |
| if (str_drc_instruction_str->downmix_id[k] == ID_FOR_BASE_LAYOUT) { |
| drc_instructions_index = n; |
| } |
| } |
| } |
| } |
| } |
| if (drc_instructions_index > -1) { |
| pstr_drc_uni_sel_proc->drc_instructions_index[2] = -1; |
| pstr_drc_uni_sel_proc->drc_instructions_index[3] = drc_instructions_index; |
| } |
| return (0); |
| } |
| |
| WORD32 impd_get_selected_drc_set(ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc, |
| WORD32 drc_set_id_selected) { |
| WORD32 n; |
| |
| ia_drc_instructions_struct* str_drc_instruction_str = NULL; |
| |
| for (n = 0; n < pstr_drc_uni_sel_proc->drc_config.drc_instructions_count_plus; |
| n++) { |
| if (pstr_drc_uni_sel_proc->drc_config.str_drc_instruction_str[n] |
| .drc_set_id == drc_set_id_selected) |
| break; |
| } |
| if (n == pstr_drc_uni_sel_proc->drc_config.drc_instructions_count_plus) { |
| return (EXTERNAL_ERROR); |
| } |
| pstr_drc_uni_sel_proc->drc_inst_index_sel = n; |
| str_drc_instruction_str = &( |
| pstr_drc_uni_sel_proc->drc_config |
| .str_drc_instruction_str[pstr_drc_uni_sel_proc->drc_inst_index_sel]); |
| |
| pstr_drc_uni_sel_proc->drc_instructions_index[0] = |
| pstr_drc_uni_sel_proc->drc_inst_index_sel; |
| return (0); |
| } |
| |
| WORD32 impd_get_dependent_drc_set( |
| ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc) { |
| ia_drc_instructions_struct* str_drc_instruction_str = NULL; |
| str_drc_instruction_str = &( |
| pstr_drc_uni_sel_proc->drc_config |
| .str_drc_instruction_str[pstr_drc_uni_sel_proc->drc_inst_index_sel]); |
| |
| if (str_drc_instruction_str->depends_on_drc_set_present == 1) { |
| WORD32 n; |
| WORD32 drc_dependent_set_id = str_drc_instruction_str->depends_on_drc_set; |
| |
| for (n = 0; |
| n < pstr_drc_uni_sel_proc->drc_config.drc_instructions_count_plus; |
| n++) { |
| if (pstr_drc_uni_sel_proc->drc_config.str_drc_instruction_str[n] |
| .drc_set_id == drc_dependent_set_id) |
| break; |
| } |
| if (n == pstr_drc_uni_sel_proc->drc_config.drc_instructions_count_plus) { |
| return (UNEXPECTED_ERROR); |
| } |
| pstr_drc_uni_sel_proc->drc_instructions_index[1] = n; |
| } else { |
| pstr_drc_uni_sel_proc->drc_instructions_index[1] = -1; |
| } |
| return (0); |
| } |
| |
| WORD32 impd_get_dependent_drc_instructions( |
| const ia_drc_config* drc_config, |
| const ia_drc_instructions_struct* str_drc_instruction_str, |
| ia_drc_instructions_struct** drc_instructions_dependent) { |
| WORD32 j; |
| ia_drc_instructions_struct* dependent_drc = NULL; |
| for (j = 0; j < drc_config->drc_instructions_uni_drc_count; j++) { |
| dependent_drc = |
| (ia_drc_instructions_struct*)&(drc_config->str_drc_instruction_str[j]); |
| if (dependent_drc->drc_set_id == |
| str_drc_instruction_str->depends_on_drc_set) { |
| break; |
| } |
| } |
| if (j == drc_config->drc_instructions_uni_drc_count) { |
| return (UNEXPECTED_ERROR); |
| } |
| if (dependent_drc->depends_on_drc_set_present == 1) { |
| return (UNEXPECTED_ERROR); |
| } |
| *drc_instructions_dependent = dependent_drc; |
| return (0); |
| } |
| |
| WORD32 impd_select_drcs_without_compr_effects( |
| ia_drc_config* pstr_drc_config, WORD32* match_found_flag, |
| WORD32* selection_candidate_count, |
| ia_selection_candidate_info_struct* selection_candidate_info) { |
| WORD32 i, k, n; |
| WORD32 selection_candidate_step_2_count = 0; |
| ia_selection_candidate_info_struct |
| selection_candidate_info_step_2[SELECTION_CANDIDATE_COUNT_MAX]; |
| WORD32 effect_types_request_table_size; |
| WORD32 match; |
| ia_drc_instructions_struct* str_drc_instruction_str; |
| |
| effect_types_request_table_size = |
| sizeof(effect_types_request_table) / sizeof(WORD32); |
| |
| k = 0; |
| for (i = 0; i < *selection_candidate_count; i++) { |
| str_drc_instruction_str = &( |
| pstr_drc_config->str_drc_instruction_str[selection_candidate_info[i] |
| .drc_instructions_index]); |
| |
| match = 1; |
| for (n = 0; n < effect_types_request_table_size; n++) { |
| if ((str_drc_instruction_str->drc_set_effect & |
| effect_types_request_table[n]) != 0x0) { |
| match = 0; |
| } |
| } |
| if (match == 1) { |
| if (k >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; |
| memcpy(&selection_candidate_info_step_2[k], &selection_candidate_info[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| k++; |
| } |
| } |
| selection_candidate_step_2_count = k; |
| |
| if (selection_candidate_step_2_count > 0) { |
| *match_found_flag = 1; |
| for (i = 0; i < selection_candidate_step_2_count; i++) { |
| memcpy(&selection_candidate_info[i], &selection_candidate_info_step_2[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| *selection_candidate_count = selection_candidate_step_2_count; |
| } |
| } else { |
| *match_found_flag = 0; |
| } |
| |
| return (0); |
| } |
| |
| WORD32 impd_match_effect_type_attempt( |
| ia_drc_config* pstr_drc_config, WORD32 requested_effect_type, |
| WORD32 state_requested, WORD32* match_found_flag, |
| WORD32* selection_candidate_count, |
| ia_selection_candidate_info_struct* selection_candidate_info) { |
| WORD32 i, k, err; |
| WORD32 selection_candidate_step_2_count = 0; |
| ia_selection_candidate_info_struct |
| selection_candidate_info_step_2[SELECTION_CANDIDATE_COUNT_MAX]; |
| ia_drc_instructions_struct* str_drc_instruction_str; |
| ia_drc_instructions_struct* drc_instructions_dependent; |
| WORD32 effect_bit_idx; |
| |
| err = |
| impd_map_requested_effect_bit_idx(requested_effect_type, &effect_bit_idx); |
| if (err) return (err); |
| |
| if (effect_bit_idx == EFFECT_BIT_NONE) { |
| err = impd_select_drcs_without_compr_effects( |
| pstr_drc_config, match_found_flag, selection_candidate_count, |
| selection_candidate_info); |
| if (err) return (err); |
| } else { |
| k = 0; |
| for (i = 0; i < *selection_candidate_count; i++) { |
| str_drc_instruction_str = |
| &(pstr_drc_config->str_drc_instruction_str |
| [selection_candidate_info[i].drc_instructions_index]); |
| if (str_drc_instruction_str->depends_on_drc_set_present == 1) { |
| err = impd_get_dependent_drc_instructions(pstr_drc_config, |
| str_drc_instruction_str, |
| &drc_instructions_dependent); |
| if (err) return (err); |
| |
| if (state_requested == 1) { |
| if (((str_drc_instruction_str->drc_set_effect & effect_bit_idx) != |
| 0x0) || |
| ((drc_instructions_dependent->drc_set_effect & effect_bit_idx) != |
| 0x0)) { |
| if (k >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; |
| memcpy(&selection_candidate_info_step_2[k], |
| &selection_candidate_info[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| k++; |
| } |
| } else { |
| if (((str_drc_instruction_str->drc_set_effect & effect_bit_idx) == |
| 0x0) && |
| ((drc_instructions_dependent->drc_set_effect & effect_bit_idx) == |
| 0x0)) { |
| if (k >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; |
| memcpy(&selection_candidate_info_step_2[k], |
| &selection_candidate_info[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| k++; |
| } |
| } |
| } else { |
| if (state_requested == 1) { |
| if ((str_drc_instruction_str->drc_set_effect & effect_bit_idx) != |
| 0x0) { |
| if (k >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; |
| memcpy(&selection_candidate_info_step_2[k], |
| &selection_candidate_info[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| k++; |
| } |
| } else { |
| if ((str_drc_instruction_str->drc_set_effect & effect_bit_idx) == |
| 0x0) { |
| if (k >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; |
| memcpy(&selection_candidate_info_step_2[k], |
| &selection_candidate_info[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| k++; |
| } |
| } |
| } |
| } |
| selection_candidate_step_2_count = k; |
| |
| if (selection_candidate_step_2_count > 0) { |
| *match_found_flag = 1; |
| for (i = 0; i < selection_candidate_step_2_count; i++) { |
| *selection_candidate_count = selection_candidate_step_2_count; |
| memcpy(&selection_candidate_info[i], |
| &selection_candidate_info_step_2[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| } |
| } else { |
| *match_found_flag = 0; |
| } |
| } |
| return (0); |
| } |
| |
| WORD32 impd_match_effect_types( |
| ia_drc_config* pstr_drc_config, WORD32 effect_type_requested_total_count, |
| WORD32 effect_type_requested_desired_count, WORD32* requested_effect_type, |
| WORD32* selection_candidate_count, |
| ia_selection_candidate_info_struct* selection_candidate_info) { |
| WORD32 k, err; |
| WORD32 match_found_flag = 0; |
| WORD32 state_requested; |
| WORD32 desired_effect_type_found, fallback_effect_type_found; |
| |
| desired_effect_type_found = 0; |
| fallback_effect_type_found = 0; |
| k = 0; |
| while (k < effect_type_requested_desired_count) { |
| state_requested = 1; |
| err = impd_match_effect_type_attempt( |
| pstr_drc_config, requested_effect_type[k], state_requested, |
| &match_found_flag, selection_candidate_count, selection_candidate_info); |
| if (err) return (err); |
| if (match_found_flag) desired_effect_type_found = 1; |
| k++; |
| } |
| if (desired_effect_type_found == 0) { |
| while ((k < effect_type_requested_total_count) && (match_found_flag == 0)) { |
| state_requested = 1; |
| err = impd_match_effect_type_attempt( |
| pstr_drc_config, requested_effect_type[k], state_requested, |
| &match_found_flag, selection_candidate_count, |
| selection_candidate_info); |
| if (err) return (err); |
| if (match_found_flag) fallback_effect_type_found = 1; |
| k++; |
| } |
| } |
| |
| return (0); |
| } |
| |
| WORD32 impd_match_dynamic_range( |
| ia_drc_config* pstr_drc_config, |
| ia_drc_loudness_info_set_struct* pstr_loudness_info, |
| ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct, |
| WORD32 num_drc_requests, WORD32* selection_candidate_count, |
| ia_selection_candidate_info_struct* selection_candidate_info) { |
| ia_drc_instructions_struct* str_drc_instruction_str; |
| WORD32 err, i, k; |
| WORD32 lp_avg_present_val; |
| FLOAT32 lp_avg_val; |
| FLOAT32 deviation_min = 1000.0f; |
| WORD32 selected[DRC_INSTRUCTIONS_COUNT_MAX]; |
| WORD32 dynamic_range_measurement_type = |
| pstr_drc_sel_proc_params_struct |
| ->requested_dyn_range_measur_type[num_drc_requests]; |
| |
| WORD32 requested_dyn_range_range_flag = |
| pstr_drc_sel_proc_params_struct |
| ->requested_dyn_range_range_flag[num_drc_requests]; |
| |
| FLOAT32 dynamic_range_requested = |
| pstr_drc_sel_proc_params_struct |
| ->requested_dyn_range_value[num_drc_requests]; |
| |
| FLOAT32 dynamic_range_min_requested = |
| pstr_drc_sel_proc_params_struct |
| ->requested_dyn_range_min_val[num_drc_requests]; |
| |
| FLOAT32 dynamic_range_max_requested = |
| pstr_drc_sel_proc_params_struct |
| ->requested_dyn_range_max_val[num_drc_requests]; |
| |
| WORD32* requested_dwnmix_id = |
| pstr_drc_sel_proc_params_struct->requested_dwnmix_id; |
| |
| WORD32 album_mode = pstr_drc_sel_proc_params_struct->album_mode; |
| |
| k = 0; |
| for (i = 0; i < *selection_candidate_count; i++) { |
| str_drc_instruction_str = &( |
| pstr_drc_config->str_drc_instruction_str[selection_candidate_info[i] |
| .drc_instructions_index]); |
| |
| err = impd_loudness_peak_to_average_info( |
| pstr_loudness_info, str_drc_instruction_str, |
| requested_dwnmix_id[selection_candidate_info[i] |
| .downmix_id_request_index], |
| dynamic_range_measurement_type, album_mode, &lp_avg_present_val, |
| &lp_avg_val); |
| if (err) return (err); |
| |
| if (lp_avg_present_val == 1) { |
| if (requested_dyn_range_range_flag == 1) { |
| if ((lp_avg_val >= dynamic_range_min_requested) && |
| (lp_avg_val <= dynamic_range_max_requested)) { |
| if (k >= DRC_INSTRUCTIONS_COUNT_MAX) return UNEXPECTED_ERROR; |
| selected[k] = i; |
| k++; |
| } |
| } else { |
| FLOAT32 deviation = |
| (FLOAT32)fabs((FLOAT64)(dynamic_range_requested - lp_avg_val)); |
| if (deviation_min >= deviation) { |
| if (deviation_min > deviation) { |
| deviation_min = deviation; |
| k = 0; |
| } |
| if (k >= DRC_INSTRUCTIONS_COUNT_MAX) return UNEXPECTED_ERROR; |
| selected[k] = i; |
| k++; |
| } |
| } |
| } |
| } |
| if (k > 0) { |
| for (i = 0; i < k; i++) { |
| memcpy(&selection_candidate_info[i], |
| &selection_candidate_info[selected[i]], |
| sizeof(ia_selection_candidate_info_struct)); |
| } |
| *selection_candidate_count = k; |
| } |
| |
| return (0); |
| } |
| |
| WORD32 impd_match_drc_characteristic_attempt( |
| ia_drc_config* pstr_drc_config, WORD32 requested_drc_characteristic, |
| WORD32* match_found_flag, WORD32* selection_candidate_count, |
| ia_selection_candidate_info_struct* selection_candidate_info) { |
| WORD32 i, k, n, b, m; |
| WORD32 ref_count; |
| WORD32 drc_characteristic; |
| FLOAT32 match_count; |
| WORD32 drc_characteristic_request_1; |
| WORD32 drc_characteristic_request_2; |
| WORD32 drc_characteristic_request_3; |
| |
| ia_drc_instructions_struct* str_drc_instruction_str = NULL; |
| ia_uni_drc_coeffs_struct* str_p_loc_drc_coefficients_uni_drc = NULL; |
| ia_gain_set_params_struct* gain_set_params = NULL; |
| *match_found_flag = 0; |
| |
| if (requested_drc_characteristic < 1) { |
| return (UNEXPECTED_ERROR); |
| } |
| if (requested_drc_characteristic < 12) { |
| drc_characteristic_request_1 = |
| drc_characteristic_order_default[requested_drc_characteristic - 1][0]; |
| drc_characteristic_request_2 = |
| drc_characteristic_order_default[requested_drc_characteristic - 1][1]; |
| drc_characteristic_request_3 = |
| drc_characteristic_order_default[requested_drc_characteristic - 1][2]; |
| } else { |
| drc_characteristic_request_1 = requested_drc_characteristic; |
| drc_characteristic_request_2 = -1; |
| drc_characteristic_request_3 = -1; |
| } |
| |
| if (pstr_drc_config->drc_coefficients_drc_count) { |
| for (i = 0; i < pstr_drc_config->drc_coefficients_drc_count; i++) { |
| str_p_loc_drc_coefficients_uni_drc = |
| &(pstr_drc_config->str_p_loc_drc_coefficients_uni_drc[i]); |
| if (str_p_loc_drc_coefficients_uni_drc->drc_location == LOCATION_SELECTED) |
| break; |
| } |
| |
| if (i == pstr_drc_config->drc_coefficients_drc_count) { |
| return (UNEXPECTED_ERROR); |
| } |
| } |
| |
| n = 0; |
| for (i = 0; i < *selection_candidate_count; i++) { |
| ref_count = 0; |
| match_count = 0; |
| |
| str_drc_instruction_str = &( |
| pstr_drc_config->str_drc_instruction_str[selection_candidate_info[i] |
| .drc_instructions_index]); |
| for (k = 0; k < str_drc_instruction_str->num_drc_ch_groups; k++) { |
| gain_set_params = |
| &(str_p_loc_drc_coefficients_uni_drc->gain_set_params |
| [str_drc_instruction_str->gain_set_index_for_channel_group[k]]); |
| for (b = 0; b < gain_set_params->band_count; b++) { |
| ref_count++; |
| drc_characteristic = gain_set_params->gain_params[b].drc_characteristic; |
| if (drc_characteristic == drc_characteristic_request_1) |
| match_count += 1.0f; |
| else if (drc_characteristic == drc_characteristic_request_2) |
| match_count += 0.75f; |
| else if (drc_characteristic == drc_characteristic_request_3) |
| match_count += 0.5f; |
| } |
| } |
| if (str_drc_instruction_str->depends_on_drc_set_present == 1) { |
| WORD32 depends_on_drc_set = str_drc_instruction_str->depends_on_drc_set; |
| for (m = 0; m < pstr_drc_config->drc_instructions_uni_drc_count; m++) { |
| if (pstr_drc_config->str_drc_instruction_str[m].drc_set_id == |
| depends_on_drc_set) |
| break; |
| } |
| if (m == pstr_drc_config->drc_instructions_uni_drc_count) { |
| return (UNEXPECTED_ERROR); |
| } |
| str_drc_instruction_str = &(pstr_drc_config->str_drc_instruction_str[m]); |
| if ((str_drc_instruction_str->drc_set_effect & |
| (EFFECT_BIT_FADE | EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) == |
| 0) { |
| if (str_drc_instruction_str->drc_set_effect != EFFECT_BIT_CLIPPING) { |
| for (k = 0; k < str_drc_instruction_str->num_drc_ch_groups; k++) { |
| gain_set_params = |
| &(str_p_loc_drc_coefficients_uni_drc->gain_set_params |
| [str_drc_instruction_str |
| ->gain_set_index_for_channel_group[k]]); |
| for (b = 0; b < gain_set_params->band_count; b++) { |
| ref_count++; |
| drc_characteristic = |
| gain_set_params->gain_params[b].drc_characteristic; |
| if (drc_characteristic == drc_characteristic_request_1) |
| match_count += 1.0f; |
| else if (drc_characteristic == drc_characteristic_request_2) |
| match_count += 0.75f; |
| else if (drc_characteristic == drc_characteristic_request_3) |
| match_count += 0.5; |
| } |
| } |
| } |
| } |
| } |
| if ((ref_count > 0) && (((FLOAT32)match_count) > 0.5f * ref_count)) { |
| if (n >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; |
| memcpy(&selection_candidate_info[n], &selection_candidate_info[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| n++; |
| } |
| } |
| if (n > 0) { |
| *selection_candidate_count = n; |
| *match_found_flag = 1; |
| } |
| |
| return (0); |
| } |
| |
| WORD32 impd_match_drc_characteristic( |
| ia_drc_config* pstr_drc_config, WORD32 requested_drc_characteristic, |
| WORD32* selection_candidate_count, |
| ia_selection_candidate_info_struct* selection_candidate_info) { |
| WORD32 k, err; |
| WORD32 match_found_flag = 0; |
| |
| WORD32* drc_characteristic_order = |
| drc_characteristic_order_default[requested_drc_characteristic - 1]; |
| WORD32 drc_characteristic_order_count = |
| sizeof(drc_characteristic_order_default[requested_drc_characteristic]) / |
| sizeof(WORD32); |
| k = 0; |
| while ((k < drc_characteristic_order_count) && (match_found_flag == 0) && |
| (drc_characteristic_order[k] > 0)) { |
| err = impd_match_drc_characteristic_attempt( |
| pstr_drc_config, drc_characteristic_order[k], &match_found_flag, |
| selection_candidate_count, selection_candidate_info); |
| if (err) return (err); |
| k++; |
| } |
| return (0); |
| } |
| |
| WORD32 impd_drc_set_preselection( |
| ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct, |
| ia_drc_config* pstr_drc_config, |
| ia_drc_loudness_info_set_struct* pstr_loudness_info, |
| WORD32 restrict_to_drc_with_album_loudness, |
| ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc, |
| WORD32* selection_candidate_count, |
| ia_selection_candidate_info_struct* selection_candidate_info) { |
| WORD32 i, j, k, l, d, n, err; |
| WORD32 downmix_id_match = 0; |
| |
| WORD32 selection_candidate_step_2_count; |
| ia_selection_candidate_info_struct |
| selection_candidate_info_step_2[SELECTION_CANDIDATE_COUNT_MAX]; |
| |
| WORD32 num_downmix_id_requests = |
| pstr_drc_sel_proc_params_struct->num_downmix_id_requests; |
| WORD32* requested_dwnmix_id = |
| pstr_drc_sel_proc_params_struct->requested_dwnmix_id; |
| FLOAT32 output_peak_level_max = |
| pstr_drc_sel_proc_params_struct->output_peak_level_max; |
| WORD32 loudness_deviation_max = |
| pstr_drc_sel_proc_params_struct->loudness_deviation_max; |
| WORD32* drc_set_id_valid_flag = pstr_drc_uni_sel_proc->drc_set_id_valid_flag; |
| WORD32* eq_set_id_valid_flag = pstr_drc_uni_sel_proc->eq_set_id_valid_flag; |
| |
| FLOAT32 output_peak_level_min = 1000.0f; |
| FLOAT32 adjustment; |
| WORD32 loudness_drc_set_id_requested; |
| |
| WORD32 num_compression_eq_count = 0; |
| WORD32 num_compression_eq_id[16]; |
| |
| WORD32 loudness_info_count = 0; |
| WORD32 eq_set_id_loudness[16]; |
| FLOAT32 loudness_normalization_gain_db[16]; |
| FLOAT32 loudness[16]; |
| WORD32 peak_info_count; |
| WORD32 eq_set_id_Peak[16]; |
| FLOAT32 signal_peak_level[16]; |
| WORD32 explicit_peak_information_present[16]; |
| |
| ia_uni_drc_coeffs_struct* str_p_loc_drc_coefficients_uni_drc = NULL; |
| ia_drc_instructions_struct* str_drc_instruction_str = NULL; |
| |
| impd_select_drc_coeff3(pstr_drc_config, &str_p_loc_drc_coefficients_uni_drc); |
| if (str_p_loc_drc_coefficients_uni_drc == NULL) return UNEXPECTED_ERROR; |
| k = 0; |
| for (d = 0; d < num_downmix_id_requests; d++) { |
| err = impd_find_eq_set_no_compression( |
| pstr_drc_config, requested_dwnmix_id[d], &num_compression_eq_count, |
| num_compression_eq_id); |
| if (err) return (err); |
| for (i = 0; i < pstr_drc_config->drc_instructions_count_plus; i++) { |
| downmix_id_match = 0; |
| str_drc_instruction_str = &(pstr_drc_config->str_drc_instruction_str[i]); |
| |
| for (j = 0; j < str_drc_instruction_str->dwnmix_id_count; j++) { |
| if ((str_drc_instruction_str->downmix_id[j] == |
| requested_dwnmix_id[d]) || |
| ((str_drc_instruction_str->downmix_id[j] == ID_FOR_BASE_LAYOUT) && |
| (str_drc_instruction_str->drc_set_id > 0)) || |
| (str_drc_instruction_str->downmix_id[j] == ID_FOR_ANY_DOWNMIX)) { |
| downmix_id_match = 1; |
| } |
| } |
| if (downmix_id_match == 1) { |
| if (pstr_drc_sel_proc_params_struct->dynamic_range_control_on == 1) { |
| if ((str_drc_instruction_str->drc_set_effect != EFFECT_BIT_FADE) && |
| (str_drc_instruction_str->drc_set_effect != |
| EFFECT_BIT_DUCK_OTHER) && |
| (str_drc_instruction_str->drc_set_effect != |
| EFFECT_BIT_DUCK_SELF) && |
| (str_drc_instruction_str->drc_set_effect != 0 || |
| str_drc_instruction_str->drc_set_id < 0) && |
| (((str_drc_instruction_str->depends_on_drc_set_present == 0) && |
| (str_drc_instruction_str->no_independent_use == 0)) || |
| (str_drc_instruction_str->depends_on_drc_set_present == 1))) { |
| WORD32 drc_is_permitted = 1; |
| if (str_drc_instruction_str->drc_set_id > 0) { |
| drc_is_permitted = |
| drc_set_id_valid_flag[str_drc_instruction_str->drc_set_id]; |
| } |
| if (drc_is_permitted == 1) { |
| err = impd_init_loudness_control( |
| pstr_drc_sel_proc_params_struct, pstr_loudness_info, |
| requested_dwnmix_id[d], str_drc_instruction_str->drc_set_id, |
| |
| num_compression_eq_count, num_compression_eq_id, |
| &loudness_info_count, eq_set_id_loudness, |
| loudness_normalization_gain_db, loudness); |
| if (err) return (err); |
| |
| if (loudness_info_count > MAX_LOUDNESS_INFO_COUNT) |
| return UNEXPECTED_ERROR; |
| |
| err = impd_signal_peak_level_info( |
| pstr_drc_config, pstr_loudness_info, str_drc_instruction_str, |
| requested_dwnmix_id[d], |
| pstr_drc_sel_proc_params_struct->album_mode, |
| num_compression_eq_count, num_compression_eq_id, |
| &peak_info_count, eq_set_id_Peak, signal_peak_level, |
| explicit_peak_information_present); |
| if (err) return (err); |
| |
| for (l = 0; l < loudness_info_count; l++) { |
| WORD32 match_found_flag = 0; |
| WORD32 p; |
| if (k >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; |
| selection_candidate_info[k].loudness_norm_db_gain_adjusted = |
| loudness_normalization_gain_db[l]; |
| |
| selection_candidate_info[k] |
| .loudness_norm_db_gain_adjusted = min( |
| selection_candidate_info[k].loudness_norm_db_gain_adjusted, |
| pstr_drc_sel_proc_params_struct->loudness_norm_gain_db_max); |
| |
| if (loudness[l] != UNDEFINED_LOUDNESS_VALUE) { |
| selection_candidate_info[k].output_loudness = |
| loudness[l] + |
| selection_candidate_info[k] |
| .loudness_norm_db_gain_adjusted; |
| } else { |
| selection_candidate_info[k].output_loudness = |
| UNDEFINED_LOUDNESS_VALUE; |
| } |
| |
| for (p = 0; p < peak_info_count; p++) { |
| if (eq_set_id_Peak[p] == eq_set_id_loudness[l]) { |
| if (eq_set_id_valid_flag[eq_set_id_Peak[p]] == 1) |
| |
| { |
| match_found_flag = 1; |
| break; |
| } |
| } |
| } |
| if (match_found_flag == 1) { |
| selection_candidate_info[k].output_peak_level = |
| signal_peak_level[p] + |
| selection_candidate_info[k] |
| .loudness_norm_db_gain_adjusted; |
| } else { |
| selection_candidate_info[k].output_peak_level = |
| selection_candidate_info[k] |
| .loudness_norm_db_gain_adjusted; |
| } |
| if ((str_drc_instruction_str->requires_eq == 1) && |
| (eq_set_id_valid_flag[eq_set_id_loudness[l]] == 0)) |
| continue; |
| selection_candidate_info[k].drc_instructions_index = i; |
| selection_candidate_info[k].downmix_id_request_index = d; |
| selection_candidate_info[k].eq_set_id = eq_set_id_loudness[l]; |
| if (explicit_peak_information_present[p] == 1) { |
| selection_candidate_info[k].selection_flags = |
| SELECTION_FLAG_EXPLICIT_PEAK_INFO_PRESENT; |
| } else { |
| selection_candidate_info[k].selection_flags = 0; |
| } |
| impd_mixing_level_info( |
| pstr_drc_sel_proc_params_struct, pstr_loudness_info, |
| requested_dwnmix_id[d], str_drc_instruction_str->drc_set_id, |
| eq_set_id_loudness[l], |
| &selection_candidate_info[k].mixing_level); |
| if (str_drc_instruction_str->drc_set_target_loudness_present && |
| ((pstr_drc_sel_proc_params_struct |
| ->loudness_normalization_on && |
| str_drc_instruction_str |
| ->drc_set_target_loudness_value_upper >= |
| pstr_drc_sel_proc_params_struct->target_loudness && |
| str_drc_instruction_str |
| ->drc_set_target_loudness_value_lower < |
| pstr_drc_sel_proc_params_struct->target_loudness) || |
| !pstr_drc_sel_proc_params_struct |
| ->loudness_normalization_on)) { |
| selection_candidate_info[k].selection_flags |= |
| SELECTION_FLAG_DRC_TARGET_LOUDNESS_MATCH; |
| if (!explicit_peak_information_present[p]) { |
| if (pstr_drc_sel_proc_params_struct |
| ->loudness_normalization_on) { |
| selection_candidate_info[k].output_peak_level = |
| pstr_drc_sel_proc_params_struct->target_loudness - |
| str_drc_instruction_str |
| ->drc_set_target_loudness_value_upper; |
| } else { |
| selection_candidate_info[k].output_peak_level = 0.0f; |
| } |
| } |
| } |
| if ((selection_candidate_info[k].selection_flags & |
| (SELECTION_FLAG_DRC_TARGET_LOUDNESS_MATCH | |
| SELECTION_FLAG_EXPLICIT_PEAK_INFO_PRESENT) || |
| !str_drc_instruction_str |
| ->drc_set_target_loudness_present)) { |
| k++; |
| } |
| } |
| } |
| } |
| } else { |
| if (str_drc_instruction_str->drc_set_id < 0) { |
| err = impd_init_loudness_control( |
| pstr_drc_sel_proc_params_struct, pstr_loudness_info, |
| requested_dwnmix_id[d], str_drc_instruction_str->drc_set_id, |
| num_compression_eq_count, num_compression_eq_id, |
| &loudness_info_count, eq_set_id_loudness, |
| loudness_normalization_gain_db, loudness); |
| if (err) return (err); |
| |
| err = impd_signal_peak_level_info( |
| pstr_drc_config, pstr_loudness_info, str_drc_instruction_str, |
| requested_dwnmix_id[d], |
| pstr_drc_sel_proc_params_struct->album_mode, |
| num_compression_eq_count, num_compression_eq_id, |
| &peak_info_count, eq_set_id_Peak, signal_peak_level, |
| explicit_peak_information_present); |
| if (err) return (err); |
| for (l = 0; l < loudness_info_count; l++) { |
| WORD32 match_found_flag = 0; |
| WORD32 p; |
| for (p = 0; p < peak_info_count; p++) { |
| if (eq_set_id_Peak[p] == eq_set_id_loudness[l]) { |
| if (eq_set_id_valid_flag[eq_set_id_Peak[p]] == 1) { |
| match_found_flag = 1; |
| break; |
| } |
| } |
| } |
| if (match_found_flag == 1) { |
| adjustment = max( |
| 0.0f, |
| signal_peak_level[p] + loudness_normalization_gain_db[l] - |
| pstr_drc_sel_proc_params_struct->output_peak_level_max); |
| adjustment = min(adjustment, max(0.0f, loudness_deviation_max)); |
| if (k >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; |
| selection_candidate_info[k].loudness_norm_db_gain_adjusted = |
| loudness_normalization_gain_db[l] - adjustment; |
| |
| selection_candidate_info[k] |
| .loudness_norm_db_gain_adjusted = min( |
| selection_candidate_info[k].loudness_norm_db_gain_adjusted, |
| pstr_drc_sel_proc_params_struct->loudness_norm_gain_db_max); |
| |
| selection_candidate_info[k].output_peak_level = |
| signal_peak_level[p] + |
| selection_candidate_info[k].loudness_norm_db_gain_adjusted; |
| if (loudness[l] != UNDEFINED_LOUDNESS_VALUE) { |
| selection_candidate_info[k].output_loudness = |
| loudness[l] + |
| selection_candidate_info[k] |
| .loudness_norm_db_gain_adjusted; |
| } else { |
| selection_candidate_info[k].output_loudness = |
| UNDEFINED_LOUDNESS_VALUE; |
| } |
| selection_candidate_info[k].drc_instructions_index = i; |
| selection_candidate_info[k].downmix_id_request_index = d; |
| selection_candidate_info[k].eq_set_id = eq_set_id_loudness[l]; |
| if (explicit_peak_information_present[p] == 1) { |
| selection_candidate_info[k].selection_flags = |
| SELECTION_FLAG_EXPLICIT_PEAK_INFO_PRESENT; |
| } else { |
| selection_candidate_info[k].selection_flags = 0; |
| } |
| impd_mixing_level_info( |
| pstr_drc_sel_proc_params_struct, pstr_loudness_info, |
| requested_dwnmix_id[d], str_drc_instruction_str->drc_set_id, |
| eq_set_id_loudness[l], |
| &selection_candidate_info[k].mixing_level); |
| k++; |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| *selection_candidate_count = k; |
| |
| if (*selection_candidate_count > SELECTION_CANDIDATE_COUNT_MAX) { |
| return UNEXPECTED_ERROR; |
| } else if (pstr_drc_sel_proc_params_struct->dynamic_range_control_on == 1) { |
| n = 0; |
| for (k = 0; k < *selection_candidate_count; k++) { |
| str_drc_instruction_str = |
| &(pstr_drc_config->str_drc_instruction_str |
| [selection_candidate_info[k].drc_instructions_index]); |
| |
| if (pstr_drc_sel_proc_params_struct->eq_set_purpose_request != |
| EQ_PURPOSE_EQ_OFF) { |
| WORD32 matching_eq_set_count = 0; |
| WORD32 matching_eq_instrucions_index[64]; |
| err = impd_match_eq_set( |
| pstr_drc_config, requested_dwnmix_id[selection_candidate_info[k] |
| .downmix_id_request_index], |
| str_drc_instruction_str->drc_set_id, eq_set_id_valid_flag, |
| &matching_eq_set_count, matching_eq_instrucions_index); |
| if (err) return (err); |
| for (j = 0; j < matching_eq_set_count; j++) { |
| if (n >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; |
| memcpy(&selection_candidate_info_step_2[n], |
| &selection_candidate_info[k], |
| sizeof(ia_selection_candidate_info_struct)); |
| selection_candidate_info_step_2[n].eq_set_id = |
| pstr_drc_config->str_drc_config_ext |
| .str_eq_instructions[matching_eq_instrucions_index[j]] |
| .eq_set_id; |
| n++; |
| } |
| } |
| if (str_drc_instruction_str->requires_eq == 0) { |
| if (n >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; |
| memcpy(&selection_candidate_info_step_2[n], |
| &selection_candidate_info[k], |
| sizeof(ia_selection_candidate_info_struct)); |
| selection_candidate_info_step_2[n].eq_set_id = 0; |
| n++; |
| } |
| } |
| if (n > SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; |
| memcpy(selection_candidate_info, selection_candidate_info_step_2, |
| n * sizeof(ia_selection_candidate_info_struct)); |
| *selection_candidate_count = n; |
| n = 0; |
| for (k = 0; k < *selection_candidate_count; k++) { |
| if ((selection_candidate_info[k].selection_flags & |
| SELECTION_FLAG_DRC_TARGET_LOUDNESS_MATCH) && |
| !(selection_candidate_info[k].selection_flags & |
| SELECTION_FLAG_EXPLICIT_PEAK_INFO_PRESENT)) { |
| memcpy(&selection_candidate_info_step_2[n], |
| &selection_candidate_info[k], |
| sizeof(ia_selection_candidate_info_struct)); |
| n++; |
| } else { |
| if (selection_candidate_info[k].output_peak_level <= |
| output_peak_level_max) { |
| memcpy(&selection_candidate_info_step_2[n], |
| &selection_candidate_info[k], |
| sizeof(ia_selection_candidate_info_struct)); |
| n++; |
| } |
| if (selection_candidate_info[k].output_peak_level < |
| output_peak_level_min) { |
| output_peak_level_min = selection_candidate_info[k].output_peak_level; |
| } |
| } |
| } |
| selection_candidate_step_2_count = n; |
| if (selection_candidate_step_2_count == 0) { |
| n = 0; |
| for (k = 0; k < *selection_candidate_count; k++) { |
| if ((selection_candidate_info[k].selection_flags & |
| SELECTION_FLAG_DRC_TARGET_LOUDNESS_MATCH) && |
| (selection_candidate_info[k].selection_flags & |
| SELECTION_FLAG_EXPLICIT_PEAK_INFO_PRESENT)) { |
| memcpy(&selection_candidate_info_step_2[n], |
| &selection_candidate_info[k], |
| sizeof(ia_selection_candidate_info_struct)); |
| n++; |
| } |
| } |
| selection_candidate_step_2_count = n; |
| } |
| if (selection_candidate_step_2_count == 0) { |
| n = 0; |
| for (k = 0; k < *selection_candidate_count; k++) { |
| if (selection_candidate_info_step_2[k].output_peak_level < |
| output_peak_level_min + 1.0f) { |
| memcpy(&selection_candidate_info_step_2[n], |
| &selection_candidate_info[k], |
| sizeof(ia_selection_candidate_info_struct)); |
| adjustment = |
| max(0.0f, selection_candidate_info_step_2[n].output_peak_level - |
| output_peak_level_max); |
| adjustment = min(adjustment, max(0.0f, loudness_deviation_max)); |
| selection_candidate_info_step_2[n].loudness_norm_db_gain_adjusted -= |
| adjustment; |
| selection_candidate_info_step_2[n].output_peak_level -= adjustment; |
| selection_candidate_info_step_2[n].output_loudness -= adjustment; |
| n++; |
| } |
| } |
| selection_candidate_step_2_count = n; |
| } |
| |
| for (n = 0; n < selection_candidate_step_2_count; n++) { |
| memcpy(&selection_candidate_info[n], &selection_candidate_info_step_2[n], |
| sizeof(ia_selection_candidate_info_struct)); |
| } |
| *selection_candidate_count = selection_candidate_step_2_count; |
| } |
| |
| if (restrict_to_drc_with_album_loudness == 1) { |
| j = 0; |
| for (k = 0; k < *selection_candidate_count; k++) { |
| loudness_drc_set_id_requested = |
| max(0, pstr_drc_config |
| ->str_drc_instruction_str[selection_candidate_info[k] |
| .drc_instructions_index] |
| .drc_set_id); |
| for (n = 0; n < pstr_loudness_info->loudness_info_album_count; n++) { |
| if (loudness_drc_set_id_requested == |
| pstr_loudness_info->str_loudness_info_album[n].drc_set_id) { |
| if (j >= SELECTION_CANDIDATE_COUNT_MAX) return UNEXPECTED_ERROR; |
| memcpy(&selection_candidate_info[j], &selection_candidate_info[k], |
| sizeof(ia_selection_candidate_info_struct)); |
| j++; |
| break; |
| } |
| } |
| } |
| *selection_candidate_count = j; |
| } |
| return (0); |
| } |
| |
| WORD32 impd_drc_set_final_selection( |
| ia_drc_config* pstr_drc_config, |
| ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct, |
| WORD32* selection_candidate_count, |
| ia_selection_candidate_info_struct* selection_candidate_info, |
| WORD32* eq_set_id_valid_flag) { |
| WORD32 k, i, n, err; |
| WORD32 selection_candidate_step_2_count; |
| ia_selection_candidate_info_struct |
| selection_candidate_info_step_2[SELECTION_CANDIDATE_COUNT_MAX]; |
| WORD32 drc_set_id_max; |
| FLOAT32 output_level_max; |
| FLOAT32 output_level_min; |
| WORD32 effect_count, effect_count_min; |
| WORD32 effect_types_request_table_size; |
| WORD32 drc_set_target_loudness_val_upper_min; |
| ia_drc_instructions_struct* str_drc_instruction_str; |
| ia_drc_instructions_struct* drc_instructions_dependent; |
| |
| if (pstr_drc_sel_proc_params_struct->eq_set_purpose_request > 0) { |
| WORD32 eq_purpose_requested = |
| pstr_drc_sel_proc_params_struct->eq_set_purpose_request; |
| |
| impd_match_eq_set_purpose(pstr_drc_config, eq_purpose_requested, |
| eq_set_id_valid_flag, selection_candidate_count, |
| selection_candidate_info, |
| selection_candidate_info_step_2); |
| } |
| |
| output_level_min = 10000.0f; |
| k = 0; |
| for (i = 0; i < *selection_candidate_count; i++) { |
| if (output_level_min >= selection_candidate_info[i].output_peak_level) { |
| if (output_level_min > selection_candidate_info[i].output_peak_level) { |
| output_level_min = selection_candidate_info[i].output_peak_level; |
| k = 0; |
| } |
| memcpy(&selection_candidate_info_step_2[k], &selection_candidate_info[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| k++; |
| } |
| } |
| selection_candidate_step_2_count = k; |
| |
| if (output_level_min <= 0.0f) { |
| selection_candidate_step_2_count = *selection_candidate_count; |
| k = 0; |
| for (i = 0; i < selection_candidate_step_2_count; i++) { |
| if (selection_candidate_info[i].output_peak_level <= 0.0f) { |
| memcpy(&selection_candidate_info_step_2[k], |
| &selection_candidate_info[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| k++; |
| } |
| } |
| selection_candidate_step_2_count = k; |
| |
| k = 0; |
| for (i = 0; i < selection_candidate_step_2_count; i++) { |
| str_drc_instruction_str = |
| &(pstr_drc_config->str_drc_instruction_str |
| [selection_candidate_info_step_2[i].drc_instructions_index]); |
| for (n = 0; n < str_drc_instruction_str->dwnmix_id_count; n++) { |
| if (pstr_drc_sel_proc_params_struct->requested_dwnmix_id |
| [selection_candidate_info_step_2[i].downmix_id_request_index] == |
| str_drc_instruction_str->downmix_id[n]) { |
| memcpy(&selection_candidate_info_step_2[k], |
| &selection_candidate_info_step_2[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| k++; |
| } |
| } |
| } |
| if (k > 0) { |
| selection_candidate_step_2_count = k; |
| } |
| |
| effect_types_request_table_size = |
| sizeof(effect_types_request_table) / sizeof(WORD32); |
| effect_count_min = 100; |
| k = 0; |
| for (i = 0; i < selection_candidate_step_2_count; i++) { |
| str_drc_instruction_str = |
| &(pstr_drc_config->str_drc_instruction_str |
| [selection_candidate_info_step_2[i].drc_instructions_index]); |
| effect_count = 0; |
| if (str_drc_instruction_str->depends_on_drc_set_present == 1) { |
| err = impd_get_dependent_drc_instructions(pstr_drc_config, |
| str_drc_instruction_str, |
| &drc_instructions_dependent); |
| if (err) return (err); |
| |
| for (n = 0; n < effect_types_request_table_size; n++) { |
| if (effect_types_request_table[n] != EFFECT_BIT_GENERAL_COMPR) { |
| if (((str_drc_instruction_str->drc_set_effect & |
| effect_types_request_table[n]) != 0x0) || |
| ((drc_instructions_dependent->drc_set_effect & |
| effect_types_request_table[n]) != 0x0)) { |
| effect_count++; |
| } |
| } |
| } |
| } else { |
| for (n = 0; n < effect_types_request_table_size; n++) { |
| if (effect_types_request_table[n] != EFFECT_BIT_GENERAL_COMPR) { |
| if ((str_drc_instruction_str->drc_set_effect & |
| effect_types_request_table[n]) != 0x0) { |
| effect_count++; |
| } |
| } |
| } |
| } |
| if (effect_count_min >= effect_count) { |
| if (effect_count_min > effect_count) { |
| effect_count_min = effect_count; |
| k = 0; |
| } |
| memcpy(&selection_candidate_info_step_2[k], |
| &selection_candidate_info_step_2[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| k++; |
| } |
| } |
| selection_candidate_step_2_count = k; |
| |
| drc_set_target_loudness_val_upper_min = 100; |
| k = 0; |
| for (i = 0; i < selection_candidate_step_2_count; i++) { |
| if (selection_candidate_info_step_2[i].selection_flags & |
| SELECTION_FLAG_DRC_TARGET_LOUDNESS_MATCH) { |
| k++; |
| } |
| } |
| if (k != 0 && k != selection_candidate_step_2_count) { |
| k = 0; |
| for (i = 0; i < selection_candidate_step_2_count; i++) { |
| if (!(selection_candidate_info_step_2[i].selection_flags & |
| SELECTION_FLAG_DRC_TARGET_LOUDNESS_MATCH)) { |
| memcpy(&selection_candidate_info_step_2[k], |
| &selection_candidate_info_step_2[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| k++; |
| } |
| } |
| selection_candidate_step_2_count = k; |
| } else if (k == selection_candidate_step_2_count) { |
| k = 0; |
| for (i = 0; i < selection_candidate_step_2_count; i++) { |
| str_drc_instruction_str = |
| &(pstr_drc_config->str_drc_instruction_str |
| [selection_candidate_info_step_2[i].drc_instructions_index]); |
| if (str_drc_instruction_str->drc_set_target_loudness_present != 1) { |
| return UNEXPECTED_ERROR; |
| } |
| if (drc_set_target_loudness_val_upper_min >= |
| str_drc_instruction_str->drc_set_target_loudness_value_upper) { |
| if (drc_set_target_loudness_val_upper_min > |
| str_drc_instruction_str->drc_set_target_loudness_value_upper) { |
| drc_set_target_loudness_val_upper_min = |
| str_drc_instruction_str->drc_set_target_loudness_value_upper; |
| k = 0; |
| } |
| memcpy(&selection_candidate_info_step_2[k], |
| &selection_candidate_info_step_2[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| k++; |
| } |
| } |
| selection_candidate_step_2_count = k; |
| } |
| |
| k = 0; |
| for (i = 0; i < selection_candidate_step_2_count; i++) { |
| str_drc_instruction_str = |
| &(pstr_drc_config->str_drc_instruction_str |
| [selection_candidate_info_step_2[i].drc_instructions_index]); |
| if (str_drc_instruction_str->drc_set_target_loudness_present && |
| pstr_drc_sel_proc_params_struct->loudness_normalization_on && |
| str_drc_instruction_str->drc_set_target_loudness_value_upper >= |
| pstr_drc_sel_proc_params_struct->target_loudness && |
| str_drc_instruction_str->drc_set_target_loudness_value_lower < |
| pstr_drc_sel_proc_params_struct->target_loudness) { |
| k++; |
| } |
| } |
| if (k != 0 && k != selection_candidate_step_2_count) { |
| k = 0; |
| for (i = 0; i < selection_candidate_step_2_count; i++) { |
| str_drc_instruction_str = |
| &(pstr_drc_config->str_drc_instruction_str |
| [selection_candidate_info_step_2[i].drc_instructions_index]); |
| if (str_drc_instruction_str->drc_set_target_loudness_present && |
| pstr_drc_sel_proc_params_struct->loudness_normalization_on && |
| str_drc_instruction_str->drc_set_target_loudness_value_upper >= |
| pstr_drc_sel_proc_params_struct->target_loudness && |
| str_drc_instruction_str->drc_set_target_loudness_value_lower < |
| pstr_drc_sel_proc_params_struct->target_loudness) { |
| memcpy(&selection_candidate_info_step_2[k], |
| &selection_candidate_info_step_2[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| k++; |
| } |
| } |
| selection_candidate_step_2_count = k; |
| drc_set_target_loudness_val_upper_min = 100; |
| k = 0; |
| for (i = 0; i < selection_candidate_step_2_count; i++) { |
| str_drc_instruction_str = |
| &(pstr_drc_config->str_drc_instruction_str |
| [selection_candidate_info_step_2[i].drc_instructions_index]); |
| if (str_drc_instruction_str->drc_set_target_loudness_present != 1) { |
| return UNEXPECTED_ERROR; |
| } |
| if (drc_set_target_loudness_val_upper_min >= |
| str_drc_instruction_str->drc_set_target_loudness_value_upper) { |
| if (drc_set_target_loudness_val_upper_min > |
| str_drc_instruction_str->drc_set_target_loudness_value_upper) { |
| drc_set_target_loudness_val_upper_min = |
| str_drc_instruction_str->drc_set_target_loudness_value_upper; |
| k = 0; |
| } |
| memcpy(&selection_candidate_info_step_2[k], |
| &selection_candidate_info_step_2[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| k++; |
| } |
| } |
| selection_candidate_step_2_count = k; |
| } else if (k == selection_candidate_step_2_count) { |
| drc_set_target_loudness_val_upper_min = 100; |
| k = 0; |
| for (i = 0; i < selection_candidate_step_2_count; i++) { |
| str_drc_instruction_str = |
| &(pstr_drc_config->str_drc_instruction_str |
| [selection_candidate_info_step_2[i].drc_instructions_index]); |
| if (str_drc_instruction_str->drc_set_target_loudness_present != 1) { |
| return UNEXPECTED_ERROR; |
| } |
| if (drc_set_target_loudness_val_upper_min >= |
| str_drc_instruction_str->drc_set_target_loudness_value_upper) { |
| if (drc_set_target_loudness_val_upper_min > |
| str_drc_instruction_str->drc_set_target_loudness_value_upper) { |
| drc_set_target_loudness_val_upper_min = |
| str_drc_instruction_str->drc_set_target_loudness_value_upper; |
| k = 0; |
| } |
| memcpy(&selection_candidate_info_step_2[k], |
| &selection_candidate_info_step_2[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| k++; |
| } |
| } |
| selection_candidate_step_2_count = k; |
| } |
| k = 0; |
| output_level_max = -1000.0f; |
| for (i = 0; i < selection_candidate_step_2_count; i++) { |
| if ((selection_candidate_info_step_2[i].output_peak_level <= 0.0f) && |
| (output_level_max <= |
| selection_candidate_info_step_2[i].output_peak_level)) { |
| if (output_level_max < |
| selection_candidate_info_step_2[i].output_peak_level) { |
| output_level_max = |
| selection_candidate_info_step_2[i].output_peak_level; |
| k = 0; |
| } |
| memcpy(&selection_candidate_info_step_2[k], |
| &selection_candidate_info_step_2[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| k++; |
| output_level_max = selection_candidate_info_step_2[i].output_peak_level; |
| } |
| } |
| selection_candidate_step_2_count = k; |
| } |
| |
| drc_set_id_max = -1000; |
| for (i = 0; i < selection_candidate_step_2_count; i++) { |
| str_drc_instruction_str = |
| &(pstr_drc_config->str_drc_instruction_str |
| [selection_candidate_info_step_2[i].drc_instructions_index]); |
| if (drc_set_id_max < str_drc_instruction_str->drc_set_id) { |
| drc_set_id_max = str_drc_instruction_str->drc_set_id; |
| memcpy(&selection_candidate_info_step_2[0], |
| &selection_candidate_info_step_2[i], |
| sizeof(ia_selection_candidate_info_struct)); |
| } |
| } |
| memcpy(&selection_candidate_info[0], &selection_candidate_info_step_2[0], |
| sizeof(ia_selection_candidate_info_struct)); |
| *selection_candidate_count = 1; |
| |
| return 0; |
| } |
| |
| WORD32 impd_select_drc_set(ia_drc_sel_pro_struct* pstr_drc_uni_sel_proc, |
| WORD32* drc_set_id_selected, |
| WORD32* eq_set_id_selected, WORD32* loud_eq_id_sel) { |
| WORD32 i, err; |
| |
| ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct = |
| &pstr_drc_uni_sel_proc->uni_drc_sel_proc_params; |
| ia_drc_config* pstr_drc_config = &pstr_drc_uni_sel_proc->drc_config; |
| ia_drc_loudness_info_set_struct* pstr_loudness_info = |
| &pstr_drc_uni_sel_proc->loudness_info_set; |
| |
| WORD32 selection_candidate_count = 0; |
| WORD32 restrict_to_drc_with_album_loudness = 0; |
| ia_selection_candidate_info_struct |
| selection_candidate_info[SELECTION_CANDIDATE_COUNT_MAX]; |
| |
| // WORD32 selected_eq_set_count = 0; |
| |
| if (pstr_drc_sel_proc_params_struct->album_mode == 1) { |
| restrict_to_drc_with_album_loudness = 1; |
| } |
| |
| while (!selection_candidate_count) { |
| err = impd_drc_set_preselection( |
| pstr_drc_sel_proc_params_struct, pstr_drc_config, pstr_loudness_info, |
| restrict_to_drc_with_album_loudness, pstr_drc_uni_sel_proc, |
| &selection_candidate_count, selection_candidate_info); |
| if (err) return err; |
| |
| if (selection_candidate_count == 0) { |
| if (restrict_to_drc_with_album_loudness == 1) { |
| restrict_to_drc_with_album_loudness = 0; |
| continue; |
| } else { |
| return (UNEXPECTED_ERROR); |
| } |
| } |
| |
| err = impd_validate_requested_drc_feature(pstr_drc_sel_proc_params_struct); |
| if (err) return (err); |
| |
| if (pstr_drc_sel_proc_params_struct->dynamic_range_control_on == 1) { |
| if (pstr_drc_sel_proc_params_struct->num_drc_feature_requests > 0) { |
| for (i = 0; |
| i < pstr_drc_sel_proc_params_struct->num_drc_feature_requests; |
| i++) { |
| switch (pstr_drc_sel_proc_params_struct->drc_feature_req_type[i]) { |
| case MATCH_EFFECT_TYPE: |
| err = impd_match_effect_types( |
| pstr_drc_config, |
| pstr_drc_sel_proc_params_struct->requested_num_drc_effects[i], |
| pstr_drc_sel_proc_params_struct |
| ->desired_num_drc_effects_of_requested[i], |
| pstr_drc_sel_proc_params_struct->requested_drc_effect_type[i], |
| &selection_candidate_count, selection_candidate_info); |
| if (err) return (err); |
| break; |
| case MATCH_DYNAMIC_RANGE: |
| err = impd_match_dynamic_range( |
| pstr_drc_config, pstr_loudness_info, |
| pstr_drc_sel_proc_params_struct, i, |
| &selection_candidate_count, selection_candidate_info); |
| if (err) return (err); |
| break; |
| case MATCH_DRC_CHARACTERISTIC: |
| err = impd_match_drc_characteristic( |
| pstr_drc_config, pstr_drc_sel_proc_params_struct |
| ->requested_drc_characteristic[i], |
| &selection_candidate_count, selection_candidate_info); |
| if (err) return (err); |
| break; |
| |
| default: |
| return (UNEXPECTED_ERROR); |
| break; |
| } |
| } |
| } else { |
| WORD32 match_found_flag = 0; |
| |
| err = impd_select_drcs_without_compr_effects( |
| pstr_drc_config, &match_found_flag, &selection_candidate_count, |
| selection_candidate_info); |
| if (err) return (err); |
| |
| if (match_found_flag == 0) { |
| WORD32 requested_num_drc_effects = 5; |
| WORD32 desired_num_drc_effects_of_requested = 1; |
| WORD32 requested_drc_effect_type[5] = { |
| EFFECT_TYPE_REQUESTED_GENERAL_COMPR, EFFECT_TYPE_REQUESTED_NIGHT, |
| EFFECT_TYPE_REQUESTED_NOISY, EFFECT_TYPE_REQUESTED_LIMITED, |
| EFFECT_TYPE_REQUESTED_LOWLEVEL}; |
| |
| err = impd_match_effect_types( |
| pstr_drc_config, requested_num_drc_effects, |
| desired_num_drc_effects_of_requested, requested_drc_effect_type, |
| &selection_candidate_count, selection_candidate_info); |
| if (err) return (err); |
| } |
| } |
| |
| if (selection_candidate_count > 0) { |
| err = impd_drc_set_final_selection( |
| pstr_drc_config, pstr_drc_sel_proc_params_struct, |
| &selection_candidate_count, selection_candidate_info, |
| pstr_drc_uni_sel_proc->eq_set_id_valid_flag); |
| if (err) return (err); |
| } else { |
| selection_candidate_count = 0; |
| return (UNEXPECTED_ERROR); |
| } |
| } |
| |
| if (selection_candidate_count == 0) { |
| if (restrict_to_drc_with_album_loudness == 1) { |
| restrict_to_drc_with_album_loudness = 0; |
| } else { |
| return (UNEXPECTED_ERROR); |
| } |
| } |
| } |
| *drc_set_id_selected = |
| pstr_drc_config |
| ->str_drc_instruction_str[selection_candidate_info[0] |
| .drc_instructions_index] |
| .drc_set_id; |
| *eq_set_id_selected = selection_candidate_info[0].eq_set_id; |
| |
| impd_select_loud_eq( |
| pstr_drc_config, |
| pstr_drc_sel_proc_params_struct->requested_dwnmix_id |
| [selection_candidate_info[0].downmix_id_request_index], |
| *drc_set_id_selected, *eq_set_id_selected, loud_eq_id_sel); |
| if (selection_candidate_count > 0) { |
| pstr_drc_uni_sel_proc->uni_drc_sel_proc_output |
| .loudness_normalization_gain_db = |
| selection_candidate_info[0].loudness_norm_db_gain_adjusted; |
| pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.output_peak_level_db = |
| selection_candidate_info[0].output_peak_level; |
| pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.output_loudness = |
| selection_candidate_info[0].output_loudness; |
| pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.active_downmix_id = |
| pstr_drc_sel_proc_params_struct->requested_dwnmix_id |
| [selection_candidate_info[0].downmix_id_request_index]; |
| pstr_drc_uni_sel_proc->uni_drc_sel_proc_output.mixing_level = |
| selection_candidate_info[0].mixing_level; |
| } |
| return (0); |
| } |