Home | History | Annotate | Download | only in drc_src
      1 /******************************************************************************
      2  *
      3  * Copyright (C) 2018 The Android Open Source Project
      4  *
      5  * Licensed under the Apache License, Version 2.0 (the "License");
      6  * you may not use this file except in compliance with the License.
      7  * You may obtain a copy of the License at:
      8  *
      9  * http://www.apache.org/licenses/LICENSE-2.0
     10  *
     11  * Unless required by applicable law or agreed to in writing, software
     12  * distributed under the License is distributed on an "AS IS" BASIS,
     13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  * See the License for the specific language governing permissions and
     15  * limitations under the License.
     16  *
     17  *****************************************************************************
     18  * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
     19 */
     20 #include <stdlib.h>
     21 #include <stdio.h>
     22 #include <math.h>
     23 #include <string.h>
     24 #include "impd_type_def.h"
     25 #include "impd_drc_extr_delta_coded_info.h"
     26 #include "impd_drc_common.h"
     27 #include "impd_drc_struct.h"
     28 #include "impd_parametric_drc_dec.h"
     29 #include "impd_drc_filter_bank.h"
     30 #include "impd_drc_rom.h"
     31 
     32 #define PI 3.14159265f
     33 
     34 #ifndef max
     35 #define max(a, b) (((a) > (b)) ? (a) : (b))
     36 #endif
     37 #ifndef min
     38 #define min(a, b) (((a) < (b)) ? (a) : (b))
     39 #endif
     40 
     41 WORD32 impd_init_parametric_drc(
     42     WORD32 drc_frame_size, WORD32 sampling_rate, WORD32 sub_band_domain_mode,
     43     ia_parametric_drc_params_struct* p_parametricdrc_params) {
     44   WORD32 sub_band_count_tbl[4] = {0, 64, 71, 256};
     45   p_parametricdrc_params->drc_frame_size = drc_frame_size;
     46   p_parametricdrc_params->sampling_rate = sampling_rate;
     47   p_parametricdrc_params->sub_band_domain_mode = sub_band_domain_mode;
     48 
     49   p_parametricdrc_params->sub_band_count =
     50       sub_band_count_tbl[sub_band_domain_mode];
     51 
     52   return 0;
     53 }
     54 
     55 WORD32 impd_init_parametric_drc_feed_fwd(
     56     ia_drc_config* pstr_drc_config, WORD32 instance_idx,
     57     WORD32 ch_count_from_dwnmix_id,
     58     ia_parametric_drc_params_struct* p_parametricdrc_params) {
     59   WORD32 err = 0, i = 0;
     60 
     61   WORD32 parametric_drc_idx =
     62       p_parametricdrc_params->parametric_drc_idx[instance_idx];
     63   WORD32 gain_set_index = p_parametricdrc_params->gain_set_index[instance_idx];
     64   WORD32* channel_map = p_parametricdrc_params->channel_map[instance_idx];
     65 
     66   ia_drc_coeff_parametric_drc_struct* hDrcCoefficientsParametricDrcBs =
     67       &(pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc);
     68   ia_parametric_drc_type_feed_forward_struct* hParametricDrcTypeFeedForwardBs =
     69       &(pstr_drc_config->str_drc_config_ext
     70             .str_parametric_drc_instructions[parametric_drc_idx]
     71             .str_parametric_drc_type_feed_forward);
     72   ia_parametric_drc_type_ff_params_struct*
     73       pstr_parametric_ffwd_type_drc_params =
     74           &(p_parametricdrc_params
     75                 ->str_parametric_drc_instance_params[instance_idx]
     76                 .str_parametric_drc_type_ff_params);
     77 
     78   /* level estimation */
     79   pstr_parametric_ffwd_type_drc_params->frame_size =
     80       p_parametricdrc_params->parametric_drc_frame_size;
     81   pstr_parametric_ffwd_type_drc_params->sub_band_domain_mode =
     82       p_parametricdrc_params->sub_band_domain_mode;
     83   pstr_parametric_ffwd_type_drc_params->sub_band_count =
     84       p_parametricdrc_params->sub_band_count;
     85   pstr_parametric_ffwd_type_drc_params->sub_band_compensation_type = 0;
     86 
     87   if (pstr_parametric_ffwd_type_drc_params->sub_band_domain_mode ==
     88       SUBBAND_DOMAIN_MODE_QMF64) {
     89     if (p_parametricdrc_params->sampling_rate == 48000) {
     90       pstr_parametric_ffwd_type_drc_params->sub_band_compensation_type = 1;
     91     } else {
     92       /* support of other sampling rates than 48000 might be missing */
     93       return UNEXPECTED_ERROR;
     94     }
     95   }
     96 
     97   pstr_parametric_ffwd_type_drc_params->audio_num_chan =
     98       p_parametricdrc_params->audio_num_chan;
     99   pstr_parametric_ffwd_type_drc_params->level_estim_k_weighting_type =
    100       hParametricDrcTypeFeedForwardBs->level_estim_k_weighting_type;
    101   pstr_parametric_ffwd_type_drc_params->level_estim_integration_time =
    102       hParametricDrcTypeFeedForwardBs->level_estim_integration_time;
    103   pstr_parametric_ffwd_type_drc_params->level_estim_frame_index = 0;
    104   pstr_parametric_ffwd_type_drc_params->level_estim_frame_count =
    105       hParametricDrcTypeFeedForwardBs->level_estim_integration_time /
    106       pstr_parametric_ffwd_type_drc_params->frame_size;
    107 
    108   memset(pstr_parametric_ffwd_type_drc_params->level, 0,
    109          PARAM_DRC_TYPE_FF_LEVEL_ESTIM_FRAME_COUNT_MAX * sizeof(FLOAT32));
    110 
    111   if (ch_count_from_dwnmix_id != 0) {
    112     memcpy(pstr_parametric_ffwd_type_drc_params->level_estim_ch_weight,
    113            hDrcCoefficientsParametricDrcBs
    114                ->str_parametric_drc_gain_set_params[gain_set_index]
    115                .level_estim_ch_weight,
    116            ch_count_from_dwnmix_id * sizeof(FLOAT32));
    117   } else {
    118     for (i = 0; i < pstr_parametric_ffwd_type_drc_params->audio_num_chan; i++) {
    119       pstr_parametric_ffwd_type_drc_params->level_estim_ch_weight[i] =
    120           (FLOAT32)channel_map[i];
    121     }
    122   }
    123 
    124   if (pstr_parametric_ffwd_type_drc_params->sub_band_domain_mode ==
    125       SUBBAND_DOMAIN_MODE_OFF) {
    126     err = impd_init_lvl_est_filt_time(
    127         pstr_parametric_ffwd_type_drc_params->level_estim_k_weighting_type,
    128         p_parametricdrc_params->sampling_rate,
    129         &pstr_parametric_ffwd_type_drc_params->pre_filt_coeff,
    130         &pstr_parametric_ffwd_type_drc_params->rlb_filt_coeff);
    131 
    132     if (err) return (err);
    133   } else {
    134     err = impd_init_lvl_est_filt_subband(
    135         pstr_parametric_ffwd_type_drc_params->level_estim_k_weighting_type,
    136         p_parametricdrc_params->sampling_rate,
    137         p_parametricdrc_params->sub_band_domain_mode,
    138         p_parametricdrc_params->sub_band_count,
    139         pstr_parametric_ffwd_type_drc_params->sub_band_compensation_type,
    140         pstr_parametric_ffwd_type_drc_params->weighting_filt,
    141         &pstr_parametric_ffwd_type_drc_params->filt_coeff_subband);
    142 
    143     if (err) return (err);
    144   }
    145 
    146   pstr_parametric_ffwd_type_drc_params->node_count =
    147       hParametricDrcTypeFeedForwardBs->node_count;
    148 
    149   memcpy(pstr_parametric_ffwd_type_drc_params->node_level,
    150          hParametricDrcTypeFeedForwardBs->node_level,
    151          pstr_parametric_ffwd_type_drc_params->node_count * sizeof(WORD32));
    152   memcpy(pstr_parametric_ffwd_type_drc_params->node_gain,
    153          hParametricDrcTypeFeedForwardBs->node_gain,
    154          pstr_parametric_ffwd_type_drc_params->node_count * sizeof(WORD32));
    155 
    156   pstr_parametric_ffwd_type_drc_params->ref_level_parametric_drc =
    157       hDrcCoefficientsParametricDrcBs
    158           ->str_parametric_drc_gain_set_params[gain_set_index]
    159           .drc_input_loudness;
    160 
    161   {
    162     WORD32 gain_smooth_attack_time_fast =
    163         hParametricDrcTypeFeedForwardBs->gain_smooth_attack_time_fast;
    164     WORD32 gain_smooth_release_time_fast =
    165         hParametricDrcTypeFeedForwardBs->gain_smooth_release_time_fast;
    166     WORD32 gain_smooth_attack_time_slow =
    167         hParametricDrcTypeFeedForwardBs->gain_smooth_attack_time_slow;
    168     WORD32 gain_smooth_release_time_slow =
    169         hParametricDrcTypeFeedForwardBs->gain_smooth_release_time_slow;
    170     WORD32 gain_smooth_hold_off =
    171         hParametricDrcTypeFeedForwardBs->gain_smooth_hold_off;
    172     WORD32 sampling_rate = p_parametricdrc_params->sampling_rate;
    173     WORD32 parametric_drc_frame_size =
    174         p_parametricdrc_params->parametric_drc_frame_size;
    175 
    176     pstr_parametric_ffwd_type_drc_params->gain_smooth_attack_alpha_fast =
    177         1 -
    178         (FLOAT32)exp(-1.0 * parametric_drc_frame_size /
    179                      (gain_smooth_attack_time_fast * sampling_rate * 0.001));
    180     pstr_parametric_ffwd_type_drc_params->gain_smooth_rel_alpha_fast =
    181         1 -
    182         (FLOAT32)exp(-1.0 * parametric_drc_frame_size /
    183                      (gain_smooth_release_time_fast * sampling_rate * 0.001));
    184     pstr_parametric_ffwd_type_drc_params->gain_smooth_attack_alpha_slow =
    185         1 -
    186         (FLOAT32)exp(-1.0 * parametric_drc_frame_size /
    187                      (gain_smooth_attack_time_slow * sampling_rate * 0.001));
    188     pstr_parametric_ffwd_type_drc_params->gain_smooth_rel_alpha_slow =
    189         1 -
    190         (FLOAT32)exp(-1.0 * parametric_drc_frame_size /
    191                      (gain_smooth_release_time_slow * sampling_rate * 0.001));
    192     pstr_parametric_ffwd_type_drc_params->gain_smooth_hold_off_count =
    193         gain_smooth_hold_off * 256 * sampling_rate /
    194         (parametric_drc_frame_size * 48000);
    195     pstr_parametric_ffwd_type_drc_params->gain_smooth_attack_threshold =
    196         hParametricDrcTypeFeedForwardBs->gain_smooth_attack_threshold;
    197     pstr_parametric_ffwd_type_drc_params->gain_smooth_rel_threshold =
    198         hParametricDrcTypeFeedForwardBs->gain_smooth_rel_threshold;
    199   }
    200 
    201   err =
    202       impd_parametric_ffwd_type_drc_reset(pstr_parametric_ffwd_type_drc_params);
    203 
    204   if (err) return (err);
    205 
    206   return 0;
    207 }
    208 
    209 VOID impd_init_parametric_drc_lim(
    210     ia_drc_config* pstr_drc_config, WORD32 instance_idx,
    211     WORD32 ch_count_from_dwnmix_id,
    212     ia_parametric_drc_params_struct* p_parametricdrc_params, pVOID* mem_ptr) {
    213   WORD32 i = 0;
    214   UWORD32 j;
    215   UWORD32 attack, sec_len;
    216 
    217   WORD32 parametric_drc_idx =
    218       p_parametricdrc_params->parametric_drc_idx[instance_idx];
    219   WORD32 gain_set_index = p_parametricdrc_params->gain_set_index[instance_idx];
    220   WORD32* channel_map = p_parametricdrc_params->channel_map[instance_idx];
    221 
    222   ia_drc_coeff_parametric_drc_struct* hDrcCoefficientsParametricDrcBs =
    223       &(pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc);
    224   ia_parametric_drc_lim_struct* hParametricDrcTypeLimBs =
    225       &(pstr_drc_config->str_drc_config_ext
    226             .str_parametric_drc_instructions[parametric_drc_idx]
    227             .parametric_drc_lim);
    228   ia_parametric_drc_type_lim_params_struct*
    229       pstr_parametric_lim_type_drc_params =
    230           &(p_parametricdrc_params
    231                 ->str_parametric_drc_instance_params[instance_idx]
    232                 .str_parametric_drc_type_lim_params);
    233 
    234   pstr_parametric_lim_type_drc_params->frame_size =
    235       p_parametricdrc_params->drc_frame_size;
    236   pstr_parametric_lim_type_drc_params->audio_num_chan =
    237       p_parametricdrc_params->audio_num_chan;
    238 
    239   if (ch_count_from_dwnmix_id != 0) {
    240     memcpy(pstr_parametric_lim_type_drc_params->level_estim_ch_weight,
    241            hDrcCoefficientsParametricDrcBs
    242                ->str_parametric_drc_gain_set_params[gain_set_index]
    243                .level_estim_ch_weight,
    244            ch_count_from_dwnmix_id * sizeof(FLOAT32));
    245   } else {
    246     for (i = 0; i < pstr_parametric_lim_type_drc_params->audio_num_chan; i++) {
    247       pstr_parametric_lim_type_drc_params->level_estim_ch_weight[i] =
    248           (FLOAT32)channel_map[i];
    249     }
    250   }
    251 
    252   attack = (UWORD32)(hParametricDrcTypeLimBs->parametric_lim_attack *
    253                      p_parametricdrc_params->sampling_rate / 1000);
    254 
    255   sec_len = (UWORD32)sqrt(attack + 1);
    256 
    257   pstr_parametric_lim_type_drc_params->sec_len = sec_len;
    258   pstr_parametric_lim_type_drc_params->num_max_buf_sec = (attack + 1) / sec_len;
    259   if (pstr_parametric_lim_type_drc_params->num_max_buf_sec * sec_len <
    260       (attack + 1))
    261     pstr_parametric_lim_type_drc_params->num_max_buf_sec++;
    262 
    263   pstr_parametric_lim_type_drc_params->max_buf = (FLOAT32*)(*mem_ptr);
    264   *mem_ptr = (pVOID)((SIZE_T)(*mem_ptr) +
    265                      pstr_parametric_lim_type_drc_params->num_max_buf_sec *
    266                          sec_len * sizeof(FLOAT32));
    267 
    268   pstr_parametric_lim_type_drc_params->attack_ms =
    269       (FLOAT32)hParametricDrcTypeLimBs->parametric_lim_attack;
    270   pstr_parametric_lim_type_drc_params->release_ms =
    271       (FLOAT32)hParametricDrcTypeLimBs->parametric_lim_release;
    272   pstr_parametric_lim_type_drc_params->attack = attack;
    273   pstr_parametric_lim_type_drc_params->attack_constant =
    274       (FLOAT32)pow(0.1, 1.0 / (attack + 1));
    275   pstr_parametric_lim_type_drc_params->release_constant = (FLOAT32)pow(
    276       0.1, 1.0 / (hParametricDrcTypeLimBs->parametric_lim_release *
    277                       p_parametricdrc_params->sampling_rate / 1000 +
    278                   1));
    279   pstr_parametric_lim_type_drc_params->threshold = (FLOAT32)pow(
    280       10.0f, 0.05f * hParametricDrcTypeLimBs->parametric_lim_threshold);
    281   pstr_parametric_lim_type_drc_params->channels =
    282       pstr_parametric_lim_type_drc_params->audio_num_chan;
    283   pstr_parametric_lim_type_drc_params->sampling_rate =
    284       p_parametricdrc_params->sampling_rate;
    285   pstr_parametric_lim_type_drc_params->cor = 1.0f;
    286   pstr_parametric_lim_type_drc_params->smooth_state_0 = 1.0;
    287 
    288   for (j = 0; j < pstr_parametric_lim_type_drc_params->num_max_buf_sec *
    289                       pstr_parametric_lim_type_drc_params->sec_len;
    290        j++) {
    291     pstr_parametric_lim_type_drc_params->max_buf[j] = 0.f;
    292   }
    293 }
    294 
    295 WORD32 impd_init_parametric_drcInstance(
    296     ia_drc_config* pstr_drc_config, WORD32 instance_idx,
    297     WORD32 ch_count_from_dwnmix_id,
    298     ia_parametric_drc_params_struct* p_parametricdrc_params, pVOID* mem_ptr) {
    299   WORD32 err = 0;
    300 
    301   WORD32 parametric_drc_idx =
    302       p_parametricdrc_params->parametric_drc_idx[instance_idx];
    303   ia_parametric_drc_instructions_struct* hParametricDrcInstructions =
    304       &(pstr_drc_config->str_drc_config_ext
    305             .str_parametric_drc_instructions[parametric_drc_idx]);
    306 
    307   p_parametricdrc_params->str_parametric_drc_instance_params[instance_idx]
    308       .disable_paramteric_drc =
    309       hParametricDrcInstructions->disable_paramteric_drc;
    310   p_parametricdrc_params->str_parametric_drc_instance_params[instance_idx]
    311       .parametric_drc_type = hParametricDrcInstructions->parametric_drc_type;
    312   p_parametricdrc_params->str_parametric_drc_instance_params[instance_idx]
    313       .str_spline_nodes.num_nodes = p_parametricdrc_params->num_nodes;
    314 
    315   if (p_parametricdrc_params->str_parametric_drc_instance_params[instance_idx]
    316           .disable_paramteric_drc == 0) {
    317     if (p_parametricdrc_params->str_parametric_drc_instance_params[instance_idx]
    318             .parametric_drc_type == PARAM_DRC_TYPE_FF) {
    319       err = impd_init_parametric_drc_feed_fwd(pstr_drc_config, instance_idx,
    320                                               ch_count_from_dwnmix_id,
    321                                               p_parametricdrc_params);
    322 
    323       if (err) return (err);
    324 
    325     } else if (p_parametricdrc_params
    326                    ->str_parametric_drc_instance_params[instance_idx]
    327                    .parametric_drc_type == PARAM_DRC_TYPE_LIM) {
    328       p_parametricdrc_params->str_parametric_drc_instance_params[instance_idx]
    329           .str_spline_nodes.num_nodes = p_parametricdrc_params->drc_frame_size;
    330 
    331       impd_init_parametric_drc_lim(pstr_drc_config, instance_idx,
    332                                    ch_count_from_dwnmix_id,
    333                                    p_parametricdrc_params, mem_ptr);
    334 
    335     } else {
    336       return (UNEXPECTED_ERROR);
    337     }
    338   }
    339 
    340   return 0;
    341 }
    342 
    343 WORD32 impd_init_parametric_drc_after_config(
    344     ia_drc_config* pstr_drc_config,
    345     ia_drc_loudness_info_set_struct* pstr_loudness_info,
    346     ia_parametric_drc_params_struct* p_parametricdrc_params, pVOID* mem_ptr) {
    347   WORD32 err = 0, instance_idx = 0, gain_set_index = 0,
    348          side_chain_config_type = 0, downmix_id = 0,
    349          ch_count_from_dwnmix_id = 0, L = 0;
    350 
    351   p_parametricdrc_params->parametric_drc_frame_size =
    352       pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc
    353           .parametric_drc_frame_size;
    354   p_parametricdrc_params->reset_parametric_drc =
    355       pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc
    356           .reset_parametric_drc;
    357   p_parametricdrc_params->num_nodes =
    358       p_parametricdrc_params->drc_frame_size /
    359       p_parametricdrc_params->parametric_drc_frame_size;
    360 
    361   switch (p_parametricdrc_params->sub_band_domain_mode) {
    362     case SUBBAND_DOMAIN_MODE_QMF64:
    363       L = AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR_QMF64;
    364       break;
    365     case SUBBAND_DOMAIN_MODE_QMF71:
    366       L = AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR_QMF71;
    367       break;
    368     case SUBBAND_DOMAIN_MODE_STFT256:
    369       L = AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR_STFT256;
    370       break;
    371     case SUBBAND_DOMAIN_MODE_OFF:
    372     default:
    373       L = 0;
    374       break;
    375   }
    376 
    377   if (p_parametricdrc_params->sub_band_domain_mode != SUBBAND_DOMAIN_MODE_OFF &&
    378       p_parametricdrc_params->parametric_drc_frame_size != L) {
    379     return (EXTERNAL_ERROR);
    380   }
    381 
    382   for (instance_idx = 0;
    383        instance_idx < p_parametricdrc_params->parametric_drc_instance_count;
    384        instance_idx++) {
    385     gain_set_index = p_parametricdrc_params->gain_set_index[instance_idx];
    386     side_chain_config_type =
    387         pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc
    388             .str_parametric_drc_gain_set_params[gain_set_index]
    389             .side_chain_config_type;
    390     downmix_id = pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc
    391                      .str_parametric_drc_gain_set_params[gain_set_index]
    392                      .downmix_id;
    393 
    394     if (side_chain_config_type == 1 &&
    395         downmix_id ==
    396             p_parametricdrc_params
    397                 ->dwnmix_id_from_drc_instructions[instance_idx]) {
    398       ch_count_from_dwnmix_id =
    399           pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc
    400               .str_parametric_drc_gain_set_params[gain_set_index]
    401               .ch_count_from_dwnmix_id;
    402     } else {
    403       ch_count_from_dwnmix_id = 0;
    404     }
    405 
    406     if (pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc
    407             .str_parametric_drc_gain_set_params[gain_set_index]
    408             .drc_input_loudness_present == 0) {
    409       WORD32 n = 0, m = 0, drcInputLoudnessFound = 0;
    410       FLOAT32 drc_input_loudness = 0.f;
    411 
    412       for (n = 0; n < pstr_loudness_info->loudness_info_count; n++) {
    413         ia_loudness_info_struct* loudness_info =
    414             &pstr_loudness_info->loudness_info[n];
    415         if (p_parametricdrc_params
    416                 ->dwnmix_id_from_drc_instructions[instance_idx] ==
    417             loudness_info->downmix_id) {
    418           if (0 == loudness_info->drc_set_id) {
    419             for (m = 0; m < loudness_info->measurement_count; m++) {
    420               if (loudness_info->loudness_measure[m].method_def ==
    421                   METHOD_DEFINITION_PROGRAM_LOUDNESS) {
    422                 drc_input_loudness =
    423                     loudness_info->loudness_measure[m].method_val;
    424                 drcInputLoudnessFound = 1;
    425                 break;
    426               }
    427             }
    428             if (drcInputLoudnessFound == 0) {
    429               for (m = 0; m < loudness_info->measurement_count; m++) {
    430                 if (loudness_info->loudness_measure[m].method_def ==
    431                     METHOD_DEFINITION_ANCHOR_LOUDNESS) {
    432                   drc_input_loudness =
    433                       loudness_info->loudness_measure[m].method_val;
    434                   drcInputLoudnessFound = 1;
    435                   break;
    436                 }
    437               }
    438             }
    439           }
    440         }
    441       }
    442       if (drcInputLoudnessFound == 0) {
    443         for (n = 0; n < pstr_loudness_info->loudness_info_count; n++) {
    444           ia_loudness_info_struct* loudness_info =
    445               &pstr_loudness_info->loudness_info[n];
    446           if (0 == loudness_info->downmix_id) {
    447             if (0 == loudness_info->drc_set_id) {
    448               for (m = 0; m < loudness_info->measurement_count; m++) {
    449                 if (loudness_info->loudness_measure[m].method_def ==
    450                     METHOD_DEFINITION_PROGRAM_LOUDNESS) {
    451                   drc_input_loudness =
    452                       loudness_info->loudness_measure[m].method_val;
    453                   drcInputLoudnessFound = 1;
    454                   break;
    455                 }
    456               }
    457               if (drcInputLoudnessFound == 0) {
    458                 for (m = 0; m < loudness_info->measurement_count; m++) {
    459                   if (loudness_info->loudness_measure[m].method_def ==
    460                       METHOD_DEFINITION_ANCHOR_LOUDNESS) {
    461                     drc_input_loudness =
    462                         loudness_info->loudness_measure[m].method_val;
    463                     drcInputLoudnessFound = 1;
    464                     break;
    465                   }
    466                 }
    467               }
    468             }
    469           }
    470         }
    471       }
    472       if (drcInputLoudnessFound == 0) {
    473         return (UNEXPECTED_ERROR);
    474       } else {
    475         pstr_drc_config->str_drc_config_ext.str_drc_coeff_param_drc
    476             .str_parametric_drc_gain_set_params[gain_set_index]
    477             .drc_input_loudness = drc_input_loudness;
    478       }
    479     }
    480 
    481     impd_init_parametric_drcInstance(pstr_drc_config, instance_idx,
    482                                      ch_count_from_dwnmix_id,
    483                                      p_parametricdrc_params, mem_ptr);
    484     if (err) return (err);
    485   }
    486 
    487   return 0;
    488 }
    489 
    490 WORD32 impd_init_lvl_est_filt_time(
    491     WORD32 level_estim_k_weighting_type, WORD32 sampling_rate,
    492     ia_2nd_order_filt_coeff_struct* pre_filt_coeff,
    493     ia_2nd_order_filt_coeff_struct* rlb_filt_coeff) {
    494   WORD32 i;
    495   const FLOAT32* ptr_samp_tbl;
    496 
    497   switch (sampling_rate) {
    498     case 96000:
    499       i = 0;
    500       break;
    501     case 88200:
    502       i = 1;
    503       break;
    504     case 64000:
    505       i = 2;
    506       break;
    507     case 48000:
    508       i = 3;
    509       break;
    510     case 44100:
    511       i = 4;
    512       break;
    513     case 32000:
    514       i = 5;
    515       break;
    516     case 24000:
    517       i = 6;
    518       break;
    519     case 22050:
    520       i = 7;
    521       break;
    522     case 16000:
    523       i = 8;
    524       break;
    525     case 12000:
    526       i = 9;
    527       break;
    528     case 11025:
    529       i = 10;
    530       break;
    531     case 8000:
    532       i = 11;
    533       break;
    534     case 7350:
    535       i = 12;
    536       break;
    537     default:
    538       i = 3;
    539       break;
    540   }
    541 
    542   ptr_samp_tbl = samp_rate_tbl[i];
    543 
    544   if (level_estim_k_weighting_type == 2) {
    545     pre_filt_coeff->b0 = ptr_samp_tbl[0];
    546     pre_filt_coeff->b1 = ptr_samp_tbl[1];
    547     pre_filt_coeff->b2 = ptr_samp_tbl[2];
    548     pre_filt_coeff->a1 = ptr_samp_tbl[3];
    549     pre_filt_coeff->a2 = ptr_samp_tbl[4];
    550   }
    551 
    552   if (level_estim_k_weighting_type == 1 || level_estim_k_weighting_type == 2) {
    553     rlb_filt_coeff->b0 = ptr_samp_tbl[5];
    554     rlb_filt_coeff->b1 = ptr_samp_tbl[6];
    555     rlb_filt_coeff->b2 = ptr_samp_tbl[7];
    556     rlb_filt_coeff->a1 = ptr_samp_tbl[8];
    557     rlb_filt_coeff->a2 = ptr_samp_tbl[9];
    558   }
    559 
    560   return 0;
    561 }
    562 
    563 WORD32 impd_init_lvl_est_filt_subband(
    564     WORD32 level_estim_k_weighting_type, WORD32 sampling_rate,
    565     WORD32 sub_band_domain_mode, WORD32 sub_band_count,
    566     WORD32 sub_band_compensation_type, FLOAT32* weighting_filt,
    567     ia_2nd_order_filt_coeff_struct* filt_coeff_subband) {
    568   FLOAT32 w0, alpha, sinw0, cosw0;
    569   FLOAT32 b0, b1, b2, a0, a1, a2;
    570   FLOAT32 num_real, num_imag, den_real, den_imag;
    571   FLOAT32* f_bands_nrm;
    572   WORD32 b;
    573   WORD32 i;
    574   const FLOAT32* ptr_samp_tbl;
    575 
    576   switch (sampling_rate) {
    577     case 96000:
    578       i = 0;
    579       break;
    580     case 88200:
    581       i = 1;
    582       break;
    583     case 64000:
    584       i = 2;
    585       break;
    586     case 48000:
    587       i = 3;
    588       break;
    589     case 44100:
    590       i = 4;
    591       break;
    592     case 32000:
    593       i = 5;
    594       break;
    595     case 24000:
    596       i = 6;
    597       break;
    598     case 22050:
    599       i = 7;
    600       break;
    601     case 16000:
    602       i = 8;
    603       break;
    604     case 12000:
    605       i = 9;
    606       break;
    607     case 11025:
    608       i = 10;
    609       break;
    610     case 8000:
    611       i = 11;
    612       break;
    613     case 7350:
    614       i = 12;
    615       break;
    616     default:
    617       i = 3;
    618       break;
    619   }
    620 
    621   ptr_samp_tbl = samp_rate_tbl[i];
    622 
    623   switch (sub_band_domain_mode) {
    624     case SUBBAND_DOMAIN_MODE_QMF64:
    625       f_bands_nrm = f_bands_nrm_QMF64;
    626       break;
    627     case SUBBAND_DOMAIN_MODE_QMF71:
    628       f_bands_nrm = f_bands_nrm_QMF71;
    629       break;
    630     case SUBBAND_DOMAIN_MODE_STFT256:
    631       f_bands_nrm = f_bands_nrm_STFT256;
    632       break;
    633     default:
    634       return UNEXPECTED_ERROR;
    635       break;
    636   }
    637 
    638   for (b = 0; b < sub_band_count; b++) {
    639     weighting_filt[b] = 1.f;
    640   }
    641 
    642   if (level_estim_k_weighting_type == 2) {
    643     b0 = ptr_samp_tbl[0];
    644     b1 = ptr_samp_tbl[1];
    645     b2 = ptr_samp_tbl[2];
    646     a1 = ptr_samp_tbl[3];
    647     a2 = ptr_samp_tbl[4];
    648     a0 = 1.f;
    649 
    650     for (b = 0; b < sub_band_count; b++) {
    651       num_real = b0 + b1 * (FLOAT32)cos(PI * f_bands_nrm[b]) +
    652                  b2 * (FLOAT32)cos(PI * 2 * f_bands_nrm[b]);
    653       num_imag = -b1 * (FLOAT32)sin(PI * f_bands_nrm[b]) -
    654                  b2 * (FLOAT32)sin(PI * 2 * f_bands_nrm[b]);
    655       den_real = a0 + a1 * (FLOAT32)cos(PI * f_bands_nrm[b]) +
    656                  a2 * (FLOAT32)cos(PI * 2 * f_bands_nrm[b]);
    657       den_imag = -a1 * (FLOAT32)sin(PI * f_bands_nrm[b]) -
    658                  a2 * (FLOAT32)sin(PI * 2 * f_bands_nrm[b]);
    659 
    660       weighting_filt[b] *=
    661           (FLOAT32)(sqrt((num_real * num_real + num_imag * num_imag) /
    662                          (den_real * den_real + den_imag * den_imag)));
    663     }
    664   }
    665 
    666   if (level_estim_k_weighting_type == 1 || level_estim_k_weighting_type == 2) {
    667     b0 = ptr_samp_tbl[5];
    668     b1 = ptr_samp_tbl[6];
    669     b2 = ptr_samp_tbl[7];
    670     a1 = ptr_samp_tbl[8];
    671     a2 = ptr_samp_tbl[9];
    672     a0 = 1.f;
    673 
    674     for (b = 0; b < sub_band_count; b++) {
    675       if (!(sub_band_compensation_type == 1 && b == 0)) {
    676         num_real = (FLOAT32)(b0 + b1 * cos(PI * f_bands_nrm[b]) +
    677                              b2 * cos(PI * 2 * f_bands_nrm[b]));
    678         num_imag = (FLOAT32)(-b1 * sin(PI * f_bands_nrm[b]) -
    679                              b2 * sin(PI * 2 * f_bands_nrm[b]));
    680         den_real = (FLOAT32)(a0 + a1 * cos(PI * f_bands_nrm[b]) +
    681                              a2 * cos(PI * 2 * f_bands_nrm[b]));
    682         den_imag = (FLOAT32)(-a1 * sin(PI * f_bands_nrm[b]) -
    683                              a2 * sin(PI * 2 * f_bands_nrm[b]));
    684 
    685         weighting_filt[b] *=
    686             (FLOAT32)(sqrt((num_real * num_real + num_imag * num_imag) /
    687                            (den_real * den_real + den_imag * den_imag)));
    688       }
    689     }
    690 
    691     if (sub_band_compensation_type == 1) {
    692       w0 = 2.0f * PI * 38.0f / (FLOAT32)sampling_rate *
    693            AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR_QMF64;
    694       sinw0 = (FLOAT32)sin(w0);
    695       cosw0 = (FLOAT32)cos(w0);
    696       alpha = sinw0;
    697 
    698       b0 = (1 + cosw0) / 2;
    699       b1 = -(1 + cosw0);
    700       b2 = (1 + cosw0) / 2;
    701       a0 = 1 + alpha;
    702       a1 = -2 * cosw0;
    703       a2 = 1 - alpha;
    704 
    705       filt_coeff_subband->b0 = b0 / a0;
    706       filt_coeff_subband->b1 = b1 / a0;
    707       filt_coeff_subband->b2 = b2 / a0;
    708       filt_coeff_subband->a1 = a1 / a0;
    709       filt_coeff_subband->a2 = a2 / a0;
    710     }
    711   }
    712 
    713   return 0;
    714 }
    715 
    716 WORD32 impd_parametric_ffwd_type_drc_reset(
    717     ia_parametric_drc_type_ff_params_struct*
    718         pstr_parametric_ffwd_type_drc_params) {
    719   WORD32 i = 0;
    720 
    721   pstr_parametric_ffwd_type_drc_params->level_estim_frame_index = 0;
    722   pstr_parametric_ffwd_type_drc_params->start_up_phase = 1;
    723   for (i = 0; i < PARAM_DRC_TYPE_FF_LEVEL_ESTIM_FRAME_COUNT_MAX; i++) {
    724     pstr_parametric_ffwd_type_drc_params->level[i] = 0.f;
    725   }
    726 
    727   for (i = 0; i < MAX_CHANNEL_COUNT; i++) {
    728     pstr_parametric_ffwd_type_drc_params->pre_filt_state[i].z1 = 0.f;
    729     pstr_parametric_ffwd_type_drc_params->pre_filt_state[i].z2 = 0.f;
    730     pstr_parametric_ffwd_type_drc_params->rlb_filt_state[i].z1 = 0.f;
    731     pstr_parametric_ffwd_type_drc_params->rlb_filt_state[i].z2 = 0.f;
    732     pstr_parametric_ffwd_type_drc_params->filt_state_subband_real[i].z1 = 0.f;
    733     pstr_parametric_ffwd_type_drc_params->filt_state_subband_real[i].z2 = 0.f;
    734     pstr_parametric_ffwd_type_drc_params->filt_state_subband_imag[i].z1 = 0.f;
    735     pstr_parametric_ffwd_type_drc_params->filt_state_subband_imag[i].z2 = 0.f;
    736   }
    737 
    738   pstr_parametric_ffwd_type_drc_params->db_level_smooth = -135.f;
    739   pstr_parametric_ffwd_type_drc_params->db_gain_smooth = 0.f;
    740   pstr_parametric_ffwd_type_drc_params->hold_counter = 0;
    741 
    742   return 0;
    743 }
    744 
    745 WORD32 impd_parametric_drc_instance_process(
    746     FLOAT32* audio_in_out_buf[], FLOAT32* audio_real_buff[],
    747     FLOAT32* audio_imag_buff[],
    748     ia_parametric_drc_params_struct* p_parametricdrc_params,
    749     ia_parametric_drc_instance_params_struct*
    750         pstr_parametric_drc_instance_params) {
    751   WORD32 err = 0, i = 0;
    752 
    753   if (pstr_parametric_drc_instance_params->disable_paramteric_drc) {
    754     for (i = 0; i < p_parametricdrc_params->num_nodes; i++) {
    755       pstr_parametric_drc_instance_params->str_spline_nodes.str_node[i]
    756           .loc_db_gain = 0.f;
    757       pstr_parametric_drc_instance_params->str_spline_nodes.str_node[i].slope =
    758           0.f;
    759       pstr_parametric_drc_instance_params->str_spline_nodes.str_node[i].time =
    760           (i + 1) * p_parametricdrc_params->parametric_drc_frame_size - 1;
    761     }
    762 
    763   } else {
    764     if (pstr_parametric_drc_instance_params->parametric_drc_type ==
    765         PARAM_DRC_TYPE_FF) {
    766       ia_parametric_drc_type_ff_params_struct*
    767           pstr_parametric_ffwd_type_drc_params =
    768               &(pstr_parametric_drc_instance_params
    769                     ->str_parametric_drc_type_ff_params);
    770       for (i = 0; i < p_parametricdrc_params->num_nodes; i++) {
    771         err = impd_parametric_ffwd_type_drc_process(
    772             audio_in_out_buf, audio_real_buff, audio_imag_buff, i,
    773             pstr_parametric_ffwd_type_drc_params,
    774             &pstr_parametric_drc_instance_params->str_spline_nodes);
    775         if (err) return (err);
    776       }
    777 
    778     } else if (pstr_parametric_drc_instance_params->parametric_drc_type ==
    779                PARAM_DRC_TYPE_LIM) {
    780       return (UNEXPECTED_ERROR);
    781 
    782     } else {
    783       return (UNEXPECTED_ERROR);
    784     }
    785   }
    786 
    787   return 0;
    788 }
    789 
    790 VOID iir_second_order_filter(ia_2nd_order_filt_coeff_struct* coeff,
    791                              ia_2nd_order_filt_state_struct* state,
    792                              WORD32 frame_len, FLOAT32* input,
    793                              FLOAT32* output) {
    794   FLOAT32 z2 = state->z2;
    795   FLOAT32 z1 = state->z1;
    796   FLOAT32 z0;
    797   WORD32 i;
    798 
    799   for (i = 0; i < frame_len; i++) {
    800     z0 = input[i] - coeff->a1 * z1 - coeff->a2 * z2;
    801     output[i] = coeff->b0 * z0 + coeff->b1 * z1 + coeff->b2 * z2;
    802     z2 = z1;
    803     z1 = z0;
    804   }
    805   state->z1 = z1;
    806   state->z2 = z2;
    807 }
    808 WORD32 impd_parametric_ffwd_type_drc_process(
    809     FLOAT32* audio_in_out_buf[], FLOAT32* audio_real_buff[],
    810     FLOAT32* audio_imag_buff[], WORD32 nodeIdx,
    811     ia_parametric_drc_type_ff_params_struct*
    812         pstr_parametric_ffwd_type_drc_params,
    813     ia_spline_nodes_struct* str_spline_nodes) {
    814   WORD32 c, t, b, n, i, offset;
    815   FLOAT32 x, y, channelLevel, level, levelDb, loc_db_gain, levelDelta, alpha;
    816 
    817   WORD32 frame_size = pstr_parametric_ffwd_type_drc_params->frame_size;
    818   WORD32 sub_band_count = pstr_parametric_ffwd_type_drc_params->sub_band_count;
    819   FLOAT32* level_estim_ch_weight =
    820       pstr_parametric_ffwd_type_drc_params->level_estim_ch_weight;
    821   WORD32 level_estim_k_weighting_type =
    822       pstr_parametric_ffwd_type_drc_params->level_estim_k_weighting_type;
    823 
    824   ia_2nd_order_filt_coeff_struct preC =
    825       pstr_parametric_ffwd_type_drc_params->pre_filt_coeff;
    826   ia_2nd_order_filt_coeff_struct rlbC =
    827       pstr_parametric_ffwd_type_drc_params->rlb_filt_coeff;
    828   ia_2nd_order_filt_state_struct* preS =
    829       pstr_parametric_ffwd_type_drc_params->pre_filt_state;
    830   ia_2nd_order_filt_state_struct* rlbS =
    831       pstr_parametric_ffwd_type_drc_params->rlb_filt_state;
    832 
    833   ia_2nd_order_filt_coeff_struct rlbC_sb =
    834       pstr_parametric_ffwd_type_drc_params->filt_coeff_subband;
    835   ia_2nd_order_filt_state_struct* rlbS_sbReal =
    836       pstr_parametric_ffwd_type_drc_params->filt_state_subband_real;
    837   ia_2nd_order_filt_state_struct* rlbS_sbImag =
    838       pstr_parametric_ffwd_type_drc_params->filt_state_subband_imag;
    839   FLOAT32* weighting_filt =
    840       pstr_parametric_ffwd_type_drc_params->weighting_filt;
    841   WORD32 sub_band_compensation_type =
    842       pstr_parametric_ffwd_type_drc_params->sub_band_compensation_type;
    843 
    844   if (audio_in_out_buf != NULL) {
    845     level = 0;
    846     offset = nodeIdx * pstr_parametric_ffwd_type_drc_params->frame_size;
    847     for (c = 0; c < pstr_parametric_ffwd_type_drc_params->audio_num_chan; c++) {
    848       channelLevel = 0.f;
    849 
    850       if (!level_estim_ch_weight[c]) continue;
    851 
    852       if (level_estim_k_weighting_type == 0) {
    853         for (t = 0; t < frame_size; t++) {
    854           x = audio_in_out_buf[c][offset + t];
    855 
    856           channelLevel += x * x;
    857         }
    858 
    859       } else if (level_estim_k_weighting_type == 1) {
    860         for (t = 0; t < frame_size; t++) {
    861           x = audio_in_out_buf[c][offset + t];
    862 
    863           iir_second_order_filter(&rlbC, &rlbS[c], 1, &x, &x);
    864 
    865           channelLevel += x * x;
    866         }
    867 
    868       } else if (level_estim_k_weighting_type == 2) {
    869         for (t = 0; t < frame_size; t++) {
    870           x = audio_in_out_buf[c][offset + t];
    871 
    872           iir_second_order_filter(&preC, &preS[c], 1, &x, &x);
    873 
    874           iir_second_order_filter(&rlbC, &rlbS[c], 1, &x, &x);
    875 
    876           channelLevel += x * x;
    877         }
    878 
    879       } else {
    880         return (UNEXPECTED_ERROR);
    881       }
    882 
    883       level += level_estim_ch_weight[c] * channelLevel;
    884     }
    885 
    886   } else {
    887     level = 0;
    888     offset = nodeIdx * pstr_parametric_ffwd_type_drc_params->sub_band_count;
    889     for (c = 0; c < pstr_parametric_ffwd_type_drc_params->audio_num_chan; c++) {
    890       channelLevel = 0.f;
    891 
    892       if (!level_estim_ch_weight[c]) continue;
    893 
    894       if (level_estim_k_weighting_type == 0) {
    895         for (b = 0; b < sub_band_count; b++) {
    896           x = audio_real_buff[c][offset + b];
    897           y = audio_imag_buff[c][offset + b];
    898 
    899           channelLevel += x * x + y * y;
    900         }
    901 
    902       } else if (level_estim_k_weighting_type == 1 ||
    903                  level_estim_k_weighting_type == 2) {
    904         for (b = 0; b < sub_band_count; b++) {
    905           x = audio_real_buff[c][offset + b] * weighting_filt[b];
    906           y = audio_imag_buff[c][offset + b] * weighting_filt[b];
    907 
    908           if (b == 0 && sub_band_compensation_type == 1) {
    909             iir_second_order_filter(&rlbC_sb, &rlbS_sbReal[c], 1, &x, &x);
    910 
    911             iir_second_order_filter(&rlbC_sb, &rlbS_sbImag[c], 1, &y, &y);
    912           }
    913 
    914           channelLevel += x * x + y * y;
    915         }
    916 
    917       } else {
    918         return (UNEXPECTED_ERROR);
    919       }
    920 
    921       level += level_estim_ch_weight[c] * channelLevel;
    922     }
    923 
    924     level /= sub_band_count;
    925   }
    926   pstr_parametric_ffwd_type_drc_params
    927       ->level[pstr_parametric_ffwd_type_drc_params->level_estim_frame_index] =
    928       level;
    929   pstr_parametric_ffwd_type_drc_params->level_estim_frame_index++;
    930 
    931   level = 0.f;
    932   if (pstr_parametric_ffwd_type_drc_params->start_up_phase) {
    933     for (i = 0;
    934          i < pstr_parametric_ffwd_type_drc_params->level_estim_frame_index;
    935          i++) {
    936       level += pstr_parametric_ffwd_type_drc_params->level[i];
    937     }
    938     level /= pstr_parametric_ffwd_type_drc_params->level_estim_frame_index *
    939              pstr_parametric_ffwd_type_drc_params->frame_size;
    940   } else {
    941     for (i = 0;
    942          i < pstr_parametric_ffwd_type_drc_params->level_estim_frame_count;
    943          i++) {
    944       level += pstr_parametric_ffwd_type_drc_params->level[i];
    945     }
    946     level /= pstr_parametric_ffwd_type_drc_params->level_estim_integration_time;
    947   }
    948   if (pstr_parametric_ffwd_type_drc_params->level_estim_frame_index ==
    949       pstr_parametric_ffwd_type_drc_params->level_estim_frame_count) {
    950     pstr_parametric_ffwd_type_drc_params->level_estim_frame_index = 0;
    951     pstr_parametric_ffwd_type_drc_params->start_up_phase = 0;
    952   }
    953 
    954   if (level < 1e-10f) level = 1e-10f;
    955   if (level_estim_k_weighting_type == 2) {
    956     levelDb = -0.691f + 10 * (FLOAT32)log10(level) + 3;
    957   } else {
    958     levelDb = 10 * (FLOAT32)log10(level) + 3;
    959   }
    960   levelDb -= pstr_parametric_ffwd_type_drc_params->ref_level_parametric_drc;
    961 
    962   for (n = 0; n < pstr_parametric_ffwd_type_drc_params->node_count; n++) {
    963     if (levelDb <=
    964         (FLOAT32)pstr_parametric_ffwd_type_drc_params->node_level[n]) {
    965       break;
    966     }
    967   }
    968   if (n == 0) {
    969     loc_db_gain = (FLOAT32)pstr_parametric_ffwd_type_drc_params->node_gain[n];
    970   } else if (n == pstr_parametric_ffwd_type_drc_params->node_count) {
    971     loc_db_gain =
    972         (FLOAT32)pstr_parametric_ffwd_type_drc_params->node_gain[n - 1] -
    973         levelDb +
    974         (FLOAT32)pstr_parametric_ffwd_type_drc_params->node_level[n - 1];
    975   } else {
    976     loc_db_gain =
    977         (FLOAT32)pstr_parametric_ffwd_type_drc_params->node_gain[n] +
    978         (levelDb -
    979          (FLOAT32)pstr_parametric_ffwd_type_drc_params->node_level[n]) /
    980             (FLOAT32)(pstr_parametric_ffwd_type_drc_params->node_level[n - 1] -
    981                       pstr_parametric_ffwd_type_drc_params->node_level[n]) *
    982             (FLOAT32)(pstr_parametric_ffwd_type_drc_params->node_gain[n - 1] -
    983                       pstr_parametric_ffwd_type_drc_params->node_gain[n]);
    984   }
    985 
    986   levelDelta = levelDb - pstr_parametric_ffwd_type_drc_params->db_level_smooth;
    987   if (loc_db_gain < pstr_parametric_ffwd_type_drc_params->db_gain_smooth) {
    988     if (levelDelta >
    989         pstr_parametric_ffwd_type_drc_params->gain_smooth_attack_threshold) {
    990       alpha =
    991           pstr_parametric_ffwd_type_drc_params->gain_smooth_attack_alpha_fast;
    992     } else {
    993       alpha =
    994           pstr_parametric_ffwd_type_drc_params->gain_smooth_attack_alpha_slow;
    995     }
    996   } else {
    997     if (levelDelta <
    998         -pstr_parametric_ffwd_type_drc_params->gain_smooth_rel_threshold) {
    999       alpha = pstr_parametric_ffwd_type_drc_params->gain_smooth_rel_alpha_fast;
   1000     } else {
   1001       alpha = pstr_parametric_ffwd_type_drc_params->gain_smooth_rel_alpha_slow;
   1002     }
   1003   }
   1004   if (loc_db_gain < pstr_parametric_ffwd_type_drc_params->db_gain_smooth ||
   1005       pstr_parametric_ffwd_type_drc_params->hold_counter == 0) {
   1006     pstr_parametric_ffwd_type_drc_params->db_level_smooth =
   1007         (1 - alpha) * pstr_parametric_ffwd_type_drc_params->db_level_smooth +
   1008         alpha * levelDb;
   1009     pstr_parametric_ffwd_type_drc_params->db_gain_smooth =
   1010         (1 - alpha) * pstr_parametric_ffwd_type_drc_params->db_gain_smooth +
   1011         alpha * loc_db_gain;
   1012   }
   1013   if (pstr_parametric_ffwd_type_drc_params->hold_counter) {
   1014     pstr_parametric_ffwd_type_drc_params->hold_counter -= 1;
   1015   }
   1016   if (loc_db_gain < pstr_parametric_ffwd_type_drc_params->db_gain_smooth) {
   1017     pstr_parametric_ffwd_type_drc_params->hold_counter =
   1018         pstr_parametric_ffwd_type_drc_params->gain_smooth_hold_off_count;
   1019   }
   1020 
   1021   str_spline_nodes->str_node[nodeIdx].loc_db_gain =
   1022       pstr_parametric_ffwd_type_drc_params->db_gain_smooth;
   1023   str_spline_nodes->str_node[nodeIdx].slope = 0.f;
   1024   str_spline_nodes->str_node[nodeIdx].time =
   1025       pstr_parametric_ffwd_type_drc_params->frame_size + offset - 1;
   1026 
   1027   return 0;
   1028 }
   1029 
   1030 WORD32 impd_parametric_lim_type_drc_process(
   1031     FLOAT32* samples[], FLOAT32 loudness_normalization_gain_db,
   1032     ia_parametric_drc_type_lim_params_struct*
   1033         pstr_parametric_lim_type_drc_params,
   1034     FLOAT32* lpcm_gains) {
   1035   WORD32 i, j;
   1036   FLOAT32 tmp, gain;
   1037   //  FLOAT32 min_gain = 1;
   1038   FLOAT32 maximum, sectionMaximum;
   1039   FLOAT32 loudness_normalization_gain =
   1040       (FLOAT32)pow(10.0f, 0.05f * loudness_normalization_gain_db);
   1041   FLOAT32* level_estim_ch_weight =
   1042       pstr_parametric_lim_type_drc_params->level_estim_ch_weight;
   1043   WORD32 num_channels = pstr_parametric_lim_type_drc_params->channels;
   1044   WORD32 attack_time_samples = pstr_parametric_lim_type_drc_params->attack;
   1045   FLOAT32 attack_constant =
   1046       pstr_parametric_lim_type_drc_params->attack_constant;
   1047   FLOAT32 release_constant =
   1048       pstr_parametric_lim_type_drc_params->release_constant;
   1049   FLOAT32 limit_threshold = pstr_parametric_lim_type_drc_params->threshold;
   1050   FLOAT32* max_buf = pstr_parametric_lim_type_drc_params->max_buf;
   1051   FLOAT32 gain_modified = pstr_parametric_lim_type_drc_params->cor;
   1052   FLOAT64 pre_smoothed_gain =
   1053       pstr_parametric_lim_type_drc_params->smooth_state_0;
   1054 
   1055   for (i = 0; i < pstr_parametric_lim_type_drc_params->frame_size; i++) {
   1056     tmp = 0.0f;
   1057     for (j = 0; j < num_channels; j++) {
   1058       if (!level_estim_ch_weight[j]) continue;
   1059       tmp =
   1060           max(tmp, (FLOAT32)fabs(loudness_normalization_gain *
   1061                                  (level_estim_ch_weight[j]) * (samples[j][i])));
   1062     }
   1063 
   1064     for (j = attack_time_samples; j > 0; j--) {
   1065       max_buf[j] = max_buf[j - 1];
   1066     }
   1067     max_buf[0] = tmp;
   1068     sectionMaximum = tmp;
   1069     for (j = 1; j < (attack_time_samples + 1); j++) {
   1070       if (max_buf[j] > sectionMaximum) sectionMaximum = max_buf[j];
   1071     }
   1072     maximum = sectionMaximum;
   1073 
   1074     if (maximum > limit_threshold) {
   1075       gain = limit_threshold / maximum;
   1076     } else {
   1077       gain = 1;
   1078     }
   1079 
   1080     if (gain < pre_smoothed_gain) {
   1081       gain_modified =
   1082           min(gain_modified,
   1083               (gain - 0.1f * (FLOAT32)pre_smoothed_gain) * 1.11111111f);
   1084     } else {
   1085       gain_modified = gain;
   1086     }
   1087 
   1088     if (gain_modified < pre_smoothed_gain) {
   1089       pre_smoothed_gain =
   1090           attack_constant * (pre_smoothed_gain - gain_modified) + gain_modified;
   1091       pre_smoothed_gain = max(pre_smoothed_gain, gain);
   1092     } else {
   1093       pre_smoothed_gain =
   1094           release_constant * (pre_smoothed_gain - gain_modified) +
   1095           gain_modified;
   1096     }
   1097 
   1098     gain = (FLOAT32)pre_smoothed_gain;
   1099 
   1100     lpcm_gains[i] = gain;
   1101   }
   1102 
   1103   pstr_parametric_lim_type_drc_params->cor = gain_modified;
   1104   pstr_parametric_lim_type_drc_params->smooth_state_0 = pre_smoothed_gain;
   1105   return 0;
   1106 }
   1107