libxaac/decoder/drc_src/impd_drc_gain_dec.c
Rajat Kumar 93ade1f683 Fix to define all tables as const in libxaac
libxaac had few tables which were not declared as constants.
Added const and did corresponding changes to build and
execute.

Bug:128433649
Test: Manual Review

Change-Id: I1babf22a45fbd595c5a9c67804ecdc0317ebb96c
2019-07-17 12:24:16 -07:00

775 lines
30 KiB
C

/******************************************************************************
*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*****************************************************************************
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
*/
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "impd_type_def.h"
#include "impd_drc_extr_delta_coded_info.h"
#include "impd_drc_common.h"
#include "impd_drc_struct.h"
#include "impd_drc_interface.h"
#include "impd_drc_filter_bank.h"
#include "impd_drc_gain_dec.h"
#include "impd_parametric_drc_dec.h"
#include "impd_drc_multi_band.h"
#include "impd_drc_process_audio.h"
#include "impd_drc_eq.h"
#include "impd_drc_gain_decoder.h"
extern const ia_cicp_sigmoid_characteristic_param_struct
pstr_cicp_sigmoid_characteristic_param[];
WORD32 impd_gain_db_to_lin(ia_interp_params_struct* interp_params_str,
WORD32 drc_band, FLOAT32 in_param_db_gain,
FLOAT32 in_param_db_slope,
FLOAT32* out_param_lin_gain,
FLOAT32* out_param_lin_slope) {
FLOAT32 loc_db_gain = in_param_db_gain;
FLOAT32 gain_ratio = 1.0;
ia_gain_modifiers_struct* pstr_gain_modifiers =
interp_params_str->pstr_gain_modifiers;
if (interp_params_str->gain_modification_flag) {
if ((interp_params_str->characteristic_index > 0) &&
(loc_db_gain != 0.0f)) {
gain_ratio = 1.0f;
}
if (loc_db_gain < 0.0f) {
gain_ratio *= interp_params_str->compress;
} else {
gain_ratio *= interp_params_str->boost;
}
}
if (pstr_gain_modifiers->gain_scaling_flag[drc_band] == 1) {
if (loc_db_gain < 0.0) {
gain_ratio *= pstr_gain_modifiers->attn_scaling[drc_band];
} else {
gain_ratio *= pstr_gain_modifiers->ampl_scaling[drc_band];
}
}
if ((interp_params_str->pstr_ducking_modifiers->ducking_scaling_flag == 1) &&
(interp_params_str->ducking_flag == 1)) {
gain_ratio *= interp_params_str->pstr_ducking_modifiers->ducking_scaling;
}
{
*out_param_lin_gain =
(FLOAT32)pow(2.0, (FLOAT64)(gain_ratio * loc_db_gain / 6.0f));
*out_param_lin_slope = SLOPE_FACTOR_DB_TO_LINEAR * gain_ratio *
*out_param_lin_gain * in_param_db_slope;
if (pstr_gain_modifiers->gain_offset_flag[drc_band] == 1) {
*out_param_lin_gain *= (FLOAT32)pow(
2.0, (FLOAT64)(pstr_gain_modifiers->gain_offset[drc_band] / 6.0f));
}
if ((interp_params_str->limiter_peak_target_present == 1) &&
(interp_params_str->clipping_flag == 1)) {
*out_param_lin_gain *= (FLOAT32)pow(
2.0, max(0.0, -interp_params_str->limiter_peak_target -
interp_params_str->loudness_normalization_gain_db) /
6.0);
if (*out_param_lin_gain >= 1.0) {
*out_param_lin_gain = 1.0;
*out_param_lin_slope = 0.0;
}
}
}
return (0);
}
WORD32
impd_compressor_io_sigmoid(
ia_split_drc_characteristic_struct* split_drc_characteristic,
FLOAT32 in_db_level, FLOAT32* out_db_gain) {
FLOAT32 tmp;
FLOAT32 in_out_ratio = split_drc_characteristic->in_out_ratio;
FLOAT32 gainDbLimit = split_drc_characteristic->gain;
FLOAT32 exp = split_drc_characteristic->exp;
tmp = (DRC_INPUT_LOUDNESS_TARGET - in_db_level) * in_out_ratio;
if (exp < 1000.0f) {
FLOAT32 x = tmp / gainDbLimit;
if (x < 0.0f) {
return (UNEXPECTED_ERROR);
}
*out_db_gain = (FLOAT32)(tmp / pow(1.0f + pow(x, exp), 1.0f / exp));
} else {
*out_db_gain = tmp;
}
if (split_drc_characteristic->flip_sign == 1) {
*out_db_gain = -*out_db_gain;
}
return (0);
}
WORD32
impd_compressor_io_sigmoid_inv(
ia_split_drc_characteristic_struct* split_drc_characteristic,
FLOAT32 loc_db_gain, FLOAT32* in_level) {
FLOAT32 in_out_ratio = split_drc_characteristic->in_out_ratio;
FLOAT32 gainDbLimit = split_drc_characteristic->gain;
FLOAT32 exp = split_drc_characteristic->exp;
FLOAT32 tmp = loc_db_gain;
if (split_drc_characteristic->flip_sign == 1) {
tmp = -loc_db_gain;
}
if (exp < 1000.0f) {
FLOAT32 x = tmp / gainDbLimit;
if (x < 0.0f) {
return (UNEXPECTED_ERROR);
}
tmp = (FLOAT32)(tmp / pow(1.0f - pow(x, exp), 1.0f / exp));
}
*in_level = DRC_INPUT_LOUDNESS_TARGET - tmp / in_out_ratio;
return (0);
}
WORD32
impd_compressor_io_nodes_lt(
ia_split_drc_characteristic_struct* split_drc_characteristic,
FLOAT32 in_db_level, FLOAT32* out_db_gain) {
WORD32 n;
FLOAT32 w;
FLOAT32* node_level = split_drc_characteristic->node_level;
FLOAT32* node_gain = split_drc_characteristic->node_gain;
if (in_db_level > DRC_INPUT_LOUDNESS_TARGET) {
return (UNEXPECTED_ERROR);
}
for (n = 1; n <= split_drc_characteristic->characteristic_node_count; n++) {
if ((in_db_level <= node_level[n - 1]) && (in_db_level > node_level[n])) {
w = (node_level[n] - in_db_level) / (node_level[n] - node_level[n - 1]);
*out_db_gain = (FLOAT32)(w * node_gain[n - 1] + (1.0 - w) * node_gain[n]);
}
}
*out_db_gain = node_gain[split_drc_characteristic->characteristic_node_count];
return (0);
}
WORD32
impd_compressor_io_nodes_rt(
ia_split_drc_characteristic_struct* split_drc_characteristic,
FLOAT32 in_db_level, FLOAT32* out_db_gain) {
WORD32 n;
FLOAT32 w;
FLOAT32* node_level = split_drc_characteristic->node_level;
FLOAT32* node_gain = split_drc_characteristic->node_gain;
if (in_db_level < DRC_INPUT_LOUDNESS_TARGET) {
return (UNEXPECTED_ERROR);
}
for (n = 1; n <= split_drc_characteristic->characteristic_node_count; n++) {
if ((in_db_level >= node_level[n - 1]) && (in_db_level < node_level[n])) {
w = (FLOAT32)(node_level[n] - in_db_level) /
(node_level[n] - node_level[n - 1]);
*out_db_gain = (FLOAT32)(w * node_gain[n - 1] + (1.0 - w) * node_gain[n]);
}
}
*out_db_gain =
(node_gain[split_drc_characteristic->characteristic_node_count]);
return (0);
}
WORD32
impd_compressor_io_nodes_inverse(
ia_split_drc_characteristic_struct* split_drc_characteristic,
FLOAT32 loc_db_gain, FLOAT32* in_level) {
WORD32 n;
FLOAT32 w;
FLOAT32* node_level = split_drc_characteristic->node_level;
FLOAT32* node_gain = split_drc_characteristic->node_gain;
WORD32 node_count = split_drc_characteristic->characteristic_node_count;
if (node_gain[1] < 0.0f) {
if (loc_db_gain <= node_gain[node_count]) {
*in_level = node_level[node_count];
} else {
if (loc_db_gain >= 0.0f) {
*in_level = DRC_INPUT_LOUDNESS_TARGET;
} else {
for (n = 1; n <= node_count; n++) {
if ((loc_db_gain <= node_gain[n - 1]) &&
(loc_db_gain > node_gain[n])) {
w = (node_gain[n] - loc_db_gain) /
(node_gain[n] - node_gain[n - 1]);
*in_level =
(FLOAT32)(w * node_level[n - 1] + (1.0 - w) * node_level[n]);
}
}
}
}
} else {
if (loc_db_gain >= node_gain[node_count]) {
*in_level = node_level[node_count];
} else {
if (loc_db_gain <= 0.0f) {
*in_level = DRC_INPUT_LOUDNESS_TARGET;
} else {
for (n = 1; n <= node_count; n++) {
if ((loc_db_gain >= node_gain[n - 1]) &&
(loc_db_gain < node_gain[n])) {
w = (FLOAT32)(node_gain[n] - loc_db_gain) /
(node_gain[n] - node_gain[n - 1]);
*in_level =
(FLOAT32)(w * node_level[n - 1] + (1.0 - w) * node_level[n]);
}
}
}
}
}
return (0);
}
WORD32
impd_map_gain(
ia_split_drc_characteristic_struct* split_drc_characteristic_source,
ia_split_drc_characteristic_struct* split_drc_characteristic_target,
FLOAT32 gain_in_db, FLOAT32* gain_out_db) {
FLOAT32 inLevel;
WORD32 err = 0;
switch (split_drc_characteristic_source->characteristic_format) {
case CHARACTERISTIC_SIGMOID:
err = impd_compressor_io_sigmoid_inv(split_drc_characteristic_source,
gain_in_db, &inLevel);
if (err) return (err);
break;
case CHARACTERISTIC_NODES:
err = impd_compressor_io_nodes_inverse(split_drc_characteristic_source,
gain_in_db, &inLevel);
if (err) return (err);
break;
case CHARACTERISTIC_PASS_THRU:
inLevel = gain_in_db;
break;
default:
return (UNEXPECTED_ERROR);
break;
}
switch (split_drc_characteristic_target->characteristic_format) {
case CHARACTERISTIC_SIGMOID:
err = impd_compressor_io_sigmoid(split_drc_characteristic_target, inLevel,
gain_out_db);
if (err) return (err);
break;
case CHARACTERISTIC_NODES:
if (inLevel < DRC_INPUT_LOUDNESS_TARGET) {
err = impd_compressor_io_nodes_lt(split_drc_characteristic_target,
inLevel, gain_out_db);
if (err) return (err);
} else {
err = impd_compressor_io_nodes_rt(split_drc_characteristic_target,
inLevel, gain_out_db);
if (err) return (err);
}
break;
case CHARACTERISTIC_PASS_THRU:
*gain_out_db = inLevel;
break;
default:
break;
}
return (0);
}
WORD32
impd_conv_to_linear_domain(ia_interp_params_struct* interp_params_str,
WORD32 drc_band, FLOAT32 in_param_db_gain,
FLOAT32 in_param_db_slope,
FLOAT32* out_param_lin_gain,
FLOAT32* out_param_lin_slope) {
WORD32 err = 0;
FLOAT32 loc_db_gain = in_param_db_gain;
FLOAT32 gain_ratio = 1.0;
FLOAT32 mapped_db_gain;
ia_gain_modifiers_struct* pstr_gain_modifiers =
interp_params_str->pstr_gain_modifiers;
if (interp_params_str->gain_modification_flag) {
ia_split_drc_characteristic_struct* split_drc_characteristic_source;
WORD32 slopeIsNegative;
if (interp_params_str->drc_characteristic_present) {
if (interp_params_str->drc_source_characteristic_cicp_format) {
} else {
slopeIsNegative = 0;
split_drc_characteristic_source =
interp_params_str->split_source_characteristic_left;
if (split_drc_characteristic_source->characteristic_format == 0) {
slopeIsNegative = 1;
} else {
if (split_drc_characteristic_source->node_gain[1] > 0.0f) {
slopeIsNegative = 1;
}
}
if (loc_db_gain == 0.0f) {
if (((pstr_gain_modifiers
->target_characteristic_left_present[drc_band] == 1) &&
(interp_params_str->split_target_characteristic_left
->characteristic_format == CHARACTERISTIC_PASS_THRU)) ||
((pstr_gain_modifiers
->target_characteristic_right_present[drc_band] == 1) &&
(interp_params_str->split_target_characteristic_right
->characteristic_format == CHARACTERISTIC_PASS_THRU))) {
mapped_db_gain = DRC_INPUT_LOUDNESS_TARGET;
loc_db_gain = DRC_INPUT_LOUDNESS_TARGET;
}
} else {
if (((loc_db_gain > 0.0f) && (slopeIsNegative == 1)) ||
((loc_db_gain < 0.0f) && (slopeIsNegative == 0))) {
if (pstr_gain_modifiers
->target_characteristic_left_present[drc_band] == 1) {
err = impd_map_gain(
split_drc_characteristic_source,
interp_params_str->split_target_characteristic_left,
loc_db_gain, &mapped_db_gain);
if (err) return (err);
gain_ratio = mapped_db_gain / loc_db_gain;
}
} else if (((loc_db_gain < 0.0f) && (slopeIsNegative == 1)) ||
((loc_db_gain > 0.0f) && (slopeIsNegative == 0))) {
if (pstr_gain_modifiers
->target_characteristic_right_present[drc_band] == 1) {
split_drc_characteristic_source =
interp_params_str->split_source_characteristic_right;
err = impd_map_gain(
split_drc_characteristic_source,
interp_params_str->split_target_characteristic_right,
loc_db_gain, &mapped_db_gain);
if (err) return (err);
gain_ratio = mapped_db_gain / loc_db_gain;
}
}
}
}
}
if (loc_db_gain < 0.0f) {
gain_ratio *= interp_params_str->compress;
} else {
gain_ratio *= interp_params_str->boost;
}
}
if (pstr_gain_modifiers->gain_scaling_flag[drc_band] == 1) {
if (loc_db_gain < 0.0) {
gain_ratio *= pstr_gain_modifiers->attn_scaling[drc_band];
} else {
gain_ratio *= pstr_gain_modifiers->ampl_scaling[drc_band];
}
}
if ((interp_params_str->pstr_ducking_modifiers->ducking_scaling_flag == 1) &&
(interp_params_str->ducking_flag == 1)) {
gain_ratio *= interp_params_str->pstr_ducking_modifiers->ducking_scaling;
}
if (interp_params_str->interpolation_loud_eq == 1) {
*out_param_lin_gain =
gain_ratio * loc_db_gain + pstr_gain_modifiers->gain_offset[drc_band];
*out_param_lin_slope = 0.0f;
} else {
*out_param_lin_gain =
(FLOAT32)pow(2.0, (FLOAT64)(gain_ratio * loc_db_gain / 6.0f));
*out_param_lin_slope = SLOPE_FACTOR_DB_TO_LINEAR * gain_ratio *
*out_param_lin_gain * in_param_db_slope;
if (pstr_gain_modifiers->gain_offset_flag[drc_band] == 1) {
*out_param_lin_gain *= (FLOAT32)pow(
2.0, (FLOAT64)(pstr_gain_modifiers->gain_offset[drc_band] / 6.0f));
}
if ((interp_params_str->limiter_peak_target_present == 1) &&
(interp_params_str->clipping_flag == 1)) {
*out_param_lin_gain *= (FLOAT32)pow(
2.0, max(0.0, -interp_params_str->limiter_peak_target -
interp_params_str->loudness_normalization_gain_db) /
6.0);
if (*out_param_lin_gain >= 1.0) {
*out_param_lin_gain = 1.0;
*out_param_lin_slope = 0.0;
}
}
}
return (0);
}
WORD32 impd_interpolate_drc_gain(ia_interp_params_struct* interp_params_str,
WORD32 drc_band, WORD32 gain_step_tdomain,
FLOAT32 gain0, FLOAT32 gain1, FLOAT32 slope0,
FLOAT32 slope1, FLOAT32* result) {
WORD32 err = 0;
WORD32 n;
FLOAT32 k1, k2, a, b, c, d;
FLOAT32 slope_t1;
FLOAT32 slope_t2;
FLOAT32 gain_t1;
FLOAT32 gain_t2;
WORD32 cubic_interpolation = 1;
WORD32 node_inser;
FLOAT32 node_inser_float;
if (gain_step_tdomain <= 0) {
return (UNEXPECTED_ERROR);
}
err = impd_conv_to_linear_domain(interp_params_str, drc_band, gain0, slope0,
&gain_t1, &slope_t1);
if (err) return (err);
err = impd_conv_to_linear_domain(interp_params_str, drc_band, gain1, slope1,
&gain_t2, &slope_t2);
if (err) return (err);
if (interp_params_str->gain_interpolation_type ==
GAIN_INTERPOLATION_TYPE_SPLINE) {
slope_t1 = slope_t1 / (FLOAT32)interp_params_str->delta_tmin;
slope_t2 = slope_t2 / (FLOAT32)interp_params_str->delta_tmin;
if ((FLOAT32)fabs((FLOAT64)slope_t1) > (FLOAT32)fabs((FLOAT64)slope_t2)) {
node_inser_float = 2.0f *
(gain_t2 - gain_t1 - slope_t2 * gain_step_tdomain) /
(slope_t1 - slope_t2);
node_inser = (WORD32)(0.5f + node_inser_float);
if ((node_inser >= 0) && (node_inser < gain_step_tdomain)) {
cubic_interpolation = 0;
result[0] = gain_t1;
result[gain_step_tdomain] = gain_t2;
a = 0.5f * (slope_t2 - slope_t1) / node_inser_float;
b = slope_t1;
c = gain_t1;
for (n = 1; n < node_inser; n++) {
FLOAT32 t = (FLOAT32)n;
result[n] = (a * t + b) * t + c;
result[n] = max(0.0f, result[n]);
}
a = slope_t2;
b = gain_t2;
for (; n < gain_step_tdomain; n++) {
FLOAT32 t = (FLOAT32)(n - gain_step_tdomain);
result[n] = a * t + b;
}
}
} else if ((FLOAT32)fabs((FLOAT64)slope_t1) <
(FLOAT32)fabs((FLOAT64)slope_t2)) {
node_inser_float = 2.0f *
(gain_t1 - gain_t2 + slope_t1 * gain_step_tdomain) /
(slope_t1 - slope_t2);
node_inser_float = gain_step_tdomain - node_inser_float;
node_inser = (WORD32)(0.5f + node_inser_float);
if ((node_inser >= 0) && (node_inser < gain_step_tdomain)) {
cubic_interpolation = 0;
result[0] = gain_t1;
result[gain_step_tdomain] = gain_t2;
a = slope_t1;
b = gain_t1;
for (n = 1; n < node_inser; n++) {
FLOAT32 t = (FLOAT32)n;
result[n] = a * t + b;
}
a = (slope_t2 - slope_t1) /
(2.0f * (gain_step_tdomain - node_inser_float));
b = -slope_t2;
c = gain_t2;
for (; n < gain_step_tdomain; n++) {
FLOAT32 t = (FLOAT32)(gain_step_tdomain - n);
result[n] = (a * t + b) * t + c;
result[n] = max(0.0f, result[n]);
}
}
}
if (cubic_interpolation == 1) {
FLOAT32 gain_step_inv = 1.0f / (FLOAT32)gain_step_tdomain;
FLOAT32 gain_step_inv2 = gain_step_inv * gain_step_inv;
k1 = (gain_t2 - gain_t1) * gain_step_inv2;
k2 = slope_t2 + slope_t1;
a = gain_step_inv * (gain_step_inv * k2 - 2.0f * k1);
b = 3.0f * k1 - gain_step_inv * (k2 + slope_t1);
c = slope_t1;
d = gain_t1;
result[0] = gain_t1;
result[gain_step_tdomain] = gain_t2;
for (n = 1; n < gain_step_tdomain; n++) {
FLOAT32 t = (FLOAT32)n;
result[n] = (((a * t + b) * t + c) * t) + d;
result[n] = max(0.0f, result[n]);
}
}
} else {
a = (gain_t2 - gain_t1) / (FLOAT32)gain_step_tdomain;
b = gain_t1;
result[0] = gain_t1;
result[gain_step_tdomain] = gain_t2;
for (n = 1; n < gain_step_tdomain; n++) {
FLOAT32 t = (FLOAT32)n;
result[n] = a * t + b;
}
}
return 0;
}
WORD32
impd_advance_buf(WORD32 drc_frame_size, ia_gain_buffer_struct* pstr_gain_buf) {
WORD32 n;
ia_interp_buf_struct* buf_interpolation;
for (n = 0; n < pstr_gain_buf->buf_interpolation_count; n++) {
buf_interpolation = &(pstr_gain_buf->buf_interpolation[n]);
buf_interpolation->prev_node = buf_interpolation->str_node;
buf_interpolation->prev_node.time -= drc_frame_size;
memmove(buf_interpolation->lpcm_gains,
buf_interpolation->lpcm_gains + drc_frame_size,
sizeof(FLOAT32) * (drc_frame_size + MAX_SIGNAL_DELAY));
}
return (0);
}
WORD32
impd_concatenate_segments(WORD32 drc_frame_size, WORD32 drc_band,
ia_interp_params_struct* interp_params_str,
ia_spline_nodes_struct* str_spline_nodes,
ia_interp_buf_struct* buf_interpolation) {
WORD32 timePrev, duration, n, err = 0;
FLOAT32 loc_db_gain = 0.0f, prev_db_gain, slope = 0.0f, slopePrev;
timePrev = buf_interpolation->prev_node.time;
prev_db_gain = buf_interpolation->prev_node.loc_db_gain;
slopePrev = buf_interpolation->prev_node.slope;
for (n = 0; n < str_spline_nodes->num_nodes; n++) {
duration = str_spline_nodes->str_node[n].time - timePrev;
loc_db_gain = str_spline_nodes->str_node[n].loc_db_gain;
slope = str_spline_nodes->str_node[n].slope;
err = impd_interpolate_drc_gain(
interp_params_str, drc_band, duration, prev_db_gain, loc_db_gain,
slopePrev, slope, buf_interpolation->lpcm_gains + MAX_SIGNAL_DELAY +
drc_frame_size + timePrev);
if (err) return (err);
timePrev = str_spline_nodes->str_node[n].time;
prev_db_gain = loc_db_gain;
slopePrev = slope;
}
buf_interpolation->str_node.loc_db_gain = loc_db_gain;
buf_interpolation->str_node.slope = slope;
buf_interpolation->str_node.time = timePrev;
return (0);
}
WORD32
impd_get_drc_gain(ia_drc_gain_dec_struct* p_drc_gain_dec_structs,
ia_drc_config* pstr_drc_config,
ia_drc_gain_struct* pstr_drc_gain, FLOAT32 compress,
FLOAT32 boost, WORD32 characteristic_index,
FLOAT32 loudness_normalization_gain_db, WORD32 sel_drc_index,
ia_drc_gain_buffers_struct* drc_gain_buffers) {
ia_drc_params_struct* ia_drc_params_struct =
&(p_drc_gain_dec_structs->ia_drc_params_struct);
WORD32 drc_instructions_index =
ia_drc_params_struct->sel_drc_array[sel_drc_index].drc_instructions_index;
if (drc_instructions_index >= 0) {
WORD32 b, g, gainElementIndex, err = 0;
WORD32 parametricDrcInstanceIndex = 0;
ia_interp_params_struct interp_params_str = {0};
ia_drc_instructions_struct* str_drc_instruction_str =
&(pstr_drc_config->str_drc_instruction_str[drc_instructions_index]);
WORD32 drc_set_effect = str_drc_instruction_str->drc_set_effect;
WORD32 num_drc_ch_groups = str_drc_instruction_str->num_drc_ch_groups;
ia_uni_drc_coeffs_struct* str_p_loc_drc_coefficients_uni_drc = NULL;
WORD32 drc_coeff_idx =
ia_drc_params_struct->sel_drc_array[sel_drc_index].drc_coeff_idx;
if (drc_coeff_idx >= 0) {
str_p_loc_drc_coefficients_uni_drc =
&(pstr_drc_config->str_p_loc_drc_coefficients_uni_drc[drc_coeff_idx]);
interp_params_str.interpolation_loud_eq = 0;
} else {
return (UNEXPECTED_ERROR);
}
interp_params_str.loudness_normalization_gain_db =
loudness_normalization_gain_db;
interp_params_str.characteristic_index = characteristic_index;
interp_params_str.compress = compress;
interp_params_str.boost = boost;
interp_params_str.limiter_peak_target_present =
str_drc_instruction_str->limiter_peak_target_present;
interp_params_str.limiter_peak_target =
str_drc_instruction_str->limiter_peak_target;
if (((drc_set_effect & (EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) ==
0) &&
(drc_set_effect != EFFECT_BIT_FADE) &&
(drc_set_effect != EFFECT_BIT_CLIPPING)) {
interp_params_str.gain_modification_flag = 1;
} else {
interp_params_str.gain_modification_flag = 0;
}
if (drc_set_effect & (EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) {
interp_params_str.ducking_flag = 1;
} else {
interp_params_str.ducking_flag = 0;
}
if (drc_set_effect == EFFECT_BIT_CLIPPING) {
interp_params_str.clipping_flag = 1;
} else {
interp_params_str.clipping_flag = 0;
}
err = impd_advance_buf(ia_drc_params_struct->drc_frame_size,
&(drc_gain_buffers->pstr_gain_buf[sel_drc_index]));
if (err) return (err);
gainElementIndex = 0;
for (g = 0; g < num_drc_ch_groups; g++) {
WORD32 gainSet = 0;
WORD32 num_drc_bands = 0;
interp_params_str.gain_interpolation_type =
str_drc_instruction_str->gain_interpolation_type_for_channel_group[g];
interp_params_str.delta_tmin =
str_drc_instruction_str->time_delta_min_for_channel_group[g];
interp_params_str.pstr_ducking_modifiers = &(
str_drc_instruction_str->str_ducking_modifiers_for_channel_group[g]);
interp_params_str.pstr_gain_modifiers =
&(str_drc_instruction_str->str_gain_modifiers_of_ch_group[g]);
if (str_drc_instruction_str->ch_group_parametric_drc_flag[g] == 0) {
gainSet = str_drc_instruction_str->gain_set_index_for_channel_group[g];
num_drc_bands = str_drc_instruction_str->band_count_of_ch_group[g];
for (b = 0; b < num_drc_bands; b++) {
ia_gain_params_struct* gain_params =
&(str_p_loc_drc_coefficients_uni_drc->gain_set_params[gainSet]
.gain_params[b]);
WORD32 seq = gain_params->gain_seq_idx;
interp_params_str.drc_characteristic_present =
gain_params->drc_characteristic_present;
interp_params_str.drc_source_characteristic_cicp_format =
gain_params->drc_characteristic_format_is_cicp;
interp_params_str.source_drc_characteristic =
gain_params->drc_characteristic;
interp_params_str.split_source_characteristic_left = &(
str_p_loc_drc_coefficients_uni_drc->str_split_characteristic_left
[gain_params->drc_characteristic_left_index]);
interp_params_str.split_source_characteristic_right = &(
str_p_loc_drc_coefficients_uni_drc->str_split_characteristic_right
[gain_params->drc_characteristic_right_index]);
interp_params_str.split_target_characteristic_left = &(
str_p_loc_drc_coefficients_uni_drc->str_split_characteristic_left
[interp_params_str.pstr_gain_modifiers
->target_characteristic_left_index[b]]);
interp_params_str.split_target_characteristic_right = &(
str_p_loc_drc_coefficients_uni_drc->str_split_characteristic_right
[interp_params_str.pstr_gain_modifiers
->target_characteristic_right_index[b]]);
err = impd_concatenate_segments(
ia_drc_params_struct->drc_frame_size, b, &interp_params_str,
&(pstr_drc_gain->drc_gain_sequence[seq].str_spline_nodes[0]),
&(drc_gain_buffers->pstr_gain_buf[sel_drc_index]
.buf_interpolation[gainElementIndex]));
if (err) return (err);
gainElementIndex++;
}
} else {
if (ia_drc_params_struct->sub_band_domain_mode ==
SUBBAND_DOMAIN_MODE_OFF &&
!(p_drc_gain_dec_structs->parametricdrc_params
.str_parametric_drc_instance_params
[parametricDrcInstanceIndex]
.parametric_drc_type == PARAM_DRC_TYPE_LIM)) {
err = impd_parametric_drc_instance_process(
p_drc_gain_dec_structs->audio_in_out_buf.audio_in_out_buf, NULL,
NULL, &p_drc_gain_dec_structs->parametricdrc_params,
&p_drc_gain_dec_structs->parametricdrc_params
.str_parametric_drc_instance_params
[parametricDrcInstanceIndex]);
if (err) return (err);
err = impd_concatenate_segments(
ia_drc_params_struct->drc_frame_size, 0, &interp_params_str,
&p_drc_gain_dec_structs->parametricdrc_params
.str_parametric_drc_instance_params
[parametricDrcInstanceIndex]
.str_spline_nodes,
&(drc_gain_buffers->pstr_gain_buf[sel_drc_index]
.buf_interpolation[gainElementIndex]));
if (err) return (err);
} else if (ia_drc_params_struct->sub_band_domain_mode ==
SUBBAND_DOMAIN_MODE_OFF &&
p_drc_gain_dec_structs->parametricdrc_params
.str_parametric_drc_instance_params
[parametricDrcInstanceIndex]
.parametric_drc_type == PARAM_DRC_TYPE_LIM) {
FLOAT32* lpcm_gains = (drc_gain_buffers->pstr_gain_buf[sel_drc_index]
.buf_interpolation[gainElementIndex])
.lpcm_gains +
MAX_SIGNAL_DELAY;
err = impd_parametric_lim_type_drc_process(
p_drc_gain_dec_structs->audio_in_out_buf.audio_in_out_buf,
loudness_normalization_gain_db,
&p_drc_gain_dec_structs->parametricdrc_params
.str_parametric_drc_instance_params
[parametricDrcInstanceIndex]
.str_parametric_drc_type_lim_params,
lpcm_gains);
if (err) return (err);
} else if (ia_drc_params_struct->sub_band_domain_mode !=
SUBBAND_DOMAIN_MODE_OFF &&
!(p_drc_gain_dec_structs->parametricdrc_params
.str_parametric_drc_instance_params
[parametricDrcInstanceIndex]
.parametric_drc_type == PARAM_DRC_TYPE_LIM)) {
err = impd_parametric_drc_instance_process(
NULL, p_drc_gain_dec_structs->audio_in_out_buf.audio_real_buff,
p_drc_gain_dec_structs->audio_in_out_buf.audio_imag_buff,
&p_drc_gain_dec_structs->parametricdrc_params,
&p_drc_gain_dec_structs->parametricdrc_params
.str_parametric_drc_instance_params
[parametricDrcInstanceIndex]);
if (err) return (err);
err = impd_concatenate_segments(
ia_drc_params_struct->drc_frame_size, 0, &interp_params_str,
&p_drc_gain_dec_structs->parametricdrc_params
.str_parametric_drc_instance_params
[parametricDrcInstanceIndex]
.str_spline_nodes,
&(drc_gain_buffers->pstr_gain_buf[sel_drc_index]
.buf_interpolation[gainElementIndex]));
if (err) return (err);
} else {
return (UNEXPECTED_ERROR);
}
gainElementIndex++;
parametricDrcInstanceIndex++;
}
}
}
return (0);
}