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 
     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_drc_filter_bank.h"
     29 #include "impd_drc_rom.h"
     30 
     31 VOID impd_compute_filt_coeff(WORD32 crossover_freq_idx,
     32                              ia_iir_filter_struct* pstr_lp_filt_coeff,
     33                              ia_iir_filter_struct* pstr_hp_filt_coeff,
     34                              ia_iir_filter_struct* pstr_ap_filt_coeff,
     35                              WORD32 filter_type) {
     36   FLOAT32 gamma = normal_cross_freq[crossover_freq_idx].gamma;
     37   FLOAT32 delta = normal_cross_freq[crossover_freq_idx].delta;
     38 
     39   if (filter_type == 0 || filter_type == 2) {
     40     pstr_lp_filt_coeff->a0 = 1.0f;
     41     pstr_lp_filt_coeff->a1 = 2.0f * (gamma - delta);
     42     pstr_lp_filt_coeff->a2 = 2.0f * (gamma + delta) - 1.0f;
     43     pstr_lp_filt_coeff->b0 = gamma;
     44     pstr_lp_filt_coeff->b1 = 2.0f * gamma;
     45     pstr_lp_filt_coeff->b2 = gamma;
     46 
     47     pstr_hp_filt_coeff->a0 = 1.0f;
     48     pstr_hp_filt_coeff->a1 = pstr_lp_filt_coeff->a1;
     49     pstr_hp_filt_coeff->a2 = pstr_lp_filt_coeff->a2;
     50     pstr_hp_filt_coeff->b0 = delta;
     51     pstr_hp_filt_coeff->b1 = -2.0f * delta;
     52     pstr_hp_filt_coeff->b2 = delta;
     53   }
     54 
     55   if (filter_type == 1 || filter_type == 2) {
     56     pstr_ap_filt_coeff->a0 = 1.0f;
     57     pstr_ap_filt_coeff->a1 = 2.0f * (gamma - delta);
     58     ;
     59     pstr_ap_filt_coeff->a2 = 2.0f * (gamma + delta) - 1.0f;
     60     ;
     61     pstr_ap_filt_coeff->b0 = pstr_ap_filt_coeff->a2;
     62     pstr_ap_filt_coeff->b1 = pstr_ap_filt_coeff->a1;
     63     pstr_ap_filt_coeff->b2 = pstr_ap_filt_coeff->a0;
     64   }
     65 
     66   return;
     67 }
     68 
     69 WORD32 impd_initialize_filt_bank(WORD32 num_sub_bands,
     70                                  ia_gain_params_struct* gain_params,
     71                                  ia_drc_filter_bank_struct* drc_filter_bank) {
     72   ia_two_band_filt_struct* str_two_band_bank;
     73   ia_three_band_filt_struct* str_three_band_bank;
     74   ia_four_band_filt_struct* str_four_band_bank;
     75   drc_filter_bank->complexity = 0;
     76   drc_filter_bank->num_bands = num_sub_bands;
     77 
     78   if (num_sub_bands == 1) {
     79     return 0;
     80   } else if (num_sub_bands == 2) {
     81     str_two_band_bank = &drc_filter_bank->str_two_band_bank;
     82     impd_compute_filt_coeff(gain_params[1].crossover_freq_idx,
     83                             &(str_two_band_bank->low_pass),
     84                             &(str_two_band_bank->high_pass), NULL, 0);
     85   } else if (num_sub_bands == 3) {
     86     str_three_band_bank = &drc_filter_bank->str_three_band_bank;
     87 
     88     impd_compute_filt_coeff(gain_params[1].crossover_freq_idx,
     89                             &(str_three_band_bank->str_low_pass_stage_2),
     90                             &(str_three_band_bank->str_high_pass_stage_2),
     91                             &(str_three_band_bank->str_all_pass_stage_2), 2);
     92     impd_compute_filt_coeff(gain_params[2].crossover_freq_idx,
     93                             &(str_three_band_bank->str_low_pass_stage_1),
     94                             &(str_three_band_bank->str_high_pass_stage_1), NULL,
     95                             0);
     96   }
     97 
     98   else if (num_sub_bands == 4) {
     99     str_four_band_bank = &drc_filter_bank->str_four_band_bank;
    100 
    101     impd_compute_filt_coeff(gain_params[1].crossover_freq_idx,
    102                             &(str_four_band_bank->str_low_pass_stage_3_low),
    103                             &(str_four_band_bank->str_high_pass_stage_3_low),
    104                             &(str_four_band_bank->str_all_pass_stage_2_high),
    105                             2);
    106     impd_compute_filt_coeff(gain_params[2].crossover_freq_idx,
    107                             &(str_four_band_bank->str_low_pass_stage_1),
    108                             &(str_four_band_bank->str_high_pass_stage_1), NULL,
    109                             0);
    110     impd_compute_filt_coeff(gain_params[3].crossover_freq_idx,
    111                             &(str_four_band_bank->str_low_pass_stage_3_high),
    112                             &(str_four_band_bank->str_high_pass_stage_3_high),
    113                             &(str_four_band_bank->str_all_pass_stage_2_low), 2);
    114   } else {
    115     return -1;
    116   }
    117 
    118   return 0;
    119 }
    120 
    121 WORD32 impd_init_all_filter_banks(
    122     ia_uni_drc_coeffs_struct* str_p_loc_drc_coefficients_uni_drc,
    123     ia_drc_instructions_struct* str_drc_instruction_str,
    124     ia_filter_banks_struct* ia_filter_banks_struct) {
    125   WORD32 err_code = 0;
    126   WORD32 b, g, i, k, m, s, crossover_freq_idx, num_ch_in_groups,
    127       num_ph_align_ch_groups;
    128   WORD32 match_found = 0, num_filter;
    129   WORD32 cascade_cross_idx[CHANNEL_GROUP_COUNT_MAX + 1]
    130                           [CHANNEL_GROUP_COUNT_MAX * 3];
    131   WORD32 count[CHANNEL_GROUP_COUNT_MAX + 1];
    132 
    133   num_ch_in_groups = 0;
    134   num_ph_align_ch_groups = str_drc_instruction_str->num_drc_ch_groups;
    135 
    136   for (g = 0; g < str_drc_instruction_str->num_drc_ch_groups; g++) {
    137     num_ch_in_groups += str_drc_instruction_str->num_chan_per_ch_group[g];
    138   }
    139 
    140   if (num_ch_in_groups < str_drc_instruction_str->audio_num_chan) {
    141     num_ph_align_ch_groups++;
    142   }
    143 
    144   ia_filter_banks_struct->nfilter_banks =
    145       str_drc_instruction_str->num_drc_ch_groups;
    146   ia_filter_banks_struct->num_ph_align_ch_groups = num_ph_align_ch_groups;
    147 
    148   if (str_p_loc_drc_coefficients_uni_drc == NULL) {
    149     ia_filter_banks_struct->str_drc_filter_bank->num_bands = 1;
    150   } else {
    151     for (g = 0; g < str_drc_instruction_str->num_drc_ch_groups; g++) {
    152       err_code = impd_initialize_filt_bank(
    153           str_p_loc_drc_coefficients_uni_drc
    154               ->gain_set_params[str_drc_instruction_str
    155                                     ->gain_set_index_for_channel_group[g]]
    156               .band_count,
    157           str_p_loc_drc_coefficients_uni_drc
    158               ->gain_set_params[str_drc_instruction_str
    159                                     ->gain_set_index_for_channel_group[g]]
    160               .gain_params,
    161           &(ia_filter_banks_struct->str_drc_filter_bank[g]));
    162       if (err_code != 0) return (err_code);
    163     }
    164   }
    165 
    166   for (g = 0; g < CHANNEL_GROUP_COUNT_MAX + 1; g++) {
    167     count[g] = 0;
    168   }
    169   for (g = 0; g < str_drc_instruction_str->num_drc_ch_groups; g++) {
    170     for (b = 1;
    171          b < str_p_loc_drc_coefficients_uni_drc
    172                  ->gain_set_params[str_drc_instruction_str
    173                                        ->gain_set_index_for_channel_group[g]]
    174                  .band_count;
    175          b++) {
    176       crossover_freq_idx =
    177           str_p_loc_drc_coefficients_uni_drc
    178               ->gain_set_params[str_drc_instruction_str
    179                                     ->gain_set_index_for_channel_group[g]]
    180               .gain_params[b]
    181               .crossover_freq_idx;
    182       for (k = 0; k < num_ph_align_ch_groups; k++) {
    183         if (k != g) {
    184           cascade_cross_idx[k][count[k]] = crossover_freq_idx;
    185           count[k]++;
    186           if (count[k] > CHANNEL_GROUP_COUNT_MAX * 3) {
    187             return -1;
    188           }
    189         }
    190       }
    191     }
    192   }
    193 
    194   i = 0;
    195   while (i < count[0]) {
    196     crossover_freq_idx = cascade_cross_idx[0][i];
    197     match_found = 0;
    198     for (g = 1; g < num_ph_align_ch_groups; g++) {
    199       match_found = 0;
    200       for (k = 0; k < count[g]; k++) {
    201         if (cascade_cross_idx[g][k] == crossover_freq_idx) {
    202           match_found = 1;
    203           break;
    204         }
    205       }
    206       if (match_found == 0) break;
    207     }
    208     if (match_found == 1) {
    209       for (g = 0; g < num_ph_align_ch_groups; g++) {
    210         for (m = 0; m < count[g]; m++) {
    211           if (cascade_cross_idx[g][m] == crossover_freq_idx) {
    212             for (s = m + 1; s < count[g]; s++) {
    213               cascade_cross_idx[g][s - 1] = cascade_cross_idx[g][s];
    214             }
    215             count[g]--;
    216             break;
    217           }
    218         }
    219       }
    220       i = 0;
    221     } else {
    222       i++;
    223     }
    224   }
    225 
    226   for (g = 0; g < num_ph_align_ch_groups; g++) {
    227     num_filter = count[g];
    228     if (num_filter > 0) {
    229       for (i = 0; i < num_filter; i++) {
    230         impd_compute_filt_coeff(
    231             cascade_cross_idx[g][i], NULL, NULL,
    232             &(ia_filter_banks_struct->str_drc_filter_bank[g]
    233                   .str_all_pass_cascade.str_all_pass_cascade_filter[i]
    234                   .str_all_pass_stage),
    235             1);
    236       }
    237       ia_filter_banks_struct->str_drc_filter_bank[g]
    238           .str_all_pass_cascade.num_filter = num_filter;
    239     }
    240 
    241     if (err_code != 0) return (err_code);
    242   }
    243 
    244   return 0;
    245 }
    246 
    247 VOID impd_iir_second_order_filter_all_pass(ia_iir_filter_struct* filter,
    248                                            WORD32 chan_idx, WORD32 frame_len,
    249                                            FLOAT32* input, FLOAT32* output) {
    250   WORD32 i;
    251   FLOAT32 tmp;
    252   FLOAT32 a1 = filter->a1;
    253   FLOAT32 a2 = filter->a2;
    254   FLOAT32 b0 = filter->b0;
    255   FLOAT32 b1 = filter->b1;
    256   FLOAT32 b2 = filter->b2;
    257 
    258   FLOAT32 st1 = filter->x_p[chan_idx * 2];
    259   FLOAT32 st2 = filter->y_p[chan_idx * 2];
    260 
    261   for (i = 0; i < frame_len; i++) {
    262     tmp = input[i];
    263     output[i] = b0 * tmp + st1;
    264     st1 = b1 * tmp - a1 * output[i] + st2;
    265     st2 = b2 * tmp - a2 * output[i];
    266   }
    267   filter->x_p[chan_idx * 2] = st1;
    268   filter->y_p[chan_idx * 2] = st2;
    269 
    270   return;
    271 }
    272 
    273 VOID impd_apply_low_high_filter(ia_iir_filter_struct* pstr_lp_filt_coeff,
    274                                 ia_iir_filter_struct* pstr_hp_filt_coeff,
    275                                 WORD32 chan_idx, WORD32 frame_len,
    276                                 FLOAT32* input, FLOAT32* output[]) {
    277   WORD32 i;
    278   FLOAT32 tmp, tmp1;
    279   FLOAT32 a1_l = pstr_lp_filt_coeff->a1;
    280   FLOAT32 a2_l = pstr_lp_filt_coeff->a2;
    281   FLOAT32 b0_l = pstr_lp_filt_coeff->b0;
    282   FLOAT32 b1_l = pstr_lp_filt_coeff->b1;
    283   FLOAT32 b2_l = pstr_lp_filt_coeff->b2;
    284 
    285   FLOAT32 st1_l = pstr_lp_filt_coeff->x_p[chan_idx * 2 + 0];
    286   FLOAT32 st2_l = pstr_lp_filt_coeff->x_p[chan_idx * 2 + 1];
    287   FLOAT32 st3_l = pstr_lp_filt_coeff->y_p[chan_idx * 2 + 0];
    288   FLOAT32 st4_l = pstr_lp_filt_coeff->y_p[chan_idx * 2 + 1];
    289 
    290   FLOAT32 a1_h = pstr_hp_filt_coeff->a1;
    291   FLOAT32 a2_h = pstr_hp_filt_coeff->a2;
    292   FLOAT32 b0_h = pstr_hp_filt_coeff->b0;
    293   FLOAT32 b1_h = pstr_hp_filt_coeff->b1;
    294   FLOAT32 b2_h = pstr_hp_filt_coeff->b2;
    295 
    296   FLOAT32 st1_h = pstr_hp_filt_coeff->x_p[chan_idx * 2 + 0];
    297   FLOAT32 st2_h = pstr_hp_filt_coeff->x_p[chan_idx * 2 + 1];
    298   FLOAT32 st3_h = pstr_hp_filt_coeff->y_p[chan_idx * 2 + 0];
    299   FLOAT32 st4_h = pstr_hp_filt_coeff->y_p[chan_idx * 2 + 1];
    300 
    301   FLOAT32* output_low = output[0];
    302   FLOAT32* output_high = output[1];
    303 
    304   for (i = 0; i < frame_len; i++) {
    305     tmp1 = input[i];
    306     tmp = b0_l * tmp1 + st1_l;
    307     st1_l = b1_l * tmp1 - a1_l * tmp + st2_l;
    308     st2_l = b2_l * tmp1 - a2_l * tmp;
    309 
    310     output_low[i] = b0_l * tmp + st3_l;
    311     st3_l = b1_l * tmp - a1_l * output_low[i] + st4_l;
    312     st4_l = b2_l * tmp - a2_l * output_low[i];
    313 
    314     tmp = b0_h * tmp1 + st1_h;
    315     st1_h = b1_h * tmp1 - a1_h * tmp + st2_h;
    316     st2_h = b2_h * tmp1 - a2_h * tmp;
    317 
    318     output_high[i] = b0_h * tmp + st3_h;
    319     st3_h = b1_h * tmp - a1_h * output_high[i] + st4_h;
    320     st4_h = b2_h * tmp - a2_h * output_high[i];
    321   }
    322   pstr_lp_filt_coeff->x_p[chan_idx * 2 + 0] = st1_l;
    323   pstr_lp_filt_coeff->x_p[chan_idx * 2 + 1] = st2_l;
    324   pstr_lp_filt_coeff->y_p[chan_idx * 2 + 0] = st3_l;
    325   pstr_lp_filt_coeff->y_p[chan_idx * 2 + 1] = st4_l;
    326 
    327   pstr_hp_filt_coeff->x_p[chan_idx * 2 + 0] = st1_h;
    328   pstr_hp_filt_coeff->x_p[chan_idx * 2 + 1] = st2_h;
    329   pstr_hp_filt_coeff->y_p[chan_idx * 2 + 0] = st3_h;
    330   pstr_hp_filt_coeff->y_p[chan_idx * 2 + 1] = st4_h;
    331 
    332   return;
    333 }
    334 VOID impd_two_band_filter_process(ia_two_band_filt_struct* str_two_band_bank,
    335                                   WORD32 chan_idx, WORD32 frame_len,
    336                                   FLOAT32* input, FLOAT32* output[]) {
    337   ia_iir_filter_struct* pstr_lp_filt_coeff = &str_two_band_bank->low_pass;
    338   ia_iir_filter_struct* pstr_hp_filt_coeff = &str_two_band_bank->high_pass;
    339 
    340   impd_apply_low_high_filter(pstr_lp_filt_coeff, pstr_hp_filt_coeff, chan_idx,
    341                              frame_len, input, output);
    342   return;
    343 }
    344 
    345 VOID impd_three_band_filter_process(
    346     ia_three_band_filt_struct* str_three_band_bank, WORD32 c, WORD32 size,
    347     FLOAT32* input, FLOAT32* output[]) {
    348   //    WORD32 err_code=0;
    349   ia_iir_filter_struct* all_pass_filter;
    350   ia_iir_filter_struct* pstr_lp_filt_coeff =
    351       &str_three_band_bank->str_low_pass_stage_1;
    352   ia_iir_filter_struct* pstr_hp_filt_coeff =
    353       &str_three_band_bank->str_high_pass_stage_1;
    354   FLOAT32* output1[2];
    355   output1[0] = output[0];
    356   output1[1] = output[1];
    357 
    358   impd_apply_low_high_filter(pstr_lp_filt_coeff, pstr_hp_filt_coeff, c, size,
    359                              input, output1);
    360 
    361   all_pass_filter = &str_three_band_bank->str_all_pass_stage_2;
    362 
    363   impd_iir_second_order_filter_all_pass(all_pass_filter, c, size, output1[1],
    364                                         output[2]);
    365   pstr_lp_filt_coeff = &str_three_band_bank->str_low_pass_stage_2;
    366   pstr_hp_filt_coeff = &str_three_band_bank->str_high_pass_stage_2;
    367 
    368   impd_apply_low_high_filter(pstr_lp_filt_coeff, pstr_hp_filt_coeff, c, size,
    369                              output1[0], output1);
    370 
    371   return;
    372 }
    373 
    374 VOID impd_four_band_filter_process(ia_four_band_filt_struct* str_four_band_bank,
    375                                    WORD32 cha_idx, WORD32 win_size,
    376                                    FLOAT32* input, FLOAT32* output[]) {
    377   //    WORD32 err_code=0;
    378   ia_iir_filter_struct* all_pass_filter;
    379   ia_iir_filter_struct* pstr_lp_filt_coeff =
    380       &str_four_band_bank->str_low_pass_stage_1;
    381   ia_iir_filter_struct* pstr_hp_filt_coeff =
    382       &str_four_band_bank->str_high_pass_stage_1;
    383   FLOAT32* output1[2];
    384   FLOAT32* output2[2];
    385   output1[0] = output[0];
    386   output1[1] = output[1];
    387   output2[0] = output[2];
    388   output2[1] = output[3];
    389 
    390   impd_apply_low_high_filter(pstr_lp_filt_coeff, pstr_hp_filt_coeff, cha_idx,
    391                              win_size, input, output1);
    392 
    393   all_pass_filter = &str_four_band_bank->str_all_pass_stage_2_low;
    394 
    395   impd_iir_second_order_filter_all_pass(all_pass_filter, cha_idx, win_size,
    396                                         output1[0], output1[0]);
    397 
    398   all_pass_filter = &str_four_band_bank->str_all_pass_stage_2_high;
    399 
    400   impd_iir_second_order_filter_all_pass(all_pass_filter, cha_idx, win_size,
    401                                         output1[1], output2[0]);
    402 
    403   pstr_lp_filt_coeff = &str_four_band_bank->str_low_pass_stage_3_low;
    404   pstr_hp_filt_coeff = &str_four_band_bank->str_high_pass_stage_3_low;
    405 
    406   impd_apply_low_high_filter(pstr_lp_filt_coeff, pstr_hp_filt_coeff, cha_idx,
    407                              win_size, output1[0], output1);
    408 
    409   pstr_lp_filt_coeff = &str_four_band_bank->str_low_pass_stage_3_high;
    410   pstr_hp_filt_coeff = &str_four_band_bank->str_high_pass_stage_3_high;
    411 
    412   impd_apply_low_high_filter(pstr_lp_filt_coeff, pstr_hp_filt_coeff, cha_idx,
    413                              win_size, output2[0], output2);
    414 
    415   return;
    416 }
    417 
    418 VOID impd_all_pass_cascade_process(
    419     ia_all_pass_cascade_struct* str_all_pass_cascade, WORD32 ch_idx,
    420     WORD32 win_size, FLOAT32* input) {
    421   WORD32 i;
    422 
    423   for (i = 0; i < str_all_pass_cascade->num_filter; i++) {
    424     impd_iir_second_order_filter_all_pass(
    425         &(str_all_pass_cascade->str_all_pass_cascade_filter[i]
    426               .str_all_pass_stage),
    427         ch_idx, win_size, input, input);
    428   }
    429 
    430   return;
    431 }