/****************************************************************************** * * 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 #include #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_filter_bank.h" #include "impd_drc_rom.h" VOID impd_signal_peak_level_info( ia_drc_config* pstr_drc_config, ia_drc_loudness_info_set_struct* pstr_loudness_info, ia_drc_instructions_struct* str_drc_instruction_str, WORD32 requested_dwnmix_id, WORD32 album_mode, WORD32 num_compression_eq_count, WORD32* num_compression_eq_id, WORD32* peak_info_count, WORD32 eq_set_id[], FLOAT32 signal_peak_level[], WORD32 explicit_peak_information_present[]) { WORD32 c, d, i, k, n, base_channel_count, mode; WORD32 pre_lim_count; WORD32 peak_count = 0; WORD32 loudness_info_count = 0; ia_loudness_info_struct* loudness_info; FLOAT32 sum, max_sum; WORD32 drc_set_id_requested = str_drc_instruction_str->drc_set_id; WORD32 loudness_drc_set_id_requested; WORD32 match_found_flag = 0; FLOAT32 signal_peak_level_tmp; eq_set_id[0] = 0; signal_peak_level[0] = 0.0f; explicit_peak_information_present[0] = 0; k = 0; if (drc_set_id_requested < 0) { for (k = 0; k < num_compression_eq_count; k++) { eq_set_id[k] = num_compression_eq_id[k]; signal_peak_level[k] = 0.0f; explicit_peak_information_present[k] = 0; } } eq_set_id[k] = 0; signal_peak_level[k] = 0.0f; explicit_peak_information_present[k] = 0; k++; pre_lim_count = k; if (drc_set_id_requested < 0) { loudness_drc_set_id_requested = 0; } else { loudness_drc_set_id_requested = drc_set_id_requested; } if (album_mode == 1) { mode = 1; loudness_info_count = pstr_loudness_info->loudness_info_album_count; } else { mode = 0; loudness_info_count = pstr_loudness_info->loudness_info_count; } for (n = 0; n < loudness_info_count; n++) { if (mode == 1) { loudness_info = &(pstr_loudness_info->str_loudness_info_album[n]); } else { loudness_info = &(pstr_loudness_info->loudness_info[n]); } if (loudness_drc_set_id_requested == loudness_info->drc_set_id && requested_dwnmix_id == loudness_info->downmix_id) { if (loudness_info->true_peak_level_present) { eq_set_id[peak_count] = loudness_info->eq_set_id; signal_peak_level[peak_count] = loudness_info->true_peak_level; explicit_peak_information_present[peak_count] = 1; match_found_flag = 1; peak_count++; } if (match_found_flag == 0) { if (loudness_info->sample_peak_level_present) { eq_set_id[peak_count] = loudness_info->eq_set_id; signal_peak_level[peak_count] = loudness_info->sample_peak_level; explicit_peak_information_present[peak_count] = 1; match_found_flag = 1; peak_count++; } } } } if (match_found_flag == 0) { for (n = 0; n < loudness_info_count; n++) { if (mode == 1) { loudness_info = &(pstr_loudness_info->str_loudness_info_album[n]); } else { loudness_info = &(pstr_loudness_info->loudness_info[n]); } if (ID_FOR_ANY_DRC == loudness_info->drc_set_id && requested_dwnmix_id == loudness_info->downmix_id) { if (loudness_info->true_peak_level_present) { eq_set_id[peak_count] = loudness_info->eq_set_id; signal_peak_level[peak_count] = loudness_info->true_peak_level; explicit_peak_information_present[peak_count] = 1; match_found_flag = 1; peak_count++; } if (match_found_flag == 0) { if (loudness_info->sample_peak_level_present) { eq_set_id[peak_count] = loudness_info->eq_set_id; signal_peak_level[peak_count] = loudness_info->sample_peak_level; explicit_peak_information_present[peak_count] = 1; match_found_flag = 1; peak_count++; } } } } } if (match_found_flag == 0) { for (i = 0; i < str_drc_instruction_str->dwnmix_id_count; i++) { if (requested_dwnmix_id == str_drc_instruction_str->downmix_id[0] || ID_FOR_ANY_DOWNMIX == str_drc_instruction_str->downmix_id[0]) { if (str_drc_instruction_str->limiter_peak_target_present) { if (str_drc_instruction_str->requires_eq == 1) { for (d = 0; d < pstr_drc_config->str_drc_config_ext.eq_instructions_count; d++) { ia_eq_instructions_struct* eq_instructions = &pstr_drc_config->str_drc_config_ext.str_eq_instructions[d]; for (c = 0; c < eq_instructions->drc_set_id_count; c++) { if ((eq_instructions->drc_set_id[c] == loudness_drc_set_id_requested) || (eq_instructions->drc_set_id[c] == ID_FOR_ANY_DRC)) { for (i = 0; i < eq_instructions->dwnmix_id_count; i++) { if ((eq_instructions->downmix_id[i] == requested_dwnmix_id) || (eq_instructions->downmix_id[i] == ID_FOR_ANY_DOWNMIX)) { eq_set_id[peak_count] = eq_instructions->eq_set_id; signal_peak_level[peak_count] = str_drc_instruction_str->limiter_peak_target; explicit_peak_information_present[peak_count] = 1; match_found_flag = 1; peak_count++; } } } } } } else { eq_set_id[peak_count] = 0; signal_peak_level[peak_count] = str_drc_instruction_str->limiter_peak_target; explicit_peak_information_present[peak_count] = 1; match_found_flag = 1; peak_count++; } } } } } if (match_found_flag == 0) { for (i = 1; i < str_drc_instruction_str->dwnmix_id_count; i++) { if (requested_dwnmix_id == str_drc_instruction_str->downmix_id[i]) { if (str_drc_instruction_str->limiter_peak_target_present) { { eq_set_id[peak_count] = 0; signal_peak_level[peak_count] = str_drc_instruction_str->limiter_peak_target; explicit_peak_information_present[peak_count] = 1; match_found_flag = 1; peak_count++; } } } } } if (match_found_flag == 0) { if (requested_dwnmix_id != ID_FOR_BASE_LAYOUT) { signal_peak_level_tmp = 0.f; for (i = 0; i < pstr_drc_config->dwnmix_instructions_count; i++) { if (pstr_drc_config->dwnmix_instructions[i].downmix_id == requested_dwnmix_id) { if (pstr_drc_config->dwnmix_instructions[i] .downmix_coefficients_present) { base_channel_count = pstr_drc_config->channel_layout.base_channel_count; max_sum = 0.0f; for (c = 0; c < pstr_drc_config->dwnmix_instructions[i].target_channel_count; c++) { sum = 0.0f; for (d = 0; d < base_channel_count; d++) { sum += pstr_drc_config->dwnmix_instructions[i] .downmix_coefficient[c * base_channel_count + d]; } if (max_sum < sum) max_sum = sum; } signal_peak_level_tmp = 20.0f * (FLOAT32)log10(max_sum); } else { } break; } } for (n = 0; n < loudness_info_count; n++) { if (mode == 1) { loudness_info = &(pstr_loudness_info->str_loudness_info_album[n]); } else { loudness_info = &(pstr_loudness_info->loudness_info[n]); } if (loudness_drc_set_id_requested == loudness_info->drc_set_id && ID_FOR_BASE_LAYOUT == loudness_info->downmix_id) { if (loudness_info->true_peak_level_present) { eq_set_id[peak_count] = loudness_info->eq_set_id; signal_peak_level[peak_count] = loudness_info->true_peak_level + signal_peak_level_tmp; explicit_peak_information_present[peak_count] = 0; match_found_flag = 1; peak_count++; } if (match_found_flag == 0) { if (loudness_info->sample_peak_level_present) { eq_set_id[peak_count] = loudness_info->eq_set_id; signal_peak_level[peak_count] = loudness_info->sample_peak_level + signal_peak_level_tmp; explicit_peak_information_present[peak_count] = 0; match_found_flag = 1; peak_count++; } } } } if (match_found_flag == 0) { for (n = 0; n < loudness_info_count; n++) { if (mode == 1) { loudness_info = &(pstr_loudness_info->str_loudness_info_album[n]); } else { loudness_info = &(pstr_loudness_info->loudness_info[n]); } if (ID_FOR_ANY_DRC == loudness_info->drc_set_id && ID_FOR_BASE_LAYOUT == loudness_info->downmix_id) { if (loudness_info->true_peak_level_present) { eq_set_id[peak_count] = loudness_info->eq_set_id; signal_peak_level[peak_count] = loudness_info->true_peak_level + signal_peak_level_tmp; explicit_peak_information_present[peak_count] = 0; match_found_flag = 1; peak_count++; } if (match_found_flag == 0) { if (loudness_info->sample_peak_level_present) { eq_set_id[peak_count] = loudness_info->eq_set_id; signal_peak_level[peak_count] = loudness_info->sample_peak_level + signal_peak_level_tmp; explicit_peak_information_present[peak_count] = 0; match_found_flag = 1; peak_count++; } } } } } if (match_found_flag == 0) { ia_drc_instructions_struct* drc_instructions_drc_tmp; for (n = 0; n < pstr_drc_config->drc_instructions_count_plus; n++) { drc_instructions_drc_tmp = &pstr_drc_config->str_drc_instruction_str[n]; if (loudness_drc_set_id_requested == drc_instructions_drc_tmp->drc_set_id) { if (ID_FOR_BASE_LAYOUT == drc_instructions_drc_tmp->downmix_id[0]) { if (drc_instructions_drc_tmp->limiter_peak_target_present) { eq_set_id[peak_count] = -1; signal_peak_level[peak_count] = drc_instructions_drc_tmp->limiter_peak_target + signal_peak_level_tmp; explicit_peak_information_present[peak_count] = 0; match_found_flag = 1; peak_count++; } } } } } } } if (peak_count > 0) { *peak_info_count = peak_count; } else { *peak_info_count = pre_lim_count; } return; } WORD32 impd_extract_loudness_peak_to_average_info( ia_loudness_info_struct* loudness_info, WORD32 dyn_range_measurement_type, WORD32* loudness_peak_2_avg_value_present, FLOAT32* loudness_peak_2_avg_value) { WORD32 k; WORD32 program_loudness_present = 0; WORD32 peak_loudness_present = 0; WORD32 match_measure_program_loudness = 0; WORD32 match_measure_peak_loudness = 0; FLOAT32 program_loudness = 0.0f; FLOAT32 peak_loudness = 0.0f; ia_loudness_measure_struct* loudness_measure = NULL; for (k = 0; k < loudness_info->measurement_count; k++) { loudness_measure = &(loudness_info->loudness_measure[k]); if (loudness_measure->method_def == METHOD_DEFINITION_PROGRAM_LOUDNESS) { if (match_measure_program_loudness < measurement_method_prog_loudness_tbl[loudness_measure ->measurement_system]) { program_loudness = loudness_measure->method_val; program_loudness_present = 1; match_measure_program_loudness = measurement_method_prog_loudness_tbl[loudness_measure ->measurement_system]; } } switch (dyn_range_measurement_type) { case SHORT_TERM_LOUDNESS_TO_AVG: if (loudness_measure->method_def == METHOD_DEFINITION_SHORT_TERM_LOUDNESS_MAX) { if (match_measure_peak_loudness < measurement_method_peak_loudness_tbl[loudness_measure ->measurement_system]) { peak_loudness = loudness_measure->method_val; peak_loudness_present = 1; match_measure_peak_loudness = measurement_method_peak_loudness_tbl[loudness_measure ->measurement_system]; } } break; case MOMENTARY_LOUDNESS_TO_AVG: if (loudness_measure->method_def == METHOD_DEFINITION_MOMENTARY_LOUDNESS_MAX) { if (match_measure_peak_loudness < measurement_method_peak_loudness_tbl[loudness_measure ->measurement_system]) { peak_loudness = loudness_measure->method_val; peak_loudness_present = 1; match_measure_peak_loudness = measurement_method_peak_loudness_tbl[loudness_measure ->measurement_system]; } } break; case TOP_OF_LOUDNESS_RANGE_TO_AVG: if (loudness_measure->method_def == METHOD_DEFINITION_MAX_OF_LOUDNESS_RANGE) { if (match_measure_peak_loudness < measurement_method_peak_loudness_tbl[loudness_measure ->measurement_system]) { peak_loudness = loudness_measure->method_val; peak_loudness_present = 1; match_measure_peak_loudness = measurement_method_peak_loudness_tbl[loudness_measure ->measurement_system]; } } break; default: return (UNEXPECTED_ERROR); break; } } if ((program_loudness_present == 1) && (peak_loudness_present == 1)) { *loudness_peak_2_avg_value = peak_loudness - program_loudness; *loudness_peak_2_avg_value_present = 1; } return (0); } WORD32 impd_loudness_peak_to_average_info( ia_drc_loudness_info_set_struct* pstr_loudness_info, ia_drc_instructions_struct* str_drc_instruction_str, WORD32 requested_dwnmix_id, WORD32 dyn_range_measurement_type, WORD32 album_mode, WORD32* loudness_peak_2_avg_value_present, FLOAT32* loudness_peak_2_avg_value) { WORD32 n, err; WORD32 drc_set_id = max(0, str_drc_instruction_str->drc_set_id); *loudness_peak_2_avg_value_present = 0; if (album_mode == 1) { for (n = 0; n < pstr_loudness_info->loudness_info_album_count; n++) { ia_loudness_info_struct* loudness_info = &(pstr_loudness_info->str_loudness_info_album[n]); if (drc_set_id == loudness_info->drc_set_id) { if (requested_dwnmix_id == loudness_info->downmix_id) { err = impd_extract_loudness_peak_to_average_info( loudness_info, dyn_range_measurement_type, loudness_peak_2_avg_value_present, loudness_peak_2_avg_value); if (err) return (err); } } } } if (*loudness_peak_2_avg_value_present == 0) { for (n = 0; n < pstr_loudness_info->loudness_info_count; n++) { ia_loudness_info_struct* loudness_info = &(pstr_loudness_info->loudness_info[n]); if (drc_set_id == loudness_info->drc_set_id) { if (requested_dwnmix_id == loudness_info->downmix_id) { err = impd_extract_loudness_peak_to_average_info( loudness_info, dyn_range_measurement_type, loudness_peak_2_avg_value_present, loudness_peak_2_avg_value); if (err) return (err); } } } } return (0); } VOID impd_overall_loudness_present(ia_loudness_info_struct* loudness_info, WORD32* loudness_info_present) { WORD32 m; *loudness_info_present = 0; for (m = 0; m < loudness_info->measurement_count; m++) { if ((loudness_info->loudness_measure[m].method_def == METHOD_DEFINITION_PROGRAM_LOUDNESS) || (loudness_info->loudness_measure[m].method_def == METHOD_DEFINITION_ANCHOR_LOUDNESS)) { *loudness_info_present = 1; } } return; } WORD32 impd_check_loud_info(WORD32 loudness_info_count, ia_loudness_info_struct* loudness_info, WORD32 requested_dwnmix_id, WORD32 drc_set_id_requested, WORD32* info_count, ia_loudness_info_struct* loudness_info_matching[]) { WORD32 n; WORD32 loudness_info_present; for (n = 0; n < loudness_info_count; n++) { if (requested_dwnmix_id == loudness_info[n].downmix_id) { if (drc_set_id_requested == loudness_info[n].drc_set_id) { impd_overall_loudness_present(&(loudness_info[n]), &loudness_info_present); if (loudness_info_present) { loudness_info_matching[*info_count] = &(loudness_info[n]); (*info_count)++; } } } } return (0); } WORD32 impd_check_loud_payload( WORD32 loudness_info_count, ia_loudness_info_struct* loudness_info, WORD32 requested_dwnmix_id, WORD32 drc_set_id_requested, WORD32* info_count, ia_loudness_info_struct* loudness_info_matching[]) { WORD32 err = 0; err = impd_check_loud_info(loudness_info_count, loudness_info, requested_dwnmix_id, drc_set_id_requested, info_count, loudness_info_matching); if (err || *info_count) goto matchEnd; err = impd_check_loud_info(loudness_info_count, loudness_info, ID_FOR_ANY_DOWNMIX, drc_set_id_requested, info_count, loudness_info_matching); if (err || *info_count) goto matchEnd; err = impd_check_loud_info(loudness_info_count, loudness_info, requested_dwnmix_id, ID_FOR_ANY_DRC, info_count, loudness_info_matching); if (err || *info_count) goto matchEnd; err = impd_check_loud_info(loudness_info_count, loudness_info, requested_dwnmix_id, ID_FOR_NO_DRC, info_count, loudness_info_matching); if (err || *info_count) goto matchEnd; err = impd_check_loud_info(loudness_info_count, loudness_info, ID_FOR_ANY_DOWNMIX, ID_FOR_ANY_DRC, info_count, loudness_info_matching); if (err || *info_count) goto matchEnd; err = impd_check_loud_info(loudness_info_count, loudness_info, ID_FOR_ANY_DOWNMIX, ID_FOR_NO_DRC, info_count, loudness_info_matching); if (err || *info_count) goto matchEnd; err = impd_check_loud_info(loudness_info_count, loudness_info, ID_FOR_BASE_LAYOUT, drc_set_id_requested, info_count, loudness_info_matching); if (err || *info_count) goto matchEnd; err = impd_check_loud_info(loudness_info_count, loudness_info, ID_FOR_BASE_LAYOUT, ID_FOR_ANY_DRC, info_count, loudness_info_matching); if (err || *info_count) goto matchEnd; err = impd_check_loud_info(loudness_info_count, loudness_info, ID_FOR_BASE_LAYOUT, ID_FOR_NO_DRC, info_count, loudness_info_matching); if (err || *info_count) goto matchEnd; matchEnd: return (err); } WORD32 impd_find_overall_loudness_info( ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct, ia_drc_loudness_info_set_struct* pstr_loudness_info, WORD32 requested_dwnmix_id, WORD32 drc_set_id_requested, WORD32* overall_loudness_info_present, WORD32* info_count, ia_loudness_info_struct* loudness_info_matching[]) { WORD32 err; WORD32 loudness_drc_set_id_requested; *info_count = 0; if (drc_set_id_requested < 0) { loudness_drc_set_id_requested = ID_FOR_NO_DRC; } else { loudness_drc_set_id_requested = drc_set_id_requested; } if (pstr_drc_sel_proc_params_struct->album_mode == 1) { err = impd_check_loud_payload( pstr_loudness_info->loudness_info_album_count, pstr_loudness_info->str_loudness_info_album, requested_dwnmix_id, loudness_drc_set_id_requested, info_count, loudness_info_matching); if (err) return (err); } if (*info_count == 0) { err = impd_check_loud_payload(pstr_loudness_info->loudness_info_count, pstr_loudness_info->loudness_info, requested_dwnmix_id, loudness_drc_set_id_requested, info_count, loudness_info_matching); if (err) return (err); } *overall_loudness_info_present = (*info_count > 0); return (0); } WORD32 impd_high_pass_loudness_adjust_info(ia_loudness_info_struct* loudness_info, WORD32* loudness_hp_adjust_present, FLOAT32* loudness_hp_adjust) { WORD32 m, k; *loudness_hp_adjust_present = 0; *loudness_hp_adjust = 0.0f; for (m = 0; m < loudness_info->measurement_count; m++) { if (loudness_info->loudness_measure[m].measurement_system == MEASUREMENT_SYSTEM_BS_1770_4_PRE_PROCESSING) { for (k = 0; k < loudness_info->measurement_count; k++) { if (loudness_info->loudness_measure[k].measurement_system == MEASUREMENT_SYSTEM_BS_1770_4) { if (loudness_info->loudness_measure[m].method_def == loudness_info->loudness_measure[k].method_def) { *loudness_hp_adjust_present = 1; *loudness_hp_adjust = loudness_info->loudness_measure[m].method_val - loudness_info->loudness_measure[k].method_val; } } } } } return (0); } WORD32 impd_find_high_pass_loudness_adjust( ia_drc_loudness_info_set_struct* pstr_loudness_info, WORD32 requested_dwnmix_id, WORD32 drc_set_id_requested, WORD32 album_mode, FLOAT32 device_cutoff_freq, WORD32* loudness_hp_adjust_present, FLOAT32* loudness_hp_adjust) { WORD32 n, err; WORD32 loudness_drc_set_id_requested; if (drc_set_id_requested < 0) { loudness_drc_set_id_requested = 0; } else { loudness_drc_set_id_requested = drc_set_id_requested; } *loudness_hp_adjust_present = 0; if (album_mode == 1) { for (n = 0; n < pstr_loudness_info->loudness_info_album_count; n++) { if ((requested_dwnmix_id == pstr_loudness_info->str_loudness_info_album[n].downmix_id) || (ID_FOR_ANY_DOWNMIX == pstr_loudness_info->str_loudness_info_album[n].downmix_id)) { if (loudness_drc_set_id_requested == pstr_loudness_info->str_loudness_info_album[n].drc_set_id) { err = impd_high_pass_loudness_adjust_info( &(pstr_loudness_info->loudness_info[n]), loudness_hp_adjust_present, loudness_hp_adjust); if (err) return (err); } } } } if (*loudness_hp_adjust_present == 0) { for (n = 0; n < pstr_loudness_info->loudness_info_count; n++) { if ((requested_dwnmix_id == pstr_loudness_info->loudness_info[n].downmix_id) || (ID_FOR_ANY_DOWNMIX == pstr_loudness_info->loudness_info[n].downmix_id)) { if (loudness_drc_set_id_requested == pstr_loudness_info->loudness_info[n].drc_set_id) { err = impd_high_pass_loudness_adjust_info( &(pstr_loudness_info->loudness_info[n]), loudness_hp_adjust_present, loudness_hp_adjust); if (err) return (err); } } } } if (*loudness_hp_adjust_present == 0) { for (n = 0; n < pstr_loudness_info->loudness_info_count; n++) { if (ID_FOR_BASE_LAYOUT == pstr_loudness_info->loudness_info[n].downmix_id) /* base layout */ { if (loudness_drc_set_id_requested == pstr_loudness_info->loudness_info[n].drc_set_id) { err = impd_high_pass_loudness_adjust_info( &(pstr_loudness_info->loudness_info[n]), loudness_hp_adjust_present, loudness_hp_adjust); if (err) return (err); } } } } if (*loudness_hp_adjust_present == 0) { for (n = 0; n < pstr_loudness_info->loudness_info_count; n++) { if (ID_FOR_BASE_LAYOUT == pstr_loudness_info->loudness_info[n].downmix_id) /* base layout */ { if (0 == pstr_loudness_info->loudness_info[n].drc_set_id) { err = impd_high_pass_loudness_adjust_info( &(pstr_loudness_info->loudness_info[n]), loudness_hp_adjust_present, loudness_hp_adjust); if (err) return (err); } } } } if (*loudness_hp_adjust_present == 0) { *loudness_hp_adjust = 0.0f; } else { *loudness_hp_adjust *= (max(20.0f, min(500.0f, device_cutoff_freq)) - 20.0f) / (500.0f - 20.0f); } return (0); } WORD32 impd_init_loudness_control( ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct, ia_drc_loudness_info_set_struct* pstr_loudness_info, WORD32 requested_dwnmix_id, WORD32 drc_set_id_requested, WORD32 num_compression_eq_count, WORD32* num_compression_eq_id, WORD32* loudness_info_count, WORD32 eq_set_id[], FLOAT32 loudness_normalization_gain_db[], FLOAT32 loudness[]) { WORD32 err, k, info_count = 0, pre_lim_count; WORD32 loudness_hp_adjust_present; WORD32 overall_loudness_info_present; FLOAT32 pre_proc_adjust; k = 0; if (drc_set_id_requested < 0) { for (k = 0; k < num_compression_eq_count; k++) { eq_set_id[k] = num_compression_eq_id[k]; loudness[k] = UNDEFINED_LOUDNESS_VALUE; loudness_normalization_gain_db[k] = 0.0f; } } if (k >= MAX_NUM_COMPRESSION_EQ) return UNEXPECTED_ERROR; eq_set_id[k] = 0; loudness[k] = UNDEFINED_LOUDNESS_VALUE; loudness_normalization_gain_db[k] = 0.0f; k++; pre_lim_count = k; if (pstr_drc_sel_proc_params_struct->loudness_normalization_on == 1) { WORD32 n; ia_loudness_info_struct* loudness_info[16]; err = impd_find_overall_loudness_info( pstr_drc_sel_proc_params_struct, pstr_loudness_info, requested_dwnmix_id, drc_set_id_requested, &overall_loudness_info_present, &info_count, loudness_info); if (err) return (err); if (overall_loudness_info_present == 1) { WORD32 requested_method_definition = METHOD_DEFINITION_PROGRAM_LOUDNESS; WORD32 other_method_definition = METHOD_DEFINITION_PROGRAM_LOUDNESS; WORD32 requested_preprocessing = 0; const WORD32* system_bonus = measurement_system_default_tbl; WORD32 match_measure; FLOAT32 method_val = 0; switch (pstr_drc_sel_proc_params_struct->loudness_measurement_method) { case USER_METHOD_DEFINITION_DEFAULT: case USER_METHOD_DEFINITION_PROGRAM_LOUDNESS: requested_method_definition = METHOD_DEFINITION_PROGRAM_LOUDNESS; other_method_definition = METHOD_DEFINITION_ANCHOR_LOUDNESS; break; case USER_METHOD_DEFINITION_ANCHOR_LOUDNESS: requested_method_definition = METHOD_DEFINITION_ANCHOR_LOUDNESS; other_method_definition = METHOD_DEFINITION_PROGRAM_LOUDNESS; break; default: return (UNEXPECTED_ERROR); break; } switch (pstr_drc_sel_proc_params_struct->loudness_measurement_system) { case USER_MEASUREMENT_SYSTEM_DEFAULT: case USER_MEASUREMENT_SYSTEM_BS_1770_4: system_bonus = measurement_system_bs1770_3_tbl; break; case USER_MEASUREMENT_SYSTEM_USER: system_bonus = measurement_system_user_tbl; break; case USER_MEASUREMENT_SYSTEM_EXPERT_PANEL: system_bonus = measurement_system_expert_tbl; break; case USER_MEASUREMENT_SYSTEM_RESERVED_A: system_bonus = measurement_system_rms_a_tbl; break; case USER_MEASUREMENT_SYSTEM_RESERVED_B: system_bonus = measurement_system_rms_b_tbl; break; case USER_MEASUREMENT_SYSTEM_RESERVED_C: system_bonus = measurement_system_rms_c_tbl; break; case USER_MEASUREMENT_SYSTEM_RESERVED_D: system_bonus = measurement_system_rms_d_tbl; break; case USER_MEASUREMENT_SYSTEM_RESERVED_E: system_bonus = measurement_system_rms_e_tbl; break; default: return (UNEXPECTED_ERROR); break; } switch (pstr_drc_sel_proc_params_struct->loudness_measurement_pre_proc) { case USER_LOUDNESS_PREPROCESSING_DEFAULT: case USER_LOUDNESS_PREPROCESSING_OFF: requested_preprocessing = 0; break; case USER_LOUDNESS_PREPROCESSING_HIGHPASS: requested_preprocessing = 1; break; default: return (UNEXPECTED_ERROR); break; } for (k = 0; k < info_count; k++) { match_measure = -1; for (n = 0; n < loudness_info[k]->measurement_count; n++) { ia_loudness_measure_struct* loudness_measure = &(loudness_info[k]->loudness_measure[n]); if (match_measure < system_bonus[loudness_measure->measurement_system] && requested_method_definition == loudness_measure->method_def) { method_val = loudness_measure->method_val; match_measure = system_bonus[loudness_measure->measurement_system]; } } if (match_measure == -1) { for (n = 0; n < loudness_info[k]->measurement_count; n++) { ia_loudness_measure_struct* loudness_measure = &(loudness_info[k]->loudness_measure[n]); if (match_measure < system_bonus[loudness_measure->measurement_system] && other_method_definition == loudness_measure->method_def) { method_val = loudness_measure->method_val; match_measure = system_bonus[loudness_measure->measurement_system]; } } } if (requested_preprocessing == 1) { err = impd_find_high_pass_loudness_adjust( pstr_loudness_info, requested_dwnmix_id, drc_set_id_requested, pstr_drc_sel_proc_params_struct->album_mode, (FLOAT32) pstr_drc_sel_proc_params_struct->device_cut_off_frequency, &loudness_hp_adjust_present, &pre_proc_adjust); if (err) return (err); if (loudness_hp_adjust_present == 0) { pre_proc_adjust = -2.0f; } method_val += pre_proc_adjust; } eq_set_id[k] = 0; loudness_normalization_gain_db[k] = pstr_drc_sel_proc_params_struct->target_loudness - method_val; loudness[k] = method_val; } } } if (info_count > 0) { *loudness_info_count = info_count; } else { *loudness_info_count = pre_lim_count; } return (0); } #define MIXING_LEVEL_DEFAULT 85.0f WORD32 impd_mixing_level_info( ia_drc_sel_proc_params_struct* pstr_drc_sel_proc_params_struct, ia_drc_loudness_info_set_struct* pstr_loudness_info, WORD32 requested_dwnmix_id, WORD32 drc_set_id_requested, WORD32 eq_set_id_requested, FLOAT32* mixing_level) { WORD32 n, k, info_count; WORD32 album_mode = pstr_drc_sel_proc_params_struct->album_mode; WORD32 loudness_drc_set_id_requested; ia_loudness_info_struct* loudness_info; *mixing_level = MIXING_LEVEL_DEFAULT; if (drc_set_id_requested < 0) { loudness_drc_set_id_requested = 0; } else { loudness_drc_set_id_requested = drc_set_id_requested; } if (album_mode == 1) { info_count = pstr_loudness_info->loudness_info_album_count; loudness_info = pstr_loudness_info->str_loudness_info_album; } else { info_count = pstr_loudness_info->loudness_info_count; loudness_info = pstr_loudness_info->loudness_info; } for (n = 0; n < info_count; n++) { if ((requested_dwnmix_id == loudness_info[n].downmix_id) || (ID_FOR_ANY_DOWNMIX == loudness_info[n].downmix_id)) { if (loudness_drc_set_id_requested == loudness_info[n].drc_set_id) { if (eq_set_id_requested == loudness_info[n].eq_set_id) { for (k = 0; k < loudness_info[n].measurement_count; k++) { if (loudness_info[n].loudness_measure[k].method_def == METHOD_DEFINITION_MIXING_LEVEL) { *mixing_level = loudness_info[n].loudness_measure[k].method_val; break; } } } } } } return (0); }