/****************************************************************************** * * 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 #include "impd_type_def.h" #include "impd_drc_bitbuffer.h" #include "impd_drc_extr_delta_coded_info.h" #include "impd_drc_common.h" #include "impd_drc_struct.h" #include "impd_drc_parser.h" #include "impd_drc_filter_bank.h" #include "impd_drc_rom.h" static VOID impd_parametric_drc_ffwd_init_drc_curve_params( WORD32 drc_characteristic, ia_parametric_drc_type_feed_forward_struct* str_parametric_drc_type_feed_forward) { WORD32* node_level = str_parametric_drc_type_feed_forward->node_level; WORD32* node_gain = str_parametric_drc_type_feed_forward->node_gain; switch (drc_characteristic) { case 7: str_parametric_drc_type_feed_forward->node_count = 5; node_level[0] = -22; node_gain[0] = 6; node_level[1] = -10; node_gain[1] = 0; node_level[2] = 10; node_gain[2] = 0; node_level[3] = 20; node_gain[3] = -5; node_level[4] = 40; node_gain[4] = -24; break; case 8: str_parametric_drc_type_feed_forward->node_count = 5; node_level[0] = -12; node_gain[0] = 6; node_level[1] = 0; node_gain[1] = 0; node_level[2] = 5; node_gain[2] = 0; node_level[3] = 15; node_gain[3] = -5; node_level[4] = 35; node_gain[4] = -24; break; case 9: str_parametric_drc_type_feed_forward->node_count = 4; node_level[0] = -34; node_gain[0] = 12; node_level[1] = -10; node_gain[1] = 0; node_level[2] = 10; node_gain[2] = 0; node_level[3] = 40; node_gain[3] = -15; break; case 10: str_parametric_drc_type_feed_forward->node_count = 5; node_level[0] = -24; node_gain[0] = 12; node_level[1] = 0; node_gain[1] = 0; node_level[2] = 5; node_gain[2] = 0; node_level[3] = 15; node_gain[3] = -5; node_level[4] = 35; node_gain[4] = -24; break; case 11: str_parametric_drc_type_feed_forward->node_count = 5; node_level[0] = -19; node_gain[0] = 15; node_level[1] = 0; node_gain[1] = 0; node_level[2] = 5; node_gain[2] = 0; node_level[3] = 15; node_gain[3] = -5; node_level[4] = 35; node_gain[4] = -24; break; default: str_parametric_drc_type_feed_forward->disable_paramteric_drc = 1; } return; } static VOID impd_parametric_drc_ffwd_init_drc_gain_smooth_params( WORD32 drc_characteristic, ia_parametric_drc_type_feed_forward_struct* str_parametric_drc_type_feed_forward) { str_parametric_drc_type_feed_forward->gain_smooth_attack_time_slow = 100; str_parametric_drc_type_feed_forward->gain_smooth_time_fast_present = 1; str_parametric_drc_type_feed_forward->gain_smooth_attack_time_fast = 10; str_parametric_drc_type_feed_forward->gain_smooth_threshold_present = 1; str_parametric_drc_type_feed_forward->gain_smooth_hold_off_count_present = 1; str_parametric_drc_type_feed_forward->gain_smooth_hold_off = 10; switch (drc_characteristic) { case 7: case 8: case 9: str_parametric_drc_type_feed_forward->gain_smooth_release_time_slow = 3000; str_parametric_drc_type_feed_forward->gain_smooth_release_time_fast = 1000; str_parametric_drc_type_feed_forward->gain_smooth_attack_threshold = 15; str_parametric_drc_type_feed_forward->gain_smooth_rel_threshold = 20; break; case 10: str_parametric_drc_type_feed_forward->gain_smooth_release_time_slow = 10000; str_parametric_drc_type_feed_forward->gain_smooth_release_time_fast = 1000; str_parametric_drc_type_feed_forward->gain_smooth_attack_threshold = 15; str_parametric_drc_type_feed_forward->gain_smooth_rel_threshold = 20; break; case 11: str_parametric_drc_type_feed_forward->gain_smooth_release_time_slow = 1000; str_parametric_drc_type_feed_forward->gain_smooth_release_time_fast = 200; str_parametric_drc_type_feed_forward->gain_smooth_attack_threshold = 10; str_parametric_drc_type_feed_forward->gain_smooth_rel_threshold = 10; break; default: str_parametric_drc_type_feed_forward->gain_smooth_release_time_slow = 3000; str_parametric_drc_type_feed_forward->gain_smooth_release_time_fast = 1000; str_parametric_drc_type_feed_forward->gain_smooth_attack_threshold = 15; str_parametric_drc_type_feed_forward->gain_smooth_rel_threshold = 20; break; } return; } static WORD32 impd_parse_parametric_drc_ffwd( ia_bit_buf_struct* it_bit_buff, WORD32 parametric_drc_frame_size, ia_parametric_drc_type_feed_forward_struct* str_parametric_drc_type_feed_forward) { WORD32 i = 0, tmp = 0; // WORD32 err = 0; str_parametric_drc_type_feed_forward->disable_paramteric_drc = 0; tmp = impd_read_bits_buf(it_bit_buff, 3); if (it_bit_buff->error) return it_bit_buff->error; str_parametric_drc_type_feed_forward->level_estim_k_weighting_type = (tmp >> 1) & 3; str_parametric_drc_type_feed_forward->level_estim_integration_time_present = tmp & 1; if (str_parametric_drc_type_feed_forward ->level_estim_integration_time_present) { tmp = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; str_parametric_drc_type_feed_forward->level_estim_integration_time = (tmp + 1) * parametric_drc_frame_size; } else { str_parametric_drc_type_feed_forward->level_estim_integration_time = parametric_drc_frame_size; } str_parametric_drc_type_feed_forward->drc_curve_definition_type = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_parametric_drc_type_feed_forward->drc_curve_definition_type == 0) { str_parametric_drc_type_feed_forward->drc_characteristic = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; impd_parametric_drc_ffwd_init_drc_curve_params( str_parametric_drc_type_feed_forward->drc_characteristic, str_parametric_drc_type_feed_forward); } else { str_parametric_drc_type_feed_forward->drc_characteristic = 0; tmp = impd_read_bits_buf(it_bit_buff, 15); if (it_bit_buff->error) return it_bit_buff->error; str_parametric_drc_type_feed_forward->node_count = ((tmp >> 12) & 3) + 2; str_parametric_drc_type_feed_forward->node_level[0] = -11 - ((tmp >> 6) & 0x3f); str_parametric_drc_type_feed_forward->node_gain[0] = (tmp & 0x3f) - 39; for (i = 1; i < str_parametric_drc_type_feed_forward->node_count; i++) { tmp = impd_read_bits_buf(it_bit_buff, 11); if (it_bit_buff->error) return it_bit_buff->error; str_parametric_drc_type_feed_forward->node_level[i] = str_parametric_drc_type_feed_forward->node_level[i - 1] + 1 + ((tmp >> 6) & 0x1f); str_parametric_drc_type_feed_forward->node_gain[i] = (tmp & 0x3f) - 39; } } impd_parametric_drc_ffwd_init_drc_gain_smooth_params( str_parametric_drc_type_feed_forward->drc_characteristic, str_parametric_drc_type_feed_forward); str_parametric_drc_type_feed_forward->drc_gain_smooth_parameters_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_parametric_drc_type_feed_forward ->drc_gain_smooth_parameters_present) { tmp = impd_read_bits_buf(it_bit_buff, 17); if (it_bit_buff->error) return it_bit_buff->error; str_parametric_drc_type_feed_forward->gain_smooth_attack_time_slow = ((tmp >> 9) & 0xff) * 5; str_parametric_drc_type_feed_forward->gain_smooth_release_time_slow = ((tmp >> 1) & 0xff) * 40; str_parametric_drc_type_feed_forward->gain_smooth_time_fast_present = tmp & 1; if (str_parametric_drc_type_feed_forward->gain_smooth_time_fast_present) { tmp = impd_read_bits_buf(it_bit_buff, 17); if (it_bit_buff->error) return it_bit_buff->error; str_parametric_drc_type_feed_forward->gain_smooth_attack_time_fast = ((tmp >> 9) & 0xff) * 5; str_parametric_drc_type_feed_forward->gain_smooth_release_time_fast = ((tmp >> 1) & 0xff) * 20; str_parametric_drc_type_feed_forward->gain_smooth_threshold_present = tmp & 1; if (str_parametric_drc_type_feed_forward->gain_smooth_threshold_present) { str_parametric_drc_type_feed_forward->gain_smooth_attack_threshold = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; if (str_parametric_drc_type_feed_forward ->gain_smooth_attack_threshold == 31) { str_parametric_drc_type_feed_forward->gain_smooth_attack_threshold = 1000; } str_parametric_drc_type_feed_forward->gain_smooth_rel_threshold = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; if (str_parametric_drc_type_feed_forward->gain_smooth_rel_threshold == 31) { str_parametric_drc_type_feed_forward->gain_smooth_rel_threshold = 1000; } } } else { str_parametric_drc_type_feed_forward->gain_smooth_attack_time_fast = str_parametric_drc_type_feed_forward->gain_smooth_attack_time_slow; str_parametric_drc_type_feed_forward->gain_smooth_release_time_fast = str_parametric_drc_type_feed_forward->gain_smooth_release_time_slow; } str_parametric_drc_type_feed_forward->gain_smooth_hold_off_count_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_parametric_drc_type_feed_forward ->gain_smooth_hold_off_count_present) { str_parametric_drc_type_feed_forward->gain_smooth_hold_off = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; } } return 0; } static WORD32 impd_parse_parametric_drc_lim( ia_bit_buf_struct* it_bit_buff, ia_parametric_drc_lim_struct* parametric_drc_lim) { // WORD32 err = 0; WORD32 tmp = 0; parametric_drc_lim->disable_paramteric_drc = 0; parametric_drc_lim->parametric_lim_threshold_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (parametric_drc_lim->parametric_lim_threshold_present) { tmp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; parametric_drc_lim->parametric_lim_threshold = -tmp * 0.125f; } else { parametric_drc_lim->parametric_lim_threshold = PARAM_DRC_TYPE_LIM_THRESHOLD_DEFAULT; } parametric_drc_lim->parametric_lim_release_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (parametric_drc_lim->parametric_lim_release_present) { tmp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; parametric_drc_lim->parametric_lim_release = tmp * 10; } else { parametric_drc_lim->parametric_lim_release = PARAM_DRC_TYPE_LIM_RELEASE_DEFAULT; } parametric_drc_lim->parametric_lim_attack = PARAM_DRC_TYPE_LIM_ATTACK_DEFAULT; parametric_drc_lim->drc_characteristic = 0; return 0; } WORD32 impd_parametric_drc_parse_gain_set_params( ia_bit_buf_struct* it_bit_buff, ia_drc_config* drc_config, ia_parametric_drc_gain_set_params_struct* str_parametric_drc_gain_set_params) { WORD32 i = 0, bsDrcInputLoudness = 0, bs_channel_weight = 0, temp; // WORD32 err = 0; temp = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; str_parametric_drc_gain_set_params->parametric_drc_id = (temp >> 3) & 0xf; str_parametric_drc_gain_set_params->side_chain_config_type = temp & 7; if (str_parametric_drc_gain_set_params->side_chain_config_type == 1) { temp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; str_parametric_drc_gain_set_params->downmix_id = (temp >> 1) & 0x7f; str_parametric_drc_gain_set_params->level_estim_channel_weight_format = temp & 1; if (str_parametric_drc_gain_set_params->downmix_id == ID_FOR_BASE_LAYOUT) { str_parametric_drc_gain_set_params->ch_count_from_dwnmix_id = drc_config->channel_layout.base_channel_count; } else if (str_parametric_drc_gain_set_params->downmix_id == ID_FOR_ANY_DOWNMIX) { str_parametric_drc_gain_set_params->ch_count_from_dwnmix_id = 1; } else { for (i = 0; i < drc_config->dwnmix_instructions_count; i++) { if (str_parametric_drc_gain_set_params->downmix_id == drc_config->dwnmix_instructions[i].downmix_id) break; } if (i == drc_config->dwnmix_instructions_count) { /* dwnmix_instructions not found */ return (UNEXPECTED_ERROR); } str_parametric_drc_gain_set_params->ch_count_from_dwnmix_id = drc_config->dwnmix_instructions[i].target_channel_count; } for (i = 0; i < str_parametric_drc_gain_set_params->ch_count_from_dwnmix_id; i++) { if (str_parametric_drc_gain_set_params ->level_estim_channel_weight_format == 0) { str_parametric_drc_gain_set_params->level_estim_ch_weight[i] = (FLOAT32)impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; } else { bs_channel_weight = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; str_parametric_drc_gain_set_params->level_estim_ch_weight[i] = (FLOAT32)pow(10.0f, 0.05f * channel_weight[bs_channel_weight]); } } } else { str_parametric_drc_gain_set_params->downmix_id = 0; str_parametric_drc_gain_set_params->ch_count_from_dwnmix_id = 0; } str_parametric_drc_gain_set_params->drc_input_loudness_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_parametric_drc_gain_set_params->drc_input_loudness_present) { bsDrcInputLoudness = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; str_parametric_drc_gain_set_params->drc_input_loudness = -57.75f + bsDrcInputLoudness * 0.25f; } return 0; } static WORD32 impd_parametric_drc_gen_virtual_gain_sets( ia_drc_config* drc_config) { WORD32 i = 0, j = 0, c1 = -1, c0 = -1, parametric_drc_id = 0, drc_characteristic = 0; ia_uni_drc_coeffs_struct* str_p_loc_drc_coefficients_uni_drc; ia_parametric_drc_instructions_struct* str_parametric_drc_instructions; ia_drc_coeff_parametric_drc_struct* str_drc_coeff_param_drc = &(drc_config->str_drc_config_ext.str_drc_coeff_param_drc); for (i = 0; i < drc_config->drc_coefficients_drc_count; i++) { if (drc_config->str_p_loc_drc_coefficients_uni_drc[i].drc_location == str_drc_coeff_param_drc->drc_location) { if (drc_config->str_p_loc_drc_coefficients_uni_drc[i].version == 0) { c0 = i; } else { c1 = i; } } } if (c1 >= 0) { str_p_loc_drc_coefficients_uni_drc = &(drc_config->str_p_loc_drc_coefficients_uni_drc[c1]); } else if (c0 >= 0) { str_p_loc_drc_coefficients_uni_drc = &(drc_config->str_p_loc_drc_coefficients_uni_drc[c0]); } else { str_p_loc_drc_coefficients_uni_drc = &drc_config->str_p_loc_drc_coefficients_uni_drc [drc_config->drc_coefficients_drc_count]; str_p_loc_drc_coefficients_uni_drc->version = 1; str_p_loc_drc_coefficients_uni_drc->drc_location = str_drc_coeff_param_drc->drc_location; str_p_loc_drc_coefficients_uni_drc->drc_frame_size_present = 0; str_p_loc_drc_coefficients_uni_drc->gain_set_count = 0; str_p_loc_drc_coefficients_uni_drc->gain_set_count_plus = 0; str_p_loc_drc_coefficients_uni_drc->drc_characteristic_left_present = 0; str_p_loc_drc_coefficients_uni_drc->drc_characteristic_right_present = 0; str_p_loc_drc_coefficients_uni_drc->shape_filters_present = 0; str_p_loc_drc_coefficients_uni_drc->gain_sequence_count = 0; drc_config->drc_coefficients_drc_count += 1; } { WORD32 tmp = str_p_loc_drc_coefficients_uni_drc->gain_set_count + str_drc_coeff_param_drc->parametric_drc_gain_set_count; if (tmp > GAIN_SET_COUNT_MAX) return UNEXPECTED_ERROR; str_p_loc_drc_coefficients_uni_drc->gain_set_count_plus = tmp; } for (i = str_p_loc_drc_coefficients_uni_drc->gain_set_count; i < str_p_loc_drc_coefficients_uni_drc->gain_set_count_plus; i++) { str_p_loc_drc_coefficients_uni_drc->gain_set_params[i].band_count = 1; parametric_drc_id = drc_config->str_drc_config_ext.str_drc_coeff_param_drc .str_parametric_drc_gain_set_params [i - str_p_loc_drc_coefficients_uni_drc->gain_set_count] .parametric_drc_id; for (j = 0; j < drc_config->str_drc_config_ext.parametric_drc_instructions_count; j++) { if (parametric_drc_id == drc_config->str_drc_config_ext.str_parametric_drc_instructions[j] .parametric_drc_id) break; } if (j == drc_config->str_drc_config_ext.parametric_drc_instructions_count) { /* str_parametric_drc_instructions not found */ return (UNEXPECTED_ERROR); } str_parametric_drc_instructions = &drc_config->str_drc_config_ext.str_parametric_drc_instructions[j]; drc_characteristic = 0; if (str_parametric_drc_instructions->parametric_drc_preset_id_present) { drc_characteristic = str_parametric_drc_instructions->drc_characteristic; } else if (str_parametric_drc_instructions->parametric_drc_type == PARAM_DRC_TYPE_FF) { if (str_parametric_drc_instructions->str_parametric_drc_type_feed_forward .drc_curve_definition_type == 0) { drc_characteristic = str_parametric_drc_instructions ->str_parametric_drc_type_feed_forward.drc_characteristic; } } if (drc_characteristic != 0) { str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .gain_params[0] .drc_characteristic_present = 1; str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .gain_params[0] .drc_characteristic_format_is_cicp = 1; str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .gain_params[0] .drc_characteristic = drc_characteristic; } else { str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .gain_params[0] .drc_characteristic_present = 0; str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .gain_params[0] .drc_characteristic_format_is_cicp = 0; str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .gain_params[0] .drc_characteristic = 0; } } return 0; } static WORD32 impd_parametic_drc_parse_coeff( ia_bit_buf_struct* it_bit_buff, ia_drc_config* drc_config, ia_drc_coeff_parametric_drc_struct* str_drc_coeff_param_drc) { WORD32 i = 0, err = 0, code = 0, mu = 0, nu = 0, temp; temp = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; str_drc_coeff_param_drc->drc_location = (temp >> 1) & 0xf; if (str_drc_coeff_param_drc->drc_location < 1 || str_drc_coeff_param_drc->drc_location > 4) return UNEXPECTED_ERROR; str_drc_coeff_param_drc->parametric_drc_frame_size_format = temp & 1; if (str_drc_coeff_param_drc->parametric_drc_frame_size_format) { code = impd_read_bits_buf(it_bit_buff, 15); if (it_bit_buff->error) return it_bit_buff->error; str_drc_coeff_param_drc->parametric_drc_frame_size = code + 1; } else { code = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; str_drc_coeff_param_drc->parametric_drc_frame_size = 1 << code; } str_drc_coeff_param_drc->parametric_drc_delay_max_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_drc_coeff_param_drc->parametric_drc_delay_max_present) { temp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; mu = (temp >> 3) & 0x1f; nu = temp & 3; str_drc_coeff_param_drc->parametric_drc_delay_max = 16 * mu * (1 << nu); } temp = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; str_drc_coeff_param_drc->reset_parametric_drc = (temp >> 6) & 1; str_drc_coeff_param_drc->parametric_drc_gain_set_count = temp & 0x3f; if (str_drc_coeff_param_drc->parametric_drc_gain_set_count > SEQUENCE_COUNT_MAX) return (UNEXPECTED_ERROR); for (i = 0; i < str_drc_coeff_param_drc->parametric_drc_gain_set_count; i++) { err = impd_parametric_drc_parse_gain_set_params( it_bit_buff, drc_config, &(str_drc_coeff_param_drc->str_parametric_drc_gain_set_params[i])); if (err) return (err); } return 0; } static WORD32 impd_parse_parametric_drc_instructions( ia_bit_buf_struct* it_bit_buff, WORD32 parametric_drc_frame_size, ia_parametric_drc_instructions_struct* str_parametric_drc_instructions) { WORD32 i = 0, err = 0, temp; WORD32 bit_size_len, bit_size, other_bit; str_parametric_drc_instructions->drc_characteristic = 0; str_parametric_drc_instructions->disable_paramteric_drc = 0; temp = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; str_parametric_drc_instructions->parametric_drc_id = (temp >> 1) & 0xf; str_parametric_drc_instructions->parametric_drc_look_ahead_flag = temp & 1; if (str_parametric_drc_instructions->parametric_drc_look_ahead_flag) { str_parametric_drc_instructions->parametric_drc_look_ahead = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; } else { str_parametric_drc_instructions->parametric_drc_look_ahead = 0; } str_parametric_drc_instructions->parametric_drc_preset_id_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_parametric_drc_instructions->parametric_drc_preset_id_present) { str_parametric_drc_instructions->parametric_drc_preset_id = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; switch (str_parametric_drc_instructions->parametric_drc_preset_id) { case 0: case 1: case 2: case 3: case 4: str_parametric_drc_instructions->drc_characteristic = str_parametric_drc_instructions->parametric_drc_preset_id + 7; str_parametric_drc_instructions->parametric_drc_type = PARAM_DRC_TYPE_FF; str_parametric_drc_instructions->str_parametric_drc_type_feed_forward .level_estim_k_weighting_type = 2; str_parametric_drc_instructions->str_parametric_drc_type_feed_forward .level_estim_integration_time = parametric_drc_frame_size; impd_parametric_drc_ffwd_init_drc_curve_params( str_parametric_drc_instructions->drc_characteristic, &str_parametric_drc_instructions ->str_parametric_drc_type_feed_forward); impd_parametric_drc_ffwd_init_drc_gain_smooth_params( str_parametric_drc_instructions->drc_characteristic, &str_parametric_drc_instructions ->str_parametric_drc_type_feed_forward); break; default: str_parametric_drc_instructions->disable_paramteric_drc = 1; break; } } else { str_parametric_drc_instructions->parametric_drc_type = impd_read_bits_buf(it_bit_buff, 3); if (it_bit_buff->error) return it_bit_buff->error; if (str_parametric_drc_instructions->parametric_drc_type == PARAM_DRC_TYPE_FF) { err = impd_parse_parametric_drc_ffwd( it_bit_buff, parametric_drc_frame_size, &(str_parametric_drc_instructions ->str_parametric_drc_type_feed_forward)); if (err) return (err); str_parametric_drc_instructions->disable_paramteric_drc = str_parametric_drc_instructions->str_parametric_drc_type_feed_forward .disable_paramteric_drc; str_parametric_drc_instructions->drc_characteristic = str_parametric_drc_instructions->str_parametric_drc_type_feed_forward .drc_characteristic; } else if (str_parametric_drc_instructions->parametric_drc_type == PARAM_DRC_TYPE_LIM) { err = impd_parse_parametric_drc_lim( it_bit_buff, &(str_parametric_drc_instructions->parametric_drc_lim)); if (err) return (err); str_parametric_drc_instructions->disable_paramteric_drc = str_parametric_drc_instructions->parametric_drc_lim .disable_paramteric_drc; str_parametric_drc_instructions->drc_characteristic = str_parametric_drc_instructions->parametric_drc_lim .drc_characteristic; if (str_parametric_drc_instructions->parametric_drc_look_ahead_flag) { str_parametric_drc_instructions->parametric_drc_lim .parametric_lim_attack = str_parametric_drc_instructions->parametric_drc_look_ahead; } } else { bit_size_len = impd_read_bits_buf(it_bit_buff, 3) + 4; if (it_bit_buff->error) return it_bit_buff->error; bit_size = impd_read_bits_buf(it_bit_buff, bit_size_len); if (it_bit_buff->error) return it_bit_buff->error; str_parametric_drc_instructions->len_bit_size = bit_size + 1; switch (str_parametric_drc_instructions->parametric_drc_type) { default: str_parametric_drc_instructions->disable_paramteric_drc = 1; for (i = 0; i < str_parametric_drc_instructions->len_bit_size; i++) { other_bit = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; } break; } } } return 0; } WORD32 impd_parse_loud_info_set_ext_eq( ia_bit_buf_struct* it_bit_buff, ia_drc_loudness_info_set_struct* loudness_info_set) { WORD32 err, i, offset, version = 1, temp; WORD32 loudness_info_v1_album_cnt, loudness_info_v1_cnt; temp = impd_read_bits_buf(it_bit_buff, 12); if (it_bit_buff->error) return it_bit_buff->error; loudness_info_v1_album_cnt = (temp >> 6) & 0x3f; loudness_info_v1_cnt = temp & 0x3f; offset = loudness_info_set->loudness_info_album_count; loudness_info_set->loudness_info_album_count += loudness_info_v1_album_cnt; if ((offset + loudness_info_v1_album_cnt) > LOUDNESS_INFO_COUNT_MAX) return (UNEXPECTED_ERROR); for (i = 0; i < loudness_info_v1_album_cnt; i++) { err = impd_parse_loudness_info( it_bit_buff, version, &loudness_info_set->str_loudness_info_album[i + offset]); if (err) return (err); } offset = loudness_info_set->loudness_info_count; loudness_info_set->loudness_info_count += loudness_info_v1_cnt; if (offset + loudness_info_v1_cnt > LOUDNESS_INFO_COUNT_MAX) return (UNEXPECTED_ERROR); for (i = 0; i < loudness_info_v1_cnt; i++) { err = impd_parse_loudness_info( it_bit_buff, version, &loudness_info_set->loudness_info[i + offset]); if (err) return (err); } return (0); } WORD32 impd_parse_ch_layout(ia_bit_buf_struct* it_bit_buff, ia_drc_params_bs_dec_struct* ia_drc_params_struct, ia_channel_layout_struct* channel_layout) { // WORD32 err = 0; WORD32 i; channel_layout->base_channel_count = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; if (channel_layout->base_channel_count > MAX_CHANNEL_COUNT) return (UNEXPECTED_ERROR); if (ia_drc_params_struct->lfe_channel_map_count != -1 && channel_layout->base_channel_count != ia_drc_params_struct->lfe_channel_map_count) { return (UNEXPECTED_ERROR); } channel_layout->layout_signaling_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (channel_layout->layout_signaling_present) { channel_layout->defined_layout = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; if (channel_layout->defined_layout == 0) { for (i = 0; i < channel_layout->base_channel_count; i++) { channel_layout->speaker_position[i] = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; if (channel_layout->speaker_position[i] == 3 || channel_layout->speaker_position[i] == 26) { ia_drc_params_struct->lfe_channel_map[i] = 1; } else { ia_drc_params_struct->lfe_channel_map[i] = 0; } } } } return (0); } WORD32 impd_parse_dwnmix_instructions( ia_bit_buf_struct* it_bit_buff, WORD32 version, ia_drc_params_bs_dec_struct* ia_drc_params_struct, ia_channel_layout_struct* channel_layout, ia_downmix_instructions_struct* dwnmix_instructions) { // WORD32 err = 0; WORD32 i, j, k, temp; temp = impd_read_bits_buf(it_bit_buff, 23); if (it_bit_buff->error) return it_bit_buff->error; dwnmix_instructions->downmix_id = (temp >> 16) & 0x7f; dwnmix_instructions->target_channel_count = (temp >> 9) & 0x7f; if (dwnmix_instructions->target_channel_count > MAX_CHANNEL_COUNT) return (UNEXPECTED_ERROR); dwnmix_instructions->target_layout = (temp >> 1) & 0xff; dwnmix_instructions->downmix_coefficients_present = temp & 1; if (dwnmix_instructions->downmix_coefficients_present) { if (version == 0) { WORD32 dmix_coeff; k = 0; for (i = 0; i < dwnmix_instructions->target_channel_count; i++) { for (j = 0; j < channel_layout->base_channel_count; j++) { dmix_coeff = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; if (k >= DOWNMIX_COEFF_COUNT_MAX) return (UNEXPECTED_ERROR); if (ia_drc_params_struct->lfe_channel_map[j]) { dwnmix_instructions->downmix_coefficient[k] = (FLOAT32)pow(10.0f, 0.05f * dwnmix_coeff_lfe[dmix_coeff]); } else { dwnmix_instructions->downmix_coefficient[k] = (FLOAT32)pow(10.0f, 0.05f * dwnmix_coeff[dmix_coeff]); } k++; } } } else { WORD32 dmix_coeff_v1, bs_dmix_offset; FLOAT32 a, b, dmix_offset, sum; bs_dmix_offset = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; k = 0; for (i = 0; i < dwnmix_instructions->target_channel_count; i++) { for (j = 0; j < channel_layout->base_channel_count; j++) { dmix_coeff_v1 = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; if (k >= DOWNMIX_COEFF_COUNT_MAX) return (UNEXPECTED_ERROR); dwnmix_instructions->downmix_coefficient[k] = dwnmix_coeff_v1[dmix_coeff_v1]; k++; } } switch (bs_dmix_offset) { case 0: dmix_offset = 0.0f; break; case 1: a = 20.0f * (FLOAT32)log10( (FLOAT32)dwnmix_instructions->target_channel_count / (FLOAT32)channel_layout->base_channel_count); dmix_offset = 0.5f * (FLOAT32)floor(0.5f + a); break; case 2: a = 20.0f * (FLOAT32)log10( (FLOAT32)dwnmix_instructions->target_channel_count / (FLOAT32)channel_layout->base_channel_count); dmix_offset = 0.5f * (FLOAT32)floor(0.5f + 2.0f * a); break; case 3: sum = 0.0f; for (k = 0; k < dwnmix_instructions->target_channel_count * channel_layout->base_channel_count; k++) { sum += (FLOAT32)pow( 10.0f, 0.1f * dwnmix_instructions->downmix_coefficient[k]); } b = 10.0f * (FLOAT32)log10(sum); dmix_offset = 0.5f * (FLOAT32)floor(0.5f + 2.0f * b); break; default: return (BITSTREAM_ERROR); break; } for (k = 0; k < dwnmix_instructions->target_channel_count * channel_layout->base_channel_count; k++) { dwnmix_instructions->downmix_coefficient[k] = (FLOAT32)pow( 10.0f, 0.05f * (dwnmix_instructions->downmix_coefficient[k] + dmix_offset)); } } } return (0); } VOID impd_drc_gen_instructions_for_drc_off(ia_drc_config* drc_config) { WORD32 i, k, s; ia_drc_instructions_struct* str_drc_instruction_str; s = -1; k = drc_config->drc_instructions_uni_drc_count; str_drc_instruction_str = &(drc_config->str_drc_instruction_str[k]); memset(str_drc_instruction_str, 0, sizeof(ia_drc_instructions_struct)); str_drc_instruction_str->drc_set_id = s; s--; str_drc_instruction_str->downmix_id[0] = ID_FOR_BASE_LAYOUT; str_drc_instruction_str->dwnmix_id_count = 1; str_drc_instruction_str->drc_apply_to_dwnmix = 0; str_drc_instruction_str->depends_on_drc_set_present = 0; str_drc_instruction_str->no_independent_use = 0; str_drc_instruction_str->gain_element_count = 0; for (i = 1; i < drc_config->dwnmix_instructions_count + 1; i++) { str_drc_instruction_str = &(drc_config->str_drc_instruction_str[k + i]); memset(str_drc_instruction_str, 0, sizeof(ia_drc_instructions_struct)); str_drc_instruction_str->drc_set_id = s; s--; str_drc_instruction_str->drc_set_complexity_level = 0; str_drc_instruction_str->requires_eq = 0; str_drc_instruction_str->downmix_id[0] = drc_config->dwnmix_instructions[i - 1].downmix_id; str_drc_instruction_str->dwnmix_id_count = 1; str_drc_instruction_str->drc_apply_to_dwnmix = 0; str_drc_instruction_str->depends_on_drc_set_present = 0; str_drc_instruction_str->no_independent_use = 0; str_drc_instruction_str->gain_element_count = 0; } drc_config->drc_instructions_count_plus = drc_config->drc_instructions_uni_drc_count + drc_config->dwnmix_instructions_count + 1; return; } WORD32 impd_parse_drc_config_ext(ia_bit_buf_struct* it_bit_buff, ia_drc_params_bs_dec_struct* ia_drc_params_struct, ia_drc_config* drc_config, ia_drc_config_ext* str_drc_config_ext) { WORD32 err = 0, i, k; WORD32 bit_size_len, ext_size_bits, bit_size, other_bit; k = 0; str_drc_config_ext->drc_config_ext_type[k] = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; while (str_drc_config_ext->drc_config_ext_type[k] != UNIDRCCONFEXT_TERM) { if (k >= (EXT_COUNT_MAX - 1)) return UNEXPECTED_ERROR; bit_size_len = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; ext_size_bits = bit_size_len + 4; bit_size = impd_read_bits_buf(it_bit_buff, ext_size_bits); if (it_bit_buff->error) return it_bit_buff->error; str_drc_config_ext->ext_bit_size[k] = bit_size + 1; switch (str_drc_config_ext->drc_config_ext_type[k]) { case UNIDRCCONFEXT_PARAM_DRC: str_drc_config_ext->parametric_drc_present = 1; err = impd_parametic_drc_parse_coeff( it_bit_buff, drc_config, &(str_drc_config_ext->str_drc_coeff_param_drc)); if (err) return (err); str_drc_config_ext->parametric_drc_instructions_count = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; if (str_drc_config_ext->parametric_drc_instructions_count > PARAM_DRC_INSTRUCTIONS_COUNT_MAX) return (UNEXPECTED_ERROR); for (i = 0; i < str_drc_config_ext->parametric_drc_instructions_count; i++) { err = impd_parse_parametric_drc_instructions( it_bit_buff, str_drc_config_ext->str_drc_coeff_param_drc .parametric_drc_frame_size, &(str_drc_config_ext->str_parametric_drc_instructions[i])); if (err) return (err); } break; case UNIDRCCONFEXT_V1: str_drc_config_ext->drc_extension_v1_present = 1; err = impd_parse_drc_ext_v1(it_bit_buff, ia_drc_params_struct, drc_config, str_drc_config_ext); if (err) return (err); break; default: for (i = 0; i < str_drc_config_ext->ext_bit_size[k]; i++) { other_bit = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; } break; } k++; str_drc_config_ext->drc_config_ext_type[k] = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; } return (0); } static WORD32 impd_parse_split_drc_characteristic( ia_bit_buf_struct* it_bit_buff, const WORD32 side, ia_split_drc_characteristic_struct* split_drc_characteristic) { // WORD32 err = 0; WORD32 i, temp; split_drc_characteristic->characteristic_format = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (split_drc_characteristic->characteristic_format == 0) { WORD32 bsGain, bsIoRatio, bsExp; bsGain = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; if (side == LEFT_SIDE) { split_drc_characteristic->gain = (FLOAT32)bsGain; } else { split_drc_characteristic->gain = (FLOAT32)-bsGain; } temp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; bsIoRatio = (temp >> 4) & 0xf; bsExp = temp & 0xf; split_drc_characteristic->in_out_ratio = 0.05f + 0.15f * bsIoRatio; if (bsExp < 15) { split_drc_characteristic->exp = 1.0f + 2.0f * bsExp; } else { split_drc_characteristic->exp = 1000.0f; } split_drc_characteristic->flip_sign = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; } else { WORD32 char_node_cnt, node_level_delta, node_gain; char_node_cnt = impd_read_bits_buf(it_bit_buff, 2); if (it_bit_buff->error) return it_bit_buff->error; split_drc_characteristic->characteristic_node_count = char_node_cnt + 1; split_drc_characteristic->node_level[0] = DRC_INPUT_LOUDNESS_TARGET; split_drc_characteristic->node_gain[0] = 0.0f; for (i = 1; i <= split_drc_characteristic->characteristic_node_count; i++) { node_level_delta = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; if (side == LEFT_SIDE) { split_drc_characteristic->node_level[i] = split_drc_characteristic->node_level[i - 1] - (1.0f + node_level_delta); } else { split_drc_characteristic->node_level[i] = split_drc_characteristic->node_level[i - 1] + (1.0f + node_level_delta); } node_gain = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; split_drc_characteristic->node_gain[i] = 0.5f * node_gain - 64.0f; } } return (0); } WORD32 impd_drc_gen_instructions_derived_data( ia_drc_config* drc_config, ia_drc_params_bs_dec_struct* ia_drc_params_struct, ia_drc_instructions_struct* str_drc_instruction_str) { WORD32 n, g; ia_uni_drc_coeffs_struct* str_p_loc_drc_coefficients_uni_drc = NULL; ia_drc_coeff_parametric_drc_struct* str_drc_coeff_param_drc = NULL; WORD32 gain_element_count = 0; for (n = 0; n < drc_config->drc_coefficients_drc_count; n++) { if (drc_config->str_p_loc_drc_coefficients_uni_drc[n].drc_location == str_drc_instruction_str->drc_location) break; } if ((n == drc_config->drc_coefficients_drc_count) && (drc_config->drc_coefficients_drc_count > 0)) { return -1; } str_p_loc_drc_coefficients_uni_drc = &(drc_config->str_p_loc_drc_coefficients_uni_drc[n]); if (drc_config->drc_config_ext_present && drc_config->str_drc_config_ext.parametric_drc_present && drc_config->str_drc_config_ext.str_drc_coeff_param_drc.drc_location == str_drc_instruction_str->drc_location) { str_drc_coeff_param_drc = &drc_config->str_drc_config_ext.str_drc_coeff_param_drc; } for (g = 0; g < str_drc_instruction_str->num_drc_ch_groups; g++) { WORD32 seq = str_drc_instruction_str->gain_set_index_for_channel_group[g]; if (seq != -1 && (drc_config->drc_coefficients_drc_count == 0 || seq >= str_p_loc_drc_coefficients_uni_drc->gain_set_count)) { str_drc_instruction_str->ch_group_parametric_drc_flag[g] = 1; if (drc_config->drc_coefficients_drc_count != 0) { seq = seq - str_p_loc_drc_coefficients_uni_drc->gain_set_count; } str_drc_instruction_str->gain_set_idx_of_ch_group_parametric_drc[g] = seq; if (str_drc_coeff_param_drc == NULL || seq >= str_drc_coeff_param_drc->parametric_drc_gain_set_count) { /* parametric drc gain set not available */ return (EXTERNAL_ERROR); } str_drc_instruction_str->gain_interpolation_type_for_channel_group[g] = 1; str_drc_instruction_str->time_delta_min_for_channel_group[g] = str_drc_coeff_param_drc->parametric_drc_frame_size; str_drc_instruction_str->time_alignment_for_channel_group[g] = 0; } else { str_drc_instruction_str->ch_group_parametric_drc_flag[g] = 0; } if (str_drc_instruction_str->ch_group_parametric_drc_flag[g] == 0) { if (seq >= str_p_loc_drc_coefficients_uni_drc->gain_set_count) { return -1; } str_drc_instruction_str->gain_interpolation_type_for_channel_group[g] = str_p_loc_drc_coefficients_uni_drc->gain_set_params[seq] .gain_interpolation_type; if (str_p_loc_drc_coefficients_uni_drc->gain_set_params[seq] .time_delt_min_flag) { str_drc_instruction_str->time_delta_min_for_channel_group[g] = str_p_loc_drc_coefficients_uni_drc->gain_set_params[seq] .time_delt_min_val; } else { str_drc_instruction_str->time_delta_min_for_channel_group[g] = ia_drc_params_struct->delta_tmin_default; } str_drc_instruction_str->time_alignment_for_channel_group[g] = str_p_loc_drc_coefficients_uni_drc->gain_set_params[seq] .time_alignment; } } if (str_drc_instruction_str->drc_set_effect & (EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) { str_drc_instruction_str->gain_element_count = str_drc_instruction_str->num_drc_ch_groups; } else { for (g = 0; g < str_drc_instruction_str->num_drc_ch_groups; g++) { if (str_drc_instruction_str->ch_group_parametric_drc_flag[g] == 1) { gain_element_count++; str_drc_instruction_str->band_count_of_ch_group[g] = 1; } else { WORD32 seq, band_count; seq = str_drc_instruction_str->gain_set_index_for_channel_group[g]; band_count = str_p_loc_drc_coefficients_uni_drc->gain_set_params[seq].band_count; str_drc_instruction_str->band_count_of_ch_group[g] = band_count; gain_element_count += band_count; } } str_drc_instruction_str->gain_element_count = gain_element_count; } return (0); } WORD32 impd_parse_drc_config(ia_bit_buf_struct* it_bit_buff, ia_drc_params_bs_dec_struct* ia_drc_params_struct, ia_drc_config* drc_config) { WORD32 i, err = 0, temp; WORD32 version = 0; drc_config->sample_rate_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (drc_config->sample_rate_present == 1) { WORD32 bssample_rate; bssample_rate = impd_read_bits_buf(it_bit_buff, 18); if (it_bit_buff->error) return it_bit_buff->error; drc_config->sampling_rate = bssample_rate + 1000; } temp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; drc_config->dwnmix_instructions_count = (temp >> 1) & 0x7f; if (drc_config->dwnmix_instructions_count > DOWNMIX_INSTRUCTION_COUNT_MAX) return (UNEXPECTED_ERROR); drc_config->drc_description_basic_present = temp & 1; if (drc_config->drc_description_basic_present == 1) { temp = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; drc_config->drc_coefficients_basic_count = (temp >> 4) & 7; drc_config->drc_instructions_basic_count = temp & 0xf; } else { drc_config->drc_coefficients_basic_count = 0; drc_config->drc_instructions_basic_count = 0; } temp = impd_read_bits_buf(it_bit_buff, 9); if (it_bit_buff->error) return it_bit_buff->error; drc_config->drc_coefficients_drc_count = (temp >> 6) & 7; drc_config->drc_instructions_uni_drc_count = temp & 0x3f; if (drc_config->drc_instructions_uni_drc_count > DRC_INSTRUCTIONS_COUNT_MAX) return (UNEXPECTED_ERROR); err = impd_parse_ch_layout(it_bit_buff, ia_drc_params_struct, &drc_config->channel_layout); if (err) return (err); for (i = 0; i < drc_config->dwnmix_instructions_count; i++) { err = impd_parse_dwnmix_instructions( it_bit_buff, version, ia_drc_params_struct, &drc_config->channel_layout, &(drc_config->dwnmix_instructions[i])); if (err) return (err); } for (i = 0; i < drc_config->drc_coefficients_basic_count; i++) { temp = impd_read_bits_buf(it_bit_buff, 11); if (it_bit_buff->error) return it_bit_buff->error; drc_config->str_drc_coefficients_basic[i].drc_location = (temp >> 7) & 0xf; drc_config->str_drc_coefficients_basic[i].drc_characteristic = temp & 0x3f; } for (i = 0; i < drc_config->drc_instructions_basic_count; i++) { err = impd_drc_parse_instructions_basic( it_bit_buff, &(drc_config->str_drc_instructions_basic[i])); if (err) return (err); } for (i = 0; i < drc_config->drc_coefficients_drc_count; i++) { err = impd_drc_parse_coeff( it_bit_buff, version, ia_drc_params_struct, &(drc_config->str_p_loc_drc_coefficients_uni_drc[i])); if (err) return (err); } for (i = 0; i < drc_config->drc_instructions_uni_drc_count; i++) { err = impd_parse_drc_instructions_uni_drc( it_bit_buff, version, drc_config, &(drc_config->str_drc_instruction_str[i])); if (err) return (err); } drc_config->drc_config_ext_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (drc_config->drc_config_ext_present == 1) { err = impd_parse_drc_config_ext(it_bit_buff, ia_drc_params_struct, drc_config, &(drc_config->str_drc_config_ext)); if (err) return (err); } if (drc_config->str_drc_config_ext.parametric_drc_present) { err = impd_parametric_drc_gen_virtual_gain_sets(drc_config); if (err) return (err); } for (i = 0; i < drc_config->drc_instructions_uni_drc_count; i++) { err = impd_drc_gen_instructions_derived_data( drc_config, ia_drc_params_struct, &(drc_config->str_drc_instruction_str[i])); if (err) return (err); } if ((drc_config->drc_instructions_uni_drc_count + drc_config->dwnmix_instructions_count) >= DRC_INSTRUCTIONS_COUNT_MAX) return (UNEXPECTED_ERROR); impd_drc_gen_instructions_for_drc_off(drc_config); return (0); } WORD32 impd_dec_method_value(ia_bit_buf_struct* it_bit_buff, WORD32 method_def, FLOAT32* method_val) { // WORD32 err = 0; WORD32 tmp; FLOAT32 val; switch (method_def) { case METHOD_DEFINITION_UNKNOWN_OTHER: case METHOD_DEFINITION_PROGRAM_LOUDNESS: case METHOD_DEFINITION_ANCHOR_LOUDNESS: case METHOD_DEFINITION_MAX_OF_LOUDNESS_RANGE: case METHOD_DEFINITION_MOMENTARY_LOUDNESS_MAX: case METHOD_DEFINITION_SHORT_TERM_LOUDNESS_MAX: tmp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; val = -57.75f + tmp * 0.25f; break; case METHOD_DEFINITION_LOUDNESS_RANGE: tmp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; if (tmp == 0) val = 0.0f; else if (tmp <= 128) val = tmp * 0.25f; else if (tmp <= 204) val = 0.5f * tmp - 32.0f; else val = tmp - 134.0f; break; case METHOD_DEFINITION_MIXING_LEVEL: tmp = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; val = tmp + 80.0f; break; case METHOD_DEFINITION_ROOM_TYPE: tmp = impd_read_bits_buf(it_bit_buff, 2); if (it_bit_buff->error) return it_bit_buff->error; val = (FLOAT32)tmp; break; case METHOD_DEFINITION_SHORT_TERM_LOUDNESS: tmp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; val = -116.f + tmp * 0.5f; break; default: return -1; break; } *method_val = val; return 0; } WORD32 impd_parse_loudness_info_set( ia_bit_buf_struct* it_bit_buff, ia_drc_loudness_info_set_struct* loudness_info_set) { WORD32 err = 0, i, version = 0, offset, temp; WORD32 loudness_info_album_count, loudness_info_count; temp = impd_read_bits_buf(it_bit_buff, 12); if (it_bit_buff->error) return it_bit_buff->error; loudness_info_album_count = (temp >> 6) & 0x3f; loudness_info_count = temp & 0x3f; offset = loudness_info_set->loudness_info_album_count; loudness_info_set->loudness_info_album_count += loudness_info_album_count; if ((offset + loudness_info_set->loudness_info_album_count) > LOUDNESS_INFO_COUNT_MAX) return (UNEXPECTED_ERROR); for (i = 0; i < loudness_info_set->loudness_info_album_count; i++) { err = impd_parse_loudness_info( it_bit_buff, version, &(loudness_info_set->str_loudness_info_album[i + offset])); if (err) return (err); } offset = loudness_info_set->loudness_info_count; loudness_info_set->loudness_info_count += loudness_info_count; if ((offset + loudness_info_set->loudness_info_count) > LOUDNESS_INFO_COUNT_MAX) return (UNEXPECTED_ERROR); for (i = 0; i < loudness_info_set->loudness_info_count; i++) { err = impd_parse_loudness_info( it_bit_buff, version, &(loudness_info_set->loudness_info[i + offset])); if (err) return (err); } loudness_info_set->loudness_info_set_ext_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (loudness_info_set->loudness_info_set_ext_present == 1) { err = impd_parse_loudness_info_set_ext(it_bit_buff, loudness_info_set); if (err) return (err); } return (0); } WORD32 impd_parse_gain_set_params_characteristics(ia_bit_buf_struct* it_bit_buff, WORD32 version, ia_gain_params_struct* gain_params) { // WORD32 err = 0; WORD32 temp; if (version == 0) { gain_params->drc_characteristic = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; if (gain_params->drc_characteristic > 0) { gain_params->drc_characteristic_present = 1; gain_params->drc_characteristic_format_is_cicp = 1; } else { gain_params->drc_characteristic_present = 0; } } else { gain_params->drc_characteristic_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (gain_params->drc_characteristic_present) { gain_params->drc_characteristic_format_is_cicp = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (gain_params->drc_characteristic_format_is_cicp) { gain_params->drc_characteristic = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; } else { temp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; gain_params->drc_characteristic_left_index = (temp >> 4) & 0xf; gain_params->drc_characteristic_right_index = temp & 0xf; } } } return (0); } WORD32 impd_parse_loudness_measure(ia_bit_buf_struct* it_bit_buff, ia_loudness_measure_struct* loudness_measure) { WORD32 err = 0, temp; loudness_measure->method_def = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; err = impd_dec_method_value(it_bit_buff, loudness_measure->method_def, &(loudness_measure->method_val)); if (err) return err; temp = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; loudness_measure->measurement_system = (temp >> 2) & 0xf; if (loudness_measure->measurement_system > MEASUREMENT_SYSTEM_RESERVED_E) return (UNEXPECTED_ERROR); /* Parsed but unused */ loudness_measure->reliability = temp & 3; return (0); } WORD32 impd_dec_gain_modifiers(ia_bit_buf_struct* it_bit_buff, WORD32 version, WORD32 band_count, ia_gain_modifiers_struct* pstr_gain_modifiers) { // WORD32 err = 0; WORD32 sign, temp; if (version > 0) { WORD32 b; for (b = 0; b < band_count; b++) { pstr_gain_modifiers->target_characteristic_left_present[b] = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (pstr_gain_modifiers->target_characteristic_left_present[b]) { pstr_gain_modifiers->target_characteristic_left_index[b] = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; } pstr_gain_modifiers->target_characteristic_right_present[b] = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (pstr_gain_modifiers->target_characteristic_right_present[b]) { pstr_gain_modifiers->target_characteristic_right_index[b] = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; } pstr_gain_modifiers->gain_scaling_flag[b] = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (pstr_gain_modifiers->gain_scaling_flag[b]) { temp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; pstr_gain_modifiers->attn_scaling[b] = ((temp >> 4) & 0xf) * 0.125f; pstr_gain_modifiers->ampl_scaling[b] = (temp & 0xf) * 0.125f; } pstr_gain_modifiers->gain_offset_flag[b] = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (pstr_gain_modifiers->gain_offset_flag[b]) { FLOAT32 gain_offset; temp = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; sign = ((temp >> 5) & 1); gain_offset = (1 + (temp & 0x1f)) * 0.25f; if (sign) { gain_offset = -gain_offset; } pstr_gain_modifiers->gain_offset[b] = gain_offset; } } if (band_count == 1) { WORD32 tmp; pstr_gain_modifiers->shape_filter_flag = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (pstr_gain_modifiers->shape_filter_flag) { tmp = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; if (tmp >= (SHAPE_FILTER_COUNT_MAX + 1)) return UNEXPECTED_ERROR; pstr_gain_modifiers->shape_filter_idx = tmp; } } } else if (version == 0) { WORD32 b, gain_scaling_flag, gain_offset_flag; FLOAT32 attn_scaling = 1.0f, ampl_scaling = 1.0f, gain_offset = 0.0f; gain_scaling_flag = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (gain_scaling_flag) { temp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; attn_scaling = ((temp >> 4) & 0xf) * 0.125f; ampl_scaling = (temp & 0xf) * 0.125f; } gain_offset_flag = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (gain_offset_flag) { temp = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; sign = ((temp >> 5) & 1); gain_offset = (1 + (temp & 0x1f)) * 0.25f; if (sign) { gain_offset = -gain_offset; } } for (b = 0; b < band_count; b++) { pstr_gain_modifiers->target_characteristic_left_present[b] = 0; pstr_gain_modifiers->target_characteristic_right_present[b] = 0; pstr_gain_modifiers->gain_scaling_flag[b] = gain_scaling_flag; pstr_gain_modifiers->attn_scaling[b] = attn_scaling; pstr_gain_modifiers->ampl_scaling[b] = ampl_scaling; pstr_gain_modifiers->gain_offset_flag[b] = gain_offset_flag; pstr_gain_modifiers->gain_offset[b] = gain_offset; } pstr_gain_modifiers->shape_filter_flag = 0; } return (0); } WORD32 impd_parse_gain_set_params(ia_bit_buf_struct* it_bit_buff, WORD32 version, WORD32* gain_seq_idx, ia_gain_set_params_struct* gain_set_params) { WORD32 err = 0, i, temp; temp = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; gain_set_params->gain_coding_profile = (temp >> 4) & 3; gain_set_params->gain_interpolation_type = (temp >> 3) & 1; gain_set_params->full_frame = (temp >> 2) & 1; gain_set_params->time_alignment = (temp >> 1) & 1; gain_set_params->time_delt_min_flag = temp & 1; if (gain_set_params->time_delt_min_flag) { WORD32 time_delta_min; time_delta_min = impd_read_bits_buf(it_bit_buff, 11); if (it_bit_buff->error) return it_bit_buff->error; gain_set_params->time_delt_min_val = time_delta_min + 1; } if (gain_set_params->gain_coding_profile == GAIN_CODING_PROFILE_CONSTANT) { gain_set_params->band_count = 1; *gain_seq_idx = (*gain_seq_idx) + 1; } else { gain_set_params->band_count = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; if (gain_set_params->band_count > BAND_COUNT_MAX) return (UNEXPECTED_ERROR); if (gain_set_params->band_count > 1) { gain_set_params->drc_band_type = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; } for (i = 0; i < gain_set_params->band_count; i++) { if (version == 0) { *gain_seq_idx = (*gain_seq_idx) + 1; } else { WORD32 indexPresent; indexPresent = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (indexPresent) { WORD32 bsIndex; bsIndex = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; *gain_seq_idx = bsIndex; } else { *gain_seq_idx = (*gain_seq_idx) + 1; } } if (*gain_seq_idx >= SEQUENCE_COUNT_MAX) return UNEXPECTED_ERROR; gain_set_params->gain_params[i].gain_seq_idx = *gain_seq_idx; err = impd_parse_gain_set_params_characteristics( it_bit_buff, version, &(gain_set_params->gain_params[i])); if (err) return (err); } if (gain_set_params->drc_band_type) { for (i = 1; i < gain_set_params->band_count; i++) { gain_set_params->gain_params[i].crossover_freq_idx = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; } } else { for (i = 1; i < gain_set_params->band_count; i++) { gain_set_params->gain_params[i].start_subband_index = impd_read_bits_buf(it_bit_buff, 10); if (it_bit_buff->error) return it_bit_buff->error; } } } return (0); } WORD32 impd_sel_drc_coeff( ia_drc_config* drc_config, WORD32 location, ia_uni_drc_coeffs_struct** str_p_loc_drc_coefficients_uni_drc) { WORD32 n; WORD32 c1 = -1; WORD32 c0 = -1; for (n = 0; n < drc_config->drc_coefficients_drc_count; n++) { if (drc_config->str_p_loc_drc_coefficients_uni_drc[n].drc_location == location) { if (drc_config->str_p_loc_drc_coefficients_uni_drc[n].version == 0) { c0 = n; } else { c1 = n; } } } if (c1 >= 0) { *str_p_loc_drc_coefficients_uni_drc = &(drc_config->str_p_loc_drc_coefficients_uni_drc[c1]); } else if (c0 >= 0) { *str_p_loc_drc_coefficients_uni_drc = &(drc_config->str_p_loc_drc_coefficients_uni_drc[c0]); } else { *str_p_loc_drc_coefficients_uni_drc = NULL; } return (0); } WORD32 impd_parse_loudness_info_set_ext( ia_bit_buf_struct* it_bit_buff, ia_drc_loudness_info_set_struct* loudness_info_set) { WORD32 err = 0, i, k; WORD32 bit_size_len, ext_size_bits, bit_size, other_bit; k = 0; loudness_info_set->str_loudness_info_set_ext.loudness_info_set_ext_type[k] = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; while (loudness_info_set->str_loudness_info_set_ext .loudness_info_set_ext_type[k] != UNIDRCLOUDEXT_TERM) { bit_size_len = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; ext_size_bits = bit_size_len + 4; bit_size = impd_read_bits_buf(it_bit_buff, ext_size_bits); if (it_bit_buff->error) return it_bit_buff->error; if (k >= (EXT_COUNT_MAX - 1)) return UNEXPECTED_ERROR; loudness_info_set->str_loudness_info_set_ext.ext_bit_size[k] = bit_size + 1; switch (loudness_info_set->str_loudness_info_set_ext .loudness_info_set_ext_type[k]) { case UNIDRCLOUDEXT_EQ: err = impd_parse_loud_info_set_ext_eq(it_bit_buff, loudness_info_set); if (err) return (err); break; default: for (i = 0; i < loudness_info_set->str_loudness_info_set_ext.ext_bit_size[k]; i++) { other_bit = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; } break; } k++; loudness_info_set->str_loudness_info_set_ext.loudness_info_set_ext_type[k] = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; } return (0); } WORD32 impd_drc_parse_coeff( ia_bit_buf_struct* it_bit_buff, WORD32 version, ia_drc_params_bs_dec_struct* ia_drc_params_struct, ia_uni_drc_coeffs_struct* str_p_loc_drc_coefficients_uni_drc) { WORD32 err = 0, i, drc_frame_size, temp; WORD32 gain_seq_idx = -1; str_p_loc_drc_coefficients_uni_drc->version = version; if (version == 0) { WORD32 gain_sequence_count = 0; temp = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; str_p_loc_drc_coefficients_uni_drc->drc_location = (temp >> 1) & 0xf; str_p_loc_drc_coefficients_uni_drc->drc_frame_size_present = temp & 1; if (str_p_loc_drc_coefficients_uni_drc->drc_frame_size_present == 1) { drc_frame_size = impd_read_bits_buf(it_bit_buff, 15); if (it_bit_buff->error) return it_bit_buff->error; str_p_loc_drc_coefficients_uni_drc->drc_frame_size = drc_frame_size + 1; if (str_p_loc_drc_coefficients_uni_drc->drc_frame_size > MAX_DRC_FRAME_SIZE) return UNEXPECTED_ERROR; } str_p_loc_drc_coefficients_uni_drc->drc_characteristic_left_present = 0; str_p_loc_drc_coefficients_uni_drc->drc_characteristic_right_present = 0; str_p_loc_drc_coefficients_uni_drc->shape_filters_present = 0; str_p_loc_drc_coefficients_uni_drc->gain_set_count = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; if (str_p_loc_drc_coefficients_uni_drc->gain_set_count > GAIN_SET_COUNT_MAX) return (UNEXPECTED_ERROR); str_p_loc_drc_coefficients_uni_drc->gain_set_count_plus = str_p_loc_drc_coefficients_uni_drc->gain_set_count; for (i = 0; i < str_p_loc_drc_coefficients_uni_drc->gain_set_count; i++) { err = impd_parse_gain_set_params( it_bit_buff, version, &gain_seq_idx, &(str_p_loc_drc_coefficients_uni_drc->gain_set_params[i])); if (err) return (err); if (str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .time_delt_min_flag) { if (str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .time_delt_min_val > ia_drc_params_struct->drc_frame_size) { /* drc time interval too big */ return (PARAM_ERROR); } str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .num_gain_max_values = ia_drc_params_struct->drc_frame_size / str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .time_delt_min_val; if (str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .num_gain_max_values > (N_DELTA_TIME_CODE_TABLE_ENTRIES_MAX / 2 - 1)) return (UNEXPECTED_ERROR); err = impd_init_tbls( str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .num_gain_max_values, &(str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .str_tables)); if (err) return (err); } gain_sequence_count += str_p_loc_drc_coefficients_uni_drc->gain_set_params[i].band_count; } str_p_loc_drc_coefficients_uni_drc->gain_sequence_count = gain_sequence_count; } else { ia_shape_filter_block_params_struct* pstr_shape_filter_block_params; for (i = 0; i < SEQUENCE_COUNT_MAX; i++) { str_p_loc_drc_coefficients_uni_drc ->gain_set_params_index_for_gain_sequence[i] = -1; } temp = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; str_p_loc_drc_coefficients_uni_drc->drc_location = (temp >> 1) & 0xf; str_p_loc_drc_coefficients_uni_drc->drc_frame_size_present = temp & 1; if (str_p_loc_drc_coefficients_uni_drc->drc_frame_size_present == 1) { drc_frame_size = impd_read_bits_buf(it_bit_buff, 15); if (it_bit_buff->error) return it_bit_buff->error; str_p_loc_drc_coefficients_uni_drc->drc_frame_size = drc_frame_size + 1; } str_p_loc_drc_coefficients_uni_drc->drc_characteristic_left_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_p_loc_drc_coefficients_uni_drc->drc_characteristic_left_present == 1) { str_p_loc_drc_coefficients_uni_drc->characteristic_left_count = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; if (str_p_loc_drc_coefficients_uni_drc->characteristic_left_count > SPLIT_CHARACTERISTIC_COUNT_MAX) return (UNEXPECTED_ERROR); for (i = 1; i <= str_p_loc_drc_coefficients_uni_drc->characteristic_left_count; i++) { err = impd_parse_split_drc_characteristic( it_bit_buff, LEFT_SIDE, &(str_p_loc_drc_coefficients_uni_drc ->str_split_characteristic_left[i])); if (err) return (err); } } str_p_loc_drc_coefficients_uni_drc->drc_characteristic_right_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_p_loc_drc_coefficients_uni_drc->drc_characteristic_right_present == 1) { str_p_loc_drc_coefficients_uni_drc->characteristic_right_count = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; if (str_p_loc_drc_coefficients_uni_drc->characteristic_right_count > SPLIT_CHARACTERISTIC_COUNT_MAX) return (UNEXPECTED_ERROR); for (i = 1; i <= str_p_loc_drc_coefficients_uni_drc->characteristic_right_count; i++) { err = impd_parse_split_drc_characteristic( it_bit_buff, RIGHT_SIDE, &(str_p_loc_drc_coefficients_uni_drc ->str_split_characteristic_right[i])); if (err) return (err); } } str_p_loc_drc_coefficients_uni_drc->shape_filters_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_p_loc_drc_coefficients_uni_drc->shape_filters_present == 1) { str_p_loc_drc_coefficients_uni_drc->shape_num_filter = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; if (str_p_loc_drc_coefficients_uni_drc->shape_num_filter > SHAPE_FILTER_COUNT_MAX) return (UNEXPECTED_ERROR); for (i = 1; i <= str_p_loc_drc_coefficients_uni_drc->shape_num_filter; i++) { pstr_shape_filter_block_params = &(str_p_loc_drc_coefficients_uni_drc ->str_shape_filter_block_params[i]); pstr_shape_filter_block_params->lf_cut_filter_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (pstr_shape_filter_block_params->lf_cut_filter_present == 1) { temp = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; pstr_shape_filter_block_params->str_lf_cut_params.corner_freq_index = (temp >> 2) & 7; pstr_shape_filter_block_params->str_lf_cut_params .filter_strength_index = temp & 3; } pstr_shape_filter_block_params->lf_boost_filter_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (pstr_shape_filter_block_params->lf_boost_filter_present == 1) { temp = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; pstr_shape_filter_block_params->str_lf_boost_params .corner_freq_index = (temp >> 2) & 7; pstr_shape_filter_block_params->str_lf_boost_params .filter_strength_index = temp & 3; } pstr_shape_filter_block_params->hf_cut_filter_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (pstr_shape_filter_block_params->hf_cut_filter_present == 1) { temp = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; pstr_shape_filter_block_params->str_hfCutParams.corner_freq_index = (temp >> 2) & 7; pstr_shape_filter_block_params->str_hfCutParams .filter_strength_index = temp & 3; } pstr_shape_filter_block_params->hf_boost_filter_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (pstr_shape_filter_block_params->hf_boost_filter_present == 1) { temp = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; pstr_shape_filter_block_params->str_hf_boost_params .corner_freq_index = (temp >> 2) & 7; pstr_shape_filter_block_params->str_hf_boost_params .filter_strength_index = temp & 3; } } } temp = impd_read_bits_buf(it_bit_buff, 12); if (it_bit_buff->error) return it_bit_buff->error; str_p_loc_drc_coefficients_uni_drc->gain_sequence_count = (temp >> 6) & 0x3f; if (str_p_loc_drc_coefficients_uni_drc->gain_sequence_count > SEQUENCE_COUNT_MAX) return UNEXPECTED_ERROR; str_p_loc_drc_coefficients_uni_drc->gain_set_count = temp & 0x3f; if (str_p_loc_drc_coefficients_uni_drc->gain_set_count > GAIN_SET_COUNT_MAX) return (UNEXPECTED_ERROR); str_p_loc_drc_coefficients_uni_drc->gain_set_count_plus = str_p_loc_drc_coefficients_uni_drc->gain_set_count; for (i = 0; i < str_p_loc_drc_coefficients_uni_drc->gain_set_count; i++) { err = impd_parse_gain_set_params( it_bit_buff, version, &gain_seq_idx, &(str_p_loc_drc_coefficients_uni_drc->gain_set_params[i])); if (err) return (err); if (str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .time_delt_min_flag) { if (str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .time_delt_min_val > ia_drc_params_struct->drc_frame_size) { /* drc time interval too big */ return (PARAM_ERROR); } str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .num_gain_max_values = ia_drc_params_struct->drc_frame_size / str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .time_delt_min_val; if (str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .num_gain_max_values > (N_DELTA_TIME_CODE_TABLE_ENTRIES_MAX / 2 - 1)) return (UNEXPECTED_ERROR); err = impd_init_tbls( str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .num_gain_max_values, &(str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .str_tables)); if (err) return (err); } } for (i = 0; i < str_p_loc_drc_coefficients_uni_drc->gain_set_count; i++) { WORD32 b; for (b = 0; b < str_p_loc_drc_coefficients_uni_drc->gain_set_params[i].band_count; b++) { str_p_loc_drc_coefficients_uni_drc ->gain_set_params_index_for_gain_sequence [str_p_loc_drc_coefficients_uni_drc->gain_set_params[i] .gain_params[b] .gain_seq_idx] = i; } } } return (0); } WORD32 impd_drc_parse_instructions_basic( ia_bit_buf_struct* it_bit_buff, ia_drc_instructions_basic_struct* str_drc_instructions_basic) { // WORD32 err = 0; WORD32 i, limiter_peak_target, temp; WORD32 additional_dmix_id_present, additional_dmix_id_cnt; temp = impd_read_bits_buf(it_bit_buff, 18); if (it_bit_buff->error) return it_bit_buff->error; str_drc_instructions_basic->drc_set_id = (temp >> 12) & 0x3f; str_drc_instructions_basic->drc_location = (temp >> 8) & 0xf; str_drc_instructions_basic->downmix_id[0] = (temp >> 1) & 0x7f; additional_dmix_id_present = temp & 1; str_drc_instructions_basic->dwnmix_id_count = 1; if (additional_dmix_id_present) { additional_dmix_id_cnt = impd_read_bits_buf(it_bit_buff, 3); if (it_bit_buff->error) return it_bit_buff->error; for (i = 0; i < additional_dmix_id_cnt; i++) { str_drc_instructions_basic->downmix_id[i + 1] = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; } str_drc_instructions_basic->dwnmix_id_count = 1 + additional_dmix_id_cnt; } str_drc_instructions_basic->drc_set_effect = impd_read_bits_buf(it_bit_buff, 16); if (it_bit_buff->error) return it_bit_buff->error; if ((str_drc_instructions_basic->drc_set_effect & (EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) == 0) { str_drc_instructions_basic->limiter_peak_target_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_drc_instructions_basic->limiter_peak_target_present) { limiter_peak_target = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; str_drc_instructions_basic->limiter_peak_target = -limiter_peak_target * 0.125f; } } str_drc_instructions_basic->drc_set_target_loudness_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; str_drc_instructions_basic->drc_set_target_loudness_value_upper = 0; str_drc_instructions_basic->drc_set_target_loudness_value_lower = -63; if (str_drc_instructions_basic->drc_set_target_loudness_present == 1) { WORD32 bsDrcSetTargetLoudnessValueUpper, bsDrcSetTargetLoudnessValueLower; bsDrcSetTargetLoudnessValueUpper = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; str_drc_instructions_basic->drc_set_target_loudness_value_upper = bsDrcSetTargetLoudnessValueUpper - 63; str_drc_instructions_basic->drc_set_target_loudness_value_lower_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_drc_instructions_basic ->drc_set_target_loudness_value_lower_present == 1) { bsDrcSetTargetLoudnessValueLower = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; str_drc_instructions_basic->drc_set_target_loudness_value_lower = bsDrcSetTargetLoudnessValueLower - 63; } } return (0); } WORD32 impd_dec_ducking_scaling(ia_bit_buf_struct* it_bit_buff, WORD32* ducking_scaling_flag, FLOAT32* p_ducking_scaling) { WORD32 ducking_scaling_present, ducking_scaling, sigma, mu; ducking_scaling_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (ducking_scaling_present == 0) { *ducking_scaling_flag = 0; *p_ducking_scaling = 1.0f; } else { *ducking_scaling_flag = 1; ducking_scaling = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; sigma = ducking_scaling >> 3; mu = ducking_scaling & 0x7; if (sigma == 0) { *p_ducking_scaling = 1.0f + 0.125f * (1.0f + mu); } else { *p_ducking_scaling = 1.0f - 0.125f * (1.0f + mu); } } return (0); } WORD32 impd_parse_drc_instructions_uni_drc( ia_bit_buf_struct* it_bit_buff, WORD32 version, ia_drc_config* drc_config, ia_drc_instructions_struct* str_drc_instruction_str) { WORD32 err = 0, i, n, k, g, c, limiter_peak_target, idx; WORD32 additional_dmix_id_present, additional_dmix_id_cnt; ia_uni_drc_coeffs_struct* str_p_loc_drc_coefficients_uni_drc = NULL; WORD32 ch_cnt; WORD32 unique_idx[MAX_CHANNEL_COUNT]; FLOAT32 unique_scaling[MAX_CHANNEL_COUNT]; WORD32 match; WORD32 dmix_id_present; WORD32 repeat_parameters, repeat_parameters_cnt; WORD32 ducking_sequence; FLOAT32 factor; str_drc_instruction_str->drc_set_id = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; if (str_drc_instruction_str->drc_set_id >= DRC_INSTRUCTIONS_COUNT_MAX) return UNEXPECTED_ERROR; if (version == 0) { str_drc_instruction_str->drc_set_complexity_level = DRC_COMPLEXITY_LEVEL_MAX; } else { str_drc_instruction_str->drc_set_complexity_level = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; } str_drc_instruction_str->drc_location = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; dmix_id_present = 1; if (version >= 1) { dmix_id_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; } if (dmix_id_present == 1) { str_drc_instruction_str->downmix_id[0] = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; if (version >= 1) { str_drc_instruction_str->drc_apply_to_dwnmix = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; } if (version == 0) { if (str_drc_instruction_str->downmix_id[0] == 0) { str_drc_instruction_str->drc_apply_to_dwnmix = 0; } else { str_drc_instruction_str->drc_apply_to_dwnmix = 1; } } additional_dmix_id_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (additional_dmix_id_present) { additional_dmix_id_cnt = impd_read_bits_buf(it_bit_buff, 3); if (it_bit_buff->error) return it_bit_buff->error; for (i = 0; i < additional_dmix_id_cnt; i++) { str_drc_instruction_str->downmix_id[i + 1] = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; } str_drc_instruction_str->dwnmix_id_count = 1 + additional_dmix_id_cnt; } else { str_drc_instruction_str->dwnmix_id_count = 1; } } else { str_drc_instruction_str->downmix_id[0] = 0; str_drc_instruction_str->dwnmix_id_count = 1; } str_drc_instruction_str->drc_set_effect = impd_read_bits_buf(it_bit_buff, 16); if (it_bit_buff->error) return it_bit_buff->error; if ((str_drc_instruction_str->drc_set_effect & (EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) == 0) { str_drc_instruction_str->limiter_peak_target_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_drc_instruction_str->limiter_peak_target_present) { limiter_peak_target = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; str_drc_instruction_str->limiter_peak_target = -limiter_peak_target * 0.125f; } } str_drc_instruction_str->drc_set_target_loudness_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; str_drc_instruction_str->drc_set_target_loudness_value_upper = 0; str_drc_instruction_str->drc_set_target_loudness_value_lower = -63; if (str_drc_instruction_str->drc_set_target_loudness_present == 1) { WORD32 bsDrcSetTargetLoudnessValueUpper, bsDrcSetTargetLoudnessValueLower; bsDrcSetTargetLoudnessValueUpper = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; str_drc_instruction_str->drc_set_target_loudness_value_upper = bsDrcSetTargetLoudnessValueUpper - 63; str_drc_instruction_str->drc_set_target_loudness_value_lower_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_drc_instruction_str->drc_set_target_loudness_value_lower_present == 1) { bsDrcSetTargetLoudnessValueLower = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; str_drc_instruction_str->drc_set_target_loudness_value_lower = bsDrcSetTargetLoudnessValueLower - 63; } } str_drc_instruction_str->depends_on_drc_set_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; str_drc_instruction_str->no_independent_use = 0; if (str_drc_instruction_str->depends_on_drc_set_present) { str_drc_instruction_str->depends_on_drc_set = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; } else { str_drc_instruction_str->no_independent_use = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; } if (version == 0) { str_drc_instruction_str->requires_eq = 0; } else { str_drc_instruction_str->requires_eq = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; } err = impd_sel_drc_coeff(drc_config, str_drc_instruction_str->drc_location, &str_p_loc_drc_coefficients_uni_drc); if (err) return (err); ch_cnt = drc_config->channel_layout.base_channel_count; if (ch_cnt > MAX_CHANNEL_COUNT) return (UNEXPECTED_ERROR); for (c = 0; c < MAX_CHANNEL_COUNT; c++) { unique_idx[c] = -10; unique_scaling[c] = -10.0f; } if (str_drc_instruction_str->drc_set_effect & (EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) { c = 0; while (c < ch_cnt) { WORD32 bs_gain_set_idx; bs_gain_set_idx = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; if (bs_gain_set_idx > GAIN_SET_COUNT_MAX) return UNEXPECTED_ERROR; str_drc_instruction_str->gain_set_index[c] = bs_gain_set_idx - 1; impd_dec_ducking_scaling( it_bit_buff, &(str_drc_instruction_str->str_ducking_modifiers_for_channel[c] .ducking_scaling_flag), &(str_drc_instruction_str->str_ducking_modifiers_for_channel[c] .ducking_scaling)); c++; repeat_parameters = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (repeat_parameters == 1) { repeat_parameters_cnt = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; repeat_parameters_cnt += 1; if ((c + repeat_parameters_cnt) > MAX_CHANNEL_COUNT) return (UNEXPECTED_ERROR); for (k = 0; k < repeat_parameters_cnt; k++) { str_drc_instruction_str->gain_set_index[c] = str_drc_instruction_str->gain_set_index[c - 1]; str_drc_instruction_str->str_ducking_modifiers_for_channel[c] = str_drc_instruction_str->str_ducking_modifiers_for_channel[c - 1]; c++; } } } if (c > ch_cnt) { return (UNEXPECTED_ERROR); } ducking_sequence = -1; g = 0; if (str_drc_instruction_str->drc_set_effect & EFFECT_BIT_DUCK_OTHER) { for (c = 0; c < ch_cnt; c++) { match = 0; idx = str_drc_instruction_str->gain_set_index[c]; factor = str_drc_instruction_str->str_ducking_modifiers_for_channel[c] .ducking_scaling; if (idx < 0) { for (n = 0; n < g; n++) { if (unique_scaling[n] == factor) { match = 1; str_drc_instruction_str->channel_group_of_ch[c] = n; break; } } if (match == 0) { unique_idx[g] = idx; unique_scaling[g] = factor; str_drc_instruction_str->channel_group_of_ch[c] = g; g++; } } else { if ((ducking_sequence > 0) && (ducking_sequence != idx)) { /* drc for ducking can have only one ducking sequence */ return (UNEXPECTED_ERROR); } ducking_sequence = idx; str_drc_instruction_str->channel_group_of_ch[c] = -1; } } str_drc_instruction_str->num_drc_ch_groups = g; if (ducking_sequence == -1) { /* ducking sequence not found */ return (UNEXPECTED_ERROR); } } else if (str_drc_instruction_str->drc_set_effect & EFFECT_BIT_DUCK_SELF) { for (c = 0; c < ch_cnt; c++) { match = 0; idx = str_drc_instruction_str->gain_set_index[c]; factor = str_drc_instruction_str->str_ducking_modifiers_for_channel[c] .ducking_scaling; if (idx >= 0) { for (n = 0; n < g; n++) { if ((unique_idx[n] == idx) && (unique_scaling[n] == factor)) { match = 1; str_drc_instruction_str->channel_group_of_ch[c] = n; break; } } if (match == 0) { unique_idx[g] = idx; unique_scaling[g] = factor; str_drc_instruction_str->channel_group_of_ch[c] = g; g++; } } else { str_drc_instruction_str->channel_group_of_ch[c] = -1; } } str_drc_instruction_str->num_drc_ch_groups = g; } if (str_drc_instruction_str->num_drc_ch_groups > min(CHANNEL_GROUP_COUNT_MAX, MAX_CHANNEL_COUNT)) return UNEXPECTED_ERROR; for (g = 0; g < str_drc_instruction_str->num_drc_ch_groups; g++) { WORD32 set = (str_drc_instruction_str->drc_set_effect & EFFECT_BIT_DUCK_OTHER) ? ducking_sequence : unique_idx[g]; if (set < 0) return UNEXPECTED_ERROR; str_drc_instruction_str->gain_set_index_for_channel_group[g] = set; str_drc_instruction_str->str_ducking_modifiers_for_channel_group[g] .ducking_scaling = unique_scaling[g]; if (unique_scaling[g] != 1.0f) { str_drc_instruction_str->str_ducking_modifiers_for_channel_group[g] .ducking_scaling_flag = 1; } else { str_drc_instruction_str->str_ducking_modifiers_for_channel_group[g] .ducking_scaling_flag = 0; } str_drc_instruction_str->band_count_of_ch_group[g] = 1; } } else { if (((version == 0) || (str_drc_instruction_str->drc_apply_to_dwnmix != 0)) && (str_drc_instruction_str->downmix_id[0] != 0) && (str_drc_instruction_str->downmix_id[0] != ID_FOR_ANY_DOWNMIX) && (str_drc_instruction_str->dwnmix_id_count == 1)) { for (i = 0; i < drc_config->dwnmix_instructions_count; i++) { if (str_drc_instruction_str->downmix_id[0] == drc_config->dwnmix_instructions[i].downmix_id) break; } if (i == drc_config->dwnmix_instructions_count) { /* dwnmix_instructions not found */ return (UNEXPECTED_ERROR); } ch_cnt = drc_config->dwnmix_instructions[i].target_channel_count; } else if (((version == 0) || (str_drc_instruction_str->drc_apply_to_dwnmix != 0)) && ((str_drc_instruction_str->downmix_id[0] == ID_FOR_ANY_DOWNMIX) || (str_drc_instruction_str->dwnmix_id_count > 1))) { ch_cnt = 1; } if (ch_cnt > MAX_CHANNEL_COUNT) return (UNEXPECTED_ERROR); c = 0; while (c < ch_cnt) { WORD32 bs_gain_set_idx; WORD32 repeat_gain_set_idx, repeat_gain_set_idx_cnt, temp; temp = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; bs_gain_set_idx = (temp >> 1) & 0x7f; repeat_gain_set_idx = temp & 1; if (bs_gain_set_idx > GAIN_SET_COUNT_MAX) return UNEXPECTED_ERROR; str_drc_instruction_str->gain_set_index[c] = bs_gain_set_idx - 1; c++; if (repeat_gain_set_idx == 1) { repeat_gain_set_idx_cnt = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; repeat_gain_set_idx_cnt += 1; if ((c + repeat_gain_set_idx_cnt) > MAX_CHANNEL_COUNT) return (UNEXPECTED_ERROR); for (k = 0; k < repeat_gain_set_idx_cnt; k++) { str_drc_instruction_str->gain_set_index[c] = bs_gain_set_idx - 1; c++; } } } if (c > ch_cnt) { return (UNEXPECTED_ERROR); } g = 0; if ((str_drc_instruction_str->downmix_id[0] == ID_FOR_ANY_DOWNMIX) || (str_drc_instruction_str->dwnmix_id_count > 1)) { WORD32 idx = str_drc_instruction_str->gain_set_index[0]; if (idx >= 0) { unique_idx[0] = idx; g = 1; } } else { for (c = 0; c < ch_cnt; c++) { WORD32 idx = str_drc_instruction_str->gain_set_index[c]; match = 0; if (idx >= 0) { for (n = 0; n < g; n++) { if (unique_idx[n] == idx) { match = 1; str_drc_instruction_str->channel_group_of_ch[c] = n; break; } } if (match == 0) { unique_idx[g] = idx; str_drc_instruction_str->channel_group_of_ch[c] = g; g++; } } else { str_drc_instruction_str->channel_group_of_ch[c] = -1; } } } str_drc_instruction_str->num_drc_ch_groups = g; if (str_drc_instruction_str->num_drc_ch_groups > min(CHANNEL_GROUP_COUNT_MAX, MAX_CHANNEL_COUNT)) return UNEXPECTED_ERROR; for (g = 0; g < str_drc_instruction_str->num_drc_ch_groups; g++) { WORD32 set, band_count; set = unique_idx[g]; if (set < 0) return UNEXPECTED_ERROR; str_drc_instruction_str->gain_set_index_for_channel_group[g] = set; if (str_p_loc_drc_coefficients_uni_drc != NULL && set < str_p_loc_drc_coefficients_uni_drc->gain_set_count) { band_count = str_p_loc_drc_coefficients_uni_drc->gain_set_params[set].band_count; } else { band_count = 1; } err = impd_dec_gain_modifiers( it_bit_buff, version, band_count, &(str_drc_instruction_str->str_gain_modifiers_of_ch_group[g])); if (err) return (err); } } return (0); } WORD32 impd_parse_loudness_info(ia_bit_buf_struct* it_bit_buff, WORD32 version, ia_loudness_info_struct* loudness_info) { WORD32 err = 0, sample_peak_level, true_peak_level, i, temp; loudness_info->drc_set_id = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; if (version >= 1) { loudness_info->eq_set_id = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; } else { loudness_info->eq_set_id = 0; } temp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; loudness_info->downmix_id = (temp >> 1) & 0x7f; loudness_info->sample_peak_level_present = temp & 1; if (loudness_info->sample_peak_level_present) { sample_peak_level = impd_read_bits_buf(it_bit_buff, 12); if (it_bit_buff->error) return it_bit_buff->error; if (sample_peak_level == 0) { loudness_info->sample_peak_level_present = 0; loudness_info->sample_peak_level = 0.0f; } else { loudness_info->sample_peak_level = 20.0f - sample_peak_level * 0.03125f; } } loudness_info->true_peak_level_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (loudness_info->true_peak_level_present) { true_peak_level = impd_read_bits_buf(it_bit_buff, 12); if (it_bit_buff->error) return it_bit_buff->error; if (true_peak_level == 0) { loudness_info->true_peak_level_present = 0; loudness_info->true_peak_level = 0.0f; } else { loudness_info->true_peak_level = 20.0f - true_peak_level * 0.03125f; } temp = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; /* Parsed but unused */ loudness_info->true_peak_level_measurement_system = (temp >> 2) & 0xf; /* Parsed but unused */ loudness_info->true_peak_level_reliability = temp & 3; } loudness_info->measurement_count = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; for (i = 0; i < loudness_info->measurement_count; i++) { err = impd_parse_loudness_measure(it_bit_buff, &(loudness_info->loudness_measure[i])); if (err) return (err); } return (0); }