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 }