libxaac/decoder/drc_src/impd_drc_static_payload.c
Ray Essick 4908247643 Sanitization fixes from new CTS tests
Updates from vendor to remedy issues exposed by new CTS tests

Bug: 77287124
Test: CTS DecoderTest, DecoderTest{AacDrc,XheAac}

@ Sanitizer fixes in libxaac

Fixes few integer overflow sanitizer errors
Progagate few errors
ENABLE_DRC macro is removed
AMMENDMENT1 macro is removed

Change-Id: Ic61163dfd6318bd4a00ed45e1295c819cb0f637b

@ Add support for audio pre-roll and DRC effect type

Also includes the following
MPEG-D DRC parameters related changes
USAC config switch changes
SBR config switch changes

Bug: 80133175
Change-Id: I0ab25641768cf523b66f7b0fcb4137429c1c4a77

@ Fixed trailing spaces

Change-Id: I32de0c9d3f7237e1fbf8dfef1cac485ef8458173

@ Replaced tabs

Change-Id: Ic741ee13d7b978b37edc27d087903caaa40b8d90
2018-05-25 11:35:52 -07:00

2550 lines
No EOL
98 KiB
C

/******************************************************************************
*
* 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"
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)
{
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;
}
str_p_loc_drc_coefficients_uni_drc->gain_set_count_plus = str_p_loc_drc_coefficients_uni_drc->gain_set_count + str_drc_coeff_param_drc->parametric_drc_gain_set_count;
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;
str_drc_coeff_param_drc->parametric_drc_frame_size_format = temp&1;
if (str_drc_coeff_param_drc->parametric_drc_frame_size)
{
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 (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;
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;
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;
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 (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;
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 (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;
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)
{
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;
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;
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;
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);
}
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;
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;
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;
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)
{
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)
{
pstr_gain_modifiers->shape_filter_idx = impd_read_bits_buf(it_bit_buff, 4);
if(it_bit_buff->error)
return it_bit_buff->error;
}
}
}
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>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;
}
}
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;
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;
}
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;
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;
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;
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;
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;
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;
str_p_loc_drc_coefficients_uni_drc->gain_set_count = temp&0x3f;
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;
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 (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;
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;
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;
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].ducking_scaling_flag = str_drc_instruction_str->str_ducking_modifiers_for_channel[c-1].ducking_scaling_flag;
str_drc_instruction_str->str_ducking_modifiers_for_channel[c].ducking_scaling = str_drc_instruction_str->str_ducking_modifiers_for_channel[c-1].ducking_scaling;
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;
}
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];
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;
}
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;
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;
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;
for (g=0; g<str_drc_instruction_str->num_drc_ch_groups; g++)
{
WORD32 set, band_count;
set = unique_idx[g];
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;
loudness_info->true_peak_level_measurement_system = (temp>>2)&0xf;
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);
}