• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
impd_compute_filt_coeff(WORD32 crossover_freq_idx,ia_iir_filter_struct * pstr_lp_filt_coeff,ia_iir_filter_struct * pstr_hp_filt_coeff,ia_iir_filter_struct * pstr_ap_filt_coeff,WORD32 filter_type)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 
impd_initialize_filt_bank(WORD32 num_sub_bands,ia_gain_params_struct * gain_params,ia_drc_filter_bank_struct * drc_filter_bank)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 
impd_init_all_filter_banks(ia_uni_drc_coeffs_struct * str_p_loc_drc_coefficients_uni_drc,ia_drc_instructions_struct * str_drc_instruction_str,ia_filter_banks_struct * ia_filter_banks_struct)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 
impd_iir_second_order_filter_all_pass(ia_iir_filter_struct * filter,WORD32 chan_idx,WORD32 frame_len,FLOAT32 * input,FLOAT32 * output)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 
impd_apply_low_high_filter(ia_iir_filter_struct * pstr_lp_filt_coeff,ia_iir_filter_struct * pstr_hp_filt_coeff,WORD32 chan_idx,WORD32 frame_len,FLOAT32 * input,FLOAT32 * output[])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 }
impd_two_band_filter_process(ia_two_band_filt_struct * str_two_band_bank,WORD32 chan_idx,WORD32 frame_len,FLOAT32 * input,FLOAT32 * output[])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 
impd_three_band_filter_process(ia_three_band_filt_struct * str_three_band_bank,WORD32 c,WORD32 size,FLOAT32 * input,FLOAT32 * output[])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 
impd_four_band_filter_process(ia_four_band_filt_struct * str_four_band_bank,WORD32 cha_idx,WORD32 win_size,FLOAT32 * input,FLOAT32 * output[])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 
impd_all_pass_cascade_process(ia_all_pass_cascade_struct * str_all_pass_cascade,WORD32 ch_idx,WORD32 win_size,FLOAT32 * input)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 }