Updates from vendor to remedy issues exposed by new CTS tests
Bug: 77287124
Test: CTS DecoderTest, DecoderTest{AacDrc,XheAac}
@ Sanitizer fixes in libxaac
Fixes few integer overflow sanitizer errors
Progagate few errors
ENABLE_DRC macro is removed
AMMENDMENT1 macro is removed
Change-Id: Ic61163dfd6318bd4a00ed45e1295c819cb0f637b
@ Add support for audio pre-roll and DRC effect type
Also includes the following
MPEG-D DRC parameters related changes
USAC config switch changes
SBR config switch changes
Bug: 80133175
Change-Id: I0ab25641768cf523b66f7b0fcb4137429c1c4a77
@ Fixed trailing spaces
Change-Id: I32de0c9d3f7237e1fbf8dfef1cac485ef8458173
@ Replaced tabs
Change-Id: Ic741ee13d7b978b37edc27d087903caaa40b8d90
1031 lines
42 KiB
C
1031 lines
42 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 <stdlib.h>
|
|
#include <stdio.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_parametric_drc_dec.h"
|
|
#include "impd_drc_filter_bank.h"
|
|
#include "impd_drc_rom.h"
|
|
|
|
|
|
#define PI 3.14159265f
|
|
|
|
#ifndef max
|
|
#define max(a, b) (((a) > (b)) ? (a) : (b))
|
|
#endif
|
|
#ifndef min
|
|
#define min(a, b) (((a) < (b)) ? (a) : (b))
|
|
#endif
|
|
|
|
|
|
WORD32 impd_init_parametric_drc( WORD32 drc_frame_size,
|
|
WORD32 sampling_rate,
|
|
WORD32 sub_band_domain_mode,
|
|
ia_parametric_drc_params_struct *p_parametricdrc_params)
|
|
{
|
|
|
|
WORD32 sub_band_count_tbl[4]={0,64,71,256};
|
|
p_parametricdrc_params->drc_frame_size = drc_frame_size;
|
|
p_parametricdrc_params->sampling_rate = sampling_rate;
|
|
p_parametricdrc_params->sub_band_domain_mode = sub_band_domain_mode;
|
|
|
|
p_parametricdrc_params->sub_band_count=sub_band_count_tbl[sub_band_domain_mode];
|
|
|
|
return 0;
|
|
}
|
|
|
|
WORD32 impd_init_parametric_drc_feed_fwd(ia_drc_config* pstr_drc_config,
|
|
WORD32 instance_idx,
|
|
WORD32 ch_count_from_dwnmix_id,
|
|
ia_parametric_drc_params_struct* p_parametricdrc_params)
|
|
{
|
|
WORD32 err = 0, i = 0;
|
|
|
|
WORD32 parametric_drc_idx = p_parametricdrc_params->parametric_drc_idx[instance_idx];
|
|
WORD32 gain_set_index = p_parametricdrc_params->gain_set_index[instance_idx];
|
|
WORD32* channel_map = p_parametricdrc_params->channel_map[instance_idx];
|
|
|
|
ia_drc_coeff_parametric_drc_struct* hDrcCoefficientsParametricDrcBs = &(pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc);
|
|
ia_parametric_drc_type_feed_forward_struct* hParametricDrcTypeFeedForwardBs = &(pstr_drc_config->str_drc_config_ext.str_parametric_drc_instructions[parametric_drc_idx].str_parametric_drc_type_feed_forward);
|
|
ia_parametric_drc_type_ff_params_struct* pstr_parametric_ffwd_type_drc_params = &(p_parametricdrc_params->str_parametric_drc_instance_params[instance_idx].str_parametric_drc_type_ff_params);
|
|
|
|
/* level estimation */
|
|
pstr_parametric_ffwd_type_drc_params->frame_size = p_parametricdrc_params->parametric_drc_frame_size;
|
|
pstr_parametric_ffwd_type_drc_params->sub_band_domain_mode = p_parametricdrc_params->sub_band_domain_mode;
|
|
pstr_parametric_ffwd_type_drc_params->sub_band_count = p_parametricdrc_params->sub_band_count;
|
|
pstr_parametric_ffwd_type_drc_params->sub_band_compensation_type = 0;
|
|
|
|
if (pstr_parametric_ffwd_type_drc_params->sub_band_domain_mode == SUBBAND_DOMAIN_MODE_QMF64)
|
|
{
|
|
if (p_parametricdrc_params->sampling_rate == 48000)
|
|
{
|
|
pstr_parametric_ffwd_type_drc_params->sub_band_compensation_type = 1;
|
|
}
|
|
else
|
|
{
|
|
/* support of other sampling rates than 48000 might be missing */
|
|
return UNEXPECTED_ERROR;
|
|
}
|
|
}
|
|
|
|
pstr_parametric_ffwd_type_drc_params->audio_num_chan = p_parametricdrc_params->audio_num_chan;
|
|
pstr_parametric_ffwd_type_drc_params->level_estim_k_weighting_type = hParametricDrcTypeFeedForwardBs->level_estim_k_weighting_type;
|
|
pstr_parametric_ffwd_type_drc_params->level_estim_integration_time = hParametricDrcTypeFeedForwardBs->level_estim_integration_time;
|
|
pstr_parametric_ffwd_type_drc_params->level_estim_frame_index = 0;
|
|
pstr_parametric_ffwd_type_drc_params->level_estim_frame_count = hParametricDrcTypeFeedForwardBs->level_estim_integration_time/pstr_parametric_ffwd_type_drc_params->frame_size;
|
|
|
|
|
|
memset(pstr_parametric_ffwd_type_drc_params->level,0,PARAM_DRC_TYPE_FF_LEVEL_ESTIM_FRAME_COUNT_MAX*sizeof(FLOAT32));
|
|
|
|
if (ch_count_from_dwnmix_id != 0)
|
|
{
|
|
|
|
memcpy(pstr_parametric_ffwd_type_drc_params->level_estim_ch_weight,
|
|
hDrcCoefficientsParametricDrcBs->str_parametric_drc_gain_set_params[gain_set_index].level_estim_ch_weight,ch_count_from_dwnmix_id*sizeof(FLOAT32));
|
|
}
|
|
else
|
|
{
|
|
|
|
for (i=0; i<pstr_parametric_ffwd_type_drc_params->audio_num_chan; i++)
|
|
{
|
|
pstr_parametric_ffwd_type_drc_params->level_estim_ch_weight[i] = (FLOAT32)channel_map[i];
|
|
}
|
|
|
|
}
|
|
|
|
if (pstr_parametric_ffwd_type_drc_params->sub_band_domain_mode==SUBBAND_DOMAIN_MODE_OFF)
|
|
{
|
|
err = impd_init_lvl_est_filt_time(pstr_parametric_ffwd_type_drc_params->level_estim_k_weighting_type,
|
|
p_parametricdrc_params->sampling_rate,
|
|
&pstr_parametric_ffwd_type_drc_params->pre_filt_coeff,
|
|
&pstr_parametric_ffwd_type_drc_params->rlb_filt_coeff);
|
|
|
|
if (err)
|
|
return (err);
|
|
}
|
|
else
|
|
{
|
|
err = impd_init_lvl_est_filt_subband(pstr_parametric_ffwd_type_drc_params->level_estim_k_weighting_type,
|
|
p_parametricdrc_params->sampling_rate,
|
|
p_parametricdrc_params->sub_band_domain_mode,
|
|
p_parametricdrc_params->sub_band_count,
|
|
pstr_parametric_ffwd_type_drc_params->sub_band_compensation_type,
|
|
pstr_parametric_ffwd_type_drc_params->weighting_filt,
|
|
&pstr_parametric_ffwd_type_drc_params->filt_coeff_subband);
|
|
|
|
if (err)
|
|
return (err);
|
|
}
|
|
|
|
pstr_parametric_ffwd_type_drc_params->node_count = hParametricDrcTypeFeedForwardBs->node_count;
|
|
|
|
|
|
memcpy(pstr_parametric_ffwd_type_drc_params->node_level,hParametricDrcTypeFeedForwardBs->node_level,pstr_parametric_ffwd_type_drc_params->node_count*sizeof(WORD32));
|
|
memcpy(pstr_parametric_ffwd_type_drc_params->node_gain,hParametricDrcTypeFeedForwardBs->node_gain,pstr_parametric_ffwd_type_drc_params->node_count*sizeof(WORD32));
|
|
|
|
pstr_parametric_ffwd_type_drc_params->ref_level_parametric_drc = hDrcCoefficientsParametricDrcBs->str_parametric_drc_gain_set_params[gain_set_index].drc_input_loudness;
|
|
|
|
{
|
|
WORD32 gain_smooth_attack_time_fast = hParametricDrcTypeFeedForwardBs->gain_smooth_attack_time_fast;
|
|
WORD32 gain_smooth_release_time_fast = hParametricDrcTypeFeedForwardBs->gain_smooth_release_time_fast;
|
|
WORD32 gain_smooth_attack_time_slow = hParametricDrcTypeFeedForwardBs->gain_smooth_attack_time_slow;
|
|
WORD32 gain_smooth_release_time_slow = hParametricDrcTypeFeedForwardBs->gain_smooth_release_time_slow;
|
|
WORD32 gain_smooth_hold_off = hParametricDrcTypeFeedForwardBs->gain_smooth_hold_off;
|
|
WORD32 sampling_rate = p_parametricdrc_params->sampling_rate;
|
|
WORD32 parametric_drc_frame_size = p_parametricdrc_params->parametric_drc_frame_size;
|
|
|
|
pstr_parametric_ffwd_type_drc_params->gain_smooth_attack_alpha_fast = 1 - (FLOAT32)exp(-1.0 * parametric_drc_frame_size / (gain_smooth_attack_time_fast * sampling_rate * 0.001));
|
|
pstr_parametric_ffwd_type_drc_params->gain_smooth_rel_alpha_fast = 1 - (FLOAT32)exp(-1.0 * parametric_drc_frame_size / (gain_smooth_release_time_fast * sampling_rate * 0.001));
|
|
pstr_parametric_ffwd_type_drc_params->gain_smooth_attack_alpha_slow = 1 - (FLOAT32)exp(-1.0 * parametric_drc_frame_size / (gain_smooth_attack_time_slow * sampling_rate * 0.001));
|
|
pstr_parametric_ffwd_type_drc_params->gain_smooth_rel_alpha_slow = 1 - (FLOAT32)exp(-1.0 * parametric_drc_frame_size / (gain_smooth_release_time_slow * sampling_rate * 0.001));
|
|
pstr_parametric_ffwd_type_drc_params->gain_smooth_hold_off_count = gain_smooth_hold_off * 256 * sampling_rate / (parametric_drc_frame_size * 48000);
|
|
pstr_parametric_ffwd_type_drc_params->gain_smooth_attack_threshold = hParametricDrcTypeFeedForwardBs->gain_smooth_attack_threshold;
|
|
pstr_parametric_ffwd_type_drc_params->gain_smooth_rel_threshold = hParametricDrcTypeFeedForwardBs->gain_smooth_rel_threshold;
|
|
}
|
|
|
|
err = impd_parametric_ffwd_type_drc_reset(pstr_parametric_ffwd_type_drc_params);
|
|
|
|
if (err)
|
|
return (err);
|
|
|
|
return 0;
|
|
}
|
|
|
|
WORD32 impd_init_parametric_drc_lim(ia_drc_config* pstr_drc_config,
|
|
WORD32 instance_idx,
|
|
WORD32 ch_count_from_dwnmix_id,
|
|
ia_parametric_drc_params_struct* p_parametricdrc_params,
|
|
pVOID *mem_ptr)
|
|
{
|
|
WORD32 err = 0, i = 0;
|
|
UWORD32 j;
|
|
UWORD32 attack, sec_len;
|
|
|
|
WORD32 parametric_drc_idx = p_parametricdrc_params->parametric_drc_idx[instance_idx];
|
|
WORD32 gain_set_index = p_parametricdrc_params->gain_set_index[instance_idx];
|
|
WORD32* channel_map = p_parametricdrc_params->channel_map[instance_idx];
|
|
|
|
ia_drc_coeff_parametric_drc_struct* hDrcCoefficientsParametricDrcBs = &(pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc);
|
|
ia_parametric_drc_lim_struct* hParametricDrcTypeLimBs = &(pstr_drc_config->str_drc_config_ext.str_parametric_drc_instructions[parametric_drc_idx].parametric_drc_lim);
|
|
ia_parametric_drc_type_lim_params_struct* pstr_parametric_lim_type_drc_params = &(p_parametricdrc_params->str_parametric_drc_instance_params[instance_idx].str_parametric_drc_type_lim_params);
|
|
|
|
pstr_parametric_lim_type_drc_params->frame_size = p_parametricdrc_params->drc_frame_size;
|
|
pstr_parametric_lim_type_drc_params->audio_num_chan = p_parametricdrc_params->audio_num_chan;
|
|
|
|
if (ch_count_from_dwnmix_id != 0)
|
|
{
|
|
memcpy(pstr_parametric_lim_type_drc_params->level_estim_ch_weight,
|
|
hDrcCoefficientsParametricDrcBs->str_parametric_drc_gain_set_params[gain_set_index].level_estim_ch_weight,ch_count_from_dwnmix_id*sizeof(FLOAT32));
|
|
}
|
|
else
|
|
{
|
|
for (i=0; i<pstr_parametric_lim_type_drc_params->audio_num_chan; i++)
|
|
{
|
|
pstr_parametric_lim_type_drc_params->level_estim_ch_weight[i] = (FLOAT32)channel_map[i];
|
|
}
|
|
|
|
}
|
|
|
|
attack = (UWORD32)(hParametricDrcTypeLimBs->parametric_lim_attack * p_parametricdrc_params->sampling_rate / 1000);
|
|
|
|
sec_len = (UWORD32)sqrt(attack+1);
|
|
|
|
pstr_parametric_lim_type_drc_params->sec_len = sec_len;
|
|
pstr_parametric_lim_type_drc_params->num_max_buf_sec = (attack+1)/sec_len;
|
|
if (pstr_parametric_lim_type_drc_params->num_max_buf_sec*sec_len < (attack+1))
|
|
pstr_parametric_lim_type_drc_params->num_max_buf_sec++;
|
|
|
|
pstr_parametric_lim_type_drc_params->max_buf =(FLOAT32*)(*mem_ptr);
|
|
*mem_ptr =(pVOID)((SIZE_T)(*mem_ptr)+pstr_parametric_lim_type_drc_params->num_max_buf_sec * sec_len*sizeof(FLOAT32));
|
|
|
|
pstr_parametric_lim_type_drc_params->attack_ms = (FLOAT32)hParametricDrcTypeLimBs->parametric_lim_attack;
|
|
pstr_parametric_lim_type_drc_params->release_ms = (FLOAT32)hParametricDrcTypeLimBs->parametric_lim_release;
|
|
pstr_parametric_lim_type_drc_params->attack = attack;
|
|
pstr_parametric_lim_type_drc_params->attack_constant = (FLOAT32)pow(0.1, 1.0 / (attack + 1));
|
|
pstr_parametric_lim_type_drc_params->release_constant = (FLOAT32)pow(0.1, 1.0 / (hParametricDrcTypeLimBs->parametric_lim_release * p_parametricdrc_params->sampling_rate / 1000 + 1));
|
|
pstr_parametric_lim_type_drc_params->threshold = (FLOAT32)pow(10.0f, 0.05f * hParametricDrcTypeLimBs->parametric_lim_threshold);
|
|
pstr_parametric_lim_type_drc_params->channels = pstr_parametric_lim_type_drc_params->audio_num_chan;
|
|
pstr_parametric_lim_type_drc_params->sampling_rate = p_parametricdrc_params->sampling_rate;
|
|
pstr_parametric_lim_type_drc_params->cor = 1.0f;
|
|
pstr_parametric_lim_type_drc_params->smooth_state_0 = 1.0;
|
|
|
|
|
|
|
|
for (j=0; j<pstr_parametric_lim_type_drc_params->num_max_buf_sec * pstr_parametric_lim_type_drc_params->sec_len; j++) {
|
|
pstr_parametric_lim_type_drc_params->max_buf[j] = 0.f;
|
|
}
|
|
|
|
|
|
|
|
if (err) return (err);
|
|
|
|
return 0;
|
|
}
|
|
|
|
WORD32 impd_init_parametric_drcInstance(ia_drc_config* pstr_drc_config,
|
|
WORD32 instance_idx,
|
|
WORD32 ch_count_from_dwnmix_id,
|
|
ia_parametric_drc_params_struct* p_parametricdrc_params,
|
|
pVOID *mem_ptr)
|
|
{
|
|
WORD32 err = 0;
|
|
|
|
WORD32 parametric_drc_idx = p_parametricdrc_params->parametric_drc_idx[instance_idx];
|
|
ia_parametric_drc_instructions_struct *hParametricDrcInstructions = &(pstr_drc_config->str_drc_config_ext.str_parametric_drc_instructions[parametric_drc_idx]);
|
|
|
|
p_parametricdrc_params->str_parametric_drc_instance_params[instance_idx].disable_paramteric_drc = hParametricDrcInstructions->disable_paramteric_drc;
|
|
p_parametricdrc_params->str_parametric_drc_instance_params[instance_idx].parametric_drc_type = hParametricDrcInstructions->parametric_drc_type;
|
|
p_parametricdrc_params->str_parametric_drc_instance_params[instance_idx].str_spline_nodes.num_nodes = p_parametricdrc_params->num_nodes;
|
|
|
|
if (p_parametricdrc_params->str_parametric_drc_instance_params[instance_idx].disable_paramteric_drc == 0)
|
|
{
|
|
|
|
if (p_parametricdrc_params->str_parametric_drc_instance_params[instance_idx].parametric_drc_type == PARAM_DRC_TYPE_FF)
|
|
{
|
|
|
|
err = impd_init_parametric_drc_feed_fwd(pstr_drc_config,
|
|
instance_idx,
|
|
ch_count_from_dwnmix_id,
|
|
p_parametricdrc_params);
|
|
|
|
if (err)
|
|
return (err);
|
|
|
|
}
|
|
else if (p_parametricdrc_params->str_parametric_drc_instance_params[instance_idx].parametric_drc_type == PARAM_DRC_TYPE_LIM)
|
|
{
|
|
|
|
p_parametricdrc_params->str_parametric_drc_instance_params[instance_idx].str_spline_nodes.num_nodes = p_parametricdrc_params->drc_frame_size;
|
|
|
|
err = impd_init_parametric_drc_lim(pstr_drc_config,
|
|
instance_idx,
|
|
ch_count_from_dwnmix_id,
|
|
p_parametricdrc_params,
|
|
mem_ptr);
|
|
|
|
if (err)
|
|
return (err);
|
|
|
|
} else {
|
|
|
|
return (UNEXPECTED_ERROR);
|
|
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
WORD32 impd_init_parametric_drc_after_config(ia_drc_config* pstr_drc_config,
|
|
ia_drc_loudness_info_set_struct* pstr_loudness_info,
|
|
ia_parametric_drc_params_struct *p_parametricdrc_params,
|
|
pVOID *mem_ptr)
|
|
{
|
|
|
|
WORD32 err = 0, instance_idx = 0, gain_set_index = 0, side_chain_config_type = 0, downmix_id = 0, ch_count_from_dwnmix_id = 0, L = 0;
|
|
|
|
p_parametricdrc_params->parametric_drc_frame_size = pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc.parametric_drc_frame_size;
|
|
p_parametricdrc_params->reset_parametric_drc = pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc.reset_parametric_drc;
|
|
p_parametricdrc_params->num_nodes = p_parametricdrc_params->drc_frame_size/p_parametricdrc_params->parametric_drc_frame_size;
|
|
|
|
switch (p_parametricdrc_params->sub_band_domain_mode) {
|
|
case SUBBAND_DOMAIN_MODE_QMF64:
|
|
L = AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR_QMF64;
|
|
break;
|
|
case SUBBAND_DOMAIN_MODE_QMF71:
|
|
L = AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR_QMF71;
|
|
break;
|
|
case SUBBAND_DOMAIN_MODE_STFT256:
|
|
L = AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR_STFT256;
|
|
break;
|
|
case SUBBAND_DOMAIN_MODE_OFF:
|
|
default:
|
|
L = 0;
|
|
break;
|
|
}
|
|
|
|
if (p_parametricdrc_params->sub_band_domain_mode != SUBBAND_DOMAIN_MODE_OFF && p_parametricdrc_params->parametric_drc_frame_size != L)
|
|
{
|
|
return (EXTERNAL_ERROR);
|
|
}
|
|
|
|
for (instance_idx=0; instance_idx<p_parametricdrc_params->parametric_drc_instance_count; instance_idx++) {
|
|
|
|
gain_set_index = p_parametricdrc_params->gain_set_index[instance_idx];
|
|
side_chain_config_type = pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc.str_parametric_drc_gain_set_params[gain_set_index].side_chain_config_type;
|
|
downmix_id = pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc.str_parametric_drc_gain_set_params[gain_set_index].downmix_id;
|
|
|
|
if (side_chain_config_type==1 && downmix_id == p_parametricdrc_params->dwnmix_id_from_drc_instructions[instance_idx]) {
|
|
ch_count_from_dwnmix_id = pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc.str_parametric_drc_gain_set_params[gain_set_index].ch_count_from_dwnmix_id;
|
|
} else {
|
|
ch_count_from_dwnmix_id = 0;
|
|
}
|
|
|
|
if (pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc.str_parametric_drc_gain_set_params[gain_set_index].drc_input_loudness_present == 0) {
|
|
WORD32 n = 0, m = 0, drcInputLoudnessFound = 0;
|
|
FLOAT32 drc_input_loudness = 0.f;
|
|
|
|
|
|
for (n=0; n<pstr_loudness_info->loudness_info_count; n++)
|
|
{
|
|
ia_loudness_info_struct* loudness_info = &pstr_loudness_info->loudness_info[n];
|
|
if (p_parametricdrc_params->dwnmix_id_from_drc_instructions[instance_idx] == loudness_info->downmix_id)
|
|
{
|
|
if (0 == loudness_info->drc_set_id)
|
|
{
|
|
for (m=0; m<loudness_info->measurement_count; m++)
|
|
{
|
|
if (loudness_info->loudness_measure[m].method_def == METHOD_DEFINITION_PROGRAM_LOUDNESS)
|
|
{
|
|
drc_input_loudness = loudness_info->loudness_measure[m].method_val;
|
|
drcInputLoudnessFound = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (drcInputLoudnessFound == 0)
|
|
{
|
|
for (m=0; m<loudness_info->measurement_count; m++)
|
|
{
|
|
if (loudness_info->loudness_measure[m].method_def == METHOD_DEFINITION_ANCHOR_LOUDNESS)
|
|
{
|
|
drc_input_loudness = loudness_info->loudness_measure[m].method_val;
|
|
drcInputLoudnessFound = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (drcInputLoudnessFound == 0)
|
|
{
|
|
for (n=0; n<pstr_loudness_info->loudness_info_count; n++)
|
|
{
|
|
ia_loudness_info_struct* loudness_info = &pstr_loudness_info->loudness_info[n];
|
|
if (0 == loudness_info->downmix_id)
|
|
{
|
|
if (0 == loudness_info->drc_set_id)
|
|
{
|
|
for (m=0; m<loudness_info->measurement_count; m++)
|
|
{
|
|
if (loudness_info->loudness_measure[m].method_def == METHOD_DEFINITION_PROGRAM_LOUDNESS)
|
|
{
|
|
drc_input_loudness = loudness_info->loudness_measure[m].method_val;
|
|
drcInputLoudnessFound = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (drcInputLoudnessFound == 0) {
|
|
for (m=0; m<loudness_info->measurement_count; m++)
|
|
{
|
|
if (loudness_info->loudness_measure[m].method_def == METHOD_DEFINITION_ANCHOR_LOUDNESS)
|
|
{
|
|
drc_input_loudness = loudness_info->loudness_measure[m].method_val;
|
|
drcInputLoudnessFound = 1;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (drcInputLoudnessFound == 0) {
|
|
return (UNEXPECTED_ERROR);
|
|
} else {
|
|
pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc.str_parametric_drc_gain_set_params[gain_set_index].drc_input_loudness = drc_input_loudness;
|
|
}
|
|
}
|
|
|
|
impd_init_parametric_drcInstance(pstr_drc_config,
|
|
instance_idx,
|
|
ch_count_from_dwnmix_id,
|
|
p_parametricdrc_params,
|
|
mem_ptr);
|
|
if (err) return (err);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
WORD32 impd_init_lvl_est_filt_time( WORD32 level_estim_k_weighting_type,
|
|
WORD32 sampling_rate,
|
|
ia_2nd_order_filt_coeff_struct* pre_filt_coeff,
|
|
ia_2nd_order_filt_coeff_struct* rlb_filt_coeff)
|
|
{
|
|
|
|
WORD32 i;
|
|
const FLOAT32* ptr_samp_tbl;
|
|
|
|
switch(sampling_rate)
|
|
{
|
|
case 96000:i=0;
|
|
break;
|
|
case 88200:i=1;
|
|
break;
|
|
case 64000:i=2;
|
|
break;
|
|
case 48000:i=3;
|
|
break;
|
|
case 44100:i=4;
|
|
break;
|
|
case 32000:i=5;
|
|
break;
|
|
case 24000:i=6;
|
|
break;
|
|
case 22050:i=7;
|
|
break;
|
|
case 16000:i=8;
|
|
break;
|
|
case 12000:i=9;
|
|
break;
|
|
case 11025:i=10;
|
|
break;
|
|
case 8000:i=11;
|
|
break;
|
|
case 7350:i=12;
|
|
break;
|
|
default:i=3;
|
|
break;
|
|
}
|
|
|
|
ptr_samp_tbl = samp_rate_tbl[i];
|
|
|
|
if (level_estim_k_weighting_type==2) {
|
|
|
|
pre_filt_coeff->b0 = ptr_samp_tbl[0];
|
|
pre_filt_coeff->b1 = ptr_samp_tbl[1];
|
|
pre_filt_coeff->b2 = ptr_samp_tbl[2];
|
|
pre_filt_coeff->a1 = ptr_samp_tbl[3];
|
|
pre_filt_coeff->a2 = ptr_samp_tbl[4];
|
|
|
|
|
|
}
|
|
|
|
if (level_estim_k_weighting_type == 1 || level_estim_k_weighting_type == 2) {
|
|
|
|
rlb_filt_coeff->b0 = ptr_samp_tbl[5];
|
|
rlb_filt_coeff->b1 = ptr_samp_tbl[6];
|
|
rlb_filt_coeff->b2 = ptr_samp_tbl[7];
|
|
rlb_filt_coeff->a1 = ptr_samp_tbl[8];
|
|
rlb_filt_coeff->a2 = ptr_samp_tbl[9];
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
WORD32 impd_init_lvl_est_filt_subband( WORD32 level_estim_k_weighting_type,
|
|
WORD32 sampling_rate,
|
|
WORD32 sub_band_domain_mode,
|
|
WORD32 sub_band_count,
|
|
WORD32 sub_band_compensation_type,
|
|
FLOAT32 *weighting_filt,
|
|
ia_2nd_order_filt_coeff_struct* filt_coeff_subband)
|
|
{
|
|
FLOAT32 w0, alpha, sinw0, cosw0;
|
|
FLOAT32 b0, b1, b2, a0, a1, a2;
|
|
FLOAT32 num_real,num_imag,den_real,den_imag;
|
|
FLOAT32 *f_bands_nrm;
|
|
WORD32 b;
|
|
WORD32 i;
|
|
const FLOAT32* ptr_samp_tbl;
|
|
|
|
switch(sampling_rate)
|
|
{
|
|
case 96000:i=0;
|
|
break;
|
|
case 88200:i=1;
|
|
break;
|
|
case 64000:i=2;
|
|
break;
|
|
case 48000:i=3;
|
|
break;
|
|
case 44100:i=4;
|
|
break;
|
|
case 32000:i=5;
|
|
break;
|
|
case 24000:i=6;
|
|
break;
|
|
case 22050:i=7;
|
|
break;
|
|
case 16000:i=8;
|
|
break;
|
|
case 12000:i=9;
|
|
break;
|
|
case 11025:i=10;
|
|
break;
|
|
case 8000:i=11;
|
|
break;
|
|
case 7350:i=12;
|
|
break;
|
|
default:i=3;
|
|
break;
|
|
}
|
|
|
|
ptr_samp_tbl = samp_rate_tbl[i];
|
|
|
|
switch (sub_band_domain_mode)
|
|
{
|
|
case SUBBAND_DOMAIN_MODE_QMF64:
|
|
f_bands_nrm = f_bands_nrm_QMF64;
|
|
break;
|
|
case SUBBAND_DOMAIN_MODE_QMF71:
|
|
f_bands_nrm = f_bands_nrm_QMF71;
|
|
break;
|
|
case SUBBAND_DOMAIN_MODE_STFT256:
|
|
f_bands_nrm = f_bands_nrm_STFT256;
|
|
break;
|
|
default:
|
|
return UNEXPECTED_ERROR;
|
|
break;
|
|
}
|
|
|
|
for (b=0; b<sub_band_count; b++)
|
|
{
|
|
weighting_filt[b] = 1.f;
|
|
}
|
|
|
|
if (level_estim_k_weighting_type == 2)
|
|
{
|
|
|
|
b0 = ptr_samp_tbl[0];
|
|
b1 = ptr_samp_tbl[1];
|
|
b2 = ptr_samp_tbl[2];
|
|
a1 = ptr_samp_tbl[3];
|
|
a2 = ptr_samp_tbl[4];
|
|
a0 = 1.f;
|
|
|
|
for (b=0; b<sub_band_count; b++)
|
|
{
|
|
|
|
num_real = b0 + b1 * (FLOAT32)cos(PI*f_bands_nrm[b]) + b2 * (FLOAT32)cos(PI*2*f_bands_nrm[b]);
|
|
num_imag = - b1 * (FLOAT32)sin(PI*f_bands_nrm[b]) - b2 * (FLOAT32)sin(PI*2*f_bands_nrm[b]);
|
|
den_real = a0 + a1 *(FLOAT32) cos(PI*f_bands_nrm[b]) + a2 * (FLOAT32)cos(PI*2*f_bands_nrm[b]);
|
|
den_imag = - a1 * (FLOAT32)sin(PI*f_bands_nrm[b]) - a2 * (FLOAT32)sin(PI*2*f_bands_nrm[b]);
|
|
|
|
weighting_filt[b] *= (FLOAT32)(sqrt((num_real*num_real+num_imag*num_imag)/(den_real*den_real+den_imag*den_imag)));
|
|
}
|
|
}
|
|
|
|
if (level_estim_k_weighting_type == 1 || level_estim_k_weighting_type == 2)
|
|
{
|
|
b0 = ptr_samp_tbl[5];
|
|
b1 = ptr_samp_tbl[6];
|
|
b2 = ptr_samp_tbl[7];
|
|
a1 = ptr_samp_tbl[8];
|
|
a2 = ptr_samp_tbl[9];
|
|
a0 = 1.f;
|
|
|
|
|
|
for (b=0; b<sub_band_count; b++)
|
|
{
|
|
|
|
if (!(sub_band_compensation_type==1 && b==0))
|
|
{
|
|
num_real =(FLOAT32)( b0 + b1 * cos(PI*f_bands_nrm[b]) + b2 * cos(PI*2*f_bands_nrm[b]));
|
|
num_imag =(FLOAT32)( - b1 * sin(PI*f_bands_nrm[b]) - b2 * sin(PI*2*f_bands_nrm[b]));
|
|
den_real = (FLOAT32)(a0 + a1 * cos(PI*f_bands_nrm[b]) + a2 * cos(PI*2*f_bands_nrm[b]));
|
|
den_imag = (FLOAT32)(- a1 * sin(PI*f_bands_nrm[b]) - a2 * sin(PI*2*f_bands_nrm[b]));
|
|
|
|
weighting_filt[b] *= (FLOAT32)(sqrt((num_real*num_real+num_imag*num_imag)/(den_real*den_real+den_imag*den_imag)));
|
|
}
|
|
}
|
|
|
|
if (sub_band_compensation_type==1)
|
|
{
|
|
|
|
w0 = 2.0f*PI * 38.0f / (FLOAT32)sampling_rate * AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR_QMF64;
|
|
sinw0 = (FLOAT32)sin(w0);
|
|
cosw0 = (FLOAT32)cos(w0);
|
|
alpha = sinw0;
|
|
|
|
b0 = (1 + cosw0)/2;
|
|
b1 = -(1 + cosw0);
|
|
b2 = (1 + cosw0)/2;
|
|
a0 = 1 + alpha;
|
|
a1 = -2*cosw0;
|
|
a2 = 1 - alpha;
|
|
|
|
filt_coeff_subband->b0 = b0/a0;
|
|
filt_coeff_subband->b1 = b1/a0;
|
|
filt_coeff_subband->b2 = b2/a0;
|
|
filt_coeff_subband->a1 = a1/a0;
|
|
filt_coeff_subband->a2 = a2/a0;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
WORD32 impd_parametric_ffwd_type_drc_reset(ia_parametric_drc_type_ff_params_struct* pstr_parametric_ffwd_type_drc_params)
|
|
{
|
|
WORD32 i = 0;
|
|
|
|
pstr_parametric_ffwd_type_drc_params->level_estim_frame_index = 0;
|
|
pstr_parametric_ffwd_type_drc_params->start_up_phase = 1;
|
|
for (i=0; i<PARAM_DRC_TYPE_FF_LEVEL_ESTIM_FRAME_COUNT_MAX; i++) {
|
|
pstr_parametric_ffwd_type_drc_params->level[i] = 0.f;
|
|
}
|
|
|
|
for (i=0; i<MAX_CHANNEL_COUNT; i++) {
|
|
pstr_parametric_ffwd_type_drc_params->pre_filt_state[i].z1 = 0.f;
|
|
pstr_parametric_ffwd_type_drc_params->pre_filt_state[i].z2 = 0.f;
|
|
pstr_parametric_ffwd_type_drc_params->rlb_filt_state[i].z1 = 0.f;
|
|
pstr_parametric_ffwd_type_drc_params->rlb_filt_state[i].z2 = 0.f;
|
|
pstr_parametric_ffwd_type_drc_params->filt_state_subband_real[i].z1 = 0.f;
|
|
pstr_parametric_ffwd_type_drc_params->filt_state_subband_real[i].z2 = 0.f;
|
|
pstr_parametric_ffwd_type_drc_params->filt_state_subband_imag[i].z1 = 0.f;
|
|
pstr_parametric_ffwd_type_drc_params->filt_state_subband_imag[i].z2 = 0.f;
|
|
}
|
|
|
|
pstr_parametric_ffwd_type_drc_params->db_level_smooth = -135.f;
|
|
pstr_parametric_ffwd_type_drc_params->db_gain_smooth = 0.f;
|
|
pstr_parametric_ffwd_type_drc_params->hold_counter = 0;
|
|
|
|
return 0;
|
|
}
|
|
|
|
WORD32 impd_parametric_drc_instance_process (FLOAT32* audio_in_out_buf[],
|
|
FLOAT32* audio_real_buff[],
|
|
FLOAT32* audio_imag_buff[],
|
|
ia_parametric_drc_params_struct* p_parametricdrc_params,
|
|
ia_parametric_drc_instance_params_struct* pstr_parametric_drc_instance_params)
|
|
{
|
|
WORD32 err = 0, i = 0;
|
|
|
|
if (pstr_parametric_drc_instance_params->disable_paramteric_drc) {
|
|
|
|
for (i=0; i<p_parametricdrc_params->num_nodes; i++) {
|
|
|
|
pstr_parametric_drc_instance_params->str_spline_nodes.str_node[i].loc_db_gain = 0.f;
|
|
pstr_parametric_drc_instance_params->str_spline_nodes.str_node[i].slope = 0.f;
|
|
pstr_parametric_drc_instance_params->str_spline_nodes.str_node[i].time = (i+1) * p_parametricdrc_params->parametric_drc_frame_size - 1;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (pstr_parametric_drc_instance_params->parametric_drc_type == PARAM_DRC_TYPE_FF) {
|
|
|
|
ia_parametric_drc_type_ff_params_struct* pstr_parametric_ffwd_type_drc_params = &(pstr_parametric_drc_instance_params->str_parametric_drc_type_ff_params);
|
|
for (i=0; i<p_parametricdrc_params->num_nodes; i++) {
|
|
err = impd_parametric_ffwd_type_drc_process(audio_in_out_buf,
|
|
audio_real_buff,
|
|
audio_imag_buff,
|
|
i,
|
|
pstr_parametric_ffwd_type_drc_params,
|
|
&pstr_parametric_drc_instance_params->str_spline_nodes);
|
|
if (err) return (err);
|
|
}
|
|
|
|
} else if (pstr_parametric_drc_instance_params->parametric_drc_type == PARAM_DRC_TYPE_LIM) {
|
|
|
|
return (UNEXPECTED_ERROR);
|
|
|
|
} else {
|
|
return (UNEXPECTED_ERROR);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
VOID iir_second_order_filter (ia_2nd_order_filt_coeff_struct* coeff,
|
|
ia_2nd_order_filt_state_struct* state,
|
|
WORD32 frame_len,
|
|
FLOAT32* input,
|
|
FLOAT32* output)
|
|
{
|
|
FLOAT32 z2=state->z2;
|
|
FLOAT32 z1=state->z1;
|
|
FLOAT32 z0;
|
|
WORD32 i;
|
|
|
|
for (i=0; i<frame_len; i++)
|
|
{
|
|
z0 = input[i] - coeff->a1 * z1 - coeff->a2 * z2;
|
|
output[i] = coeff->b0 * z0 + coeff->b1 * z1 + coeff->b2 * z2;
|
|
z2 = z1;
|
|
z1 = z0;
|
|
|
|
}
|
|
state->z1=z1;
|
|
state->z2=z2;
|
|
}
|
|
WORD32 impd_parametric_ffwd_type_drc_process(FLOAT32* audio_in_out_buf[],
|
|
FLOAT32* audio_real_buff[],
|
|
FLOAT32* audio_imag_buff[],
|
|
WORD32 nodeIdx,
|
|
ia_parametric_drc_type_ff_params_struct* pstr_parametric_ffwd_type_drc_params,
|
|
ia_spline_nodes_struct* str_spline_nodes)
|
|
{
|
|
WORD32 c, t, b, n, i, offset;
|
|
FLOAT32 x, y, channelLevel, level, levelDb, loc_db_gain, levelDelta, alpha;
|
|
|
|
WORD32 frame_size = pstr_parametric_ffwd_type_drc_params->frame_size;
|
|
WORD32 sub_band_count = pstr_parametric_ffwd_type_drc_params->sub_band_count;
|
|
FLOAT32 *level_estim_ch_weight = pstr_parametric_ffwd_type_drc_params->level_estim_ch_weight;
|
|
WORD32 level_estim_k_weighting_type = pstr_parametric_ffwd_type_drc_params->level_estim_k_weighting_type;
|
|
|
|
ia_2nd_order_filt_coeff_struct preC = pstr_parametric_ffwd_type_drc_params->pre_filt_coeff;
|
|
ia_2nd_order_filt_coeff_struct rlbC = pstr_parametric_ffwd_type_drc_params->rlb_filt_coeff;
|
|
ia_2nd_order_filt_state_struct* preS = pstr_parametric_ffwd_type_drc_params->pre_filt_state;
|
|
ia_2nd_order_filt_state_struct* rlbS = pstr_parametric_ffwd_type_drc_params->rlb_filt_state;
|
|
|
|
ia_2nd_order_filt_coeff_struct rlbC_sb = pstr_parametric_ffwd_type_drc_params->filt_coeff_subband;
|
|
ia_2nd_order_filt_state_struct* rlbS_sbReal = pstr_parametric_ffwd_type_drc_params->filt_state_subband_real;
|
|
ia_2nd_order_filt_state_struct* rlbS_sbImag = pstr_parametric_ffwd_type_drc_params->filt_state_subband_imag;
|
|
FLOAT32 *weighting_filt = pstr_parametric_ffwd_type_drc_params->weighting_filt;
|
|
WORD32 sub_band_compensation_type = pstr_parametric_ffwd_type_drc_params->sub_band_compensation_type;
|
|
|
|
if (audio_in_out_buf != NULL) {
|
|
|
|
level = 0;
|
|
offset = nodeIdx * pstr_parametric_ffwd_type_drc_params->frame_size;
|
|
for(c=0; c<pstr_parametric_ffwd_type_drc_params->audio_num_chan; c++) {
|
|
channelLevel = 0.f;
|
|
|
|
if (!level_estim_ch_weight[c]) continue;
|
|
|
|
if (level_estim_k_weighting_type == 0) {
|
|
|
|
for(t=0; t<frame_size; t++) {
|
|
|
|
x = audio_in_out_buf[c][offset+t];
|
|
|
|
channelLevel += x * x;
|
|
|
|
}
|
|
|
|
} else if (level_estim_k_weighting_type == 1) {
|
|
|
|
for(t=0; t<frame_size; t++) {
|
|
|
|
x = audio_in_out_buf[c][offset+t];
|
|
|
|
iir_second_order_filter(&rlbC,&rlbS[c],1,&x,&x);
|
|
|
|
channelLevel += x * x;
|
|
|
|
}
|
|
|
|
} else if (level_estim_k_weighting_type == 2) {
|
|
|
|
for(t=0; t<frame_size; t++) {
|
|
|
|
x = audio_in_out_buf[c][offset+t];
|
|
|
|
iir_second_order_filter(&preC,&preS[c],1,&x,&x);
|
|
|
|
iir_second_order_filter(&rlbC,&rlbS[c],1,&x,&x);
|
|
|
|
channelLevel += x * x;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return (UNEXPECTED_ERROR);
|
|
|
|
}
|
|
|
|
level += level_estim_ch_weight[c] * channelLevel;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
level = 0;
|
|
offset = nodeIdx * pstr_parametric_ffwd_type_drc_params->sub_band_count;
|
|
for(c=0; c<pstr_parametric_ffwd_type_drc_params->audio_num_chan; c++) {
|
|
channelLevel = 0.f;
|
|
|
|
if (!level_estim_ch_weight[c]) continue;
|
|
|
|
if (level_estim_k_weighting_type == 0) {
|
|
|
|
for(b=0; b<sub_band_count; b++) {
|
|
|
|
x = audio_real_buff[c][offset+b];
|
|
y = audio_imag_buff[c][offset+b];
|
|
|
|
channelLevel += x * x + y * y;
|
|
|
|
}
|
|
|
|
} else if (level_estim_k_weighting_type == 1||level_estim_k_weighting_type == 2) {
|
|
|
|
for(b=0; b<sub_band_count; b++) {
|
|
|
|
x = audio_real_buff[c][offset+b] * weighting_filt[b];
|
|
y = audio_imag_buff[c][offset+b] * weighting_filt[b];
|
|
|
|
if (b==0 && sub_band_compensation_type==1) {
|
|
|
|
iir_second_order_filter(&rlbC_sb,&rlbS_sbReal[c],1,&x,&x);
|
|
|
|
iir_second_order_filter(&rlbC_sb,&rlbS_sbImag[c],1,&y,&y);
|
|
|
|
}
|
|
|
|
channelLevel += x * x + y * y;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
return (UNEXPECTED_ERROR);
|
|
|
|
}
|
|
|
|
level += level_estim_ch_weight[c] * channelLevel;
|
|
|
|
}
|
|
|
|
level /= sub_band_count;
|
|
}
|
|
pstr_parametric_ffwd_type_drc_params->level[pstr_parametric_ffwd_type_drc_params->level_estim_frame_index] = level;
|
|
pstr_parametric_ffwd_type_drc_params->level_estim_frame_index++;
|
|
|
|
level = 0.f;
|
|
if (pstr_parametric_ffwd_type_drc_params->start_up_phase) {
|
|
for (i=0; i<pstr_parametric_ffwd_type_drc_params->level_estim_frame_index; i++) {
|
|
level += pstr_parametric_ffwd_type_drc_params->level[i];
|
|
}
|
|
level /= pstr_parametric_ffwd_type_drc_params->level_estim_frame_index * pstr_parametric_ffwd_type_drc_params->frame_size;
|
|
} else {
|
|
for (i=0; i<pstr_parametric_ffwd_type_drc_params->level_estim_frame_count; i++) {
|
|
level += pstr_parametric_ffwd_type_drc_params->level[i];
|
|
}
|
|
level /= pstr_parametric_ffwd_type_drc_params->level_estim_integration_time;
|
|
}
|
|
if (pstr_parametric_ffwd_type_drc_params->level_estim_frame_index == pstr_parametric_ffwd_type_drc_params->level_estim_frame_count) {
|
|
pstr_parametric_ffwd_type_drc_params->level_estim_frame_index = 0;
|
|
pstr_parametric_ffwd_type_drc_params->start_up_phase = 0;
|
|
}
|
|
|
|
if (level < 1e-10f) level = 1e-10f;
|
|
if (level_estim_k_weighting_type == 2) {
|
|
levelDb = -0.691f + 10 * (FLOAT32)log10(level) + 3;
|
|
} else {
|
|
levelDb = 10 * (FLOAT32)log10(level) + 3;
|
|
}
|
|
levelDb -= pstr_parametric_ffwd_type_drc_params->ref_level_parametric_drc;
|
|
|
|
for(n=0; n<pstr_parametric_ffwd_type_drc_params->node_count; n++) {
|
|
if (levelDb <= (FLOAT32)pstr_parametric_ffwd_type_drc_params->node_level[n]) {
|
|
break;
|
|
}
|
|
}
|
|
if (n == 0) {
|
|
loc_db_gain = (FLOAT32)pstr_parametric_ffwd_type_drc_params->node_gain[n];
|
|
} else if (n == pstr_parametric_ffwd_type_drc_params->node_count) {
|
|
loc_db_gain = (FLOAT32)pstr_parametric_ffwd_type_drc_params->node_gain[n-1] - levelDb + (FLOAT32)pstr_parametric_ffwd_type_drc_params->node_level[n-1];
|
|
} else {
|
|
loc_db_gain = (FLOAT32)pstr_parametric_ffwd_type_drc_params->node_gain[n] + (levelDb - (FLOAT32)pstr_parametric_ffwd_type_drc_params->node_level[n]) / (FLOAT32)(pstr_parametric_ffwd_type_drc_params->node_level[n-1] - pstr_parametric_ffwd_type_drc_params->node_level[n]) * (FLOAT32)(pstr_parametric_ffwd_type_drc_params->node_gain[n-1] - pstr_parametric_ffwd_type_drc_params->node_gain[n]);
|
|
}
|
|
|
|
levelDelta = levelDb - pstr_parametric_ffwd_type_drc_params->db_level_smooth;
|
|
if (loc_db_gain < pstr_parametric_ffwd_type_drc_params->db_gain_smooth) {
|
|
if (levelDelta > pstr_parametric_ffwd_type_drc_params->gain_smooth_attack_threshold) {
|
|
alpha = pstr_parametric_ffwd_type_drc_params->gain_smooth_attack_alpha_fast;
|
|
} else {
|
|
alpha = pstr_parametric_ffwd_type_drc_params->gain_smooth_attack_alpha_slow;
|
|
}
|
|
} else {
|
|
if (levelDelta < -pstr_parametric_ffwd_type_drc_params->gain_smooth_rel_threshold) {
|
|
alpha = pstr_parametric_ffwd_type_drc_params->gain_smooth_rel_alpha_fast;
|
|
} else {
|
|
alpha = pstr_parametric_ffwd_type_drc_params->gain_smooth_rel_alpha_slow;
|
|
}
|
|
}
|
|
if (loc_db_gain < pstr_parametric_ffwd_type_drc_params->db_gain_smooth || pstr_parametric_ffwd_type_drc_params->hold_counter == 0) {
|
|
pstr_parametric_ffwd_type_drc_params->db_level_smooth = (1-alpha) * pstr_parametric_ffwd_type_drc_params->db_level_smooth + alpha * levelDb;
|
|
pstr_parametric_ffwd_type_drc_params->db_gain_smooth = (1-alpha) * pstr_parametric_ffwd_type_drc_params->db_gain_smooth + alpha * loc_db_gain;
|
|
}
|
|
if (pstr_parametric_ffwd_type_drc_params->hold_counter) {
|
|
pstr_parametric_ffwd_type_drc_params->hold_counter -= 1;
|
|
}
|
|
if (loc_db_gain < pstr_parametric_ffwd_type_drc_params->db_gain_smooth) {
|
|
pstr_parametric_ffwd_type_drc_params->hold_counter = pstr_parametric_ffwd_type_drc_params->gain_smooth_hold_off_count;
|
|
}
|
|
|
|
|
|
str_spline_nodes->str_node[nodeIdx].loc_db_gain = pstr_parametric_ffwd_type_drc_params->db_gain_smooth;
|
|
str_spline_nodes->str_node[nodeIdx].slope = 0.f;
|
|
str_spline_nodes->str_node[nodeIdx].time = pstr_parametric_ffwd_type_drc_params->frame_size + offset - 1;
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
WORD32 impd_parametric_lim_type_drc_process(FLOAT32* samples[],
|
|
FLOAT32 loudness_normalization_gain_db,
|
|
ia_parametric_drc_type_lim_params_struct* pstr_parametric_lim_type_drc_params,
|
|
FLOAT32* lpcm_gains)
|
|
{
|
|
WORD32 i, j;
|
|
FLOAT32 tmp, gain;
|
|
// FLOAT32 min_gain = 1;
|
|
FLOAT32 maximum, sectionMaximum;
|
|
FLOAT32 loudness_normalization_gain = (FLOAT32)pow(10.0f, 0.05f * loudness_normalization_gain_db);
|
|
FLOAT32* level_estim_ch_weight = pstr_parametric_lim_type_drc_params->level_estim_ch_weight;
|
|
WORD32 num_channels = pstr_parametric_lim_type_drc_params->channels;
|
|
WORD32 attack_time_samples = pstr_parametric_lim_type_drc_params->attack;
|
|
FLOAT32 attack_constant = pstr_parametric_lim_type_drc_params->attack_constant;
|
|
FLOAT32 release_constant = pstr_parametric_lim_type_drc_params->release_constant;
|
|
FLOAT32 limit_threshold = pstr_parametric_lim_type_drc_params->threshold;
|
|
FLOAT32* max_buf = pstr_parametric_lim_type_drc_params->max_buf;
|
|
FLOAT32 gain_modified = pstr_parametric_lim_type_drc_params->cor;
|
|
FLOAT64 pre_smoothed_gain = pstr_parametric_lim_type_drc_params->smooth_state_0;
|
|
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < pstr_parametric_lim_type_drc_params->frame_size; i++) {
|
|
tmp =0.0f;
|
|
for (j = 0; j < num_channels; j++){
|
|
if (!level_estim_ch_weight[j])
|
|
continue;
|
|
tmp = max(tmp, (FLOAT32)fabs(loudness_normalization_gain*(level_estim_ch_weight[j])*(samples[j][i])));
|
|
}
|
|
|
|
for (j = attack_time_samples; j >0; j--) {
|
|
max_buf[j]=max_buf[j-1];
|
|
}
|
|
max_buf[0] = tmp;
|
|
sectionMaximum=tmp;
|
|
for (j = 1; j < (attack_time_samples+1); j++) {
|
|
if (max_buf[j] > sectionMaximum)
|
|
sectionMaximum = max_buf[j];
|
|
}
|
|
maximum=sectionMaximum;
|
|
|
|
if (maximum > limit_threshold) {
|
|
gain = limit_threshold / maximum;
|
|
}
|
|
else {
|
|
gain = 1;
|
|
}
|
|
|
|
if (gain < pre_smoothed_gain) {
|
|
gain_modified = min(gain_modified, (gain - 0.1f * (FLOAT32)pre_smoothed_gain) * 1.11111111f);
|
|
}
|
|
else {
|
|
gain_modified = gain;
|
|
}
|
|
|
|
if (gain_modified < pre_smoothed_gain) {
|
|
pre_smoothed_gain = attack_constant * (pre_smoothed_gain - gain_modified) + gain_modified;
|
|
pre_smoothed_gain = max(pre_smoothed_gain, gain);
|
|
}
|
|
else {
|
|
pre_smoothed_gain = release_constant * (pre_smoothed_gain - gain_modified) + gain_modified;
|
|
}
|
|
|
|
gain = (FLOAT32)pre_smoothed_gain;
|
|
|
|
lpcm_gains[i] = gain;
|
|
}
|
|
|
|
|
|
pstr_parametric_lim_type_drc_params->cor = gain_modified;
|
|
pstr_parametric_lim_type_drc_params->smooth_state_0 = pre_smoothed_gain;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|