/****************************************************************************** * * Copyright (C) 2018 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ***************************************************************************** * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore */ #include <stdio.h> #include <string.h> #include <math.h> #include "impd_type_def.h" #include "impd_drc_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" WORD32 impd_parse_loud_eq_instructions( ia_bit_buf_struct* it_bit_buff, ia_loud_eq_instructions_struct* loud_eq_instructions); WORD32 impd_parse_eq_coefficients(ia_bit_buf_struct* it_bit_buff, ia_eq_coeff_struct* str_eq_coeff); WORD32 impd_parse_eq_instructions( ia_bit_buf_struct* it_bit_buff, ia_drc_config* drc_config, ia_eq_instructions_struct* str_eq_instructions); WORD32 impd_dec_initial_gain(ia_bit_buf_struct* it_bit_buff, const WORD32 gain_coding_profile, FLOAT32* initial_gain) { WORD32 sign, magn, bit_2_extract; switch (gain_coding_profile) { case GAIN_CODING_PROFILE_REGULAR: sign = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; magn = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; *initial_gain = magn * 0.125f; if (sign) *initial_gain = -*initial_gain; break; case GAIN_CODING_PROFILE_FADING: case GAIN_CODING_PROFILE_CLIPPING: bit_2_extract = (gain_coding_profile == GAIN_CODING_PROFILE_FADING) ? 10 : 8; sign = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (sign == 0) *initial_gain = 0.0f; else { magn = impd_read_bits_buf(it_bit_buff, bit_2_extract); if (it_bit_buff->error) return it_bit_buff->error; *initial_gain = -(magn + 1) * 0.125f; } break; case GAIN_CODING_PROFILE_CONSTANT: break; default: return (UNEXPECTED_ERROR); } return (0); } WORD32 impd_dec_gains(ia_bit_buf_struct* it_bit_buff, WORD32 no_nodes, WORD32 gain_coding_profile, ia_node_struct* str_node) { WORD32 err = 0, k, e, m; WORD32 bit; WORD32 num_bits_read; WORD32 code; WORD32 code_found; FLOAT32 drc_gain_delta = 0; const ia_delta_gain_code_table_struct* ptr_delta_gain_code_table; WORD32 no_delta_gain_entries; err = impd_dec_initial_gain(it_bit_buff, gain_coding_profile, &(str_node[0].loc_db_gain)); if (err) return (err); impd_get_delta_gain_code_tbl(gain_coding_profile, &ptr_delta_gain_code_table, &no_delta_gain_entries); for (k = 1; k < no_nodes; k++) { num_bits_read = 0; code = 0; code_found = 0; e = 0; while ((e < no_delta_gain_entries) && (!code_found)) { for (m = 0; m < ptr_delta_gain_code_table[e].size - num_bits_read; m++) { bit = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; code = (code << 1) + bit; num_bits_read++; } while (num_bits_read == ptr_delta_gain_code_table[e].size) { if (code == ptr_delta_gain_code_table[e].code) { drc_gain_delta = ptr_delta_gain_code_table[e].value; code_found = 1; break; } e++; } } if (code_found == 0) { return (UNEXPECTED_ERROR); } str_node[k].loc_db_gain = str_node[k - 1].loc_db_gain + drc_gain_delta; } return (0); } WORD32 impd_dec_slopes(ia_bit_buf_struct* it_bit_buff, WORD32* no_nodes, WORD32 gain_interpolation_type, ia_node_struct* str_node) { WORD32 k, e, m, bit; WORD32 code; WORD32 code_found; FLOAT32 slope_value = 0; bool end_marker = 0; WORD32 num_bits_read; const ia_slope_code_table_struct* ptr_slope_code_table; WORD32 no_slope_code_entries; ptr_slope_code_table = &(slope_code_tbl_entries_by_size[0]); no_slope_code_entries = NUM_SLOPE_TBL_ENTRIES; k = 0; while (end_marker != 1) { k++; end_marker = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; } *no_nodes = k; if (gain_interpolation_type == GAIN_INTERPOLATION_TYPE_SPLINE) { for (k = 0; k < *no_nodes; k++) { num_bits_read = 0; code = 0; code_found = 0; e = 0; while ((e < no_slope_code_entries) && (!code_found)) { for (m = 0; m < ptr_slope_code_table[e].size - num_bits_read; m++) { bit = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; code = (code << 1) + bit; num_bits_read++; } while (num_bits_read == ptr_slope_code_table[e].size) { if (code == ptr_slope_code_table[e].code) { slope_value = ptr_slope_code_table[e].value; code_found = 1; break; } e++; } } str_node[k].slope = slope_value; } } else { for (k = 0; k < *no_nodes; k++) { str_node[k].slope = 0.0f; } } return (0); } WORD32 impd_dec_times(ia_bit_buf_struct* it_bit_buff, ia_tables_struct* str_tables, WORD32 num_nodes, WORD32 delta_tmin, WORD32 drc_frame_size, WORD32 full_frame, WORD32 time_offset, ia_node_struct* str_node) { WORD32 k, e, m; WORD32 bit; WORD32 num_bits_read; WORD32 code; WORD32 code_found = 0; WORD32 time_delta = 0; WORD32 time_offs = time_offset; ia_delta_time_code_table_entry_struct* delta_time_code_table = str_tables->delta_time_code_table; bool frame_end_flag; WORD32 node_time_tmp; bool node_res_flag; WORD32 exit_cnt; if (full_frame == 0) { frame_end_flag = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; } else { frame_end_flag = 1; } if (frame_end_flag == 1) { node_res_flag = 0; for (k = 0; k < num_nodes - 1; k++) { num_bits_read = 0; code = 0; code_found = 0; exit_cnt = 0; e = 1; while ((e < N_DELTA_TIME_CODE_TABLE_ENTRIES_MAX) && (!code_found)) { exit_cnt++; if (exit_cnt > 100000) { return -1; } for (m = 0; m < delta_time_code_table[e].size - num_bits_read; m++) { bit = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; code = (code << 1) + bit; num_bits_read++; } while (num_bits_read == delta_time_code_table[e].size) { if (code == delta_time_code_table[e].code) { time_delta = delta_time_code_table[e].value; code_found = 1; break; } e++; } } node_time_tmp = time_offs + time_delta * delta_tmin; if (node_time_tmp > drc_frame_size + time_offset) { if (node_res_flag == 0) { str_node[k].time = drc_frame_size + time_offset; node_res_flag = 1; } str_node[k + 1].time = node_time_tmp; } else { str_node[k].time = node_time_tmp; } time_offs = node_time_tmp; } if (node_res_flag == 0) { str_node[k].time = drc_frame_size + time_offset; } } else { for (k = 0; k < num_nodes; k++) { num_bits_read = 0; code = 0; code_found = 0; e = 1; exit_cnt = 0; while ((e < N_DELTA_TIME_CODE_TABLE_ENTRIES_MAX) && (!code_found)) { exit_cnt++; if (exit_cnt > 100000) { return (BITSTREAM_ERROR); } for (m = 0; m < delta_time_code_table[e].size - num_bits_read; m++) { bit = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; code = (code << 1) + bit; num_bits_read++; } while (num_bits_read == delta_time_code_table[e].size) { if (code == delta_time_code_table[e].code) { time_delta = delta_time_code_table[e].value; code_found = 1; break; } e++; } } str_node[k].time = time_offs + time_delta * delta_tmin; time_offs = str_node[k].time; } } return (0); } WORD32 impd_drc_uni_gain_read(ia_bit_buf_struct* it_bit_buff, ia_drc_bits_dec_struct* pstr_drc_uni_bs_dec, ia_drc_config* drc_config, ia_drc_gain_struct* pstr_uni_drc_gain) { WORD32 err = 0; WORD32 seq; static WORD32 pkt_loss_frame_cnt = 0; ia_spline_nodes_struct* str_spline_nodes = {0}; { WORD32 gain_sequence_count = drc_config->str_p_loc_drc_coefficients_uni_drc[0].gain_sequence_count; for (seq = 0; seq < gain_sequence_count; seq++) { WORD32 index = drc_config->str_p_loc_drc_coefficients_uni_drc[0] .gain_set_params_index_for_gain_sequence[seq]; ia_gain_set_params_struct* gain_set_params = &(drc_config->str_p_loc_drc_coefficients_uni_drc ->gain_set_params[index]); if (gain_set_params->gain_coding_profile == GAIN_CODING_PROFILE_CONSTANT) { str_spline_nodes = &(pstr_uni_drc_gain->drc_gain_sequence[seq].str_spline_nodes[0]); str_spline_nodes->num_nodes = 1; str_spline_nodes->str_node[0].slope = 0.0; str_spline_nodes->str_node[0].time = (pstr_drc_uni_bs_dec->ia_drc_params_struct).drc_frame_size - 1; str_spline_nodes->str_node[0].loc_db_gain = 0.0f; } else { err = impd_parse_drc_gain_sequence( it_bit_buff, pstr_drc_uni_bs_dec, gain_set_params, &(pstr_uni_drc_gain->drc_gain_sequence[seq])); if (err) return (err); } } } if (it_bit_buff->ptr_bit_buf_base == NULL) { pkt_loss_frame_cnt++; if (pkt_loss_frame_cnt * (FLOAT32)pstr_drc_uni_bs_dec->ia_drc_params_struct.drc_frame_size / drc_config->sampling_rate > MAXPACKETLOSSTIME) { drc_config->apply_drc = 0; } } else { pstr_uni_drc_gain->uni_drc_gain_ext_flag = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (pstr_uni_drc_gain->uni_drc_gain_ext_flag == 1) { err = impd_parse_uni_drc_gain_ext(it_bit_buff, &(pstr_uni_drc_gain->uni_drc_gain_ext)); if (err) return (err); } pkt_loss_frame_cnt = 0; drc_config->apply_drc = 1; } return (0); } WORD32 impd_parse_uni_drc_gain_ext( ia_bit_buf_struct* it_bit_buff, ia_uni_drc_gain_ext_struct* uni_drc_gain_ext) { WORD32 i, k; WORD32 bit_size_len, ext_size_bits, bit_size, other_bit; k = 0; uni_drc_gain_ext->uni_drc_gain_ext_type[k] = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; while (uni_drc_gain_ext->uni_drc_gain_ext_type[k] != UNIDRCGAINEXT_TERM) { bit_size_len = impd_read_bits_buf(it_bit_buff, 3); 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; uni_drc_gain_ext->ext_bit_size[k] = bit_size + 1; switch (uni_drc_gain_ext->uni_drc_gain_ext_type[k]) { default: for (i = 0; i < uni_drc_gain_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++; uni_drc_gain_ext->uni_drc_gain_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_parse_spline_nodes(ia_bit_buf_struct* it_bit_buff, ia_drc_bits_dec_struct* pstr_drc_uni_bs_dec, ia_gain_set_params_struct* gain_set_params, ia_spline_nodes_struct* str_spline_nodes) { WORD32 err = 0; WORD32 time_offset; if (gain_set_params->time_alignment == 0) { time_offset = -1; } else { if (gain_set_params->time_delt_min_flag) { time_offset = -gain_set_params->time_delt_min_val + (gain_set_params->time_delt_min_val - 1) / 2; } else { time_offset = -pstr_drc_uni_bs_dec->ia_drc_params_struct.delta_tmin_default + (pstr_drc_uni_bs_dec->ia_drc_params_struct.delta_tmin_default - 1) / 2; } } if (it_bit_buff->ptr_bit_buf_base == NULL) { FLOAT32 prev_db_gain = str_spline_nodes->str_node[str_spline_nodes->num_nodes - 1].loc_db_gain; str_spline_nodes->drc_gain_coding_mode = 0; str_spline_nodes->num_nodes = 1; if (prev_db_gain < 0) { str_spline_nodes->str_node[0].loc_db_gain = prev_db_gain; } else { str_spline_nodes->str_node[0].loc_db_gain = 0.f; } str_spline_nodes->str_node[0].slope = 0.0; str_spline_nodes->str_node[0].time = (pstr_drc_uni_bs_dec->ia_drc_params_struct).drc_frame_size + time_offset; } else { str_spline_nodes->drc_gain_coding_mode = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error == PROC_COMPLETE) { str_spline_nodes->drc_gain_coding_mode = 0; str_spline_nodes->str_node[0].slope = 0.0; str_spline_nodes->str_node[0].time = (pstr_drc_uni_bs_dec->ia_drc_params_struct).drc_frame_size + time_offset; str_spline_nodes->str_node[0].loc_db_gain = str_spline_nodes->str_node[str_spline_nodes->num_nodes - 1] .loc_db_gain; str_spline_nodes->num_nodes = 1; } else { if (it_bit_buff->error) return (it_bit_buff->error); } if (str_spline_nodes->drc_gain_coding_mode == 0) { str_spline_nodes->num_nodes = 1; err = impd_dec_initial_gain(it_bit_buff, gain_set_params->gain_coding_profile, &(str_spline_nodes->str_node[0].loc_db_gain)); if (err) return (err); str_spline_nodes->str_node[0].slope = 0.0; str_spline_nodes->str_node[0].time = (pstr_drc_uni_bs_dec->ia_drc_params_struct).drc_frame_size + time_offset; } else { err = impd_dec_slopes(it_bit_buff, &str_spline_nodes->num_nodes, gain_set_params->gain_interpolation_type, str_spline_nodes->str_node); if (err) return (err); if (gain_set_params->time_delt_min_flag) { err = impd_dec_times( it_bit_buff, &gain_set_params->str_tables, str_spline_nodes->num_nodes, gain_set_params->time_delt_min_val, (pstr_drc_uni_bs_dec->ia_drc_params_struct).drc_frame_size, gain_set_params->full_frame, time_offset, str_spline_nodes->str_node); if (err) return (err); err = impd_dec_gains(it_bit_buff, str_spline_nodes->num_nodes, gain_set_params->gain_coding_profile, str_spline_nodes->str_node); if (err) return (err); } else { err = impd_dec_times( it_bit_buff, &pstr_drc_uni_bs_dec->tables_default, str_spline_nodes->num_nodes, (pstr_drc_uni_bs_dec->ia_drc_params_struct).delta_tmin_default, (pstr_drc_uni_bs_dec->ia_drc_params_struct).drc_frame_size, gain_set_params->full_frame, time_offset, str_spline_nodes->str_node); if (err) return (err); err = impd_dec_gains(it_bit_buff, str_spline_nodes->num_nodes, gain_set_params->gain_coding_profile, str_spline_nodes->str_node); if (err) return (err); } } } return (0); } WORD32 impd_parse_drc_gain_sequence( ia_bit_buf_struct* it_bit_buff, ia_drc_bits_dec_struct* pstr_drc_uni_bs_dec, ia_gain_set_params_struct* gain_set_params, ia_drc_gain_sequence_struct* drc_gain_sequence) { WORD32 err = 0, i; WORD32 prev_frame_time_buf[NODE_COUNT_MAX], cur_frame_time_buf[NODE_COUNT_MAX]; WORD32 num_nodes_node_reservoir, num_nodes_cur, k, m; if (((pstr_drc_uni_bs_dec->ia_drc_params_struct).delay_mode == DELAY_MODE_LOW_DELAY) && (gain_set_params->full_frame == 0)) { return (PARAM_ERROR); } i = 0; { err = impd_parse_spline_nodes(it_bit_buff, pstr_drc_uni_bs_dec, gain_set_params, &(drc_gain_sequence->str_spline_nodes[i])); if (err) return (err); num_nodes_node_reservoir = 0; num_nodes_cur = 0; for (k = 0; k < drc_gain_sequence->str_spline_nodes[i].num_nodes; k++) { if (drc_gain_sequence->str_spline_nodes[i].str_node[k].time >= pstr_drc_uni_bs_dec->ia_drc_params_struct.drc_frame_size) { prev_frame_time_buf[num_nodes_node_reservoir] = drc_gain_sequence->str_spline_nodes[i].str_node[k].time; num_nodes_node_reservoir++; } else { cur_frame_time_buf[num_nodes_cur] = drc_gain_sequence->str_spline_nodes[i].str_node[k].time; num_nodes_cur++; } } for (k = 0; k < num_nodes_node_reservoir; k++) { drc_gain_sequence->str_spline_nodes[i].str_node[k].time = prev_frame_time_buf[k] - 2 * pstr_drc_uni_bs_dec->ia_drc_params_struct.drc_frame_size; } for (m = 0; m < num_nodes_cur; m++, k++) { drc_gain_sequence->str_spline_nodes[i].str_node[k].time = cur_frame_time_buf[m]; } } return (0); } WORD32 impd_parse_drc_ext_v1(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 dwnmix_instructions_v1_flag; WORD32 dwnmix_instructions_v1_count; WORD32 drc_coeffs_and_instructions_uni_drc_v1_flag; WORD32 drc_coefficients_uni_drc_v1_count; WORD32 drc_instructions_uni_drc_v1_count; WORD32 i = 0, err = 0; const WORD32 version = 1; dwnmix_instructions_v1_flag = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (dwnmix_instructions_v1_flag == 1) { dwnmix_instructions_v1_count = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; for (i = 0; i < dwnmix_instructions_v1_count; i++) { err = impd_parse_dwnmix_instructions( it_bit_buff, version, ia_drc_params_struct, &drc_config->channel_layout, &drc_config ->dwnmix_instructions[i + drc_config->dwnmix_instructions_count]); if (err) return (err); } drc_config->dwnmix_instructions_count += dwnmix_instructions_v1_count; } drc_coeffs_and_instructions_uni_drc_v1_flag = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (drc_coeffs_and_instructions_uni_drc_v1_flag == 1) { drc_coefficients_uni_drc_v1_count = impd_read_bits_buf(it_bit_buff, 3); if (it_bit_buff->error) return it_bit_buff->error; for (i = 0; i < drc_coefficients_uni_drc_v1_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 + drc_config->drc_coefficients_drc_count]); if (err) return (err); } drc_config->drc_coefficients_drc_count += drc_coefficients_uni_drc_v1_count; drc_instructions_uni_drc_v1_count = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; for (i = 0; i < drc_instructions_uni_drc_v1_count; i++) { err = impd_parse_drc_instructions_uni_drc( it_bit_buff, version, drc_config, &drc_config->str_drc_instruction_str [i + drc_config->drc_instructions_uni_drc_count]); if (err) return (err); } drc_config->drc_instructions_uni_drc_count += drc_instructions_uni_drc_v1_count; } str_drc_config_ext->loud_eq_instructions_flag = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_drc_config_ext->loud_eq_instructions_flag == 1) { str_drc_config_ext->loud_eq_instructions_count = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; for (i = 0; i < str_drc_config_ext->loud_eq_instructions_count; i++) { err = impd_parse_loud_eq_instructions( it_bit_buff, &str_drc_config_ext->loud_eq_instructions[i]); if (err) return (err); } } else { str_drc_config_ext->loud_eq_instructions_count = 0; } str_drc_config_ext->eq_flag = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_drc_config_ext->eq_flag == 1) { err = impd_parse_eq_coefficients(it_bit_buff, &str_drc_config_ext->str_eq_coeff); if (err) return (err); str_drc_config_ext->eq_instructions_count = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; for (i = 0; i < str_drc_config_ext->eq_instructions_count; i++) { err = impd_parse_eq_instructions( it_bit_buff, drc_config, &str_drc_config_ext->str_eq_instructions[i]); if (err) return (err); } } return 0; } WORD32 impd_parse_filt_block(ia_bit_buf_struct* it_bit_buff, ia_filt_block_struct* str_filter_block, WORD32 block_count) { // WORD32 err = 0; WORD32 k, j, temp; ia_filt_ele_struct* str_filter_element; for (j = 0; j < block_count; j++) { str_filter_block->filter_element_count = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; str_filter_element = &str_filter_block->str_filter_element[0]; for (k = 0; k < str_filter_block->filter_element_count; k++) { temp = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; str_filter_element->filt_ele_idx = (temp & 0x7E) >> 1; str_filter_element->filt_ele_gain_flag = temp & 1; ; if (str_filter_element->filt_ele_gain_flag) { WORD32 bs_filter_element_gain; bs_filter_element_gain = impd_read_bits_buf(it_bit_buff, 10); if (it_bit_buff->error) return it_bit_buff->error; str_filter_element->filt_ele_gain = bs_filter_element_gain * 0.125f - 96.0f; } str_filter_element++; } str_filter_block++; } return (0); } WORD32 impd_parse_unique_td_filt_ele( ia_bit_buf_struct* it_bit_buff, ia_unique_td_filt_element* unique_td_filt_ele, WORD32 td_filter_element_count) { WORD32 m, sign, j, temp; FLOAT32 tmp; for (j = 0; j < td_filter_element_count; j++) { unique_td_filt_ele->eq_filter_format = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (unique_td_filt_ele->eq_filter_format == 0) { WORD32 bs_real_zero_radius, bs_generic_zero_radius, bs_generic_zero_angle; WORD32 bs_real_pole_radius, bs_cmplx_pole_radius, bs_cmplx_pole_angle; WORD32 bs_real_zero_radius_one_count; temp = impd_read_bits_buf(it_bit_buff, 23); if (it_bit_buff->error) return it_bit_buff->error; bs_real_zero_radius_one_count = (temp >> 20) & 7; unique_td_filt_ele->bs_real_zero_radius_one_count = 2 * bs_real_zero_radius_one_count; unique_td_filt_ele->real_zero_count = (temp & 0xFC000) >> 14; unique_td_filt_ele->generic_zero_count = (temp & 0x3F00) >> 8; unique_td_filt_ele->real_pole_count = (temp & 0xF0) >> 4; unique_td_filt_ele->cmplx_pole_count = temp & 0xF; temp = impd_read_bits_buf( it_bit_buff, unique_td_filt_ele->bs_real_zero_radius_one_count); if (it_bit_buff->error) return it_bit_buff->error; for (m = unique_td_filt_ele->bs_real_zero_radius_one_count - 1; m >= 0; m--) { unique_td_filt_ele->zero_sign[m] = (temp & 1); temp = temp >> 1; } for (m = 0; m < unique_td_filt_ele->real_zero_count; m++) { temp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; bs_real_zero_radius = (temp & 0xFE) >> 1; sign = temp & 0x01; tmp = 1.0f - zero_pole_radius_tbl[bs_real_zero_radius]; sign = sign << 1; unique_td_filt_ele->real_zero_radius[m] = (1 - sign) * tmp; } for (m = 0; m < unique_td_filt_ele->generic_zero_count; m++) { temp = impd_read_bits_buf(it_bit_buff, 14); if (it_bit_buff->error) return it_bit_buff->error; bs_generic_zero_radius = (temp & 0x3F80) >> 7; unique_td_filt_ele->generic_zero_radius[m] = 1.0f - zero_pole_radius_tbl[bs_generic_zero_radius]; bs_generic_zero_angle = (temp & 0x7F); unique_td_filt_ele->generic_zero_angle[m] = zero_pole_angle_tbl[bs_generic_zero_angle]; } for (m = 0; m < unique_td_filt_ele->real_pole_count; m++) { temp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; bs_real_pole_radius = (temp & 0xFE) >> 1; sign = temp & 0x01; tmp = 1.0f - zero_pole_radius_tbl[bs_real_pole_radius]; sign = sign << 1; unique_td_filt_ele->real_pole_radius[m] = (1 - sign) * tmp; } for (m = 0; m < unique_td_filt_ele->cmplx_pole_count; m++) { temp = impd_read_bits_buf(it_bit_buff, 14); if (it_bit_buff->error) return it_bit_buff->error; bs_cmplx_pole_radius = (temp & 0x3F80) >> 7; unique_td_filt_ele->complex_pole_radius[m] = 1.0f - zero_pole_radius_tbl[bs_cmplx_pole_radius]; bs_cmplx_pole_angle = (temp & 0x7F); unique_td_filt_ele->complex_pole_angle[m] = zero_pole_angle_tbl[bs_cmplx_pole_angle]; } } else { temp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; unique_td_filt_ele->fir_filt_order = (temp & 0xFE) >> 1; unique_td_filt_ele->fir_symmetry = temp & 0x01; for (m = 0; m < unique_td_filt_ele->fir_filt_order / 2 + 1; m++) { WORD32 sign, bs_fir_coeff; FLOAT32 tmp; temp = impd_read_bits_buf(it_bit_buff, 11); if (it_bit_buff->error) return it_bit_buff->error; sign = (temp >> 10) & 0x01; bs_fir_coeff = temp & 0x03FF; tmp = (FLOAT32)pow(10.0f, -0.05f * bs_fir_coeff * 0.0625f); sign = sign << 1; unique_td_filt_ele->fir_coeff[m] = (1 - sign) * tmp; } } unique_td_filt_ele++; } return (0); } WORD32 impd_decode_eq_slope_code(ia_bit_buf_struct* it_bit_buff, FLOAT32* eq_slope, WORD32 num_eq_nodes) { WORD32 bits = 0; WORD32 k; for (k = 0; k < num_eq_nodes; k++) { bits = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (bits == 0x1) { *eq_slope = 0.0f; } else { bits = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; *eq_slope = eq_slope_tbl[bits]; } eq_slope++; } return (0); } WORD32 impd_decode_gain_initial_code(ia_bit_buf_struct* it_bit_buff, FLOAT32* eq_gain_initial) { WORD32 bits, bits1; bits1 = impd_read_bits_buf(it_bit_buff, 2); if (it_bit_buff->error) return it_bit_buff->error; switch (bits1) { case 0x0: bits = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; *eq_gain_initial = 0.5f * bits - 8.0f; break; case 0x1: case 0x2: bits = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; if (bits < 8) { *eq_gain_initial = bits1 * bits - bits1 * 16.0f; } else { *eq_gain_initial = (FLOAT32)bits1 * bits; } break; case 0x3: bits = impd_read_bits_buf(it_bit_buff, 3); if (it_bit_buff->error) return it_bit_buff->error; *eq_gain_initial = 4.0f * bits - 64.0f; break; default: break; } return (0); } WORD32 impd_parse_eq_subband_gain_spline( ia_bit_buf_struct* it_bit_buff, ia_eq_subband_gain_spline_struct* str_eq_subband_gain_spline, WORD32 eq_subband_gains_count) { WORD32 err = 0, eq_nodes_cnt, j, k, bits, *eq_freq_delta; FLOAT32* peq_gain_delta; for (j = 0; j < eq_subband_gains_count; j++) { eq_nodes_cnt = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; str_eq_subband_gain_spline->num_eq_nodes = eq_nodes_cnt + 2; err = impd_decode_eq_slope_code(it_bit_buff, &(str_eq_subband_gain_spline->eq_slope[0]), str_eq_subband_gain_spline->num_eq_nodes); if (err) return (err); eq_freq_delta = &(str_eq_subband_gain_spline->eq_freq_delta[1]); for (k = 1; k < str_eq_subband_gain_spline->num_eq_nodes; k++) { bits = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; *eq_freq_delta = bits + 1; eq_freq_delta++; } err = impd_decode_gain_initial_code( it_bit_buff, &(str_eq_subband_gain_spline->eq_gain_initial)); if (err) return (err); peq_gain_delta = &(str_eq_subband_gain_spline->eq_gain_delta[1]); for (k = 1; k < str_eq_subband_gain_spline->num_eq_nodes; k++) { bits = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; *peq_gain_delta = eq_gain_delta_tbl[bits]; peq_gain_delta++; } str_eq_subband_gain_spline++; } return (0); } WORD32 impd_parse_eq_subband_gain_vector( ia_bit_buf_struct* it_bit_buff, const WORD32 eq_subband_gain_count, ia_eq_subband_gain_vector* str_eq_subband_gain_vector, WORD32 eq_subband_gains_count) { WORD32 m, k, temp; for (k = 0; k < eq_subband_gains_count; k++) { for (m = 0; m < eq_subband_gain_count; m++) { WORD32 sign, bs_eq_subband_gain; temp = impd_read_bits_buf(it_bit_buff, 9); if (it_bit_buff->error) return it_bit_buff->error; sign = (temp >> 8) & 1; bs_eq_subband_gain = temp & 0x7F; sign = sign << 1; str_eq_subband_gain_vector->eq_subband_gain[m] = ((1 - sign) * bs_eq_subband_gain) * 0.125f; } str_eq_subband_gain_vector++; } return (0); } WORD32 impd_parse_eq_coefficients(ia_bit_buf_struct* it_bit_buff, ia_eq_coeff_struct* str_eq_coeff) { WORD32 err = 0; WORD32 eq_gain_cnt, mu, nu, temp; WORD32 subband_gain_len_tbl[7] = {0, 32, 39, 64, 71, 128, 135}; str_eq_coeff->eq_delay_max_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_eq_coeff->eq_delay_max_present) { mu = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; nu = impd_read_bits_buf(it_bit_buff, 3); if (it_bit_buff->error) return it_bit_buff->error; str_eq_coeff->eq_delay_max = 16 * mu * (1 << nu); } str_eq_coeff->unique_filter_block_count = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; err = impd_parse_filt_block(it_bit_buff, &(str_eq_coeff->str_filter_block[0]), str_eq_coeff->unique_filter_block_count); if (err) return (err); str_eq_coeff->unique_td_filter_element_count = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; err = impd_parse_unique_td_filt_ele( it_bit_buff, &(str_eq_coeff->unique_td_filt_ele[0]), str_eq_coeff->unique_td_filter_element_count); if (err) return (err); str_eq_coeff->unique_eq_subband_gains_count = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; if (str_eq_coeff->unique_eq_subband_gains_count > 0) { temp = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; str_eq_coeff->eq_subband_gain_representation = (temp >> 4) & 0x01; str_eq_coeff->eq_subband_gain_format = temp & 0x0F; if (str_eq_coeff->eq_subband_gain_format == GAINFORMAT_UNIFORM) { eq_gain_cnt = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; str_eq_coeff->eq_subband_gain_count = eq_gain_cnt + 1; } else str_eq_coeff->eq_subband_gain_count = subband_gain_len_tbl[str_eq_coeff->eq_subband_gain_format]; if (str_eq_coeff->eq_subband_gain_representation == 1) { err = impd_parse_eq_subband_gain_spline( it_bit_buff, &(str_eq_coeff->str_eq_subband_gain_spline[0]), str_eq_coeff->unique_eq_subband_gains_count); if (err) return (err); } else { err = impd_parse_eq_subband_gain_vector( it_bit_buff, str_eq_coeff->eq_subband_gain_count, &(str_eq_coeff->str_eq_subband_gain_vector[0]), str_eq_coeff->unique_eq_subband_gains_count); if (err) return (err); } } return (0); } WORD32 impd_parser_td_filter_cascade( ia_bit_buf_struct* it_bit_buff, ia_eq_instructions_struct* str_eq_instructions, ia_td_filter_cascade_struct* str_td_filter_cascade) { // WORD32 err=0, WORD32 i, ii, k; WORD32 eq_cascade_gain; ia_filter_block_refs_struct* str_filter_block_refs = &(str_td_filter_cascade->str_filter_block_refs[0]); for (i = 0; i < str_eq_instructions->eq_ch_group_count; i++) { str_td_filter_cascade->eq_cascade_gain_present[i] = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_td_filter_cascade->eq_cascade_gain_present[i]) { eq_cascade_gain = impd_read_bits_buf(it_bit_buff, 10); if (it_bit_buff->error) return it_bit_buff->error; str_td_filter_cascade->eq_cascade_gain[i] = 0.125f * eq_cascade_gain - 96.0f; } else { str_td_filter_cascade->eq_cascade_gain[i] = 0.0f; } str_filter_block_refs->filter_block_count = impd_read_bits_buf(it_bit_buff, 4); if (it_bit_buff->error) return it_bit_buff->error; for (ii = 0; ii < str_filter_block_refs->filter_block_count; ii++) { str_filter_block_refs->filter_block_index[ii] = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; } str_filter_block_refs++; } str_td_filter_cascade->eq_phase_alignment_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_td_filter_cascade->eq_phase_alignment_present) { for (i = 0; i < str_eq_instructions->eq_ch_group_count; i++) { for (k = i + 1; k < str_eq_instructions->eq_ch_group_count; k++) { str_td_filter_cascade->eq_phase_alignment[i][k] = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; } } } else { for (i = 0; i < str_eq_instructions->eq_ch_group_count; i++) { for (k = i + 1; k < str_eq_instructions->eq_ch_group_count; k++) str_td_filter_cascade->eq_phase_alignment[i][k] = 1; } } return (0); } WORD32 impd_parse_eq_instructions( ia_bit_buf_struct* it_bit_buff, ia_drc_config* drc_config, ia_eq_instructions_struct* str_eq_instructions) { WORD32 i, k, channel_count, temp; WORD32 dmix_id_present, additional_dmix_id_present, additional_dmix_id_cnt = 0; WORD32 additional_drc_set_id_present, additional_drc_set_id_cnt; temp = impd_read_bits_buf(it_bit_buff, 11); if (it_bit_buff->error) return it_bit_buff->error; str_eq_instructions->eq_set_id = (temp >> 5) & 0x3F; str_eq_instructions->eq_set_complexity_level = (temp >> 1) & 0x0F; dmix_id_present = temp & 0x01; if (dmix_id_present) { temp = impd_read_bits_buf(it_bit_buff, 9); if (it_bit_buff->error) return it_bit_buff->error; str_eq_instructions->downmix_id[0] = (temp >> 2) & 0x7F; str_eq_instructions->eq_apply_to_downmix = (temp >> 1) & 0x01; additional_dmix_id_present = temp & 0x01; if (additional_dmix_id_present) { additional_dmix_id_cnt = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; for (i = 1; i < additional_dmix_id_cnt + 1; i++) { str_eq_instructions->downmix_id[i] = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; } } } else { str_eq_instructions->downmix_id[0] = 0; } str_eq_instructions->dwnmix_id_count = 1 + additional_dmix_id_cnt; temp = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; str_eq_instructions->drc_set_id[0] = (temp >> 1) & 0x3F; additional_drc_set_id_present = temp & 0x01; if (additional_drc_set_id_present) { additional_drc_set_id_cnt = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; for (i = 1; i < additional_drc_set_id_cnt + 1; i++) { str_eq_instructions->drc_set_id[i] = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; } } else { additional_drc_set_id_cnt = 0; } str_eq_instructions->drc_set_id_count = 1 + additional_drc_set_id_cnt; temp = impd_read_bits_buf(it_bit_buff, 17); if (it_bit_buff->error) return it_bit_buff->error; str_eq_instructions->eq_set_purpose = (temp >> 1) & 0xFFFF; str_eq_instructions->depends_on_eq_set_present = temp & 0x01; if (str_eq_instructions->depends_on_eq_set_present) { str_eq_instructions->depends_on_eq_set = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; } else { str_eq_instructions->no_independent_eq_use = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; } str_eq_instructions->eq_channel_count = channel_count = drc_config->channel_layout.base_channel_count; if ((dmix_id_present == 1) && (str_eq_instructions->eq_apply_to_downmix == 1) && (str_eq_instructions->downmix_id[0] != 0) && (str_eq_instructions->downmix_id[0] != ID_FOR_ANY_DOWNMIX) && (str_eq_instructions->dwnmix_id_count == 1)) { for (i = 0; i < drc_config->dwnmix_instructions_count; i++) { if (str_eq_instructions->downmix_id[0] == drc_config->dwnmix_instructions[i].downmix_id) break; } if (i == drc_config->dwnmix_instructions_count) { return UNEXPECTED_ERROR; } str_eq_instructions->eq_channel_count = channel_count = drc_config->dwnmix_instructions[i].target_channel_count; } else if ((str_eq_instructions->downmix_id[0] == ID_FOR_ANY_DOWNMIX) || (str_eq_instructions->dwnmix_id_count > 1)) { channel_count = 1; } str_eq_instructions->eq_ch_group_count = 0; for (i = 0; i < channel_count; i++) { WORD32 new_group = 1; str_eq_instructions->eq_ch_group_of_channel[i] = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; for (k = 0; k < i; k++) { if (str_eq_instructions->eq_ch_group_of_channel[i] == str_eq_instructions->eq_ch_group_of_channel[k]) { new_group = 0; break; } } if (new_group == 1) { str_eq_instructions->eq_ch_group_count += 1; } } str_eq_instructions->td_filter_cascade_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_eq_instructions->td_filter_cascade_present) { impd_parser_td_filter_cascade( it_bit_buff, str_eq_instructions, &(str_eq_instructions->str_td_filter_cascade)); } str_eq_instructions->subband_gains_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_eq_instructions->subband_gains_present) { for (i = 0; i < str_eq_instructions->eq_ch_group_count; i++) { str_eq_instructions->subband_gains_index[i] = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; } } str_eq_instructions->eq_transition_duration_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (str_eq_instructions->eq_transition_duration_present) { WORD32 bs_eq_transition_duration; bs_eq_transition_duration = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; str_eq_instructions->eq_transition_duration = (WORD32)( 0.001f * (FLOAT32)pow(2.0f, 2.0f + bs_eq_transition_duration * 0.0625f)); } return (0); } WORD32 impd_parse_loud_eq_instructions( ia_bit_buf_struct* it_bit_buff, ia_loud_eq_instructions_struct* loud_eq_instructions) { WORD32 i, bs_loud_eq_scaling, bs_loud_eq_offset, temp; WORD32 dmix_id_present, additional_dmix_id_present, additional_dmix_id_cnt = 0; WORD32 drc_set_id_present, additional_drc_set_id_present, additional_drc_set_id_cnt = 0; WORD32 eq_set_id_present, additional_eq_set_id_present, additional_eq_set_id_cnt = 0; temp = impd_read_bits_buf(it_bit_buff, 9); if (it_bit_buff->error) return it_bit_buff->error; loud_eq_instructions->loud_eq_set_id = (temp >> 5) & 0x0F; loud_eq_instructions->drc_location = (temp >> 1) & 0x0F; dmix_id_present = temp & 0x01; if (dmix_id_present) { temp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; loud_eq_instructions->downmix_id[0] = (temp >> 1) & 0x7F; additional_dmix_id_present = temp & 0x01; if (additional_dmix_id_present) { additional_dmix_id_cnt = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; for (i = 1; i < additional_dmix_id_cnt + 1; i++) { loud_eq_instructions->downmix_id[i] = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; } } } else { loud_eq_instructions->downmix_id[0] = 0; } loud_eq_instructions->dwnmix_id_count = 1 + additional_dmix_id_cnt; drc_set_id_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (drc_set_id_present) { temp = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; loud_eq_instructions->drc_set_id[0] = (temp >> 1) & 0x3F; additional_drc_set_id_present = temp & 0x01; if (additional_drc_set_id_present) { additional_drc_set_id_cnt = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; for (i = 1; i < additional_drc_set_id_cnt + 1; i++) { loud_eq_instructions->drc_set_id[i] = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; } } } else { loud_eq_instructions->drc_set_id[0] = 0; } loud_eq_instructions->drc_set_id_count = 1 + additional_drc_set_id_cnt; eq_set_id_present = impd_read_bits_buf(it_bit_buff, 1); if (it_bit_buff->error) return it_bit_buff->error; if (eq_set_id_present) { temp = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; loud_eq_instructions->eq_set_id[0] = (temp >> 1) & 0x3F; additional_eq_set_id_present = temp & 0x01; if (additional_eq_set_id_present) { additional_eq_set_id_cnt = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; for (i = 0; i < additional_eq_set_id_cnt; i++) { loud_eq_instructions->eq_set_id[i + 1] = impd_read_bits_buf(it_bit_buff, 6); if (it_bit_buff->error) return it_bit_buff->error; } } } else { loud_eq_instructions->eq_set_id[0] = 0; } loud_eq_instructions->eq_set_id_count = 1 + additional_eq_set_id_cnt; temp = impd_read_bits_buf(it_bit_buff, 8); if (it_bit_buff->error) return it_bit_buff->error; loud_eq_instructions->loudness_after_drc = (temp >> 7) & 0x01; loud_eq_instructions->loudness_after_eq = (temp >> 6) & 0x01; loud_eq_instructions->loud_eq_gain_sequence_count = temp & 0x3F; for (i = 0; i < loud_eq_instructions->loud_eq_gain_sequence_count; i++) { temp = impd_read_bits_buf(it_bit_buff, 7); if (it_bit_buff->error) return it_bit_buff->error; loud_eq_instructions->gain_seq_idx[i] = (temp >> 1) & 0x3F; loud_eq_instructions->drc_characteristic_format_is_cicp[i] = temp & 0x01; if (loud_eq_instructions->drc_characteristic_format_is_cicp[i]) { loud_eq_instructions->drc_characteristic[i] = 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; loud_eq_instructions->drc_characteristic_left_index[i] = (temp >> 4) & 0x0F; loud_eq_instructions->drc_characteristic_right_index[i] = temp & 0x0F; } temp = impd_read_bits_buf(it_bit_buff, 9); if (it_bit_buff->error) return it_bit_buff->error; loud_eq_instructions->frequency_range_index[i] = (temp >> 3) & 0x3F; bs_loud_eq_scaling = temp & 0x07; loud_eq_instructions->loud_eq_scaling[i] = (FLOAT32)pow(2.0f, -0.5f * bs_loud_eq_scaling); bs_loud_eq_offset = impd_read_bits_buf(it_bit_buff, 5); if (it_bit_buff->error) return it_bit_buff->error; loud_eq_instructions->loud_eq_offset[i] = 1.5f * bs_loud_eq_offset - 16.0f; } return (0); }