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 <stdio.h>
     21 #include <stdlib.h>
     22 #include <math.h>
     23 #include <string.h>
     24 
     25 #include "impd_type_def.h"
     26 #include "impd_drc_extr_delta_coded_info.h"
     27 #include "impd_drc_common.h"
     28 #include "impd_drc_struct.h"
     29 #include "impd_parametric_drc_dec.h"
     30 #include "impd_drc_filter_bank.h"
     31 #include "impd_drc_multi_band.h"
     32 #include "impd_drc_gain_dec.h"
     33 #include "impd_drc_process_audio.h"
     34 #include "impd_drc_interface.h"
     35 #include "impd_drc_gain_dec.h"
     36 #include "impd_drc_eq.h"
     37 #include "impd_drc_gain_decoder.h"
     38 #include "impd_drc_rom.h"
     39 
     40 WORD32 impd_shape_filt_block_adapt(const FLOAT32 drc_gain,
     41                                    shape_filter_block* shape_filter_block) {
     42   //    WORD32 err = 0;
     43   WORD32 i;
     44   FLOAT32 warpedGain, x1, y1;
     45   shape_filter_block->drc_gain_last = drc_gain;
     46   for (i = 0; i < 4; i++) {
     47     if (shape_filter_block->shape_filter[i].type == SHAPE_FILTER_TYPE_OFF)
     48       continue;
     49     else if (shape_filter_block->shape_filter[i].type ==
     50                  SHAPE_FILTER_TYPE_LF_CUT ||
     51              shape_filter_block->shape_filter[i].type ==
     52                  SHAPE_FILTER_TYPE_HF_CUT) {
     53       if (drc_gain < 1.0f)
     54         warpedGain = -1.0f;
     55       else
     56         warpedGain =
     57             (drc_gain - 1.0f) /
     58             (drc_gain - 1.0f + shape_filter_block->shape_filter[i].gain_offset);
     59       x1 = shape_filter_block->shape_filter[i].a1;
     60     } else if (shape_filter_block->shape_filter[i].type ==
     61                    SHAPE_FILTER_TYPE_LF_BOOST ||
     62                shape_filter_block->shape_filter[i].type ==
     63                    SHAPE_FILTER_TYPE_HF_BOOST) {
     64       if (drc_gain >= 1.0f)
     65         warpedGain = -1.0f;
     66       else
     67         warpedGain =
     68             (1.0f - drc_gain) /
     69             (1.0f +
     70              drc_gain *
     71                  (shape_filter_block->shape_filter[i].gain_offset - 1.0f));
     72       x1 = shape_filter_block->shape_filter[i].b1;
     73     }
     74 
     75     if (warpedGain <= 0.0f) {
     76       y1 = x1;
     77     } else if (warpedGain <
     78                shape_filter_block->shape_filter[i].warped_gain_max) {
     79       y1 = x1 + shape_filter_block->shape_filter[i].factor * warpedGain;
     80     } else {
     81       y1 = shape_filter_block->shape_filter[i].y1_bound;
     82     }
     83     if (shape_filter_block->shape_filter[i].type == SHAPE_FILTER_TYPE_LF_CUT) {
     84       shape_filter_block->shape_filter[i].b1 = y1;
     85     } else if (shape_filter_block->shape_filter[i].type ==
     86                SHAPE_FILTER_TYPE_HF_CUT) {
     87       shape_filter_block->shape_filter[i].g_norm =
     88           shape_filter_block->shape_filter[i].coeff_sum /
     89           (shape_filter_block->shape_filter[i].partial_coeff_sum + y1);
     90       shape_filter_block->shape_filter[i].b1 = y1;
     91     } else if (shape_filter_block->shape_filter[i].type ==
     92                SHAPE_FILTER_TYPE_HF_BOOST) {
     93       shape_filter_block->shape_filter[i].g_norm =
     94           (shape_filter_block->shape_filter[i].partial_coeff_sum + y1) /
     95           shape_filter_block->shape_filter[i].coeff_sum;
     96       shape_filter_block->shape_filter[i].a1 = y1;
     97     } else if (shape_filter_block->shape_filter[i].type ==
     98                SHAPE_FILTER_TYPE_LF_BOOST) {
     99       shape_filter_block->shape_filter[i].a1 = y1;
    100     }
    101   }
    102   return (0);
    103 }
    104 
    105 WORD32 resetshape_flter_block(shape_filter_block* shape_filter_block) {
    106   WORD32 i, c;
    107   shape_filter_block->drc_gain_last = -1.0f;
    108   impd_shape_filt_block_adapt(1.0f, shape_filter_block);
    109   for (i = 0; i < 4; i++) {
    110     for (c = 0; c < MAX_CHANNEL_COUNT; c++) {
    111       shape_filter_block->shape_filter[i].audio_in_state_1[c] = 0.0f;
    112       shape_filter_block->shape_filter[i].audio_in_state_2[c] = 0.0f;
    113       shape_filter_block->shape_filter[i].audio_out_state_1[c] = 0.0f;
    114       shape_filter_block->shape_filter[i].audio_out_state_2[c] = 0.0f;
    115     }
    116   }
    117   return (0);
    118 }
    119 
    120 WORD32 impd_shape_filt_block_init(
    121     ia_shape_filter_block_params_struct* shape_flter_block_params,
    122     shape_filter_block* shape_filter_block) {
    123   // WORD32 err = 0;
    124   FLOAT32 x1;
    125   FLOAT32 x2 = 0.0f;
    126   FLOAT32 radius;
    127   if (shape_flter_block_params->lf_cut_filter_present) {
    128     ia_shape_filter_params_struct* params =
    129         &shape_flter_block_params->str_lf_cut_params;
    130     shape_filter_block->shape_filter[0].type = SHAPE_FILTER_TYPE_LF_CUT;
    131     shape_filter_block->shape_filter[0].gain_offset =
    132         shape_filt_lf_gain_offset_tbl[params->corner_freq_index]
    133                                      [params->filter_strength_index];
    134     shape_filter_block->shape_filter[0].y1_bound =
    135         shape_filt_lf_y1_bound_tbl[params->corner_freq_index]
    136                                   [params->filter_strength_index];
    137     x1 = -shape_filt_lf_radius_tbl[params->corner_freq_index];
    138     shape_filter_block->shape_filter[0].warped_gain_max =
    139         SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE /
    140         (SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE +
    141          shape_filter_block->shape_filter[0].gain_offset);
    142     shape_filter_block->shape_filter[0].factor =
    143         (shape_filter_block->shape_filter[0].y1_bound - x1) /
    144         shape_filter_block->shape_filter[0].warped_gain_max;
    145     shape_filter_block->shape_filter[0].a1 = x1;
    146 
    147   } else {
    148     shape_filter_block->shape_filter[0].type = SHAPE_FILTER_TYPE_OFF;
    149   }
    150   if (shape_flter_block_params->lf_boost_filter_present) {
    151     ia_shape_filter_params_struct* params =
    152         &shape_flter_block_params->str_lf_boost_params;
    153     shape_filter_block->shape_filter[1].type = SHAPE_FILTER_TYPE_LF_BOOST;
    154     shape_filter_block->shape_filter[1].gain_offset =
    155         shape_filt_lf_gain_offset_tbl[params->corner_freq_index]
    156                                      [params->filter_strength_index];
    157     shape_filter_block->shape_filter[1].y1_bound =
    158         shape_filt_lf_y1_bound_tbl[params->corner_freq_index]
    159                                   [params->filter_strength_index];
    160     x1 = -shape_filt_lf_radius_tbl[params->corner_freq_index];
    161     shape_filter_block->shape_filter[1].warped_gain_max =
    162         SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE /
    163         (SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE +
    164          shape_filter_block->shape_filter[1].gain_offset);
    165     shape_filter_block->shape_filter[1].factor =
    166         (shape_filter_block->shape_filter[1].y1_bound - x1) /
    167         shape_filter_block->shape_filter[1].warped_gain_max;
    168     shape_filter_block->shape_filter[1].b1 = x1;
    169 
    170   } else {
    171     shape_filter_block->shape_filter[1].type = SHAPE_FILTER_TYPE_OFF;
    172   }
    173   if (shape_flter_block_params->hf_cut_filter_present) {
    174     ia_shape_filter_params_struct* params =
    175         &shape_flter_block_params->str_hfCutParams;
    176     shape_filter_block->shape_filter[2].type = SHAPE_FILTER_TYPE_HF_CUT;
    177     shape_filter_block->shape_filter[2].gain_offset =
    178         shape_filt_hf_gain_offset_tbl[params->corner_freq_index]
    179                                      [params->filter_strength_index];
    180     shape_filter_block->shape_filter[2].y1_bound =
    181         shape_filt_hf_y1_bound_tbl[params->corner_freq_index]
    182                                   [params->filter_strength_index];
    183     radius = shape_filt_hf_radius_tbl[params->corner_freq_index];
    184     x1 = (FLOAT32)(
    185         -2.0f * radius *
    186         cos(2.0f * M_PI *
    187             shape_filt_cutoff_freq_norm_hf_tbl[params->corner_freq_index]));
    188     x2 = radius * radius;
    189     shape_filter_block->shape_filter[2].warped_gain_max =
    190         SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE /
    191         (SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE +
    192          shape_filter_block->shape_filter[2].gain_offset);
    193     shape_filter_block->shape_filter[2].factor =
    194         (shape_filter_block->shape_filter[2].y1_bound - x1) /
    195         shape_filter_block->shape_filter[2].warped_gain_max;
    196     shape_filter_block->shape_filter[2].coeff_sum = 1.0f + x1 + x2;
    197     shape_filter_block->shape_filter[2].partial_coeff_sum = 1.0f + x2;
    198     shape_filter_block->shape_filter[2].a1 = x1;
    199     shape_filter_block->shape_filter[2].a2 = x2;
    200     shape_filter_block->shape_filter[2].b2 = x2;
    201   } else {
    202     shape_filter_block->shape_filter[2].type = SHAPE_FILTER_TYPE_OFF;
    203   }
    204   if (shape_flter_block_params->hf_boost_filter_present) {
    205     ia_shape_filter_params_struct* params =
    206         &shape_flter_block_params->str_hf_boost_params;
    207     shape_filter_block->shape_filter[3].type = SHAPE_FILTER_TYPE_HF_BOOST;
    208     shape_filter_block->shape_filter[3].gain_offset =
    209         shape_filt_hf_gain_offset_tbl[params->corner_freq_index]
    210                                      [params->filter_strength_index];
    211     shape_filter_block->shape_filter[3].y1_bound =
    212         shape_filt_hf_y1_bound_tbl[params->corner_freq_index]
    213                                   [params->filter_strength_index];
    214     radius = shape_filt_hf_radius_tbl[params->corner_freq_index];
    215     x1 = (FLOAT32)(
    216         -2.0f * radius *
    217         cos(2.0f * M_PI *
    218             shape_filt_cutoff_freq_norm_hf_tbl[params->corner_freq_index]));
    219     x2 = radius * radius;
    220     shape_filter_block->shape_filter[3].warped_gain_max =
    221         SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE /
    222         (SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE +
    223          shape_filter_block->shape_filter[3].gain_offset);
    224     shape_filter_block->shape_filter[3].factor =
    225         (shape_filter_block->shape_filter[3].y1_bound - x1) /
    226         shape_filter_block->shape_filter[3].warped_gain_max;
    227     shape_filter_block->shape_filter[3].coeff_sum = 1.0f + x1 + x2;
    228     shape_filter_block->shape_filter[3].partial_coeff_sum = 1.0f + x2;
    229     shape_filter_block->shape_filter[3].b1 = x1;
    230     shape_filter_block->shape_filter[3].b2 = x2;
    231     shape_filter_block->shape_filter[3].a2 = x2;
    232 
    233   } else {
    234     shape_filter_block->shape_filter[3].type = SHAPE_FILTER_TYPE_OFF;
    235   }
    236   resetshape_flter_block(shape_filter_block);
    237   shape_filter_block->shape_flter_block_flag = 1;
    238   return (0);
    239 }
    240 
    241 WORD32 impd_shape_filt_block_time_process(
    242     shape_filter_block* shape_filter_block, FLOAT32* drc_gain,
    243     const WORD32 channel, FLOAT32* audio_in, WORD32 start, WORD32 end) {
    244   WORD32 i, j, err = 0;
    245   FLOAT32 audio_out;
    246 
    247   if (shape_filter_block->shape_flter_block_flag) {
    248     for (i = start; i < end; i++) {
    249       FLOAT32 tmp = audio_in[i];
    250       for (j = 0; j < 4; j++) {
    251         if (shape_filter_block->shape_filter[j].type ==
    252                 SHAPE_FILTER_TYPE_LF_CUT ||
    253             shape_filter_block->shape_filter[j].type ==
    254                 SHAPE_FILTER_TYPE_LF_BOOST) {
    255           audio_out = tmp +
    256                       shape_filter_block->shape_filter[j].b1 *
    257                           shape_filter_block->shape_filter[j]
    258                               .audio_in_state_1[channel] -
    259                       shape_filter_block->shape_filter[j].a1 *
    260                           shape_filter_block->shape_filter[j]
    261                               .audio_out_state_1[channel];
    262           shape_filter_block->shape_filter[j].audio_in_state_1[channel] = tmp;
    263           shape_filter_block->shape_filter[j].audio_out_state_1[channel] =
    264               audio_out;
    265 
    266         } else if (shape_filter_block->shape_filter[j].type ==
    267                        SHAPE_FILTER_TYPE_HF_CUT ||
    268                    shape_filter_block->shape_filter[j].type ==
    269                        SHAPE_FILTER_TYPE_HF_BOOST) {
    270           audio_out = shape_filter_block->shape_filter[j].g_norm * tmp +
    271                       shape_filter_block->shape_filter[j].b1 *
    272                           shape_filter_block->shape_filter[j]
    273                               .audio_in_state_1[channel] +
    274                       shape_filter_block->shape_filter[j].b2 *
    275                           shape_filter_block->shape_filter[j]
    276                               .audio_in_state_2[channel] -
    277                       shape_filter_block->shape_filter[j].a1 *
    278                           shape_filter_block->shape_filter[j]
    279                               .audio_out_state_1[channel] -
    280                       shape_filter_block->shape_filter[j].a2 *
    281                           shape_filter_block->shape_filter[j]
    282                               .audio_out_state_2[channel];
    283           shape_filter_block->shape_filter[j].audio_in_state_2[channel] =
    284               shape_filter_block->shape_filter[j].audio_in_state_1[channel];
    285           shape_filter_block->shape_filter[j].audio_in_state_1[channel] =
    286               shape_filter_block->shape_filter[j].g_norm * tmp;
    287           shape_filter_block->shape_filter[j].audio_out_state_2[channel] =
    288               shape_filter_block->shape_filter[j].audio_out_state_1[channel];
    289           shape_filter_block->shape_filter[j].audio_out_state_1[channel] =
    290               audio_out;
    291         } else {
    292           audio_out = tmp;
    293         }
    294         tmp = audio_out;
    295       }
    296 
    297       audio_in[i] = audio_out * drc_gain[i];
    298     }
    299 
    300   } else {
    301     for (i = start; i < end; i++) {
    302       audio_in[i] = audio_in[i] * drc_gain[i];
    303     }
    304   }
    305 
    306   return err;
    307 }
    308