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 }