| /****************************************************************************** |
| * |
| * 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) { |
| static const 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; |
| } |
| |
| VOID 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 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; |
| } |
| } |
| |
| 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; |
| |
| impd_init_parametric_drc_lim(pstr_drc_config, instance_idx, |
| ch_count_from_dwnmix_id, |
| p_parametricdrc_params, mem_ptr); |
| |
| } 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; |
| } |
| } |
| |
| err = 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; |
| const 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; |
| } |
| |
| VOID 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; |
| } |