* Loudness leveling support for encoder and decoder
- Addition of loudness leveling support to encoder and
decoder as per ISO/IEC 23003-4:2020/Amd.2:2023(E)
Testing:
Encoder: Smoke-test
Decoder: CTS and Conformance for x86, x86_64, armv7 and armv8 are
passing
* Addressed review comments
* Addressed minor nits in documentation
---------
Co-authored-by: Akshay Ragir <100833@ittiam.com>
3371 lines
131 KiB
C
3371 lines
131 KiB
C
/******************************************************************************
|
|
* *
|
|
* Copyright (C) 2023 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 <math.h>
|
|
#include <string.h>
|
|
#include "ixheaac_type_def.h"
|
|
#include "ixheaac_error_standards.h"
|
|
#include "ixheaace_error_codes.h"
|
|
|
|
#include "iusace_bitbuffer.h"
|
|
#include "iusace_cnst.h"
|
|
#include "impd_drc_common_enc.h"
|
|
#include "impd_drc_uni_drc.h"
|
|
#include "impd_drc_tables.h"
|
|
#include "impd_drc_api.h"
|
|
#include "impd_drc_uni_drc_eq.h"
|
|
#include "impd_drc_uni_drc_filter_bank.h"
|
|
#include "impd_drc_gain_enc.h"
|
|
#include "impd_drc_struct_def.h"
|
|
#include "impd_drc_enc.h"
|
|
#include "impd_drc_mux.h"
|
|
|
|
static IA_ERRORCODE impd_drc_get_drc_complexity_level(
|
|
ia_drc_uni_drc_config_struct *pstr_uni_drc_config, ia_drc_gain_enc_struct *pstr_drc_gain_enc,
|
|
ia_drc_instructions_uni_drc *pstr_drc_instructions_uni_drc, VOID *ptr_scratch) {
|
|
IA_ERRORCODE err_code = IA_NO_ERROR;
|
|
LOOPIDX c, g, k, i, group;
|
|
WORD32 band_count;
|
|
WORD32 gain_set_index;
|
|
WORD32 skip_set;
|
|
WORD32 gain_set_index_offset;
|
|
WORD32 parametric_drc_type = 0;
|
|
WORD32 channel_count_side_chain;
|
|
WORD32 channel_count_drom_downmix_id;
|
|
WORD32 channel_count_temp;
|
|
WORD32 weighting_filter_order;
|
|
WORD32 channel_count = pstr_uni_drc_config->str_channel_layout.base_ch_count;
|
|
FLOAT32 w_mod, cplx, cplx_tmp, ratio;
|
|
ia_drc_gain_modifiers_struct *pstr_gain_modifiers = NULL;
|
|
ia_drc_shape_filter_block_params_struct *pstr_shape_filter_block_params = NULL;
|
|
ia_drc_gain_set_params_struct *pstr_gain_set_params = NULL;
|
|
ia_drc_parametric_drc_instructions_struct *pstr_parametric_drc_instructions = NULL;
|
|
ia_drc_parametric_drc_gain_set_params_struct *pstr_parametric_drc_gain_set_params = NULL;
|
|
|
|
if (pstr_drc_instructions_uni_drc->drc_apply_to_downmix != 0 &&
|
|
((pstr_drc_instructions_uni_drc->downmix_id == 0x7F) ||
|
|
(pstr_drc_instructions_uni_drc->additional_downmix_id_count != 0))) {
|
|
channel_count = 1;
|
|
} else if ((pstr_drc_instructions_uni_drc->drc_apply_to_downmix != 0) &&
|
|
(pstr_drc_instructions_uni_drc->downmix_id != 0) &&
|
|
(pstr_drc_instructions_uni_drc->downmix_id != 0x7F) &&
|
|
(pstr_drc_instructions_uni_drc->additional_downmix_id_count == 0)) {
|
|
for (i = 0; i < pstr_uni_drc_config->downmix_instructions_count; i++) {
|
|
if (pstr_drc_instructions_uni_drc->downmix_id ==
|
|
pstr_uni_drc_config->str_downmix_instructions[i].downmix_id) {
|
|
break;
|
|
}
|
|
}
|
|
if (i == pstr_uni_drc_config->downmix_instructions_count) {
|
|
return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
|
|
}
|
|
channel_count = pstr_uni_drc_config->str_downmix_instructions[i].target_ch_count;
|
|
}
|
|
|
|
pstr_drc_instructions_uni_drc->drc_channel_count = channel_count;
|
|
group = 0;
|
|
for (c = 0; c < pstr_drc_instructions_uni_drc->drc_channel_count; c++) {
|
|
gain_set_index = pstr_drc_instructions_uni_drc->gain_set_index[c];
|
|
skip_set = FALSE;
|
|
if (gain_set_index < 0) {
|
|
pstr_drc_instructions_uni_drc->channel_group_for_channel[c] = -1;
|
|
} else {
|
|
for (k = c - 1; k >= 0; k--) {
|
|
if (pstr_drc_instructions_uni_drc->gain_set_index[k] == gain_set_index) {
|
|
pstr_drc_instructions_uni_drc->channel_group_for_channel[c] =
|
|
pstr_drc_instructions_uni_drc->channel_group_for_channel[k];
|
|
skip_set = TRUE;
|
|
}
|
|
}
|
|
if (skip_set == FALSE) {
|
|
pstr_drc_instructions_uni_drc->channel_group_for_channel[c] = group;
|
|
group++;
|
|
}
|
|
}
|
|
}
|
|
if (group != pstr_drc_instructions_uni_drc->num_drc_channel_groups) {
|
|
return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
|
|
}
|
|
|
|
for (g = 0; g < pstr_drc_instructions_uni_drc->num_drc_channel_groups; g++) {
|
|
pstr_drc_instructions_uni_drc->num_channels_per_channel_group[g] = 0;
|
|
for (c = 0; c < pstr_drc_instructions_uni_drc->drc_channel_count; c++) {
|
|
if (pstr_drc_instructions_uni_drc->channel_group_for_channel[c] == g) {
|
|
pstr_drc_instructions_uni_drc->num_channels_per_channel_group[g]++;
|
|
}
|
|
}
|
|
}
|
|
|
|
cplx = 0.0f;
|
|
|
|
if (pstr_drc_gain_enc->domain == TIME_DOMAIN) {
|
|
w_mod = COMPLEXITY_W_MOD_TIME;
|
|
} else {
|
|
w_mod = COMPLEXITY_W_MOD_SUBBAND;
|
|
}
|
|
for (c = 0; c < pstr_drc_instructions_uni_drc->drc_channel_count; c++) {
|
|
if (pstr_drc_instructions_uni_drc->gain_set_index[c] >= 0) {
|
|
cplx += w_mod;
|
|
}
|
|
}
|
|
|
|
if (pstr_drc_gain_enc->domain != TIME_DOMAIN) {
|
|
pstr_gain_set_params =
|
|
pstr_uni_drc_config->str_uni_drc_config_ext.str_drc_coefficients_uni_drc_v1[0]
|
|
.str_gain_set_params;
|
|
for (c = 0; c < pstr_drc_instructions_uni_drc->drc_channel_count; c++) {
|
|
gain_set_index = pstr_drc_instructions_uni_drc->gain_set_index[c];
|
|
if (gain_set_index >= 0) {
|
|
if (pstr_gain_set_params[gain_set_index].drc_band_type == 1) {
|
|
band_count = pstr_gain_set_params[gain_set_index].band_count;
|
|
if (band_count > 1) {
|
|
cplx += COMPLEXITY_W_LAP * band_count;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
err_code = impd_drc_init_all_filter_banks(
|
|
&pstr_uni_drc_config->str_uni_drc_config_ext.str_drc_coefficients_uni_drc_v1[0],
|
|
pstr_drc_instructions_uni_drc, &pstr_drc_gain_enc->str_filter_banks, ptr_scratch);
|
|
|
|
if (err_code) return err_code;
|
|
|
|
cplx += COMPLEXITY_W_IIR * pstr_drc_gain_enc->str_filter_banks.complexity;
|
|
|
|
for (g = 0; g < pstr_drc_instructions_uni_drc->num_drc_channel_groups; g++) {
|
|
pstr_gain_modifiers = &pstr_drc_instructions_uni_drc->str_gain_modifiers[g];
|
|
if (pstr_gain_modifiers->shape_filter_present == 1) {
|
|
cplx_tmp = 0.0f;
|
|
pstr_shape_filter_block_params =
|
|
&pstr_uni_drc_config->str_uni_drc_config_ext.str_drc_coefficients_uni_drc_v1[0]
|
|
.str_shape_filter_block_params[pstr_gain_modifiers->shape_filter_index];
|
|
if (pstr_shape_filter_block_params->lf_cut_filter_present == 1) {
|
|
cplx_tmp += COMPLEXITY_W_SHAPE;
|
|
}
|
|
if (pstr_shape_filter_block_params->lf_boost_filter_present == 1) {
|
|
cplx_tmp += COMPLEXITY_W_SHAPE;
|
|
}
|
|
if (pstr_shape_filter_block_params->hf_cut_filter_present == 1) {
|
|
cplx_tmp += COMPLEXITY_W_SHAPE * 2.0f;
|
|
}
|
|
if (pstr_shape_filter_block_params->hf_boost_filter_present == 1) {
|
|
cplx_tmp += COMPLEXITY_W_SHAPE * 2.0f;
|
|
}
|
|
cplx += cplx_tmp * pstr_drc_instructions_uni_drc->num_channels_per_channel_group[g];
|
|
}
|
|
}
|
|
}
|
|
|
|
for (g = 0; g < pstr_drc_instructions_uni_drc->num_drc_channel_groups; g++) {
|
|
gain_set_index_offset = 0;
|
|
gain_set_index = -1;
|
|
for (c = 0; c < pstr_drc_instructions_uni_drc->drc_channel_count; c++) {
|
|
if (pstr_drc_instructions_uni_drc->channel_group_for_channel[c] == g) {
|
|
gain_set_index = pstr_drc_instructions_uni_drc->gain_set_index[c];
|
|
break;
|
|
}
|
|
}
|
|
if (pstr_uni_drc_config->str_uni_drc_config_ext.drc_coefficients_uni_drc_v1_count > 0) {
|
|
gain_set_index_offset =
|
|
pstr_uni_drc_config->str_uni_drc_config_ext.str_drc_coefficients_uni_drc_v1[0]
|
|
.gain_set_count;
|
|
pstr_gain_set_params =
|
|
pstr_uni_drc_config->str_uni_drc_config_ext.str_drc_coefficients_uni_drc_v1[0]
|
|
.str_gain_set_params;
|
|
}
|
|
if (gain_set_index >= gain_set_index_offset) {
|
|
pstr_parametric_drc_instructions = NULL;
|
|
pstr_parametric_drc_gain_set_params =
|
|
&pstr_uni_drc_config->str_uni_drc_config_ext.str_drc_coeff_parametric_drc
|
|
.parametric_drc_gain_set_params[gain_set_index - gain_set_index_offset];
|
|
for (i = 0;
|
|
i < pstr_uni_drc_config->str_uni_drc_config_ext.parametric_drc_instructions_count;
|
|
i++) {
|
|
if (pstr_parametric_drc_gain_set_params->parametric_drc_id ==
|
|
pstr_uni_drc_config->str_uni_drc_config_ext.str_parametric_drc_instructions[i]
|
|
.parametric_drc_id) {
|
|
pstr_parametric_drc_instructions =
|
|
&pstr_uni_drc_config->str_uni_drc_config_ext.str_parametric_drc_instructions[i];
|
|
break;
|
|
}
|
|
}
|
|
if (pstr_parametric_drc_instructions != NULL) {
|
|
if (pstr_parametric_drc_instructions->parametric_drc_preset_id_present) {
|
|
switch (pstr_parametric_drc_instructions->parametric_drc_preset_id) {
|
|
case 0:
|
|
case 1:
|
|
case 2:
|
|
case 3:
|
|
case 4:
|
|
parametric_drc_type = PARAM_DRC_TYPE_FF;
|
|
break;
|
|
case 5:
|
|
parametric_drc_type = PARAM_DRC_TYPE_LIM;
|
|
break;
|
|
default:
|
|
return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
|
|
break;
|
|
}
|
|
} else {
|
|
parametric_drc_type = pstr_parametric_drc_instructions->parametric_drc_type;
|
|
}
|
|
}
|
|
channel_count_side_chain = pstr_drc_instructions_uni_drc->num_channels_per_channel_group[g];
|
|
if (pstr_parametric_drc_gain_set_params->side_chain_config_type == 1) {
|
|
channel_count_temp = 0;
|
|
if (pstr_parametric_drc_gain_set_params->downmix_id == 0x0) {
|
|
channel_count_drom_downmix_id = pstr_uni_drc_config->str_channel_layout.base_ch_count;
|
|
} else if (pstr_parametric_drc_gain_set_params->downmix_id == 0x7F) {
|
|
channel_count_drom_downmix_id = 1;
|
|
} else {
|
|
for (i = 0; i < pstr_uni_drc_config->downmix_instructions_count; i++) {
|
|
if (pstr_parametric_drc_gain_set_params->downmix_id ==
|
|
pstr_uni_drc_config->str_downmix_instructions[i].downmix_id) {
|
|
break;
|
|
}
|
|
}
|
|
if (i == pstr_uni_drc_config->downmix_instructions_count) {
|
|
return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
|
|
}
|
|
channel_count_drom_downmix_id =
|
|
pstr_uni_drc_config->str_downmix_instructions[i].target_ch_count;
|
|
}
|
|
|
|
for (i = 0; i < channel_count_drom_downmix_id; i++) {
|
|
if (pstr_parametric_drc_gain_set_params->level_estim_channel_weight[i] != 0) {
|
|
channel_count_temp++;
|
|
}
|
|
}
|
|
channel_count_side_chain = channel_count_temp;
|
|
}
|
|
if (pstr_parametric_drc_instructions != NULL) {
|
|
if (pstr_drc_gain_enc->domain == TIME_DOMAIN) {
|
|
if (parametric_drc_type == PARAM_DRC_TYPE_FF) {
|
|
weighting_filter_order = 2;
|
|
if (pstr_parametric_drc_instructions->parametric_drc_preset_id_present == 0) {
|
|
if (pstr_parametric_drc_instructions->str_parametric_drc_type_feed_forward
|
|
.level_estim_k_weighting_type == 0) {
|
|
weighting_filter_order = 0;
|
|
} else if (pstr_parametric_drc_instructions->str_parametric_drc_type_feed_forward
|
|
.level_estim_k_weighting_type == 1) {
|
|
weighting_filter_order = 1;
|
|
}
|
|
}
|
|
cplx += channel_count_side_chain *
|
|
(COMPLEXITY_W_PARAM_DRC_FILT * weighting_filter_order + 1) +
|
|
3;
|
|
} else if (parametric_drc_type == PARAM_DRC_TYPE_LIM) {
|
|
ratio = 1.0f;
|
|
if (pstr_parametric_drc_instructions->parametric_drc_look_ahead_present == 1) {
|
|
ratio = (FLOAT32)pstr_parametric_drc_instructions->parametric_drc_look_ahead /
|
|
(FLOAT32)PARAM_DRC_TYPE_LIM_ATTACK_DEFAULT;
|
|
}
|
|
cplx += (FLOAT32)(channel_count_side_chain * COMPLEXITY_W_PARAM_LIM_FILT +
|
|
COMPLEXITY_W_PARAM_DRC_ATTACK * sqrt(ratio));
|
|
}
|
|
} else {
|
|
if (parametric_drc_type == PARAM_DRC_TYPE_FF) {
|
|
cplx += channel_count_side_chain * COMPLEXITY_W_PARAM_DRC_SUBBAND;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (pstr_drc_gain_enc->domain == TIME_DOMAIN && pstr_gain_set_params != NULL) {
|
|
if (pstr_gain_set_params[gain_set_index].gain_interpolation_type ==
|
|
GAIN_INTERPOLATION_TYPE_SPLINE) {
|
|
cplx += COMPLEXITY_W_SPLINE;
|
|
}
|
|
if (pstr_gain_set_params[gain_set_index].gain_interpolation_type ==
|
|
GAIN_INTERPOLATION_TYPE_LINEAR) {
|
|
cplx += COMPLEXITY_W_LINEAR;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (pstr_drc_instructions_uni_drc->downmix_id == 0x7F) {
|
|
channel_count = pstr_uni_drc_config->str_channel_layout.base_ch_count;
|
|
}
|
|
|
|
cplx = (FLOAT32)(log10(cplx / channel_count) / log10(2.0f));
|
|
pstr_drc_instructions_uni_drc->drc_set_complexity_level = (WORD32)MAX(0, ceil(cplx));
|
|
|
|
if (pstr_drc_instructions_uni_drc->drc_set_complexity_level > DRC_COMPLEXITY_LEVEL_MAX) {
|
|
return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
|
|
}
|
|
|
|
return IA_NO_ERROR;
|
|
}
|
|
|
|
static IA_ERRORCODE impd_drc_get_eq_complexity_level(
|
|
ia_drc_uni_drc_config_ext_struct *pstr_uni_drc_config_ext,
|
|
ia_drc_gain_enc_struct *pstr_drc_params, ia_drc_eq_instructions_struct *pstr_eq_instructions,
|
|
VOID *ptr_scratch, WORD32 *scratch_used) {
|
|
IA_ERRORCODE err_code = IA_NO_ERROR;
|
|
WORD32 subband_domain_mode;
|
|
ia_drc_eq_set_struct *pstr_eq_set = &pstr_drc_params->str_eq_set;
|
|
|
|
if ((pstr_drc_params->domain == TIME_DOMAIN) &&
|
|
(pstr_eq_instructions->td_filter_cascade_present == 0) &&
|
|
(pstr_eq_instructions->subband_gains_present == 0)) {
|
|
pstr_eq_instructions->eq_set_complexity_level = 0;
|
|
return err_code;
|
|
}
|
|
|
|
subband_domain_mode = SUBBAND_DOMAIN_MODE_OFF;
|
|
if (pstr_eq_instructions->subband_gains_present == 1) {
|
|
subband_domain_mode = SUBBAND_DOMAIN_MODE_QMF64;
|
|
}
|
|
memset(pstr_eq_set, 0, sizeof(ia_drc_eq_set_struct));
|
|
|
|
err_code = impd_drc_derive_eq_set(&pstr_uni_drc_config_ext->str_eq_coefficients,
|
|
pstr_eq_instructions, (FLOAT32)pstr_drc_params->sample_rate,
|
|
pstr_drc_params->drc_frame_size, subband_domain_mode,
|
|
pstr_eq_set, ptr_scratch, scratch_used);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return err_code;
|
|
}
|
|
|
|
err_code =
|
|
impd_drc_get_eq_complexity(pstr_eq_set, &pstr_eq_instructions->eq_set_complexity_level);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return err_code;
|
|
}
|
|
|
|
return err_code;
|
|
}
|
|
|
|
static WORD32 impd_drc_encode_downmix_coefficient(FLOAT32 downmix_coeff, FLOAT32 downmix_offset) {
|
|
WORD32 idx, code;
|
|
FLOAT32 coeff_db;
|
|
const FLOAT32 *coeff_table;
|
|
|
|
coeff_table = impd_drc_downmix_coeff_v1;
|
|
coeff_db = 20.0f * (FLOAT32)log10(downmix_coeff) - downmix_offset;
|
|
|
|
if (coeff_db >= coeff_table[30]) {
|
|
idx = 0;
|
|
while (coeff_db < coeff_table[idx]) {
|
|
idx++;
|
|
}
|
|
if ((idx > 0) && (coeff_db > 0.5f * (coeff_table[idx - 1] + coeff_table[idx]))) {
|
|
idx--;
|
|
}
|
|
code = idx;
|
|
} else {
|
|
code = 31;
|
|
}
|
|
|
|
return code;
|
|
}
|
|
|
|
static VOID impd_drc_dec_write_downmix_coeff_v1(ia_bit_buf_struct *it_bit_buf,
|
|
const FLOAT32 downmix_coeff[],
|
|
const WORD32 base_ch_count,
|
|
const WORD32 target_ch_count,
|
|
WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX i, j;
|
|
WORD32 bs_downmix_offset = 0, code;
|
|
WORD32 bit_cnt_local = 0;
|
|
FLOAT32 downmix_offset[3];
|
|
FLOAT32 tmp;
|
|
FLOAT32 quant_err, quant_err_min;
|
|
const FLOAT32 *coeff_table;
|
|
|
|
coeff_table = impd_drc_downmix_coeff_v1;
|
|
tmp = (FLOAT32)log10((FLOAT32)target_ch_count / (FLOAT32)base_ch_count);
|
|
downmix_offset[0] = 0.0f;
|
|
downmix_offset[1] = (FLOAT32)(0.5f * floor(0.5f + 20.0f * tmp));
|
|
downmix_offset[2] = (FLOAT32)(0.5f * floor(0.5f + 40.0f * tmp));
|
|
|
|
quant_err_min = 1000.0f;
|
|
for (i = 0; i < 3; i++) {
|
|
quant_err = 0.0f;
|
|
for (j = 0; j < (target_ch_count * base_ch_count); j++) {
|
|
code = impd_drc_encode_downmix_coefficient(downmix_coeff[j], downmix_offset[i]);
|
|
quant_err += (FLOAT32)fabs(20.0f * log10(downmix_coeff[j]) -
|
|
(coeff_table[code] + downmix_offset[i]));
|
|
}
|
|
if (quant_err_min > quant_err) {
|
|
quant_err_min = quant_err;
|
|
bs_downmix_offset = i;
|
|
}
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bs_downmix_offset, 4);
|
|
|
|
for (j = 0; j < target_ch_count * base_ch_count; j++) {
|
|
code =
|
|
impd_drc_encode_downmix_coefficient(downmix_coeff[j], downmix_offset[bs_downmix_offset]);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 5);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static VOID impd_drc_enc_downmix_coeff(const FLOAT32 downmix_coeff_var,
|
|
const WORD32 is_lfe_channel, WORD32 *code_size,
|
|
WORD32 *code) {
|
|
LOOPIDX idx;
|
|
const FLOAT32 *coeff_table;
|
|
FLOAT32 coeff_db;
|
|
|
|
coeff_db = 20.0f * (FLOAT32)log10(downmix_coeff_var);
|
|
|
|
if (is_lfe_channel == TRUE) {
|
|
coeff_table = impd_drc_downmix_coeff_lfe;
|
|
} else {
|
|
coeff_table = impd_drc_downmix_coeff;
|
|
}
|
|
if (coeff_db >= coeff_table[14]) {
|
|
idx = 0;
|
|
while (coeff_db < coeff_table[idx]) {
|
|
idx++;
|
|
}
|
|
if ((idx > 0) && (coeff_db > 0.5f * (coeff_table[idx - 1] + coeff_table[idx]))) {
|
|
idx--;
|
|
}
|
|
*code = idx;
|
|
} else {
|
|
*code = 15;
|
|
}
|
|
|
|
*code_size = 4;
|
|
}
|
|
|
|
static VOID impd_drc_enc_peak(const FLOAT32 peak_level, WORD32 *code, WORD32 *code_size) {
|
|
WORD32 bits;
|
|
|
|
bits = ((WORD32)(0.5f + 32.0f * (20.0f - peak_level) + 10000.0f)) - 10000;
|
|
bits = MIN(0x0FFF, bits);
|
|
bits = MAX(0x1, bits);
|
|
|
|
*code = bits;
|
|
*code_size = 12;
|
|
}
|
|
|
|
static IA_ERRORCODE impd_drc_enc_method_value(const WORD32 method_definition,
|
|
const FLOAT32 method_value, WORD32 *code_size,
|
|
WORD32 *code) {
|
|
WORD32 bits;
|
|
switch (method_definition) {
|
|
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:
|
|
bits = ((WORD32)(0.5f + 4.0f * (method_value + 57.75f) + 10000.0f)) - 10000;
|
|
bits = MIN(0x0FF, bits);
|
|
bits = MAX(0x0, bits);
|
|
*code_size = 8;
|
|
break;
|
|
case METHOD_DEFINITION_LOUDNESS_RANGE:
|
|
if (method_value >= 121.0f) {
|
|
bits = 255;
|
|
} else if (method_value > 70.0f) {
|
|
bits = ((WORD32)((method_value - 70.0f) + 0.5f)) + 204;
|
|
} else if (method_value > 32.0f) {
|
|
bits = ((WORD32)(2.0f * (method_value - 32.0f) + 0.5f)) + 128;
|
|
} else if (method_value >= 0.0f) {
|
|
bits = (WORD32)(4.0f * method_value + 0.5f);
|
|
} else {
|
|
bits = 0;
|
|
}
|
|
*code_size = 8;
|
|
break;
|
|
case METHOD_DEFINITION_MIXING_LEVEL:
|
|
bits = (WORD32)(0.5f + method_value - 80.0f);
|
|
bits = MIN(0x1F, bits);
|
|
bits = MAX(0x0, bits);
|
|
*code_size = 5;
|
|
break;
|
|
case METHOD_DEFINITION_ROOM_TYPE:
|
|
bits = (WORD32)(0.5f + method_value);
|
|
if (bits > 0x2) {
|
|
return IA_EXHEAACE_CONFIG_FATAL_DRC_PARAM_OUT_OF_RANGE;
|
|
}
|
|
bits = MIN(0x2, bits);
|
|
bits = MAX(0x0, bits);
|
|
*code_size = 2;
|
|
break;
|
|
case METHOD_DEFINITION_SHORT_TERM_LOUDNESS:
|
|
bits = ((WORD32)(0.5f + 2.0f * (method_value + 116.f) + 10000.0f)) - 10000;
|
|
bits = MIN(0x0FF, bits);
|
|
bits = MAX(0x0, bits);
|
|
*code_size = 8;
|
|
break;
|
|
default: {
|
|
return IA_EXHEAACE_CONFIG_FATAL_DRC_PARAM_OUT_OF_RANGE;
|
|
}
|
|
}
|
|
*code = bits;
|
|
|
|
return IA_NO_ERROR;
|
|
}
|
|
|
|
static VOID impd_drc_quantize_ducking_scaling(
|
|
ia_drc_ducking_modifiers_struct *pstr_ducking_modifiers) {
|
|
WORD32 mu;
|
|
FLOAT32 delta;
|
|
|
|
if (pstr_ducking_modifiers->ducking_scaling_present) {
|
|
delta = pstr_ducking_modifiers->ducking_scaling - 1.0f;
|
|
|
|
if (delta <= 0.0f) {
|
|
mu = -1 + (WORD32)(0.5f - 8.0f * delta);
|
|
if (mu != -1) {
|
|
mu = MIN(7, mu);
|
|
mu = MAX(0, mu);
|
|
pstr_ducking_modifiers->ducking_scaling_quantized = 1.0f - 0.125f * (1.0f + mu);
|
|
} else {
|
|
pstr_ducking_modifiers->ducking_scaling_quantized = 1.0f;
|
|
pstr_ducking_modifiers->ducking_scaling_present = FALSE;
|
|
}
|
|
} else {
|
|
mu = -1 + (WORD32)(0.5f + 8.0f * delta);
|
|
if (mu != -1) {
|
|
mu = MIN(7, mu);
|
|
mu = MAX(0, mu);
|
|
pstr_ducking_modifiers->ducking_scaling_quantized = 1.0f + 0.125f * (1.0f + mu);
|
|
} else {
|
|
pstr_ducking_modifiers->ducking_scaling_quantized = 1.0f;
|
|
pstr_ducking_modifiers->ducking_scaling_present = FALSE;
|
|
}
|
|
}
|
|
} else {
|
|
pstr_ducking_modifiers->ducking_scaling_quantized = 1.0f;
|
|
}
|
|
}
|
|
|
|
static VOID impd_drc_enc_ducking_scaling(const FLOAT32 scaling, WORD32 *bits,
|
|
FLOAT32 *scaling_quantized,
|
|
WORD32 *remove_scaling_value) {
|
|
WORD32 mu, sigma;
|
|
FLOAT32 delta;
|
|
|
|
delta = scaling - 1.0f;
|
|
*remove_scaling_value = FALSE;
|
|
if (delta <= 0.0f) {
|
|
mu = -1 + (WORD32)(0.5f - 8.0f * delta);
|
|
sigma = -1;
|
|
*bits = 1 << 3;
|
|
} else {
|
|
mu = -1 + (WORD32)(0.5f + 8.0f * delta);
|
|
sigma = 0;
|
|
*bits = 0;
|
|
}
|
|
if (mu != -1) {
|
|
mu = MIN(7, mu);
|
|
mu = MAX(0, mu);
|
|
*bits += mu;
|
|
if (sigma == 0) {
|
|
*scaling_quantized = 1.0f + 0.125f * (1.0f + mu);
|
|
} else {
|
|
*scaling_quantized = 1.0f - 0.125f * (1.0f + mu);
|
|
}
|
|
} else {
|
|
*scaling_quantized = 1.0f;
|
|
*remove_scaling_value = TRUE;
|
|
}
|
|
}
|
|
|
|
static VOID impd_drc_enc_ducking_modifiers(
|
|
ia_bit_buf_struct *it_bit_buf, ia_drc_ducking_modifiers_struct *pstr_ducking_modifiers,
|
|
WORD32 *ptr_bit_cnt) {
|
|
WORD32 bits;
|
|
WORD32 remove_scaling_value;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
if (pstr_ducking_modifiers->ducking_scaling_present == FALSE) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_ducking_modifiers->ducking_scaling_present, 1);
|
|
} else {
|
|
impd_drc_enc_ducking_scaling(pstr_ducking_modifiers->ducking_scaling, &bits,
|
|
&(pstr_ducking_modifiers->ducking_scaling_quantized),
|
|
&remove_scaling_value);
|
|
|
|
if (remove_scaling_value) {
|
|
pstr_ducking_modifiers->ducking_scaling_present = FALSE;
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_ducking_modifiers->ducking_scaling_present, 1);
|
|
|
|
if (pstr_ducking_modifiers->ducking_scaling_present) {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bits, 4);
|
|
}
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static VOID impd_drc_enc_gain_modifiers(ia_bit_buf_struct *it_bit_buf, const WORD32 version,
|
|
const WORD32 band_count,
|
|
ia_drc_gain_modifiers_struct *pstr_gain_modifiers,
|
|
WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX idx;
|
|
WORD32 tmp, sign;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
if (version == 1) {
|
|
for (idx = 0; idx < band_count; idx++) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_gain_modifiers->target_characteristic_left_present[idx], 1);
|
|
if (pstr_gain_modifiers->target_characteristic_left_present[idx]) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_gain_modifiers->target_characteristic_left_index[idx], 4);
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_gain_modifiers->target_characteristic_right_present[idx], 1);
|
|
if (pstr_gain_modifiers->target_characteristic_right_present[idx]) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_gain_modifiers->target_characteristic_right_index[idx], 4);
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_gain_modifiers->gain_scaling_present[idx], 1);
|
|
if (pstr_gain_modifiers->gain_scaling_present[idx]) {
|
|
tmp = (WORD32)(0.5f + 8.0f * pstr_gain_modifiers->attenuation_scaling[idx]);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, tmp, 4);
|
|
|
|
tmp = (WORD32)(0.5f + 8.0f * pstr_gain_modifiers->amplification_scaling[idx]);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, tmp, 4);
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_gain_modifiers->gain_offset_present[idx], 1);
|
|
if (pstr_gain_modifiers->gain_offset_present[idx]) {
|
|
if (pstr_gain_modifiers->gain_offset[idx] >= 0.0f) {
|
|
tmp = (WORD32)(0.5f + MAX(0.0f, 4.0f * pstr_gain_modifiers->gain_offset[idx] - 1.0f));
|
|
sign = 0;
|
|
} else {
|
|
tmp = (WORD32)(0.5f + MAX(0.0f, -4.0f * pstr_gain_modifiers->gain_offset[idx] - 1.0f));
|
|
sign = 1;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, sign, 1);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, tmp, 5);
|
|
}
|
|
}
|
|
if (band_count == 1) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_gain_modifiers->shape_filter_present, 1);
|
|
if (pstr_gain_modifiers->shape_filter_present) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_gain_modifiers->shape_filter_index, 4);
|
|
}
|
|
}
|
|
} else if (version == 0) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_gain_modifiers->gain_scaling_present[0], 1);
|
|
|
|
if (pstr_gain_modifiers->gain_scaling_present[0]) {
|
|
tmp = (WORD32)(0.5f + 8.0f * pstr_gain_modifiers->attenuation_scaling[0]);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, tmp, 4);
|
|
|
|
tmp = (WORD32)(0.5f + 8.0f * pstr_gain_modifiers->amplification_scaling[0]);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, tmp, 4);
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_gain_modifiers->gain_offset_present[0], 1);
|
|
if (pstr_gain_modifiers->gain_offset_present[0]) {
|
|
if (pstr_gain_modifiers->gain_offset[0] >= 0.0f) {
|
|
tmp = (WORD32)(0.5f + MAX(0.0f, 4.0f * pstr_gain_modifiers->gain_offset[0] - 1.0f));
|
|
sign = 0;
|
|
} else {
|
|
tmp = (WORD32)(0.5f + MAX(0.0f, -4.0f * pstr_gain_modifiers->gain_offset[0] - 1.0f));
|
|
sign = 1;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, sign, 1);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, tmp, 5);
|
|
}
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static IA_ERRORCODE impd_drc_write_loudness_measure(
|
|
ia_bit_buf_struct *it_bit_buf, ia_drc_loudness_measure_struct *pstr_loudness_measure,
|
|
WORD32 *ptr_bit_cnt) {
|
|
IA_ERRORCODE err_code = IA_NO_ERROR;
|
|
WORD32 code, code_size;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_loudness_measure->method_definition, 4);
|
|
|
|
err_code = impd_drc_enc_method_value(pstr_loudness_measure->method_definition,
|
|
pstr_loudness_measure->method_value, &code_size, &code);
|
|
if (err_code) return (err_code);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, (UWORD8)code_size);
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_loudness_measure->measurement_system, 4);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_loudness_measure->reliability, 2);
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
|
|
return IA_NO_ERROR;
|
|
}
|
|
|
|
static IA_ERRORCODE impd_drc_write_loudness_info(ia_bit_buf_struct *it_bit_buf,
|
|
const WORD32 version,
|
|
ia_drc_loudness_info_struct *pstr_loudness_info,
|
|
WORD32 *ptr_bit_cnt) {
|
|
IA_ERRORCODE err_code = IA_NO_ERROR;
|
|
LOOPIDX idx;
|
|
WORD32 code, code_size;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_loudness_info->drc_set_id, 6);
|
|
if (version >= 1) {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_loudness_info->eq_set_id, 6);
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_loudness_info->downmix_id, 7);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_loudness_info->sample_peak_level_present, 1);
|
|
if (pstr_loudness_info->sample_peak_level_present) {
|
|
impd_drc_enc_peak(pstr_loudness_info->sample_peak_level, &code, &code_size);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, (UWORD8)code_size);
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_loudness_info->true_peak_level_present, 1);
|
|
if (pstr_loudness_info->true_peak_level_present) {
|
|
impd_drc_enc_peak(pstr_loudness_info->true_peak_level, &code, &code_size);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, (UWORD8)code_size);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loudness_info->true_peak_level_measurement_system, 4);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_loudness_info->true_peak_level_reliability, 2);
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_loudness_info->measurement_count, 4);
|
|
|
|
for (idx = 0; idx < pstr_loudness_info->measurement_count; idx++) {
|
|
err_code = impd_drc_write_loudness_measure(
|
|
it_bit_buf, &(pstr_loudness_info->str_loudness_measure[idx]), &bit_cnt_local);
|
|
|
|
if (err_code) return (err_code);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
|
|
return IA_NO_ERROR;
|
|
}
|
|
|
|
static IA_ERRORCODE impd_drc_write_drc_instruct_uni_drc(
|
|
ia_bit_buf_struct *it_bit_buf, const WORD32 version,
|
|
ia_drc_uni_drc_config_struct *pstr_uni_drc_config, ia_drc_gain_enc_struct *pstr_gain_enc,
|
|
ia_drc_instructions_uni_drc *pstr_drc_instructions_uni_drc, VOID *ptr_scratch,
|
|
WORD32 *ptr_bit_cnt) {
|
|
IA_ERRORCODE err_code = IA_NO_ERROR;
|
|
LOOPIDX i, j, n;
|
|
WORD32 g, k, tmp, tmp_2, match, channel_count;
|
|
WORD32 bs_sequence_index, sequence_index_prev, repeat_sequence_count;
|
|
WORD32 ducking_sequence, index;
|
|
WORD32 repeat_parameters_count;
|
|
WORD32 bit_cnt_local = 0;
|
|
WORD32 band_count = 0;
|
|
WORD32 *unique_index;
|
|
FLOAT32 *unique_scaling;
|
|
FLOAT32 ducking_scaling_quantized_prev, factor;
|
|
ia_drc_ducking_modifiers_struct *pstr_ducking_modifiers;
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_instructions_uni_drc->drc_set_id, 6);
|
|
if (version == 1) {
|
|
err_code = impd_drc_get_drc_complexity_level(pstr_uni_drc_config, pstr_gain_enc,
|
|
pstr_drc_instructions_uni_drc, ptr_scratch);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return (err_code);
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_instructions_uni_drc->drc_set_complexity_level, 4);
|
|
}
|
|
|
|
unique_index = (WORD32 *)ptr_scratch;
|
|
unique_scaling =
|
|
(FLOAT32 *)((UWORD8 *)ptr_scratch + (MAX_CHANNEL_COUNT) * sizeof(unique_index[0]));
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_instructions_uni_drc->drc_location, 4);
|
|
|
|
if (version != 1) {
|
|
pstr_drc_instructions_uni_drc->downmix_id_present = 1;
|
|
} else {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_instructions_uni_drc->downmix_id_present, 1);
|
|
}
|
|
|
|
if (pstr_drc_instructions_uni_drc->downmix_id_present != 1) {
|
|
pstr_drc_instructions_uni_drc->downmix_id = 0;
|
|
} else {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_instructions_uni_drc->downmix_id, 7);
|
|
if (version == 1) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_instructions_uni_drc->drc_apply_to_downmix, 1);
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_instructions_uni_drc->additional_downmix_id_present, 1);
|
|
|
|
if (pstr_drc_instructions_uni_drc->additional_downmix_id_present) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_instructions_uni_drc->additional_downmix_id_count, 3);
|
|
for (i = 0; i < pstr_drc_instructions_uni_drc->additional_downmix_id_count; i++) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_instructions_uni_drc->additional_downmix_id[i], 7);
|
|
}
|
|
} else {
|
|
pstr_drc_instructions_uni_drc->additional_downmix_id_count = 0;
|
|
}
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_instructions_uni_drc->drc_set_effect, 16);
|
|
|
|
if ((pstr_drc_instructions_uni_drc->drc_set_effect &
|
|
(EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) == 0) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_instructions_uni_drc->limiter_peak_target_present, 1);
|
|
if (pstr_drc_instructions_uni_drc->limiter_peak_target_present) {
|
|
tmp = (WORD32)(0.5f - 8.0f * pstr_drc_instructions_uni_drc->limiter_peak_target);
|
|
tmp = MAX(0, tmp);
|
|
tmp = MIN(0xFF, tmp);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, tmp, 8);
|
|
}
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_instructions_uni_drc->drc_set_target_loudness_present, 1);
|
|
|
|
if (pstr_drc_instructions_uni_drc->drc_set_target_loudness_present == 1) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_instructions_uni_drc->drc_set_target_loudness_value_upper + 63, 6);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_instructions_uni_drc->drc_set_target_loudness_value_lower_present,
|
|
1);
|
|
if (pstr_drc_instructions_uni_drc->drc_set_target_loudness_value_lower_present == 1) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_instructions_uni_drc->drc_set_target_loudness_value_lower + 63, 6);
|
|
}
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_instructions_uni_drc->depends_on_drc_set_present, 1);
|
|
|
|
if (pstr_drc_instructions_uni_drc->depends_on_drc_set_present) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_instructions_uni_drc->depends_on_drc_set, 6);
|
|
} else {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_instructions_uni_drc->no_independent_use, 1);
|
|
}
|
|
|
|
if (version == 1) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_instructions_uni_drc->requires_eq, 1);
|
|
}
|
|
|
|
channel_count = pstr_uni_drc_config->str_channel_layout.base_ch_count;
|
|
if (pstr_drc_instructions_uni_drc->drc_set_effect &
|
|
(EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) {
|
|
i = 0;
|
|
while (i < channel_count) {
|
|
pstr_ducking_modifiers = pstr_drc_instructions_uni_drc->str_ducking_modifiers_for_channel;
|
|
bs_sequence_index = pstr_drc_instructions_uni_drc->gain_set_index[i] + 1;
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bs_sequence_index, 6);
|
|
|
|
impd_drc_enc_ducking_modifiers(it_bit_buf, &(pstr_ducking_modifiers[i]), &bit_cnt_local);
|
|
|
|
sequence_index_prev = pstr_drc_instructions_uni_drc->gain_set_index[i];
|
|
ducking_scaling_quantized_prev = pstr_ducking_modifiers[i].ducking_scaling_quantized;
|
|
i++;
|
|
|
|
if (i < channel_count) {
|
|
impd_drc_quantize_ducking_scaling(&(pstr_ducking_modifiers[i]));
|
|
}
|
|
|
|
repeat_parameters_count = 0;
|
|
while ((i < channel_count) && (repeat_parameters_count <= 32) &&
|
|
(sequence_index_prev == pstr_drc_instructions_uni_drc->gain_set_index[i]) &&
|
|
(ducking_scaling_quantized_prev ==
|
|
pstr_ducking_modifiers[i].ducking_scaling_quantized)) {
|
|
repeat_parameters_count++;
|
|
i++;
|
|
if (i < channel_count) {
|
|
impd_drc_quantize_ducking_scaling(&(pstr_ducking_modifiers[i]));
|
|
}
|
|
}
|
|
if (repeat_parameters_count <= 0) {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, 0, 1);
|
|
} else {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, 1, 1);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, repeat_parameters_count - 1, 5);
|
|
}
|
|
}
|
|
for (j = 0; j < MAX_CHANNEL_COUNT; j++) {
|
|
unique_index[j] = -10;
|
|
unique_scaling[j] = -10.0f;
|
|
}
|
|
|
|
ducking_sequence = -1;
|
|
g = 0;
|
|
|
|
if (pstr_drc_instructions_uni_drc->drc_set_effect & EFFECT_BIT_DUCK_SELF) {
|
|
for (j = 0; j < channel_count; j++) {
|
|
match = FALSE;
|
|
index = pstr_drc_instructions_uni_drc->gain_set_index[j];
|
|
factor =
|
|
pstr_drc_instructions_uni_drc->str_ducking_modifiers_for_channel[j].ducking_scaling;
|
|
for (n = 0; n < g; n++) {
|
|
if ((index >= 0) && (unique_index[n] == index) && (unique_scaling[n] == factor)) {
|
|
match = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (match == FALSE) {
|
|
if (index >= 0) {
|
|
unique_index[g] = index;
|
|
unique_scaling[g] = factor;
|
|
g++;
|
|
}
|
|
}
|
|
}
|
|
pstr_drc_instructions_uni_drc->num_drc_channel_groups = g;
|
|
} else if (pstr_drc_instructions_uni_drc->drc_set_effect & EFFECT_BIT_DUCK_OTHER) {
|
|
for (j = 0; j < channel_count; j++) {
|
|
match = FALSE;
|
|
index = pstr_drc_instructions_uni_drc->gain_set_index[j];
|
|
factor =
|
|
pstr_drc_instructions_uni_drc->str_ducking_modifiers_for_channel[j].ducking_scaling;
|
|
for (n = 0; n < g; n++) {
|
|
if (((index >= 0) && (unique_index[n] == index)) ||
|
|
((index < 0) && (unique_scaling[n] == factor))) {
|
|
match = TRUE;
|
|
break;
|
|
}
|
|
}
|
|
if (match == FALSE) {
|
|
if (index < 0) {
|
|
unique_index[g] = index;
|
|
unique_scaling[g] = factor;
|
|
g++;
|
|
} else {
|
|
if ((ducking_sequence > 0) && (ducking_sequence != index)) {
|
|
return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
|
|
}
|
|
ducking_sequence = index;
|
|
}
|
|
}
|
|
}
|
|
pstr_drc_instructions_uni_drc->num_drc_channel_groups = g;
|
|
if (ducking_sequence < 0) {
|
|
return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
|
|
}
|
|
}
|
|
|
|
for (g = 0; g < pstr_drc_instructions_uni_drc->num_drc_channel_groups; g++) {
|
|
if (pstr_drc_instructions_uni_drc->drc_set_effect & EFFECT_BIT_DUCK_SELF) {
|
|
pstr_drc_instructions_uni_drc->gain_set_index_for_channel_group[g] = unique_index[g];
|
|
} else if (pstr_drc_instructions_uni_drc->drc_set_effect & EFFECT_BIT_DUCK_OTHER) {
|
|
pstr_drc_instructions_uni_drc->gain_set_index_for_channel_group[g] = -1;
|
|
}
|
|
|
|
pstr_drc_instructions_uni_drc->str_ducking_modifiers_for_channel_group[g].ducking_scaling =
|
|
unique_scaling[g];
|
|
if (unique_scaling[g] == 1.0f) {
|
|
pstr_drc_instructions_uni_drc->str_ducking_modifiers_for_channel_group[g]
|
|
.ducking_scaling_present = FALSE;
|
|
} else {
|
|
pstr_drc_instructions_uni_drc->str_ducking_modifiers_for_channel_group[g]
|
|
.ducking_scaling_present = TRUE;
|
|
}
|
|
}
|
|
} else {
|
|
if ((version == 0 || pstr_drc_instructions_uni_drc->drc_apply_to_downmix != 0) &&
|
|
((pstr_drc_instructions_uni_drc->downmix_id == 0x7F) ||
|
|
(pstr_drc_instructions_uni_drc->additional_downmix_id_count != 0))) {
|
|
channel_count = 1;
|
|
} else if ((version == 0 || pstr_drc_instructions_uni_drc->drc_apply_to_downmix != 0) &&
|
|
(pstr_drc_instructions_uni_drc->downmix_id != 0) &&
|
|
(pstr_drc_instructions_uni_drc->downmix_id != 0x7F) &&
|
|
(pstr_drc_instructions_uni_drc->additional_downmix_id_count == 0)) {
|
|
for (i = 0; i < pstr_uni_drc_config->downmix_instructions_count; i++) {
|
|
if (pstr_drc_instructions_uni_drc->downmix_id ==
|
|
pstr_uni_drc_config->str_downmix_instructions[i].downmix_id) {
|
|
break;
|
|
}
|
|
}
|
|
if (i == pstr_uni_drc_config->downmix_instructions_count) {
|
|
return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
|
|
}
|
|
channel_count = pstr_uni_drc_config->str_downmix_instructions[i].target_ch_count;
|
|
}
|
|
|
|
i = 0;
|
|
while (i < channel_count) {
|
|
bs_sequence_index = pstr_drc_instructions_uni_drc->gain_set_index[i] + 1;
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bs_sequence_index, 6);
|
|
sequence_index_prev = pstr_drc_instructions_uni_drc->gain_set_index[i];
|
|
i++;
|
|
|
|
repeat_sequence_count = 0;
|
|
while ((i < channel_count) &&
|
|
(sequence_index_prev == pstr_drc_instructions_uni_drc->gain_set_index[i]) &&
|
|
(repeat_sequence_count <= 32)) {
|
|
repeat_sequence_count++;
|
|
i++;
|
|
}
|
|
if (repeat_sequence_count <= 0) {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, 0, 1);
|
|
} else {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, 1, 1);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, repeat_sequence_count - 1, 5);
|
|
}
|
|
}
|
|
for (i = 0; i < MAX_CHANNEL_COUNT; i++) {
|
|
unique_index[i] = -1;
|
|
}
|
|
|
|
k = 0;
|
|
for (i = 0; i < channel_count; i++) {
|
|
tmp_2 = pstr_drc_instructions_uni_drc->gain_set_index[i];
|
|
if (tmp_2 >= 0) {
|
|
match = FALSE;
|
|
for (n = 0; n < k; n++) {
|
|
if (unique_index[n] == tmp_2) {
|
|
match = TRUE;
|
|
}
|
|
}
|
|
if (match == FALSE) {
|
|
unique_index[k] = tmp_2;
|
|
k++;
|
|
}
|
|
}
|
|
}
|
|
pstr_drc_instructions_uni_drc->num_drc_channel_groups = k;
|
|
for (i = 0; i < pstr_drc_instructions_uni_drc->num_drc_channel_groups; i++) {
|
|
band_count = 0;
|
|
pstr_drc_instructions_uni_drc->gain_set_index_for_channel_group[i] = unique_index[i];
|
|
|
|
if (pstr_uni_drc_config->str_uni_drc_config_ext.drc_coefficients_uni_drc_v1_count > 0) {
|
|
band_count =
|
|
pstr_uni_drc_config->str_uni_drc_config_ext.str_drc_coefficients_uni_drc_v1[0]
|
|
.str_gain_set_params[pstr_drc_instructions_uni_drc
|
|
->gain_set_index_for_channel_group[i]]
|
|
.band_count;
|
|
} else if (pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) {
|
|
band_count = pstr_uni_drc_config->str_drc_coefficients_uni_drc[0]
|
|
.str_gain_set_params[pstr_drc_instructions_uni_drc
|
|
->gain_set_index_for_channel_group[i]]
|
|
.band_count;
|
|
}
|
|
|
|
impd_drc_enc_gain_modifiers(it_bit_buf, version, band_count,
|
|
&(pstr_drc_instructions_uni_drc->str_gain_modifiers[i]),
|
|
&bit_cnt_local);
|
|
}
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
return err_code;
|
|
}
|
|
|
|
#ifdef LOUDNESS_LEVELING_SUPPORT
|
|
static UWORD32 get_num_ducking_only_drc_sets(
|
|
ia_drc_instructions_uni_drc const *pstr_drc_instructions_uni_drc,
|
|
UWORD32 drc_intructions_uni_drc_count) {
|
|
UWORD32 num_ducking_only_drc_sets = 0;
|
|
for (UWORD16 i = 0; i < drc_intructions_uni_drc_count; i++) {
|
|
if (pstr_drc_instructions_uni_drc[i].ducking_only_set_present) {
|
|
num_ducking_only_drc_sets++;
|
|
}
|
|
}
|
|
|
|
return num_ducking_only_drc_sets;
|
|
}
|
|
|
|
static WORD32 write_loudness_leveling_extension(ia_bit_buf_struct *it_bit_buf,
|
|
ia_drc_uni_drc_config_struct *pstr_uni_drc_config,
|
|
ia_drc_gain_enc_struct *pstr_gain_enc,
|
|
VOID *ptr_scratch, WORD32 *bit_cnt) {
|
|
IA_ERRORCODE err_code = IA_NO_ERROR;
|
|
WORD32 bit_cnt_local = 0;
|
|
WORD32 drc_instructions_uni_drc_count_v1 =
|
|
pstr_uni_drc_config->str_uni_drc_config_ext.drc_instructions_uni_drc_v1_count;
|
|
WORD32 drc_instructions_uni_drc_count = pstr_uni_drc_config->drc_instructions_uni_drc_count;
|
|
WORD32 version = 0;
|
|
WORD16 ducking_set_expected = 0;
|
|
// V0 instructions
|
|
for (WORD16 i = 0; i < drc_instructions_uni_drc_count; i++) {
|
|
ia_drc_instructions_uni_drc *pstr_drc_instruction =
|
|
&pstr_uni_drc_config->str_drc_instructions_uni_drc[i];
|
|
if (pstr_drc_instruction->drc_set_effect & EFFECT_BIT_DUCK_SELF) {
|
|
if (ducking_set_expected) {
|
|
ia_drc_instructions_uni_drc *pstr_drc_instruction_prev =
|
|
&pstr_uni_drc_config->str_drc_instructions_uni_drc[i - 1];
|
|
if (pstr_drc_instruction_prev->ducking_only_set_present) {
|
|
err_code = impd_drc_write_drc_instruct_uni_drc(it_bit_buf, version, pstr_uni_drc_config,
|
|
pstr_gain_enc, pstr_drc_instruction,
|
|
ptr_scratch, &bit_cnt_local);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return (err_code);
|
|
}
|
|
}
|
|
ducking_set_expected = 0;
|
|
} else {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_instruction->leveling_present, 1);
|
|
if (pstr_drc_instruction->leveling_present) {
|
|
ducking_set_expected = 1;
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_instruction->ducking_only_set_present, 1);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// V1 instructions
|
|
version = 1;
|
|
ducking_set_expected = 0;
|
|
for (WORD16 i = 0; i < drc_instructions_uni_drc_count_v1; i++) {
|
|
ia_drc_instructions_uni_drc *pstr_drc_instruction =
|
|
&pstr_uni_drc_config->str_uni_drc_config_ext.str_drc_instructions_uni_drc_v1[i];
|
|
if (pstr_drc_instruction->drc_set_effect & EFFECT_BIT_DUCK_SELF) {
|
|
if (ducking_set_expected) {
|
|
ia_drc_instructions_uni_drc *pstr_drc_instruction_prev =
|
|
&pstr_uni_drc_config->str_uni_drc_config_ext.str_drc_instructions_uni_drc_v1[i - 1];
|
|
if (pstr_drc_instruction_prev->ducking_only_set_present) {
|
|
err_code = impd_drc_write_drc_instruct_uni_drc(it_bit_buf, version, pstr_uni_drc_config,
|
|
pstr_gain_enc, pstr_drc_instruction,
|
|
ptr_scratch, &bit_cnt_local);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return (err_code);
|
|
}
|
|
}
|
|
ducking_set_expected = 0;
|
|
} else {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_instruction->leveling_present, 1);
|
|
if (pstr_drc_instruction->leveling_present) {
|
|
ducking_set_expected = 1;
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_instruction->ducking_only_set_present, 1);
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
*bit_cnt += bit_cnt_local;
|
|
return IA_NO_ERROR;
|
|
}
|
|
#endif
|
|
|
|
static VOID impd_drc_write_gain_params(ia_bit_buf_struct *it_bit_buf, const WORD32 version,
|
|
const WORD32 band_count, const WORD32 drc_band_type,
|
|
ia_drc_gain_params_struct *pstr_gain_params,
|
|
WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX idx;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
if (version != 1) {
|
|
for (idx = 0; idx < band_count; idx++) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_gain_params[idx].drc_characteristic, 7);
|
|
}
|
|
} else {
|
|
WORD32 index_present;
|
|
WORD32 gain_sequence_index_last = -1;
|
|
for (idx = 0; idx < band_count; idx++) {
|
|
if (pstr_gain_params[idx].gain_sequence_index == gain_sequence_index_last + 1) {
|
|
index_present = 0;
|
|
} else {
|
|
index_present = 1;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, index_present, 1);
|
|
|
|
if (index_present == 1) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_gain_params[idx].gain_sequence_index, 6);
|
|
gain_sequence_index_last = pstr_gain_params[idx].gain_sequence_index;
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_gain_params[idx].drc_characteristic_present, 1);
|
|
if (pstr_gain_params[idx].drc_characteristic_present) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_gain_params[idx].drc_characteristic_format_is_cicp, 1);
|
|
if (pstr_gain_params[idx].drc_characteristic_format_is_cicp == 1) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_gain_params[idx].drc_characteristic, 7);
|
|
} else {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_gain_params[idx].drc_characteristic_left_index, 4);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_gain_params[idx].drc_characteristic_right_index, 4);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (idx = 1; idx < band_count; idx++) {
|
|
if (drc_band_type) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_gain_params[idx].crossover_freq_index, 4);
|
|
} else {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_gain_params[idx].start_sub_band_index, 10);
|
|
}
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static VOID impd_drc_write_gain_set_params(ia_bit_buf_struct *it_bit_buf, const WORD32 version,
|
|
ia_drc_gain_set_params_struct *pstr_gain_set_params,
|
|
WORD32 *ptr_bit_cnt) {
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_gain_set_params->gain_coding_profile, 2);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_gain_set_params->gain_interpolation_type, 1);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_gain_set_params->full_frame, 1);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_gain_set_params->time_alignment, 1);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_gain_set_params->time_delta_min_present, 1);
|
|
|
|
if (pstr_gain_set_params->time_delta_min_present) {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_gain_set_params->delta_tmin - 1, 11);
|
|
}
|
|
if (pstr_gain_set_params->gain_coding_profile != GAIN_CODING_PROFILE_CONSTANT) {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_gain_set_params->band_count, 4);
|
|
if (pstr_gain_set_params->band_count > 1) {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_gain_set_params->drc_band_type, 1);
|
|
}
|
|
|
|
impd_drc_write_gain_params(it_bit_buf, version, pstr_gain_set_params->band_count,
|
|
pstr_gain_set_params->drc_band_type,
|
|
pstr_gain_set_params->gain_params, &bit_cnt_local);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static VOID impd_drc_write_split_drc_characteristic(
|
|
ia_bit_buf_struct *it_bit_buf, const WORD32 side,
|
|
ia_drc_split_drc_characteristic_struct *pstr_split_characteristic, WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX idx;
|
|
WORD32 bs_node_gain, bs_node_level_delta;
|
|
WORD32 bit_cnt_local = 0;
|
|
FLOAT32 bs_node_level_previous;
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_split_characteristic->characteristic_format, 1);
|
|
|
|
if (pstr_split_characteristic->characteristic_format != 0) {
|
|
bs_node_level_previous = DRC_INPUT_LOUDNESS_TARGET;
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_split_characteristic->characteristic_node_count - 1, 2);
|
|
|
|
for (idx = 1; idx <= pstr_split_characteristic->characteristic_node_count; idx++) {
|
|
bs_node_level_delta = (WORD32)(floor(fabs(pstr_split_characteristic->node_level[idx] -
|
|
bs_node_level_previous) +
|
|
0.5f) -
|
|
1);
|
|
|
|
if (bs_node_level_delta < 0) {
|
|
bs_node_level_delta = 0;
|
|
}
|
|
if (bs_node_level_delta > 31) {
|
|
bs_node_level_delta = 31;
|
|
}
|
|
if (side == RIGHT_SIDE) {
|
|
bs_node_level_previous = bs_node_level_previous + (bs_node_level_delta + 1);
|
|
} else {
|
|
bs_node_level_previous = bs_node_level_previous - (bs_node_level_delta + 1);
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bs_node_level_delta, 5);
|
|
|
|
bs_node_gain =
|
|
(WORD32)floor((pstr_split_characteristic->node_gain[idx] + 64.0f) * 2.0f + 0.5f);
|
|
|
|
if (bs_node_gain < 0) {
|
|
bs_node_gain = 0;
|
|
}
|
|
if (bs_node_gain > 255) {
|
|
bs_node_gain = 255;
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bs_node_gain, 8);
|
|
}
|
|
} else {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_split_characteristic->bs_gain, 6);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_split_characteristic->bs_io_ratio, 4);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_split_characteristic->bs_exp, 4);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_split_characteristic->flip_sign, 1);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static VOID impd_drc_write_shape_filter_block_params(
|
|
ia_bit_buf_struct *it_bit_buf,
|
|
ia_drc_shape_filter_block_params_struct *pstr_shape_filter_block_params,
|
|
WORD32 *ptr_bit_cnt) {
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_shape_filter_block_params->lf_cut_filter_present, 1);
|
|
if (pstr_shape_filter_block_params->lf_cut_filter_present == 1) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_shape_filter_block_params->str_lf_cut_params.corner_freq_index, 3);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_shape_filter_block_params->str_lf_cut_params.filter_strength_index, 2);
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_shape_filter_block_params->lf_boost_filter_present, 1);
|
|
if (pstr_shape_filter_block_params->lf_boost_filter_present == 1) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_shape_filter_block_params->str_lf_boost_params.corner_freq_index, 3);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_shape_filter_block_params->str_lf_boost_params.filter_strength_index, 2);
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_shape_filter_block_params->hf_cut_filter_present, 1);
|
|
if (pstr_shape_filter_block_params->hf_cut_filter_present == 1) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_shape_filter_block_params->str_hf_cut_params.corner_freq_index, 3);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_shape_filter_block_params->str_hf_cut_params.filter_strength_index, 2);
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_shape_filter_block_params->hf_boost_filter_present, 1);
|
|
if (pstr_shape_filter_block_params->hf_boost_filter_present == 1) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_shape_filter_block_params->str_hf_boost_params.corner_freq_index, 3);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_shape_filter_block_params->str_hf_boost_params.filter_strength_index, 2);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static VOID impd_drc_write_drc_coeff_uni_drc(
|
|
ia_bit_buf_struct *it_bit_buf, const WORD32 version,
|
|
ia_drc_coefficients_uni_drc_struct *pstr_drc_coefficients_uni_drc, WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX idx;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_coefficients_uni_drc->drc_location, 4);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_coefficients_uni_drc->drc_frame_size_present, 1);
|
|
|
|
if (pstr_drc_coefficients_uni_drc->drc_frame_size_present) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, (pstr_drc_coefficients_uni_drc->drc_frame_size - 1), 15);
|
|
}
|
|
|
|
if (version != 1) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_coefficients_uni_drc->gain_set_count, 6);
|
|
|
|
for (idx = 0; idx < pstr_drc_coefficients_uni_drc->gain_set_count; idx++) {
|
|
impd_drc_write_gain_set_params(it_bit_buf, version,
|
|
&(pstr_drc_coefficients_uni_drc->str_gain_set_params[idx]),
|
|
&bit_cnt_local);
|
|
}
|
|
} else {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_coefficients_uni_drc->drc_characteristic_left_present, 1);
|
|
if (pstr_drc_coefficients_uni_drc->drc_characteristic_left_present) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_coefficients_uni_drc->characteristic_left_count, 4);
|
|
|
|
for (idx = 1; idx <= pstr_drc_coefficients_uni_drc->characteristic_left_count; idx++) {
|
|
impd_drc_write_split_drc_characteristic(
|
|
it_bit_buf, LEFT_SIDE,
|
|
&pstr_drc_coefficients_uni_drc->str_split_characteristic_left[idx], &bit_cnt_local);
|
|
}
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_coefficients_uni_drc->drc_characteristic_right_present, 1);
|
|
if (pstr_drc_coefficients_uni_drc->drc_characteristic_right_present) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_coefficients_uni_drc->characteristic_right_count, 4);
|
|
for (idx = 1; idx <= pstr_drc_coefficients_uni_drc->characteristic_right_count; idx++) {
|
|
impd_drc_write_split_drc_characteristic(
|
|
it_bit_buf, RIGHT_SIDE,
|
|
&pstr_drc_coefficients_uni_drc->str_split_characteristic_right[idx], &bit_cnt_local);
|
|
}
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_coefficients_uni_drc->shape_filters_present, 1);
|
|
if (pstr_drc_coefficients_uni_drc->shape_filters_present) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_coefficients_uni_drc->shape_filter_count, 4);
|
|
for (idx = 1; idx <= pstr_drc_coefficients_uni_drc->shape_filter_count; idx++) {
|
|
impd_drc_write_shape_filter_block_params(
|
|
it_bit_buf, &pstr_drc_coefficients_uni_drc->str_shape_filter_block_params[idx],
|
|
&bit_cnt_local);
|
|
}
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_coefficients_uni_drc->gain_sequence_count, 6);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_coefficients_uni_drc->gain_set_count, 6);
|
|
|
|
for (idx = 0; idx < pstr_drc_coefficients_uni_drc->gain_set_count; idx++) {
|
|
impd_drc_write_gain_set_params(it_bit_buf, version,
|
|
&(pstr_drc_coefficients_uni_drc->str_gain_set_params[idx]),
|
|
&bit_cnt_local);
|
|
}
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static VOID impd_drc_write_downmix_instructions(
|
|
ia_bit_buf_struct *it_bit_buf, const WORD32 version, ia_drc_gain_enc_struct *pstr_gain_enc,
|
|
ia_drc_downmix_instructions_struct *pstr_downmix_instructions, WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX idx;
|
|
WORD32 code, code_size;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_downmix_instructions->downmix_id, 7);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_downmix_instructions->target_ch_count, 7);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_downmix_instructions->target_layout, 8);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_downmix_instructions->downmix_coefficients_present, 1);
|
|
|
|
if (pstr_downmix_instructions->downmix_coefficients_present) {
|
|
if (version != 1) {
|
|
WORD32 is_lfe_channel = FALSE;
|
|
for (idx = 0;
|
|
idx < (pstr_downmix_instructions->target_ch_count * pstr_gain_enc->base_ch_count);
|
|
idx++) {
|
|
impd_drc_enc_downmix_coeff(pstr_downmix_instructions->downmix_coeff[idx], is_lfe_channel,
|
|
&code_size, &code);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, (UWORD8)code_size);
|
|
}
|
|
} else {
|
|
impd_drc_dec_write_downmix_coeff_v1(
|
|
it_bit_buf, pstr_downmix_instructions->downmix_coeff, pstr_gain_enc->base_ch_count,
|
|
pstr_downmix_instructions->target_ch_count, &bit_cnt_local);
|
|
}
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static VOID impd_drc_enc_channel_weight(const FLOAT32 channel_weight_lin, WORD32 *code_size,
|
|
WORD32 *code) {
|
|
LOOPIDX idx;
|
|
FLOAT32 channel_weight_db;
|
|
const FLOAT32 *channel_weight_table;
|
|
|
|
channel_weight_table = impd_drc_channel_weight;
|
|
channel_weight_db = 20.0f * (FLOAT32)log10(channel_weight_lin);
|
|
|
|
if (channel_weight_db >= channel_weight_table[14]) {
|
|
idx = 0;
|
|
while (channel_weight_db < channel_weight_table[idx]) {
|
|
idx++;
|
|
}
|
|
if ((idx > 0) && (channel_weight_db >
|
|
0.5f * (channel_weight_table[idx - 1] + channel_weight_table[idx]))) {
|
|
idx--;
|
|
}
|
|
*code = idx;
|
|
} else {
|
|
*code = 15;
|
|
}
|
|
|
|
*code_size = 4;
|
|
}
|
|
|
|
static IA_ERRORCODE impd_drc_write_parametric_drc_gain_set_params(
|
|
ia_bit_buf_struct *it_bit_buf, ia_drc_uni_drc_config_struct *pstr_uni_drc_config,
|
|
ia_drc_parametric_drc_gain_set_params_struct *pstr_parametric_drc_gain_set_params,
|
|
WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX idx;
|
|
WORD32 code_size = 0, code = 0;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_gain_set_params->parametric_drc_id, 4);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_gain_set_params->side_chain_config_type, 3);
|
|
|
|
if (pstr_parametric_drc_gain_set_params->side_chain_config_type == 1) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_parametric_drc_gain_set_params->downmix_id, 7);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_gain_set_params->level_estim_channel_weight_format, 1);
|
|
|
|
if (pstr_parametric_drc_gain_set_params->downmix_id == 0x7F) {
|
|
pstr_parametric_drc_gain_set_params->channel_count_drom_downmix_id = 1;
|
|
} else if (pstr_parametric_drc_gain_set_params->downmix_id == 0x0) {
|
|
pstr_parametric_drc_gain_set_params->channel_count_drom_downmix_id =
|
|
pstr_uni_drc_config->str_channel_layout.base_ch_count;
|
|
} else {
|
|
for (idx = 0; idx < pstr_uni_drc_config->downmix_instructions_count; idx++) {
|
|
if (pstr_parametric_drc_gain_set_params->downmix_id ==
|
|
pstr_uni_drc_config->str_downmix_instructions[idx].downmix_id) {
|
|
break;
|
|
}
|
|
}
|
|
if (idx == pstr_uni_drc_config->downmix_instructions_count) {
|
|
return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
|
|
}
|
|
pstr_parametric_drc_gain_set_params->channel_count_drom_downmix_id =
|
|
pstr_uni_drc_config->str_downmix_instructions[idx].target_ch_count;
|
|
}
|
|
|
|
for (idx = 0; idx < pstr_parametric_drc_gain_set_params->channel_count_drom_downmix_id;
|
|
idx++) {
|
|
if (pstr_parametric_drc_gain_set_params->level_estim_channel_weight_format != 0) {
|
|
impd_drc_enc_channel_weight(
|
|
pstr_parametric_drc_gain_set_params->level_estim_channel_weight[idx], &code_size,
|
|
&code);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, (UWORD8)code_size);
|
|
} else {
|
|
if (pstr_parametric_drc_gain_set_params->level_estim_channel_weight[idx] == 0) {
|
|
code = 0;
|
|
} else {
|
|
code = 1;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_gain_set_params->drc_input_loudness_present, 1);
|
|
if (pstr_parametric_drc_gain_set_params->drc_input_loudness_present) {
|
|
code = ((WORD32)(0.5f +
|
|
4.0f * (pstr_parametric_drc_gain_set_params->drc_input_loudness + 57.75f) +
|
|
10000.0f)) -
|
|
10000;
|
|
code = MIN(0x0FF, code);
|
|
code = MAX(0x0, code);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 8);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
|
|
return IA_NO_ERROR;
|
|
}
|
|
|
|
static VOID impd_drc_write_parametric_drc_type_feed_forward(
|
|
ia_bit_buf_struct *it_bit_buf, WORD32 drc_frame_size_parametric_drc,
|
|
ia_drc_parametric_drc_type_feed_forward_struct *pstr_parametric_drc_type_feed_forward,
|
|
WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX idx;
|
|
WORD32 code = 0;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_type_feed_forward->level_estim_k_weighting_type, 2);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_type_feed_forward->level_estim_integration_time_present, 1);
|
|
|
|
if (pstr_parametric_drc_type_feed_forward->level_estim_integration_time_present) {
|
|
code =
|
|
(WORD32)(((FLOAT32)pstr_parametric_drc_type_feed_forward->level_estim_integration_time /
|
|
drc_frame_size_parametric_drc +
|
|
0.5f) -
|
|
1);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 6);
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_type_feed_forward->drc_curve_definition_type, 1);
|
|
if (pstr_parametric_drc_type_feed_forward->drc_curve_definition_type != 0) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_type_feed_forward->node_count - 2, 3);
|
|
|
|
for (idx = 0; idx < pstr_parametric_drc_type_feed_forward->node_count; idx++) {
|
|
if (idx == 0) {
|
|
code = -11 - pstr_parametric_drc_type_feed_forward->node_level[0];
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 6);
|
|
} else {
|
|
code = pstr_parametric_drc_type_feed_forward->node_level[idx] -
|
|
pstr_parametric_drc_type_feed_forward->node_level[idx - 1] - 1;
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 5);
|
|
}
|
|
code = pstr_parametric_drc_type_feed_forward->node_gain[idx] + 39;
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 6);
|
|
}
|
|
} else {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_type_feed_forward->drc_characteristic, 7);
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_type_feed_forward->drc_gain_smooth_parameters_present, 1);
|
|
if (pstr_parametric_drc_type_feed_forward->drc_gain_smooth_parameters_present) {
|
|
code = (WORD32)(pstr_parametric_drc_type_feed_forward->gain_smooth_attack_time_slow * 0.2);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 8);
|
|
|
|
code = (WORD32)(pstr_parametric_drc_type_feed_forward->gain_smooth_release_time_slow * 0.025);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 8);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_type_feed_forward->gain_smooth_time_fast_present, 1);
|
|
if (pstr_parametric_drc_type_feed_forward->gain_smooth_time_fast_present) {
|
|
code = (WORD32)(pstr_parametric_drc_type_feed_forward->gain_smooth_attack_time_fast * 0.2);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 8);
|
|
|
|
code =
|
|
(WORD32)(pstr_parametric_drc_type_feed_forward->gain_smooth_release_time_fast * 0.05);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 8);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_type_feed_forward->gain_smooth_threshold_present, 1);
|
|
if (pstr_parametric_drc_type_feed_forward->gain_smooth_threshold_present) {
|
|
if (pstr_parametric_drc_type_feed_forward->gain_smooth_attack_threshold <= 30) {
|
|
code = pstr_parametric_drc_type_feed_forward->gain_smooth_attack_threshold;
|
|
} else {
|
|
code = 31;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 5);
|
|
|
|
if (pstr_parametric_drc_type_feed_forward->gain_smooth_release_threshold <= 30) {
|
|
code = pstr_parametric_drc_type_feed_forward->gain_smooth_release_threshold;
|
|
} else {
|
|
code = 31;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 5);
|
|
}
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_type_feed_forward->gain_smooth_hold_off_count_present, 1);
|
|
if (pstr_parametric_drc_type_feed_forward->gain_smooth_hold_off_count_present) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_type_feed_forward->gain_smooth_hold_off, 7);
|
|
}
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static VOID impd_drc_write_parametric_drc_type_lim(
|
|
ia_bit_buf_struct *it_bit_buf,
|
|
ia_drc_parametric_drc_type_lim_struct *pstr_parametric_drc_type_lim, WORD32 *ptr_bit_cnt) {
|
|
WORD32 temp = 0;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_type_lim->parametric_lim_threshold_present, 1);
|
|
if (pstr_parametric_drc_type_lim->parametric_lim_threshold_present) {
|
|
temp = (WORD32)(0.5f - 8.0f * pstr_parametric_drc_type_lim->parametric_lim_threshold);
|
|
temp = MAX(0, temp);
|
|
temp = MIN(0xFF, temp);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, temp, 8);
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_type_lim->parametric_lim_release_present, 1);
|
|
if (pstr_parametric_drc_type_lim->parametric_lim_release_present) {
|
|
temp = (WORD32)(pstr_parametric_drc_type_lim->parametric_lim_release * 0.1);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, temp, 8);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static IA_ERRORCODE impd_drc_write_parametric_drc_instructions(
|
|
ia_bit_buf_struct *it_bit_buf, WORD32 drc_frame_size_parametric_drc,
|
|
ia_drc_parametric_drc_instructions_struct *pstr_parametric_drc_instructions,
|
|
WORD32 *ptr_bit_cnt) {
|
|
WORD32 bit_size = 0, len_size_bits = 0, bit_size_len = 0;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_parametric_drc_instructions->parametric_drc_id, 4);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_instructions->parametric_drc_look_ahead_present, 1);
|
|
|
|
if (pstr_parametric_drc_instructions->parametric_drc_look_ahead_present) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_instructions->parametric_drc_look_ahead, 7);
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_instructions->parametric_drc_preset_id_present, 1);
|
|
if (!(pstr_parametric_drc_instructions->parametric_drc_preset_id_present)) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_instructions->parametric_drc_type, 3);
|
|
|
|
if (pstr_parametric_drc_instructions->parametric_drc_type == PARAM_DRC_TYPE_LIM) {
|
|
impd_drc_write_parametric_drc_type_lim(
|
|
it_bit_buf, &(pstr_parametric_drc_instructions->str_parametric_drc_type_lim),
|
|
&bit_cnt_local);
|
|
} else if (pstr_parametric_drc_instructions->parametric_drc_type == PARAM_DRC_TYPE_FF) {
|
|
impd_drc_write_parametric_drc_type_feed_forward(
|
|
it_bit_buf, drc_frame_size_parametric_drc,
|
|
&(pstr_parametric_drc_instructions->str_parametric_drc_type_feed_forward),
|
|
&bit_cnt_local);
|
|
} else {
|
|
bit_size = pstr_parametric_drc_instructions->len_bit_size - 1;
|
|
len_size_bits = (WORD32)(log((FLOAT32)bit_size) / log(2.f)) + 1;
|
|
bit_size_len = len_size_bits - 4;
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bit_size_len, 4);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bit_size, (UWORD8)bit_size);
|
|
switch (pstr_parametric_drc_instructions->parametric_drc_type) {
|
|
default:
|
|
return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
|
|
}
|
|
}
|
|
} else {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_parametric_drc_instructions->parametric_drc_preset_id, 7);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
|
|
return IA_NO_ERROR;
|
|
}
|
|
|
|
static IA_ERRORCODE impd_drc_write_drc_coeff_parametric_drc(
|
|
ia_bit_buf_struct *it_bit_buf, ia_drc_uni_drc_config_struct *pstr_uni_drc_config,
|
|
ia_drc_coeff_parametric_drc_struct *pstr_drc_coeff_parametric_drc, WORD32 *ptr_bit_cnt) {
|
|
IA_ERRORCODE err_code = IA_NO_ERROR;
|
|
LOOPIDX idx;
|
|
WORD32 bits = 0, mu = 0, nu = 0;
|
|
WORD32 bit_cnt_local = 0;
|
|
FLOAT32 exp = 0.f;
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_coeff_parametric_drc->drc_location, 4);
|
|
|
|
exp = (FLOAT32)(log(pstr_drc_coeff_parametric_drc->parametric_drc_frame_size) / log(2));
|
|
if (exp == (FLOAT32)((WORD32)exp)) {
|
|
pstr_drc_coeff_parametric_drc->parametric_drc_frame_size_format = 0;
|
|
} else {
|
|
pstr_drc_coeff_parametric_drc->parametric_drc_frame_size_format = 1;
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_coeff_parametric_drc->parametric_drc_frame_size_format, 1);
|
|
if (!(pstr_drc_coeff_parametric_drc->parametric_drc_frame_size_format)) {
|
|
bits = (WORD32)exp;
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bits, 4);
|
|
} else {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, (pstr_drc_coeff_parametric_drc->parametric_drc_frame_size - 1), 15);
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_coeff_parametric_drc->parametric_drc_delay_max_present, 1);
|
|
if (pstr_drc_coeff_parametric_drc->parametric_drc_delay_max_present == 1) {
|
|
for (nu = 0; nu < 8; nu++) {
|
|
mu = pstr_drc_coeff_parametric_drc->parametric_drc_delay_max / (16 << nu);
|
|
if (mu * (16 << nu) < pstr_drc_coeff_parametric_drc->parametric_drc_delay_max) {
|
|
mu++;
|
|
}
|
|
if (mu < 32) {
|
|
break;
|
|
}
|
|
}
|
|
if (nu == 8) {
|
|
mu = 31;
|
|
nu = 7;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, mu, 5);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, nu, 3);
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_coeff_parametric_drc->reset_parametric_drc, 1);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_drc_coeff_parametric_drc->parametric_drc_gain_set_count, 6);
|
|
for (idx = 0; idx < pstr_drc_coeff_parametric_drc->parametric_drc_gain_set_count; idx++) {
|
|
err_code = impd_drc_write_parametric_drc_gain_set_params(
|
|
it_bit_buf, pstr_uni_drc_config,
|
|
&(pstr_drc_coeff_parametric_drc->parametric_drc_gain_set_params[idx]), &bit_cnt_local);
|
|
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return err_code;
|
|
}
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
|
|
return err_code;
|
|
}
|
|
|
|
static VOID impd_drc_write_loud_eq_instructions(
|
|
ia_bit_buf_struct *it_bit_buf, ia_drc_loud_eq_instructions_struct *pstr_loud_eq_instructions,
|
|
WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX idx;
|
|
WORD32 bit_cnt_local = 0;
|
|
WORD32 bs_loud_eq_offset;
|
|
WORD32 bs_loud_eq_scaling;
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_loud_eq_instructions->loud_eq_set_id, 4);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_loud_eq_instructions->drc_location, 4);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_loud_eq_instructions->downmix_id_present, 1);
|
|
if (pstr_loud_eq_instructions->downmix_id_present) {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_loud_eq_instructions->downmix_id, 7);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loud_eq_instructions->additional_downmix_id_present, 1);
|
|
if (!(pstr_loud_eq_instructions->additional_downmix_id_present)) {
|
|
pstr_loud_eq_instructions->additional_downmix_id_count = 0;
|
|
} else {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loud_eq_instructions->additional_downmix_id_count, 7);
|
|
for (idx = 0; idx < pstr_loud_eq_instructions->additional_downmix_id_count; idx++) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loud_eq_instructions->additional_downmix_id[idx], 7);
|
|
}
|
|
}
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_loud_eq_instructions->drc_set_id_present, 1);
|
|
if (pstr_loud_eq_instructions->drc_set_id_present) {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_loud_eq_instructions->drc_set_id, 6);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loud_eq_instructions->additional_drc_set_id_present, 1);
|
|
if (!(pstr_loud_eq_instructions->additional_drc_set_id_present)) {
|
|
pstr_loud_eq_instructions->additional_drc_set_id_count = 0;
|
|
} else {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loud_eq_instructions->additional_drc_set_id_count, 6);
|
|
for (idx = 0; idx < pstr_loud_eq_instructions->additional_drc_set_id_count; idx++) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loud_eq_instructions->additional_drc_set_id[idx], 6);
|
|
}
|
|
}
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_loud_eq_instructions->eq_set_id_present, 1);
|
|
if (pstr_loud_eq_instructions->eq_set_id_present) {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_loud_eq_instructions->eq_set_id, 6);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loud_eq_instructions->additional_eq_set_id_present, 1);
|
|
if (!(pstr_loud_eq_instructions->additional_eq_set_id_present)) {
|
|
pstr_loud_eq_instructions->additional_eq_set_id_count = 0;
|
|
} else {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loud_eq_instructions->additional_eq_set_id_count, 6);
|
|
for (idx = 0; idx < pstr_loud_eq_instructions->additional_eq_set_id_count; idx++) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loud_eq_instructions->additional_eq_set_id[idx], 6);
|
|
}
|
|
}
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_loud_eq_instructions->loudness_after_drc, 1);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_loud_eq_instructions->loudness_after_eq, 1);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loud_eq_instructions->loud_eq_gain_sequence_count, 6);
|
|
for (idx = 0; idx < pstr_loud_eq_instructions->loud_eq_gain_sequence_count; idx++) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_loud_eq_instructions->gain_sequence_index[idx], 6);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loud_eq_instructions->drc_characteristic_format_is_cicp[idx], 1);
|
|
if (pstr_loud_eq_instructions->drc_characteristic_format_is_cicp[idx] == 1) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loud_eq_instructions->drc_characteristic[idx], 7);
|
|
} else {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loud_eq_instructions->drc_characteristic_left_index[idx], 4);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loud_eq_instructions->drc_characteristic_right_index[idx], 4);
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loud_eq_instructions->frequency_range_index[idx], 6);
|
|
bs_loud_eq_scaling = (WORD32)floor(
|
|
0.5f - 2.0f * INV_LOG10_2 * log10(pstr_loud_eq_instructions->loud_eq_scaling[idx]));
|
|
if (bs_loud_eq_scaling < 0) {
|
|
bs_loud_eq_scaling = 0;
|
|
} else if (bs_loud_eq_scaling > 7) {
|
|
bs_loud_eq_scaling = 7;
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bs_loud_eq_scaling, 3);
|
|
bs_loud_eq_offset =
|
|
(WORD32)floor(0.5f + pstr_loud_eq_instructions->loud_eq_offset[idx] / 1.5f + 16.0f);
|
|
if (bs_loud_eq_offset < 0) {
|
|
bs_loud_eq_offset = 0;
|
|
} else if (bs_loud_eq_offset > 31) {
|
|
bs_loud_eq_offset = 31;
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bs_loud_eq_offset, 5);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static VOID impd_drc_write_filter_element(ia_bit_buf_struct *it_bit_buf,
|
|
ia_drc_filter_element_struct *pstr_filter_element,
|
|
WORD32 *ptr_bit_cnt) {
|
|
WORD32 bs_filter_element_gain;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_filter_element->filter_element_index, 6);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_filter_element->filter_element_gain_present, 1);
|
|
if (pstr_filter_element->filter_element_gain_present) {
|
|
bs_filter_element_gain =
|
|
(WORD32)floor(0.5f + 8.0f * (pstr_filter_element->filter_element_gain + 96.0f));
|
|
bs_filter_element_gain = MAX(0, bs_filter_element_gain);
|
|
bs_filter_element_gain = MIN(1023, bs_filter_element_gain);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bs_filter_element_gain, 10);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static VOID impd_drc_write_filter_block(ia_bit_buf_struct *it_bit_buf,
|
|
ia_drc_filter_block_struct *pstr_filter_block,
|
|
WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX idx;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_filter_block->filter_element_count, 6);
|
|
for (idx = 0; idx < pstr_filter_block->filter_element_count; idx++) {
|
|
impd_drc_write_filter_element(it_bit_buf, &(pstr_filter_block->filter_element[idx]),
|
|
&bit_cnt_local);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static IA_ERRORCODE impd_drc_encode_radius(FLOAT32 radius, WORD32 *code) {
|
|
LOOPIDX idx;
|
|
FLOAT32 rho;
|
|
|
|
if (radius < 0.0f) {
|
|
return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
|
|
}
|
|
rho = 1.0f - radius;
|
|
if ((rho < 0.0f) || (rho > 1.0f)) {
|
|
if (rho < 0.0f) {
|
|
rho = 0.0f;
|
|
}
|
|
if (rho > 1.0f) {
|
|
rho = 1.0f;
|
|
}
|
|
}
|
|
if (rho > impd_drc_zero_pole_radius_table[127]) {
|
|
rho = impd_drc_zero_pole_radius_table[127];
|
|
}
|
|
idx = 0;
|
|
while (rho > impd_drc_zero_pole_radius_table[idx]) {
|
|
idx++;
|
|
}
|
|
if (idx == 0) {
|
|
return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
|
|
}
|
|
if (rho <
|
|
0.5f * (impd_drc_zero_pole_radius_table[idx - 1] + impd_drc_zero_pole_radius_table[idx])) {
|
|
idx--;
|
|
}
|
|
*code = idx;
|
|
|
|
return IA_NO_ERROR;
|
|
}
|
|
|
|
static LOOPIDX impd_drc_encode_angle(FLOAT32 angle) {
|
|
LOOPIDX idx;
|
|
|
|
if ((angle < 0.0f) || (angle > 1.0f)) {
|
|
if (angle < 0.0f) {
|
|
angle = 0.0f;
|
|
}
|
|
if (angle > 1.0f) {
|
|
angle = 1.0f;
|
|
}
|
|
}
|
|
idx = 0;
|
|
while (angle > impd_drc_zero_pole_angle_table[idx]) {
|
|
idx++;
|
|
}
|
|
if (idx == 0) {
|
|
return idx;
|
|
}
|
|
if (angle <
|
|
0.5f * (impd_drc_zero_pole_angle_table[idx - 1] + impd_drc_zero_pole_angle_table[idx])) {
|
|
idx--;
|
|
}
|
|
|
|
return (idx);
|
|
}
|
|
|
|
static IA_ERRORCODE impd_drc_write_unique_td_filter_element(
|
|
ia_bit_buf_struct *it_bit_buf,
|
|
ia_drc_unique_td_filter_element_struct *pstr_unique_td_filter_element, WORD32 *ptr_bit_cnt) {
|
|
IA_ERRORCODE err_code = IA_NO_ERROR;
|
|
LOOPIDX idx;
|
|
WORD32 sign, code;
|
|
WORD32 bs_real_zero_radius_one_count;
|
|
WORD32 bs_fir_coefficient;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_unique_td_filter_element->eq_filter_format, 1);
|
|
if (pstr_unique_td_filter_element->eq_filter_format != 0) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_unique_td_filter_element->fir_filter_order, 7);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_unique_td_filter_element->fir_symmetry, 1);
|
|
|
|
for (idx = 0; idx < pstr_unique_td_filter_element->fir_filter_order / 2 + 1; idx++) {
|
|
if (pstr_unique_td_filter_element->fir_coefficient[idx] >= 0.0f) {
|
|
sign = 0;
|
|
} else {
|
|
sign = 1;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, sign, 1);
|
|
|
|
bs_fir_coefficient =
|
|
(WORD32)floor(0.5f - log10(fabs(pstr_unique_td_filter_element->fir_coefficient[idx])) /
|
|
(0.05f * 0.0625f));
|
|
|
|
if (bs_fir_coefficient > 1023) {
|
|
bs_fir_coefficient = 1023;
|
|
}
|
|
if (bs_fir_coefficient < 0) {
|
|
bs_fir_coefficient = 0;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bs_fir_coefficient, 10);
|
|
}
|
|
} else {
|
|
bs_real_zero_radius_one_count = pstr_unique_td_filter_element->real_zero_radius_one_count / 2;
|
|
if ((pstr_unique_td_filter_element->real_zero_radius_one_count ==
|
|
2 * bs_real_zero_radius_one_count) &&
|
|
(bs_real_zero_radius_one_count < 8)) {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bs_real_zero_radius_one_count, 3);
|
|
} else {
|
|
return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_unique_td_filter_element->real_zero_count, 6);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_unique_td_filter_element->generic_zero_count, 6);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_unique_td_filter_element->real_pole_count, 4);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_unique_td_filter_element->complex_pole_count, 4);
|
|
|
|
for (idx = 0; idx < pstr_unique_td_filter_element->real_zero_radius_one_count; idx++) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, (UWORD32)pstr_unique_td_filter_element->zero_sign[idx], 1);
|
|
}
|
|
|
|
for (idx = 0; idx < pstr_unique_td_filter_element->real_zero_count; idx++) {
|
|
err_code = impd_drc_encode_radius(
|
|
(FLOAT32)fabs(pstr_unique_td_filter_element->real_zero_radius[idx]), &code);
|
|
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return err_code;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 7);
|
|
|
|
if (pstr_unique_td_filter_element->real_zero_radius[idx] >= 0.0f) {
|
|
sign = 0;
|
|
} else {
|
|
sign = 1;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, sign, 1);
|
|
}
|
|
|
|
for (idx = 0; idx < pstr_unique_td_filter_element->generic_zero_count; idx++) {
|
|
err_code =
|
|
impd_drc_encode_radius(pstr_unique_td_filter_element->generic_zero_radius[idx], &code);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return err_code;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 7);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf,
|
|
impd_drc_encode_angle(pstr_unique_td_filter_element->generic_zero_angle[idx]), 7);
|
|
}
|
|
|
|
for (idx = 0; idx < pstr_unique_td_filter_element->real_pole_count; idx++) {
|
|
err_code = impd_drc_encode_radius(
|
|
(FLOAT32)fabs(pstr_unique_td_filter_element->real_pole_radius[idx]), &code);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return err_code;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 7);
|
|
|
|
if (pstr_unique_td_filter_element->real_pole_radius[idx] >= 0.0f) {
|
|
sign = 0;
|
|
} else {
|
|
sign = 1;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, sign, 1);
|
|
}
|
|
|
|
for (idx = 0; idx < pstr_unique_td_filter_element->complex_pole_count; idx++) {
|
|
err_code =
|
|
impd_drc_encode_radius(pstr_unique_td_filter_element->complex_pole_radius[idx], &code);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return err_code;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 7);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf,
|
|
impd_drc_encode_angle(pstr_unique_td_filter_element->complex_pole_angle[idx]), 7);
|
|
}
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
|
|
return err_code;
|
|
}
|
|
|
|
static VOID impd_drc_encode_eq_slope(FLOAT32 eq_slope, WORD32 *size, WORD32 *code) {
|
|
LOOPIDX idx;
|
|
|
|
if (fabs(eq_slope) >= 0.5f) {
|
|
*size = 5;
|
|
if (eq_slope > 32.0f) {
|
|
*code = 15;
|
|
} else if (eq_slope <= -32.0f) {
|
|
*code = 0;
|
|
} else {
|
|
idx = 1;
|
|
while (eq_slope > impd_drc_eq_slope_table[idx]) {
|
|
idx++;
|
|
}
|
|
if (eq_slope < 0.5f * (impd_drc_eq_slope_table[idx - 1] + impd_drc_eq_slope_table[idx])) {
|
|
idx--;
|
|
}
|
|
*code = idx;
|
|
}
|
|
} else {
|
|
*size = 1;
|
|
*code = 1;
|
|
}
|
|
}
|
|
|
|
static VOID impd_drc_encode_eq_gain_initial(FLOAT32 eq_gain_initial, WORD32 *prefix_code,
|
|
WORD32 *size, WORD32 *code) {
|
|
if ((eq_gain_initial > -8.5f) && (eq_gain_initial < 7.75f)) {
|
|
*size = 5;
|
|
*prefix_code = 0;
|
|
*code = (WORD32)floor(0.5f + 2.0f * (MAX(-8.0f, eq_gain_initial) + 8.0f));
|
|
} else if (eq_gain_initial < 0.0f) {
|
|
if (eq_gain_initial > -17.0f) {
|
|
*size = 4;
|
|
*prefix_code = 1;
|
|
*code = (WORD32)floor(0.5f + MAX(-16.0f, eq_gain_initial) + 16.0f);
|
|
} else if (eq_gain_initial > -34.0f) {
|
|
*size = 4;
|
|
*prefix_code = 2;
|
|
*code = (WORD32)floor(0.5f + 0.5f * (MAX(-32.0f, eq_gain_initial) + 32.0f));
|
|
} else {
|
|
*size = 3;
|
|
*prefix_code = 3;
|
|
*code = (WORD32)floor(0.5f + 0.25f * (MAX(-64.0f, eq_gain_initial) + 64.0f));
|
|
}
|
|
} else {
|
|
if (eq_gain_initial >= 15.5f) {
|
|
*size = 4;
|
|
*prefix_code = 2;
|
|
*code = (WORD32)floor(0.5f + 0.5f * MIN(30.0f, eq_gain_initial));
|
|
} else {
|
|
*size = 4;
|
|
*prefix_code = 1;
|
|
*code = (WORD32)floor(0.5f + eq_gain_initial);
|
|
}
|
|
}
|
|
}
|
|
|
|
static VOID impd_drc_encode_eq_gain_delta(FLOAT32 eq_gain_delta, WORD32 *code) {
|
|
LOOPIDX idx;
|
|
|
|
if (eq_gain_delta >= 32.0f) {
|
|
*code = 31;
|
|
} else if (eq_gain_delta <= -22.0f) {
|
|
*code = 0;
|
|
} else {
|
|
idx = 1;
|
|
while (eq_gain_delta > impd_drc_eq_gain_delta_table[idx]) {
|
|
idx++;
|
|
}
|
|
if (eq_gain_delta <
|
|
0.5f * (impd_drc_eq_gain_delta_table[idx - 1] + impd_drc_eq_gain_delta_table[idx])) {
|
|
idx--;
|
|
}
|
|
*code = idx;
|
|
}
|
|
}
|
|
|
|
static VOID impd_drc_write_eq_subband_gain_spline(
|
|
ia_bit_buf_struct *it_bit_buf,
|
|
ia_drc_eq_subband_gain_spline_struct *pstr_eq_subband_gain_spline, WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX idx;
|
|
WORD32 size, code, prefix_code;
|
|
WORD32 bit_cnt_local = 0;
|
|
WORD32 bs_eq_node_count = pstr_eq_subband_gain_spline->n_eq_nodes - 2;
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bs_eq_node_count, 5);
|
|
|
|
for (idx = 0; idx < pstr_eq_subband_gain_spline->n_eq_nodes; idx++) {
|
|
impd_drc_encode_eq_slope(pstr_eq_subband_gain_spline->eq_slope[idx], &size, &code);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, (UWORD8)size);
|
|
}
|
|
|
|
for (idx = 1; idx < pstr_eq_subband_gain_spline->n_eq_nodes; idx++) {
|
|
code = MIN(15, pstr_eq_subband_gain_spline->eq_freq_delta[idx] - 1);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 4);
|
|
}
|
|
|
|
impd_drc_encode_eq_gain_initial(pstr_eq_subband_gain_spline->eq_gain_initial, &prefix_code,
|
|
&size, &code);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, prefix_code, 2);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, (UWORD8)size);
|
|
|
|
for (idx = 1; idx < pstr_eq_subband_gain_spline->n_eq_nodes; idx++) {
|
|
impd_drc_encode_eq_gain_delta(pstr_eq_subband_gain_spline->eq_gain_delta[idx], &code);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, code, 5);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static VOID impd_drc_write_eq_subband_gain_vector(
|
|
ia_bit_buf_struct *it_bit_buf, WORD32 eq_subband_gain_count,
|
|
ia_drc_eq_subband_gain_vector_struct *pstr_eq_subband_gain_vector, WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX idx = 0;
|
|
WORD32 sign;
|
|
WORD32 bs_eq_subband_gain;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
for (idx = 0; idx < eq_subband_gain_count; idx++) {
|
|
bs_eq_subband_gain =
|
|
(WORD32)floor(0.5f + fabs(pstr_eq_subband_gain_vector->eq_subband_gain[idx] * 8.0f));
|
|
|
|
if (pstr_eq_subband_gain_vector->eq_subband_gain[idx] >= 0.0f) {
|
|
sign = 0;
|
|
} else {
|
|
sign = 1;
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, sign, 1);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bs_eq_subband_gain, 8);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static IA_ERRORCODE impd_drc_write_eq_coefficients(
|
|
ia_bit_buf_struct *it_bit_buf, ia_drc_eq_coefficients_struct *pstr_eq_coefficients,
|
|
WORD32 *ptr_bit_cnt) {
|
|
IA_ERRORCODE err_code = IA_NO_ERROR;
|
|
LOOPIDX idx;
|
|
WORD32 bs_eq_gain_count;
|
|
WORD32 mu = 0, nu = 0;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_coefficients->eq_delay_max_present, 1);
|
|
if (pstr_eq_coefficients->eq_delay_max_present == 1) {
|
|
for (nu = 0; nu < 8; nu++) {
|
|
mu = pstr_eq_coefficients->eq_delay_max / (16 << nu);
|
|
if (mu * (16 << nu) < pstr_eq_coefficients->eq_delay_max) {
|
|
mu++;
|
|
}
|
|
if (mu < 32) {
|
|
break;
|
|
}
|
|
}
|
|
if (nu == 8) {
|
|
mu = 31;
|
|
nu = 7;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, mu, 5);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, nu, 3);
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_coefficients->unique_filter_block_count, 6);
|
|
for (idx = 0; idx < pstr_eq_coefficients->unique_filter_block_count; idx++) {
|
|
impd_drc_write_filter_block(it_bit_buf, &(pstr_eq_coefficients->str_filter_block[idx]),
|
|
&bit_cnt_local);
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_coefficients->unique_td_filter_element_count, 6);
|
|
for (idx = 0; idx < pstr_eq_coefficients->unique_td_filter_element_count; idx++) {
|
|
err_code = impd_drc_write_unique_td_filter_element(
|
|
it_bit_buf, &(pstr_eq_coefficients->str_unique_td_filter_element[idx]), &bit_cnt_local);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return err_code;
|
|
}
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_coefficients->unique_eq_subband_gains_count, 6);
|
|
if (pstr_eq_coefficients->unique_eq_subband_gains_count > 0) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_eq_coefficients->eq_subband_gain_representation, 1);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_coefficients->eq_subband_gain_format, 4);
|
|
|
|
switch (pstr_eq_coefficients->eq_subband_gain_format) {
|
|
case GAINFORMAT_QMFHYBRID135:
|
|
pstr_eq_coefficients->eq_subband_gain_count = 135;
|
|
break;
|
|
case GAINFORMAT_QMF128:
|
|
pstr_eq_coefficients->eq_subband_gain_count = 128;
|
|
break;
|
|
case GAINFORMAT_QMFHYBRID71:
|
|
pstr_eq_coefficients->eq_subband_gain_count = 71;
|
|
break;
|
|
case GAINFORMAT_QMF64:
|
|
pstr_eq_coefficients->eq_subband_gain_count = 64;
|
|
break;
|
|
case GAINFORMAT_QMFHYBRID39:
|
|
pstr_eq_coefficients->eq_subband_gain_count = 39;
|
|
break;
|
|
case GAINFORMAT_QMF32:
|
|
pstr_eq_coefficients->eq_subband_gain_count = 32;
|
|
break;
|
|
case GAINFORMAT_UNIFORM:
|
|
default:
|
|
bs_eq_gain_count = pstr_eq_coefficients->eq_subband_gain_count - 1;
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bs_eq_gain_count, 8);
|
|
break;
|
|
}
|
|
|
|
for (idx = 0; idx < pstr_eq_coefficients->unique_eq_subband_gains_count; idx++) {
|
|
if (pstr_eq_coefficients->eq_subband_gain_representation != 1) {
|
|
impd_drc_write_eq_subband_gain_vector(
|
|
it_bit_buf, pstr_eq_coefficients->eq_subband_gain_count,
|
|
&(pstr_eq_coefficients->str_eq_subband_gain_vector[idx]), &bit_cnt_local);
|
|
} else {
|
|
impd_drc_write_eq_subband_gain_spline(
|
|
it_bit_buf, &(pstr_eq_coefficients->str_eq_subband_gain_spline[idx]), &bit_cnt_local);
|
|
}
|
|
}
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
|
|
return err_code;
|
|
}
|
|
|
|
static VOID impd_drc_write_filter_block_refs(
|
|
ia_bit_buf_struct *it_bit_buf, ia_drc_filter_block_refs_struct *pstr_filter_block_refs,
|
|
WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX idx;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_filter_block_refs->filter_block_count, 4);
|
|
for (idx = 0; idx < pstr_filter_block_refs->filter_block_count; idx++) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_filter_block_refs->filter_block_index[idx], 7);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static VOID impd_drc_write_td_filter_cascade(
|
|
ia_bit_buf_struct *it_bit_buf, const WORD32 eq_channel_group_count,
|
|
ia_drc_td_filter_cascade_struct *pstr_td_filter_cascade, WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX i, j;
|
|
WORD32 bs_eq_cascade_gain;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
for (i = 0; i < eq_channel_group_count; i++) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_td_filter_cascade->eq_cascade_gain_present[i], 1);
|
|
if (pstr_td_filter_cascade->eq_cascade_gain_present[i] == 1) {
|
|
bs_eq_cascade_gain =
|
|
(WORD32)floor(0.5f + 8.0f * (pstr_td_filter_cascade->eq_cascade_gain[i] + 96.0f));
|
|
bs_eq_cascade_gain = MAX(0, bs_eq_cascade_gain);
|
|
bs_eq_cascade_gain = MIN(1023, bs_eq_cascade_gain);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bs_eq_cascade_gain, 10);
|
|
}
|
|
impd_drc_write_filter_block_refs(
|
|
it_bit_buf, &(pstr_td_filter_cascade->str_filter_block_refs[i]), &bit_cnt_local);
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_td_filter_cascade->eq_phase_alignment_present, 1);
|
|
if (pstr_td_filter_cascade->eq_phase_alignment_present == 1) {
|
|
for (i = 0; i < eq_channel_group_count; i++) {
|
|
for (j = i + 1; j < eq_channel_group_count; j++) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_td_filter_cascade->eq_phase_alignment[i][j], 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static IA_ERRORCODE impd_drc_write_eq_instructions(
|
|
ia_bit_buf_struct *it_bit_buf, ia_drc_uni_drc_config_ext_struct *pstr_uni_drc_config_ext,
|
|
ia_drc_gain_enc_struct *pstr_gain_enc, ia_drc_eq_instructions_struct *pstr_eq_instructions,
|
|
WORD32 *ptr_bit_cnt, VOID *ptr_scratch, WORD32 *scratch_used) {
|
|
IA_ERRORCODE err_code = IA_NO_ERROR;
|
|
LOOPIDX idx;
|
|
WORD32 bs_eq_transition_duration;
|
|
WORD32 bit_cnt_local = 0;
|
|
FLOAT32 temp;
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->eq_set_id, 6);
|
|
|
|
err_code = impd_drc_get_eq_complexity_level(pstr_uni_drc_config_ext, pstr_gain_enc,
|
|
pstr_eq_instructions, ptr_scratch, scratch_used);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return err_code;
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->eq_set_complexity_level, 4);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->downmix_id_present, 1);
|
|
if (pstr_eq_instructions->downmix_id_present == 1) {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->downmix_id, 7);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->eq_apply_to_downmix, 1);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->additional_downmix_id_present, 1);
|
|
if (pstr_eq_instructions->additional_downmix_id_present == 1) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->additional_downmix_id_count, 7);
|
|
for (idx = 0; idx < pstr_eq_instructions->additional_downmix_id_count; idx++) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_eq_instructions->additional_downmix_id[idx], 7);
|
|
}
|
|
}
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->drc_set_id, 6);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->additional_drc_set_id_present, 1);
|
|
if (pstr_eq_instructions->additional_drc_set_id_present == 1) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->additional_drc_set_id_count, 6);
|
|
for (idx = 0; idx < pstr_eq_instructions->additional_drc_set_id_count; idx++) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->additional_drc_set_id[idx], 6);
|
|
}
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->eq_set_purpose, 16);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->depends_on_eq_set_present, 1);
|
|
if (pstr_eq_instructions->depends_on_eq_set_present != 1) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->no_independent_eq_use, 1);
|
|
} else {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->depends_on_eq_set, 6);
|
|
}
|
|
|
|
for (idx = 0; idx < pstr_eq_instructions->eq_channel_count; idx++) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_eq_instructions->eq_channel_group_for_channel[idx], 7);
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->td_filter_cascade_present, 1);
|
|
if (pstr_eq_instructions->td_filter_cascade_present == 1) {
|
|
impd_drc_write_td_filter_cascade(it_bit_buf, pstr_eq_instructions->eq_channel_group_count,
|
|
&(pstr_eq_instructions->str_td_filter_cascade),
|
|
&bit_cnt_local);
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->subband_gains_present, 1);
|
|
if (pstr_eq_instructions->subband_gains_present == 1) {
|
|
for (idx = 0; idx < pstr_eq_instructions->eq_channel_group_count; idx++) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->subband_gains_index[idx], 6);
|
|
}
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_eq_instructions->eq_transition_duration_present, 1);
|
|
if (pstr_eq_instructions->eq_transition_duration_present == 1) {
|
|
temp = MAX(0.004f, pstr_eq_instructions->eq_transition_duration);
|
|
temp = MIN(0.861f, temp);
|
|
bs_eq_transition_duration =
|
|
(WORD32)floor(0.5f + 4.0f * (log10(1000.0f * temp) / log10(2.0f) - 2.0f));
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bs_eq_transition_duration, 5);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
|
|
return err_code;
|
|
}
|
|
|
|
static IA_ERRORCODE impd_drc_write_uni_drc_config_extn(
|
|
ia_drc_enc_state *pstr_drc_state, ia_drc_gain_enc_struct *pstr_gain_enc,
|
|
ia_drc_uni_drc_config_struct *pstr_uni_drc_config,
|
|
ia_drc_uni_drc_config_ext_struct *pstr_uni_drc_config_ext, WORD32 *ptr_bit_cnt,
|
|
FLAG write_bs) {
|
|
IA_ERRORCODE err_code = IA_NO_ERROR;
|
|
LOOPIDX idx;
|
|
WORD32 version;
|
|
WORD32 counter = 0;
|
|
WORD32 ext_size_bits = 0, bit_size_len = 0, bit_size = 0;
|
|
WORD32 bit_cnt_local = 0, bit_cnt_local_ext = 0;
|
|
WORD32 *scratch_used = &pstr_drc_state->drc_scratch_used;
|
|
VOID *ptr_scratch = &pstr_drc_state->drc_scratch_mem;
|
|
ia_bit_buf_struct *it_bit_buf = NULL;
|
|
ia_bit_buf_struct *ptr_bit_buf_ext = NULL;
|
|
|
|
if (write_bs) {
|
|
it_bit_buf = &pstr_drc_state->str_bit_buf_cfg;
|
|
ptr_bit_buf_ext = &pstr_drc_state->str_bit_buf_cfg_ext;
|
|
|
|
iusace_reset_bit_buffer(ptr_bit_buf_ext);
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_uni_drc_config_ext->uni_drc_config_ext_type[counter], 4);
|
|
while (counter < 2 &&
|
|
pstr_uni_drc_config_ext->uni_drc_config_ext_type[counter] != UNIDRC_CONF_EXT_TERM) {
|
|
switch (pstr_uni_drc_config_ext->uni_drc_config_ext_type[counter]) {
|
|
case UNIDRC_CONF_EXT_PARAM_DRC: {
|
|
#ifdef LOUDNESS_LEVELING_SUPPORT
|
|
bit_cnt_local_ext = 0;
|
|
#endif // LOUDNESS_LEVELING_SUPPORT
|
|
err_code = impd_drc_write_drc_coeff_parametric_drc(
|
|
ptr_bit_buf_ext, pstr_uni_drc_config,
|
|
&(pstr_uni_drc_config_ext->str_drc_coeff_parametric_drc), &bit_cnt_local_ext);
|
|
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return err_code;
|
|
}
|
|
|
|
bit_cnt_local_ext += iusace_write_bits_buf(
|
|
ptr_bit_buf_ext, pstr_uni_drc_config_ext->parametric_drc_instructions_count, 4);
|
|
for (idx = 0; idx < pstr_uni_drc_config_ext->parametric_drc_instructions_count; idx++) {
|
|
err_code = impd_drc_write_parametric_drc_instructions(
|
|
ptr_bit_buf_ext,
|
|
pstr_uni_drc_config_ext->str_drc_coeff_parametric_drc.parametric_drc_frame_size,
|
|
&(pstr_uni_drc_config_ext->str_parametric_drc_instructions[idx]),
|
|
&bit_cnt_local_ext);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return err_code;
|
|
}
|
|
}
|
|
} break;
|
|
case UNIDRC_CONF_EXT_V1: {
|
|
version = 1;
|
|
#ifdef LOUDNESS_LEVELING_SUPPORT
|
|
bit_cnt_local_ext = 0;
|
|
#endif // LOUDNESS_LEVELING_SUPPORT
|
|
bit_cnt_local_ext += iusace_write_bits_buf(
|
|
ptr_bit_buf_ext, pstr_uni_drc_config_ext->downmix_instructions_v1_present, 1);
|
|
if (pstr_uni_drc_config_ext->downmix_instructions_v1_present == 1) {
|
|
bit_cnt_local_ext += iusace_write_bits_buf(
|
|
ptr_bit_buf_ext, pstr_uni_drc_config_ext->downmix_instructions_v1_count, 7);
|
|
for (idx = 0; idx < pstr_uni_drc_config_ext->downmix_instructions_v1_count; idx++) {
|
|
impd_drc_write_downmix_instructions(
|
|
ptr_bit_buf_ext, version, pstr_gain_enc,
|
|
&(pstr_uni_drc_config_ext->str_downmix_instructions_v1[idx]), &bit_cnt_local_ext);
|
|
}
|
|
}
|
|
|
|
bit_cnt_local_ext += iusace_write_bits_buf(
|
|
ptr_bit_buf_ext,
|
|
pstr_uni_drc_config_ext->drc_coeffs_and_instructions_uni_drc_v1_present, 1);
|
|
if (pstr_uni_drc_config_ext->drc_coeffs_and_instructions_uni_drc_v1_present == 1) {
|
|
bit_cnt_local_ext += iusace_write_bits_buf(
|
|
ptr_bit_buf_ext, pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count, 3);
|
|
for (idx = 0; idx < pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count; idx++) {
|
|
impd_drc_write_drc_coeff_uni_drc(
|
|
ptr_bit_buf_ext, version,
|
|
&(pstr_uni_drc_config_ext->str_drc_coefficients_uni_drc_v1[idx]),
|
|
&bit_cnt_local_ext);
|
|
}
|
|
#ifdef LOUDNESS_LEVELING_SUPPORT
|
|
UWORD32 num_ducking_only_drc_sets = get_num_ducking_only_drc_sets(
|
|
pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1,
|
|
pstr_uni_drc_config_ext->drc_instructions_uni_drc_v1_count);
|
|
|
|
bit_cnt_local_ext +=
|
|
iusace_write_bits_buf(ptr_bit_buf_ext,
|
|
pstr_uni_drc_config_ext->drc_instructions_uni_drc_v1_count -
|
|
num_ducking_only_drc_sets,
|
|
6);
|
|
#else
|
|
bit_cnt_local_ext += iusace_write_bits_buf(
|
|
ptr_bit_buf_ext, pstr_uni_drc_config_ext->drc_instructions_uni_drc_v1_count, 6);
|
|
#endif
|
|
for (idx = 0; idx < pstr_uni_drc_config_ext->drc_instructions_uni_drc_v1_count; idx++) {
|
|
#ifdef LOUDNESS_LEVELING_SUPPORT
|
|
if (idx > 0 && pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1[idx - 1]
|
|
.ducking_only_set_present) {
|
|
continue;
|
|
}
|
|
#endif
|
|
err_code = impd_drc_write_drc_instruct_uni_drc(
|
|
ptr_bit_buf_ext, version, pstr_uni_drc_config, pstr_gain_enc,
|
|
&(pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1[idx]), ptr_scratch,
|
|
&bit_cnt_local_ext);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return (err_code);
|
|
}
|
|
}
|
|
}
|
|
|
|
bit_cnt_local_ext += iusace_write_bits_buf(
|
|
ptr_bit_buf_ext, pstr_uni_drc_config_ext->loud_eq_instructions_present, 1);
|
|
if (pstr_uni_drc_config_ext->loud_eq_instructions_present == 1) {
|
|
bit_cnt_local_ext += iusace_write_bits_buf(
|
|
ptr_bit_buf_ext, pstr_uni_drc_config_ext->loud_eq_instructions_count, 4);
|
|
for (idx = 0; idx < pstr_uni_drc_config_ext->loud_eq_instructions_count; idx++) {
|
|
impd_drc_write_loud_eq_instructions(
|
|
ptr_bit_buf_ext, &(pstr_uni_drc_config_ext->str_loud_eq_instructions[idx]),
|
|
&bit_cnt_local_ext);
|
|
}
|
|
}
|
|
|
|
bit_cnt_local_ext +=
|
|
iusace_write_bits_buf(ptr_bit_buf_ext, pstr_uni_drc_config_ext->eq_present, 1);
|
|
if (pstr_uni_drc_config_ext->eq_present == 1) {
|
|
err_code = impd_drc_write_eq_coefficients(
|
|
ptr_bit_buf_ext, &(pstr_uni_drc_config_ext->str_eq_coefficients),
|
|
&bit_cnt_local_ext);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return err_code;
|
|
}
|
|
|
|
bit_cnt_local_ext += iusace_write_bits_buf(
|
|
ptr_bit_buf_ext, pstr_uni_drc_config_ext->eq_instructions_count, 4);
|
|
for (idx = 0; idx < pstr_uni_drc_config_ext->eq_instructions_count; idx++) {
|
|
err_code = impd_drc_write_eq_instructions(
|
|
ptr_bit_buf_ext, pstr_uni_drc_config_ext, pstr_gain_enc,
|
|
&(pstr_uni_drc_config_ext->str_eq_instructions[idx]), &bit_cnt_local_ext,
|
|
ptr_scratch, scratch_used);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return (err_code);
|
|
}
|
|
}
|
|
}
|
|
} break;
|
|
|
|
#ifdef LOUDNESS_LEVELING_SUPPORT
|
|
case UNIDRCCONFEXT_LEVELING: {
|
|
bit_cnt_local_ext = 0;
|
|
err_code = write_loudness_leveling_extension(
|
|
ptr_bit_buf_ext, pstr_uni_drc_config, pstr_gain_enc, ptr_scratch, &bit_cnt_local_ext);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return (err_code);
|
|
}
|
|
} break;
|
|
#endif
|
|
default:
|
|
break;
|
|
}
|
|
|
|
pstr_uni_drc_config_ext->ext_bit_size[counter] = bit_cnt_local_ext;
|
|
bit_size = pstr_uni_drc_config_ext->ext_bit_size[counter] - 1;
|
|
ext_size_bits = (WORD32)(log((FLOAT32)bit_size) / log(2.f)) + 1;
|
|
#ifdef LOUDNESS_LEVELING_SUPPORT
|
|
ext_size_bits = (ext_size_bits < 4) ? 4 : ext_size_bits;
|
|
#endif // LOUDNESS_LEVELING_SUPPORT
|
|
bit_size_len = ext_size_bits - 4;
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bit_size_len, 4);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bit_size, (UWORD8)ext_size_bits);
|
|
|
|
switch (pstr_uni_drc_config_ext->uni_drc_config_ext_type[counter]) {
|
|
case UNIDRC_CONF_EXT_PARAM_DRC: {
|
|
err_code = impd_drc_write_drc_coeff_parametric_drc(
|
|
it_bit_buf, pstr_uni_drc_config,
|
|
&(pstr_uni_drc_config_ext->str_drc_coeff_parametric_drc), &bit_cnt_local);
|
|
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return (err_code);
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_uni_drc_config_ext->parametric_drc_instructions_count, 4);
|
|
for (idx = 0; idx < pstr_uni_drc_config_ext->parametric_drc_instructions_count; idx++) {
|
|
err_code = impd_drc_write_parametric_drc_instructions(
|
|
it_bit_buf,
|
|
pstr_uni_drc_config_ext->str_drc_coeff_parametric_drc.parametric_drc_frame_size,
|
|
&(pstr_uni_drc_config_ext->str_parametric_drc_instructions[idx]), &bit_cnt_local);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return (err_code);
|
|
}
|
|
}
|
|
} break;
|
|
case UNIDRC_CONF_EXT_V1: {
|
|
version = 1;
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_uni_drc_config_ext->downmix_instructions_v1_present, 1);
|
|
if (pstr_uni_drc_config_ext->downmix_instructions_v1_present == 1) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_uni_drc_config_ext->downmix_instructions_v1_count, 7);
|
|
for (idx = 0; idx < pstr_uni_drc_config_ext->downmix_instructions_v1_count; idx++) {
|
|
impd_drc_write_downmix_instructions(
|
|
it_bit_buf, version, pstr_gain_enc,
|
|
&(pstr_uni_drc_config_ext->str_downmix_instructions_v1[idx]), &bit_cnt_local);
|
|
}
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_uni_drc_config_ext->drc_coeffs_and_instructions_uni_drc_v1_present,
|
|
1);
|
|
if (pstr_uni_drc_config_ext->drc_coeffs_and_instructions_uni_drc_v1_present == 1) {
|
|
version = 1;
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count, 3);
|
|
for (idx = 0; idx < pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count; idx++) {
|
|
impd_drc_write_drc_coeff_uni_drc(
|
|
it_bit_buf, version,
|
|
&(pstr_uni_drc_config_ext->str_drc_coefficients_uni_drc_v1[idx]), &bit_cnt_local);
|
|
}
|
|
#ifdef LOUDNESS_LEVELING_SUPPORT
|
|
UWORD32 num_ducking_only_drc_sets = get_num_ducking_only_drc_sets(
|
|
pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1,
|
|
pstr_uni_drc_config_ext->drc_instructions_uni_drc_v1_count);
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf,
|
|
pstr_uni_drc_config_ext->drc_instructions_uni_drc_v1_count -
|
|
num_ducking_only_drc_sets,
|
|
6);
|
|
#else
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_uni_drc_config_ext->drc_instructions_uni_drc_v1_count, 6);
|
|
#endif
|
|
for (idx = 0; idx < pstr_uni_drc_config_ext->drc_instructions_uni_drc_v1_count; idx++) {
|
|
#ifdef LOUDNESS_LEVELING_SUPPORT
|
|
if (idx > 0 && pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1[idx - 1]
|
|
.ducking_only_set_present) {
|
|
continue;
|
|
}
|
|
#endif
|
|
err_code = impd_drc_write_drc_instruct_uni_drc(
|
|
it_bit_buf, version, pstr_uni_drc_config, pstr_gain_enc,
|
|
&(pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1[idx]), ptr_scratch,
|
|
&bit_cnt_local);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return (err_code);
|
|
}
|
|
}
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_uni_drc_config_ext->loud_eq_instructions_present, 1);
|
|
if (pstr_uni_drc_config_ext->loud_eq_instructions_present == 1) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_uni_drc_config_ext->loud_eq_instructions_count, 4);
|
|
for (idx = 0; idx < pstr_uni_drc_config_ext->loud_eq_instructions_count; idx++) {
|
|
impd_drc_write_loud_eq_instructions(
|
|
it_bit_buf, &(pstr_uni_drc_config_ext->str_loud_eq_instructions[idx]),
|
|
&bit_cnt_local);
|
|
}
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_uni_drc_config_ext->eq_present, 1);
|
|
if (pstr_uni_drc_config_ext->eq_present == 1) {
|
|
err_code = impd_drc_write_eq_coefficients(
|
|
it_bit_buf, &(pstr_uni_drc_config_ext->str_eq_coefficients), &bit_cnt_local);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return err_code;
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_uni_drc_config_ext->eq_instructions_count, 4);
|
|
for (idx = 0; idx < pstr_uni_drc_config_ext->eq_instructions_count; idx++) {
|
|
err_code = impd_drc_write_eq_instructions(
|
|
it_bit_buf, pstr_uni_drc_config_ext, pstr_gain_enc,
|
|
&(pstr_uni_drc_config_ext->str_eq_instructions[idx]), &bit_cnt_local, ptr_scratch,
|
|
scratch_used);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return err_code;
|
|
}
|
|
}
|
|
}
|
|
} break;
|
|
#ifdef LOUDNESS_LEVELING_SUPPORT
|
|
case UNIDRCCONFEXT_LEVELING: {
|
|
err_code = write_loudness_leveling_extension(it_bit_buf, pstr_uni_drc_config,
|
|
pstr_gain_enc, ptr_scratch, &bit_cnt_local);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return (err_code);
|
|
}
|
|
} break;
|
|
#endif
|
|
default:
|
|
for (idx = 0; idx < pstr_uni_drc_config_ext->ext_bit_size[counter]; idx++) {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, 0, 1);
|
|
}
|
|
break;
|
|
}
|
|
|
|
counter++;
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_uni_drc_config_ext->uni_drc_config_ext_type[counter], 4);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
|
|
return err_code;
|
|
}
|
|
|
|
IA_ERRORCODE impd_drc_write_loudness_info_set_extension(
|
|
ia_drc_enc_state *pstr_drc_state, ia_bit_buf_struct *it_bit_buf,
|
|
ia_drc_loudness_info_set_extension_struct *pstr_loudness_info_set_extension,
|
|
WORD32 *ptr_bit_cnt, FLAG write_bs) {
|
|
IA_ERRORCODE err_code = IA_NO_ERROR;
|
|
LOOPIDX idx;
|
|
WORD32 counter = 0, version = 1;
|
|
WORD32 ext_size_bits = 0, bit_size_len = 0, bit_size = 0;
|
|
WORD32 bit_cnt_local = 0;
|
|
WORD32 bit_cnt_local_tmp = 0;
|
|
ia_drc_loudness_info_set_ext_eq_struct *pstr_loudness_info_set_ext_eq =
|
|
&pstr_loudness_info_set_extension->str_loudness_info_set_ext_eq;
|
|
ia_bit_buf_struct *ptr_bit_buf_tmp = NULL;
|
|
|
|
if (write_bs) {
|
|
ptr_bit_buf_tmp = &pstr_drc_state->str_bit_buf_cfg_tmp;
|
|
|
|
iusace_reset_bit_buffer(ptr_bit_buf_tmp);
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loudness_info_set_extension->loudness_info_set_ext_type[counter], 4);
|
|
while ((counter < 2) &&
|
|
(pstr_loudness_info_set_extension->loudness_info_set_ext_type[counter] !=
|
|
UNIDRC_LOUD_EXT_TERM)) {
|
|
switch (pstr_loudness_info_set_extension->loudness_info_set_ext_type[counter]) {
|
|
case UNIDRC_LOUD_EXT_EQ: {
|
|
bit_cnt_local_tmp += iusace_write_bits_buf(
|
|
ptr_bit_buf_tmp, pstr_loudness_info_set_ext_eq->loudness_info_v1_album_count, 6);
|
|
|
|
bit_cnt_local_tmp += iusace_write_bits_buf(
|
|
ptr_bit_buf_tmp, pstr_loudness_info_set_ext_eq->loudness_info_v1_count, 6);
|
|
for (idx = 0; idx < pstr_loudness_info_set_ext_eq->loudness_info_v1_album_count; idx++) {
|
|
err_code = impd_drc_write_loudness_info(
|
|
ptr_bit_buf_tmp, version,
|
|
&(pstr_loudness_info_set_ext_eq->str_loudness_info_v1_album[idx]),
|
|
&bit_cnt_local_tmp);
|
|
if (err_code) {
|
|
return err_code;
|
|
}
|
|
}
|
|
for (idx = 0; idx < pstr_loudness_info_set_ext_eq->loudness_info_v1_count; idx++) {
|
|
err_code = impd_drc_write_loudness_info(
|
|
ptr_bit_buf_tmp, version,
|
|
&(pstr_loudness_info_set_ext_eq->str_loudness_info_v1[idx]), &bit_cnt_local_tmp);
|
|
if (err_code) {
|
|
return (err_code);
|
|
}
|
|
}
|
|
} break;
|
|
default:
|
|
break;
|
|
}
|
|
pstr_loudness_info_set_extension->ext_bit_size[counter] = bit_cnt_local_tmp;
|
|
bit_size = pstr_loudness_info_set_extension->ext_bit_size[counter] - 1;
|
|
ext_size_bits = (WORD32)(log((FLOAT32)bit_size) / log(2.f)) + 1;
|
|
bit_size_len = ext_size_bits - 4;
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bit_size_len, 4);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bit_size, (UWORD8)ext_size_bits);
|
|
|
|
switch (pstr_loudness_info_set_extension->loudness_info_set_ext_type[counter]) {
|
|
case UNIDRC_LOUD_EXT_EQ: {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loudness_info_set_ext_eq->loudness_info_v1_album_count, 6);
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loudness_info_set_ext_eq->loudness_info_v1_count, 6);
|
|
for (idx = 0; idx < pstr_loudness_info_set_ext_eq->loudness_info_v1_album_count; idx++) {
|
|
err_code = impd_drc_write_loudness_info(
|
|
it_bit_buf, version,
|
|
&(pstr_loudness_info_set_ext_eq->str_loudness_info_v1_album[idx]), &bit_cnt_local);
|
|
if (err_code) {
|
|
return err_code;
|
|
}
|
|
}
|
|
for (idx = 0; idx < pstr_loudness_info_set_ext_eq->loudness_info_v1_count; idx++) {
|
|
err_code = impd_drc_write_loudness_info(
|
|
it_bit_buf, version, &(pstr_loudness_info_set_ext_eq->str_loudness_info_v1[idx]),
|
|
&bit_cnt_local);
|
|
if (err_code) {
|
|
return (err_code);
|
|
}
|
|
}
|
|
} break;
|
|
default:
|
|
for (idx = 0; idx < pstr_loudness_info_set_extension->ext_bit_size[counter]; idx++) {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, 0, 1);
|
|
}
|
|
break;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_loudness_info_set_extension->loudness_info_set_ext_type[counter], 4);
|
|
|
|
counter++;
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
|
|
return IA_NO_ERROR;
|
|
}
|
|
|
|
IA_ERRORCODE impd_drc_write_loudness_info_set(ia_drc_enc_state *pstr_drc_state,
|
|
ia_bit_buf_struct *it_bit_buf, WORD32 *ptr_bit_cnt,
|
|
FLAG write_bs) {
|
|
IA_ERRORCODE err_code = IA_NO_ERROR;
|
|
LOOPIDX idx;
|
|
WORD32 version = 0;
|
|
WORD32 bit_cnt_local = 0;
|
|
ia_drc_gain_enc_struct *pstr_gain_enc = &pstr_drc_state->str_gain_enc;
|
|
ia_drc_loudness_info_set_struct *pstr_loudness_info_set =
|
|
&(pstr_gain_enc->str_loudness_info_set);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_loudness_info_set->loudness_info_album_count, 6);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_loudness_info_set->loudness_info_count, 6);
|
|
|
|
for (idx = 0; idx < pstr_loudness_info_set->loudness_info_album_count; idx++) {
|
|
err_code = impd_drc_write_loudness_info(it_bit_buf, version,
|
|
&pstr_loudness_info_set->str_loudness_info_album[idx],
|
|
&bit_cnt_local);
|
|
if (err_code) {
|
|
return err_code;
|
|
}
|
|
}
|
|
|
|
for (idx = 0; idx < pstr_loudness_info_set->loudness_info_count; idx++) {
|
|
err_code = impd_drc_write_loudness_info(
|
|
it_bit_buf, version, &pstr_loudness_info_set->str_loudness_info[idx], &bit_cnt_local);
|
|
if (err_code) {
|
|
return err_code;
|
|
}
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_loudness_info_set->loudness_info_set_ext_present, 1);
|
|
if (pstr_loudness_info_set->loudness_info_set_ext_present) {
|
|
err_code = impd_drc_write_loudness_info_set_extension(
|
|
pstr_drc_state, it_bit_buf, &pstr_loudness_info_set->str_loudness_info_set_extension,
|
|
&bit_cnt_local, write_bs);
|
|
if (err_code) {
|
|
return err_code;
|
|
}
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
|
|
return err_code;
|
|
}
|
|
|
|
IA_ERRORCODE impd_drc_write_uni_drc_config(ia_drc_enc_state *pstr_drc_state, WORD32 *ptr_bit_cnt,
|
|
FLAG write_bs) {
|
|
IA_ERRORCODE err_code = IA_NO_ERROR;
|
|
LOOPIDX idx;
|
|
WORD32 version = 0;
|
|
WORD32 bit_cnt_local = 0;
|
|
VOID *ptr_scratch = pstr_drc_state->drc_scratch_mem;
|
|
ia_bit_buf_struct *it_bit_buf = NULL;
|
|
ia_drc_gain_enc_struct *pstr_gain_enc = &pstr_drc_state->str_gain_enc;
|
|
ia_drc_uni_drc_config_struct *pstr_uni_drc_config = &(pstr_gain_enc->str_uni_drc_config);
|
|
|
|
if (write_bs) {
|
|
it_bit_buf = &pstr_drc_state->str_bit_buf_cfg;
|
|
}
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_uni_drc_config->sample_rate_present, 1);
|
|
|
|
if (1 == pstr_uni_drc_config->sample_rate_present) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, (pstr_uni_drc_config->sample_rate - 1000), 18);
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_uni_drc_config->downmix_instructions_count, 7);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_uni_drc_config->drc_description_basic_present, 1);
|
|
|
|
if (1 == pstr_uni_drc_config->drc_description_basic_present) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_uni_drc_config->drc_coefficients_basic_count, 3);
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_uni_drc_config->drc_instructions_basic_count, 4);
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_uni_drc_config->drc_coefficients_uni_drc_count, 3);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_uni_drc_config->drc_instructions_uni_drc_count, 6);
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_uni_drc_config->str_channel_layout.base_ch_count, 7);
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_uni_drc_config->str_channel_layout.layout_signaling_present, 1);
|
|
if (1 == pstr_uni_drc_config->str_channel_layout.layout_signaling_present) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_uni_drc_config->str_channel_layout.defined_layout, 8);
|
|
if (0 == pstr_uni_drc_config->str_channel_layout.defined_layout) {
|
|
for (idx = 0; idx < pstr_uni_drc_config->str_channel_layout.base_ch_count; idx++) {
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_uni_drc_config->str_channel_layout.speaker_position[idx], 7);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (idx = 0; idx < pstr_uni_drc_config->downmix_instructions_count; idx++) {
|
|
// downmixInstructions();
|
|
}
|
|
|
|
for (idx = 0; idx < pstr_uni_drc_config->drc_coefficients_basic_count; idx++) {
|
|
// drcCoefficientsBasic();
|
|
}
|
|
|
|
for (idx = 0; idx < pstr_uni_drc_config->drc_instructions_basic_count; idx++) {
|
|
// drcInstructionsBasics();
|
|
}
|
|
|
|
for (idx = 0; idx < pstr_uni_drc_config->drc_coefficients_uni_drc_count; idx++) {
|
|
impd_drc_write_drc_coeff_uni_drc(it_bit_buf, version,
|
|
&(pstr_uni_drc_config->str_drc_coefficients_uni_drc[idx]),
|
|
&bit_cnt_local);
|
|
}
|
|
|
|
for (idx = 0; idx < pstr_uni_drc_config->drc_instructions_uni_drc_count; idx++) {
|
|
err_code = impd_drc_write_drc_instruct_uni_drc(
|
|
it_bit_buf, version, pstr_uni_drc_config, pstr_gain_enc,
|
|
&(pstr_uni_drc_config->str_drc_instructions_uni_drc[idx]), ptr_scratch, &bit_cnt_local);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return err_code;
|
|
}
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_uni_drc_config->uni_drc_config_ext_present, 1);
|
|
if (pstr_uni_drc_config->uni_drc_config_ext_present) {
|
|
err_code = impd_drc_write_uni_drc_config_extn(
|
|
pstr_drc_state, pstr_gain_enc, pstr_uni_drc_config,
|
|
&(pstr_uni_drc_config->str_uni_drc_config_ext), &bit_cnt_local, write_bs);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return (err_code);
|
|
}
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
|
|
return err_code;
|
|
}
|
|
|
|
IA_ERRORCODE impd_drc_write_measured_loudness_info(ia_drc_enc_state *pstr_drc_state) {
|
|
|
|
IA_ERRORCODE err_code = IA_NO_ERROR;
|
|
ia_bit_buf_struct *it_bit_buf_lis = &pstr_drc_state->str_bit_buf_cfg_ext;
|
|
WORD32 bit_cnt_lis = 0;
|
|
err_code = impd_drc_write_loudness_info_set(pstr_drc_state, it_bit_buf_lis, &bit_cnt_lis, 1);
|
|
if (err_code & IA_FATAL_ERROR) {
|
|
return (err_code);
|
|
}
|
|
pstr_drc_state->drc_config_ext_data_size_bit = bit_cnt_lis;
|
|
|
|
return err_code;
|
|
}
|
|
|
|
IA_ERRORCODE impd_drc_enc_initial_gain(const WORD32 gain_coding_profile, FLOAT32 gain_initial,
|
|
FLOAT32 *gain_initial_quant, WORD32 *code_size,
|
|
WORD32 *code) {
|
|
WORD32 sign, magnitude, bits, size;
|
|
|
|
switch (gain_coding_profile) {
|
|
case GAIN_CODING_PROFILE_CONSTANT: {
|
|
bits = 0;
|
|
size = 0;
|
|
} break;
|
|
case GAIN_CODING_PROFILE_CLIPPING: {
|
|
if (gain_initial > -0.0625f) {
|
|
sign = 0;
|
|
*gain_initial_quant = 0.0f;
|
|
bits = sign;
|
|
size = 1;
|
|
} else {
|
|
sign = 1;
|
|
gain_initial = MAX(-1000.0f, gain_initial);
|
|
magnitude = (WORD32)(-1.0f + 0.5f - 8.0f * gain_initial);
|
|
magnitude = MIN(0xFF, magnitude);
|
|
*gain_initial_quant = -(magnitude + 1) * 0.125f;
|
|
bits = (sign << 8) + magnitude;
|
|
size = 9;
|
|
}
|
|
} break;
|
|
case GAIN_CODING_PROFILE_FADING: {
|
|
if (gain_initial > -0.0625f) {
|
|
sign = 0;
|
|
*gain_initial_quant = 0.0f;
|
|
bits = sign;
|
|
size = 1;
|
|
} else {
|
|
sign = 1;
|
|
gain_initial = MAX(-1000.0f, gain_initial);
|
|
magnitude = (WORD32)(-1.0f + 0.5f - 8.0f * gain_initial);
|
|
magnitude = MIN(0x3FF, magnitude);
|
|
*gain_initial_quant = -(magnitude + 1) * 0.125f;
|
|
bits = (sign << 10) + magnitude;
|
|
size = 11;
|
|
}
|
|
} break;
|
|
case GAIN_CODING_PROFILE_REGULAR: {
|
|
if (gain_initial < 0.0f) {
|
|
sign = 1;
|
|
gain_initial = MAX(-1000.0f, gain_initial);
|
|
magnitude = (WORD32)(0.5f - 8.0f * gain_initial);
|
|
magnitude = MIN(0xFF, magnitude);
|
|
*gain_initial_quant = -magnitude * 0.125f;
|
|
} else {
|
|
sign = 0;
|
|
gain_initial = MIN(1000.0f, gain_initial);
|
|
magnitude = (WORD32)(0.5f + 8.0f * gain_initial);
|
|
magnitude = MIN(0xFF, magnitude);
|
|
*gain_initial_quant = magnitude * 0.125f;
|
|
}
|
|
bits = (sign << 8) + magnitude;
|
|
size = 9;
|
|
} break;
|
|
default:
|
|
return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
|
|
}
|
|
|
|
*code = bits;
|
|
*code_size = size;
|
|
|
|
return IA_NO_ERROR;
|
|
}
|
|
|
|
static VOID impd_drc_write_spline_nodes(ia_bit_buf_struct *it_bit_buf,
|
|
ia_drc_gain_enc_struct *pstr_gain_enc,
|
|
ia_drc_gain_set_params_struct *pstr_gain_set_params,
|
|
ia_drc_group_for_output_struct *pstr_drc_group_for_output,
|
|
WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX idx;
|
|
WORD32 frame_end_flag;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, pstr_drc_group_for_output->coding_mode, 1);
|
|
if (pstr_drc_group_for_output->coding_mode != 0) {
|
|
for (idx = 0; idx < pstr_drc_group_for_output->n_gain_values - 1; idx++) {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, 0, 1);
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, 1, 1);
|
|
|
|
if (pstr_gain_set_params->gain_interpolation_type == GAIN_INTERPOLATION_TYPE_SPLINE) {
|
|
for (idx = 0; idx < pstr_drc_group_for_output->n_gain_values; idx++) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_group_for_output->slope_code[idx],
|
|
(UWORD8)pstr_drc_group_for_output->slope_code_size[idx]);
|
|
}
|
|
}
|
|
|
|
if (pstr_gain_set_params->full_frame == 0 && pstr_drc_group_for_output->n_gain_values > 0) {
|
|
if (pstr_drc_group_for_output->ts_gain_quant[pstr_drc_group_for_output->n_gain_values -
|
|
1] == (pstr_gain_enc->drc_frame_size - 1)) {
|
|
frame_end_flag = 1;
|
|
} else {
|
|
frame_end_flag = 0;
|
|
}
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, frame_end_flag, 1);
|
|
} else {
|
|
frame_end_flag = 1;
|
|
}
|
|
|
|
for (idx = 0; idx < pstr_drc_group_for_output->n_gain_values; idx++) {
|
|
if (idx < (pstr_drc_group_for_output->n_gain_values - 1) || !frame_end_flag) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_group_for_output->time_delta_code[idx],
|
|
(UWORD8)pstr_drc_group_for_output->time_delta_code_size[idx]);
|
|
}
|
|
}
|
|
for (idx = 0; idx < pstr_drc_group_for_output->n_gain_values; idx++) {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_group_for_output->gain_code[idx],
|
|
(UWORD8)pstr_drc_group_for_output->gain_code_length[idx]);
|
|
}
|
|
} else {
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_drc_group_for_output->gain_code[0],
|
|
(UWORD8)pstr_drc_group_for_output->gain_code_length[0]);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
static VOID impd_drc_write_uni_drc_gain_extension(
|
|
ia_bit_buf_struct *it_bit_buf, ia_drc_uni_drc_gain_ext_struct *pstr_uni_drc_gain_ext,
|
|
WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX idx;
|
|
WORD32 counter = 0;
|
|
WORD32 ext_size_bits, bit_size_len, bit_size;
|
|
WORD32 bit_cnt_local = 0;
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, pstr_uni_drc_gain_ext->uni_drc_gain_ext_type[counter], 4);
|
|
while (pstr_uni_drc_gain_ext->uni_drc_gain_ext_type[counter] != UNIDRC_GAIN_EXT_TERM) {
|
|
bit_size = pstr_uni_drc_gain_ext->ext_bit_size[counter] - 1;
|
|
ext_size_bits = (WORD32)(log((FLOAT32)bit_size) / log(2.f)) + 1;
|
|
bit_size_len = ext_size_bits - 4;
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bit_size_len, 3);
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, bit_size, (UWORD8)ext_size_bits);
|
|
switch (pstr_uni_drc_gain_ext->uni_drc_gain_ext_type[counter]) {
|
|
default:
|
|
for (idx = 0; idx < pstr_uni_drc_gain_ext->ext_bit_size[counter]; idx++) {
|
|
bit_cnt_local += iusace_write_bits_buf(it_bit_buf, 0, 1);
|
|
}
|
|
}
|
|
counter++;
|
|
|
|
bit_cnt_local += iusace_write_bits_buf(
|
|
it_bit_buf, pstr_uni_drc_gain_ext->uni_drc_gain_ext_type[counter], 4);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|
|
|
|
VOID impd_drc_write_uni_drc_gain(ia_drc_enc_state *pstr_drc_state, WORD32 *ptr_bit_cnt) {
|
|
LOOPIDX idx;
|
|
WORD32 bit_cnt_local = 0;
|
|
ia_bit_buf_struct *it_bit_buf = &pstr_drc_state->str_bit_buf_out;
|
|
ia_drc_gain_enc_struct *pstr_gain_enc = &pstr_drc_state->str_gain_enc;
|
|
ia_drc_group_for_output_struct *pstr_drc_group_for_output;
|
|
ia_drc_gain_set_params_struct *pstr_gain_set_params;
|
|
ia_drc_uni_drc_gain_ext_struct str_uni_drc_gain_extension =
|
|
pstr_drc_state->str_enc_gain_extension;
|
|
|
|
for (idx = 0; idx < pstr_gain_enc->n_sequences; idx++) {
|
|
pstr_drc_group_for_output =
|
|
&(pstr_gain_enc->str_drc_gain_seq_buf[idx].str_drc_group_for_output);
|
|
pstr_gain_set_params = &(pstr_gain_enc->str_drc_gain_seq_buf[idx].str_gain_set_params);
|
|
|
|
if (pstr_gain_set_params->gain_coding_profile < GAIN_CODING_PROFILE_CONSTANT) {
|
|
impd_drc_write_spline_nodes(it_bit_buf, pstr_gain_enc, pstr_gain_set_params,
|
|
pstr_drc_group_for_output, &bit_cnt_local);
|
|
}
|
|
}
|
|
|
|
bit_cnt_local +=
|
|
iusace_write_bits_buf(it_bit_buf, str_uni_drc_gain_extension.uni_drc_gain_ext_present, 1);
|
|
if (str_uni_drc_gain_extension.uni_drc_gain_ext_present) {
|
|
impd_drc_write_uni_drc_gain_extension(it_bit_buf, &str_uni_drc_gain_extension,
|
|
&bit_cnt_local);
|
|
}
|
|
|
|
if (bit_cnt_local & 0x07) {
|
|
pstr_drc_state->bit_buf_base_out[bit_cnt_local >> 3] |= 0xFF >> (bit_cnt_local & 0x07);
|
|
|
|
bit_cnt_local += 8 - (bit_cnt_local & 0x07);
|
|
}
|
|
|
|
*ptr_bit_cnt += bit_cnt_local;
|
|
}
|