1 /******************************************************************************
2 * *
3 * Copyright (C) 2023 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
21 #include <math.h>
22 #include <string.h>
23 #include "ixheaac_type_def.h"
24 #include "ixheaac_error_standards.h"
25 #include "ixheaace_error_codes.h"
26
27 #include "impd_drc_common_enc.h"
28 #include "impd_drc_uni_drc.h"
29 #include "impd_drc_uni_drc_eq.h"
30
impd_drc_derive_subband_center_freq(const WORD32 eq_subband_gain_count,const WORD32 eq_subband_gain_format,const FLOAT32 audio_sample_rate,FLOAT32 * ptr_subband_center_freq)31 static IA_ERRORCODE impd_drc_derive_subband_center_freq(const WORD32 eq_subband_gain_count,
32 const WORD32 eq_subband_gain_format,
33 const FLOAT32 audio_sample_rate,
34 FLOAT32 *ptr_subband_center_freq) {
35 LOOPIDX idx;
36 FLOAT32 width, offset;
37
38 switch (eq_subband_gain_format) {
39 case GAINFORMAT_QMF32:
40 case GAINFORMAT_QMF64:
41 case GAINFORMAT_QMF128:
42 case GAINFORMAT_UNIFORM:
43 width = 0.5f * audio_sample_rate / (FLOAT32)eq_subband_gain_count;
44 offset = 0.5f * width;
45 for (idx = 0; idx < eq_subband_gain_count; idx++) {
46 ptr_subband_center_freq[idx] = idx * width + offset;
47 }
48 break;
49 case GAINFORMAT_QMFHYBRID39:
50 case GAINFORMAT_QMFHYBRID71:
51 case GAINFORMAT_QMFHYBRID135:
52 return IA_EXHEAACE_CONFIG_FATAL_DRC_UNSUPPORTED_CONFIG;
53 break;
54 default:
55 break;
56 }
57
58 return IA_NO_ERROR;
59 }
60
impd_drc_derive_zero_response(const FLOAT32 radius,const FLOAT32 angle_radian,const FLOAT32 frequency_radian,FLOAT32 * response)61 static VOID impd_drc_derive_zero_response(const FLOAT32 radius, const FLOAT32 angle_radian,
62 const FLOAT32 frequency_radian, FLOAT32 *response) {
63 *response =
64 (FLOAT32)(1.0f + radius * radius - 2.0f * radius * cos(frequency_radian - angle_radian));
65 }
66
impd_drc_derive_pole_response(const FLOAT32 radius,const FLOAT32 angle_radian,const FLOAT32 frequency_radian,FLOAT32 * response)67 static VOID impd_drc_derive_pole_response(const FLOAT32 radius, const FLOAT32 angle_radian,
68 const FLOAT32 frequency_radian, FLOAT32 *response) {
69 *response =
70 (FLOAT32)(1.0f + radius * radius - 2.0f * radius * cos(frequency_radian - angle_radian));
71 *response = 1.0f / *response;
72 }
73
impd_drc_derive_fir_filter_response(const WORD32 fir_order,const WORD32 fir_symmetry,const FLOAT32 * ptr_fir_coeff,const FLOAT32 frequency_radian,FLOAT32 * response)74 static VOID impd_drc_derive_fir_filter_response(const WORD32 fir_order, const WORD32 fir_symmetry,
75 const FLOAT32 *ptr_fir_coeff,
76 const FLOAT32 frequency_radian,
77 FLOAT32 *response) {
78 LOOPIDX idx;
79 WORD32 order_2;
80 FLOAT32 sum = 0.0f;
81
82 if ((fir_order & 0x1) != 0) {
83 order_2 = (fir_order + 1) / 2;
84 if (fir_symmetry != 0) {
85 for (idx = 1; idx <= order_2; idx++) {
86 sum += (FLOAT32)(ptr_fir_coeff[order_2 - idx] * sin((idx - 0.5f) * frequency_radian));
87 }
88 } else {
89 for (idx = 1; idx <= order_2; idx++) {
90 sum += (FLOAT32)(ptr_fir_coeff[order_2 - idx] * cos((idx - 0.5f) * frequency_radian));
91 }
92 }
93 sum *= 2.0f;
94 } else {
95 order_2 = fir_order / 2;
96 if (fir_symmetry != 0) {
97 for (idx = 1; idx <= order_2; idx++) {
98 sum += (FLOAT32)(ptr_fir_coeff[order_2 - idx] * sin(idx * frequency_radian));
99 }
100 sum *= 2.0f;
101 } else {
102 sum = ptr_fir_coeff[order_2];
103 }
104 }
105
106 *response = sum;
107 }
108
impd_drc_derive_filter_element_response(ia_drc_unique_td_filter_element_struct * pstr_unique_td_filter_element,const FLOAT32 frequency_radian,FLOAT32 * response)109 static VOID impd_drc_derive_filter_element_response(
110 ia_drc_unique_td_filter_element_struct *pstr_unique_td_filter_element,
111 const FLOAT32 frequency_radian, FLOAT32 *response) {
112 LOOPIDX idx;
113 FLOAT32 response_part, radius, angle_radian;
114 FLOAT64 combined_response = 1.0;
115
116 if (pstr_unique_td_filter_element->eq_filter_format != FILTER_ELEMENT_FORMAT_POLE_ZERO) {
117 impd_drc_derive_fir_filter_response(pstr_unique_td_filter_element->fir_filter_order,
118 pstr_unique_td_filter_element->fir_symmetry,
119 pstr_unique_td_filter_element->fir_coefficient,
120 frequency_radian, &response_part);
121 combined_response *= response_part;
122 } else {
123 for (idx = 0; idx < pstr_unique_td_filter_element->real_zero_radius_one_count; idx++) {
124 impd_drc_derive_zero_response(1.0f,
125 (FLOAT32)(M_PI)*pstr_unique_td_filter_element->zero_sign[idx],
126 frequency_radian, &response_part);
127 combined_response *= response_part;
128 }
129 for (idx = 0; idx < pstr_unique_td_filter_element->real_zero_count; idx++) {
130 if (pstr_unique_td_filter_element->real_zero_radius[idx] >= 0.0f) {
131 radius = pstr_unique_td_filter_element->real_zero_radius[idx];
132 angle_radian = 0.0f;
133 } else {
134 radius = -pstr_unique_td_filter_element->real_zero_radius[idx];
135 angle_radian = (FLOAT32)(M_PI);
136 }
137 impd_drc_derive_zero_response(radius, angle_radian, frequency_radian, &response_part);
138 combined_response *= response_part;
139 impd_drc_derive_zero_response(1.0f / radius, angle_radian, frequency_radian,
140 &response_part);
141 combined_response *= response_part;
142 }
143
144 combined_response = sqrt(combined_response);
145
146 for (idx = 0; idx < pstr_unique_td_filter_element->generic_zero_count; idx++) {
147 radius = pstr_unique_td_filter_element->generic_zero_radius[idx];
148
149 impd_drc_derive_zero_response(
150 radius, (FLOAT32)(M_PI)*pstr_unique_td_filter_element->generic_zero_angle[idx],
151 frequency_radian, &response_part);
152 combined_response *= response_part;
153
154 impd_drc_derive_zero_response(
155 1.0f / radius, (FLOAT32)(M_PI)*pstr_unique_td_filter_element->generic_zero_angle[idx],
156 frequency_radian, &response_part);
157 combined_response *= response_part;
158 }
159 for (idx = 0; idx < pstr_unique_td_filter_element->real_pole_count; idx++) {
160 if (pstr_unique_td_filter_element->real_pole_radius[idx] >= 0.0f) {
161 radius = pstr_unique_td_filter_element->real_pole_radius[idx];
162 angle_radian = 0.0f;
163 } else {
164 radius = -pstr_unique_td_filter_element->real_pole_radius[idx];
165 angle_radian = (FLOAT32)(-M_PI);
166 }
167 impd_drc_derive_pole_response(radius, angle_radian, frequency_radian, &response_part);
168 combined_response *= response_part;
169 }
170 for (idx = 0; idx < pstr_unique_td_filter_element->complex_pole_count; idx++) {
171 impd_drc_derive_pole_response(
172 pstr_unique_td_filter_element->real_pole_radius[idx],
173 (FLOAT32)(M_PI)*pstr_unique_td_filter_element->complex_pole_angle[idx],
174 frequency_radian, &response_part);
175 combined_response *= response_part * response_part;
176 }
177 }
178
179 *response = (FLOAT32)combined_response;
180 }
181
impd_drc_derive_filter_block_response(ia_drc_unique_td_filter_element_struct * pstr_unique_td_filter_element,ia_drc_filter_block_struct * pstr_filter_block,const FLOAT32 frequency_radian,FLOAT32 * response)182 static VOID impd_drc_derive_filter_block_response(
183 ia_drc_unique_td_filter_element_struct *pstr_unique_td_filter_element,
184 ia_drc_filter_block_struct *pstr_filter_block, const FLOAT32 frequency_radian,
185 FLOAT32 *response) {
186 LOOPIDX idx;
187 FLOAT32 response_part;
188 FLOAT64 combined_response = 1.0;
189 ia_drc_filter_element_struct *pstr_filter_element;
190
191 for (idx = 0; idx < pstr_filter_block->filter_element_count; idx++) {
192 pstr_filter_element = &pstr_filter_block->filter_element[idx];
193 impd_drc_derive_filter_element_response(
194 &(pstr_unique_td_filter_element[pstr_filter_element->filter_element_index]),
195 frequency_radian, &response_part);
196 combined_response *= response_part;
197
198 if (pstr_filter_element->filter_element_gain_present == 1) {
199 combined_response *= pow(10.0f, 0.05f * pstr_filter_element->filter_element_gain);
200 }
201 }
202
203 *response = (FLOAT32)combined_response;
204 }
205
impd_drc_derive_subband_gains_from_td_cascade(ia_drc_unique_td_filter_element_struct * pstr_unique_td_filter_element,ia_drc_filter_block_struct * pstr_filter_block,ia_drc_td_filter_cascade_struct * pstr_td_filter_cascade,const WORD32 eq_subband_gain_format,const WORD32 eq_channel_group_count,const FLOAT32 audio_sample_rate,const WORD32 eq_frame_size_subband,ia_drc_subband_filter_struct * pstr_subband_filter,VOID * ptr_scratch)206 static IA_ERRORCODE impd_drc_derive_subband_gains_from_td_cascade(
207 ia_drc_unique_td_filter_element_struct *pstr_unique_td_filter_element,
208 ia_drc_filter_block_struct *pstr_filter_block,
209 ia_drc_td_filter_cascade_struct *pstr_td_filter_cascade, const WORD32 eq_subband_gain_format,
210 const WORD32 eq_channel_group_count, const FLOAT32 audio_sample_rate,
211 const WORD32 eq_frame_size_subband, ia_drc_subband_filter_struct *pstr_subband_filter,
212 VOID *ptr_scratch) {
213 IA_ERRORCODE err_code = IA_NO_ERROR;
214 LOOPIDX i, j, k;
215 WORD32 eq_subband_gain_count = pstr_subband_filter->coeff_count;
216 FLOAT32 response_part, frequency_radian;
217 FLOAT32 *ptr_subband_center_freq = (FLOAT32 *)ptr_scratch;
218 FLOAT64 combined_response;
219
220 err_code = impd_drc_derive_subband_center_freq(eq_subband_gain_count, eq_subband_gain_format,
221 audio_sample_rate, ptr_subband_center_freq);
222 if (err_code & IA_FATAL_ERROR) {
223 return err_code;
224 }
225
226 for (i = 0; i < eq_channel_group_count; i++) {
227 for (j = 0; j < eq_subband_gain_count; j++) {
228 combined_response = pow(10.0f, 0.05f * pstr_td_filter_cascade->eq_cascade_gain[i]);
229 frequency_radian = 2.0f * (FLOAT32)M_PI * ptr_subband_center_freq[j] / audio_sample_rate;
230
231 for (k = 0; k < pstr_td_filter_cascade->str_filter_block_refs[i].filter_block_count; k++) {
232 impd_drc_derive_filter_block_response(
233 pstr_unique_td_filter_element,
234 &(pstr_filter_block[pstr_td_filter_cascade->str_filter_block_refs[i]
235 .filter_block_index[k]]),
236 frequency_radian, &response_part);
237 combined_response *= response_part;
238 }
239 pstr_subband_filter[i].subband_coeff[j] = (FLOAT32)combined_response;
240 }
241 pstr_subband_filter[i].eq_frame_size_subband = eq_frame_size_subband;
242 }
243
244 return err_code;
245 }
246
impd_drc_check_presence_and_add_cascade(ia_drc_cascade_alignment_group_struct * pstr_cascade_alignment_group,const WORD32 index_c1,const WORD32 index_c2,WORD32 * done)247 static VOID impd_drc_check_presence_and_add_cascade(
248 ia_drc_cascade_alignment_group_struct *pstr_cascade_alignment_group, const WORD32 index_c1,
249 const WORD32 index_c2, WORD32 *done) {
250 LOOPIDX i, j;
251
252 *done = 0;
253 for (i = 0; i < pstr_cascade_alignment_group->member_count; i++) {
254 if (pstr_cascade_alignment_group->member_index[i] == index_c1) {
255 for (j = 0; j < pstr_cascade_alignment_group->member_count; j++) {
256 if (pstr_cascade_alignment_group->member_index[j] == index_c2) {
257 *done = 1;
258 }
259 }
260 if (*done == 0) {
261 pstr_cascade_alignment_group->member_index[pstr_cascade_alignment_group->member_count] =
262 index_c2;
263 pstr_cascade_alignment_group->member_count++;
264 *done = 1;
265 }
266 }
267 }
268 }
269
impd_drc_derive_cascade_alignment_groups(const WORD32 eq_channel_group_count,const WORD32 eq_phase_alignment_present,const WORD32 eq_phase_alignment[EQ_MAX_CHANNEL_GROUP_COUNT][EQ_MAX_CHANNEL_GROUP_COUNT],WORD32 * cascade_alignment_group_count,ia_drc_cascade_alignment_group_struct * pstr_cascade_alignment_group)270 static VOID impd_drc_derive_cascade_alignment_groups(
271 const WORD32 eq_channel_group_count, const WORD32 eq_phase_alignment_present,
272 const WORD32 eq_phase_alignment[EQ_MAX_CHANNEL_GROUP_COUNT][EQ_MAX_CHANNEL_GROUP_COUNT],
273 WORD32 *cascade_alignment_group_count,
274 ia_drc_cascade_alignment_group_struct *pstr_cascade_alignment_group) {
275 LOOPIDX i, j, k;
276 WORD32 group_count = 0, done;
277
278 if (eq_phase_alignment_present != 0) {
279 for (i = 0; i < eq_channel_group_count; i++) {
280 for (j = i + 1; j < eq_channel_group_count; j++) {
281 if (eq_phase_alignment[i][j] == 1) {
282 done = 0;
283 for (k = 0; k < group_count; k++) {
284 impd_drc_check_presence_and_add_cascade(&pstr_cascade_alignment_group[k], i, j,
285 &done);
286 if (done == 0) {
287 impd_drc_check_presence_and_add_cascade(&pstr_cascade_alignment_group[k], j, i,
288 &done);
289 }
290 }
291 if (done == 0) {
292 pstr_cascade_alignment_group[group_count].member_count = 2;
293 pstr_cascade_alignment_group[group_count].member_index[0] = i;
294 pstr_cascade_alignment_group[group_count].member_index[1] = j;
295 group_count++;
296 }
297 }
298 }
299 }
300 } else {
301 if (eq_channel_group_count > 1) {
302 for (i = 0; i < eq_channel_group_count; i++) {
303 pstr_cascade_alignment_group[group_count].member_index[i] = i;
304 }
305 pstr_cascade_alignment_group[group_count].member_count = eq_channel_group_count;
306 group_count = 1;
307 }
308 }
309
310 *cascade_alignment_group_count = group_count;
311 }
312
impd_drc_derive_allpass_chain(ia_drc_filter_cascade_t_domain_struct * pstr_filter_cascade_t_domain,ia_drc_allpass_chain_struct * pstr_allpass_chain)313 static IA_ERRORCODE impd_drc_derive_allpass_chain(
314 ia_drc_filter_cascade_t_domain_struct *pstr_filter_cascade_t_domain,
315 ia_drc_allpass_chain_struct *pstr_allpass_chain) {
316 LOOPIDX i, j;
317 WORD32 allpass_count = 0;
318
319 for (i = 0; i < pstr_filter_cascade_t_domain->block_count; i++) {
320 ia_drc_eq_filter_element_struct *pstr_eq_filter_element =
321 &pstr_filter_cascade_t_domain->str_eq_filter_block[i].str_eq_filter_element[0];
322
323 if (pstr_filter_cascade_t_domain->str_eq_filter_block[i]
324 .str_matching_phase_filter_element_0.is_valid != 1) {
325 return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
326 } else {
327 pstr_allpass_chain->str_matching_phase_filter[allpass_count] =
328 pstr_filter_cascade_t_domain->str_eq_filter_block[i]
329 .str_matching_phase_filter_element_0;
330 allpass_count++;
331 }
332
333 for (j = 0; j < pstr_eq_filter_element->phase_alignment_filter_count; j++) {
334 if (pstr_eq_filter_element->str_phase_alignment_filter[j].is_valid != 1) {
335 return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
336 } else {
337 pstr_allpass_chain->str_matching_phase_filter[allpass_count] =
338 pstr_eq_filter_element->str_phase_alignment_filter[j];
339 allpass_count++;
340 }
341 }
342 }
343 pstr_allpass_chain->allpass_count = allpass_count;
344
345 return IA_NO_ERROR;
346 }
347
impd_drc_add_allpass_filter_chain(ia_drc_allpass_chain_struct * pstr_allpass_chain,ia_drc_filter_cascade_t_domain_struct * pstr_filter_cascade_t_domain)348 static VOID impd_drc_add_allpass_filter_chain(
349 ia_drc_allpass_chain_struct *pstr_allpass_chain,
350 ia_drc_filter_cascade_t_domain_struct *pstr_filter_cascade_t_domain) {
351 LOOPIDX idx;
352
353 for (idx = 0; idx < pstr_allpass_chain->allpass_count; idx++) {
354 pstr_filter_cascade_t_domain
355 ->str_phase_alignment_filter[pstr_filter_cascade_t_domain->phase_alignment_filter_count +
356 idx] = pstr_allpass_chain->str_matching_phase_filter[idx];
357 }
358 pstr_filter_cascade_t_domain->phase_alignment_filter_count += pstr_allpass_chain->allpass_count;
359 }
360
impd_drc_phase_align_cascade_group(const WORD32 cascade_alignment_group_count,ia_drc_cascade_alignment_group_struct * pstr_cascade_alignment_group,ia_drc_filter_cascade_t_domain_struct * pstr_filter_cascade_t_domain,VOID * ptr_scratch,WORD32 * scratch_used)361 static IA_ERRORCODE impd_drc_phase_align_cascade_group(
362 const WORD32 cascade_alignment_group_count,
363 ia_drc_cascade_alignment_group_struct *pstr_cascade_alignment_group,
364 ia_drc_filter_cascade_t_domain_struct *pstr_filter_cascade_t_domain, VOID *ptr_scratch,
365 WORD32 *scratch_used) {
366 IA_ERRORCODE err_code = IA_NO_ERROR;
367 LOOPIDX i, j, k;
368 WORD32 cascade_index;
369 ia_drc_allpass_chain_struct *pstr_allpass_chain =
370 (ia_drc_allpass_chain_struct *)((pUWORD8)(ptr_scratch)) + *scratch_used;
371
372 for (i = 0; i < cascade_alignment_group_count; i++) {
373 for (j = 0; j < pstr_cascade_alignment_group[i].member_count; j++) {
374 cascade_index = pstr_cascade_alignment_group[i].member_index[j];
375
376 err_code = impd_drc_derive_allpass_chain(&pstr_filter_cascade_t_domain[cascade_index],
377 &pstr_allpass_chain[j]);
378 if (err_code & IA_FATAL_ERROR) {
379 return err_code;
380 }
381 pstr_allpass_chain[j].matches_cascade_index = cascade_index;
382 }
383 for (j = 0; j < pstr_cascade_alignment_group[i].member_count; j++) {
384 cascade_index = pstr_cascade_alignment_group[i].member_index[j];
385 for (k = 0; k < pstr_cascade_alignment_group[i].member_count; k++) {
386 if (cascade_index != pstr_allpass_chain[k].matches_cascade_index) {
387 impd_drc_add_allpass_filter_chain(&pstr_allpass_chain[k],
388 &pstr_filter_cascade_t_domain[cascade_index]);
389 }
390 }
391 }
392 }
393
394 return err_code;
395 }
396
impd_drc_derive_matching_phase_filter_params(const WORD32 config,FLOAT32 radius,FLOAT32 angle,ia_drc_phase_alignment_filter_struct * pstr_phase_alignment_filter)397 static VOID impd_drc_derive_matching_phase_filter_params(
398 const WORD32 config, FLOAT32 radius, FLOAT32 angle,
399 ia_drc_phase_alignment_filter_struct *pstr_phase_alignment_filter) {
400 LOOPIDX idx;
401 WORD32 section = pstr_phase_alignment_filter->section_count;
402 FLOAT32 z_real, z_imag, product;
403 ia_drc_filter_section_struct *pstr_filter_section =
404 &pstr_phase_alignment_filter->str_filter_section[section];
405
406 switch (config) {
407 case CONFIG_COMPLEX_POLE:
408 z_real = (FLOAT32)(radius * cos((FLOAT32)M_PI * angle));
409 z_imag = (FLOAT32)(radius * sin((FLOAT32)M_PI * angle));
410 product = z_real * z_real + z_imag * z_imag;
411 pstr_phase_alignment_filter->gain *= product;
412 pstr_filter_section->var_a1 = -2.0f * z_real;
413 pstr_filter_section->var_a2 = product;
414 pstr_filter_section->var_b1 = -2.0f * z_real / product;
415 pstr_filter_section->var_b2 = 1.0f / product;
416 pstr_phase_alignment_filter->section_count++;
417 break;
418 case CONFIG_REAL_POLE:
419 pstr_phase_alignment_filter->gain *= (-radius);
420 pstr_filter_section->var_a1 = -radius;
421 pstr_filter_section->var_a2 = 0.0f;
422 pstr_filter_section->var_b1 = -1.0f / radius;
423 pstr_filter_section->var_b2 = 0.0f;
424 pstr_phase_alignment_filter->section_count++;
425 break;
426 default:
427 break;
428 }
429 for (idx = 0; idx < MAX_EQ_CHANNEL_COUNT; idx++) {
430 pstr_filter_section->str_filter_section_state[idx].state_in_1 = 0.0f;
431 pstr_filter_section->str_filter_section_state[idx].state_out_1 = 0.0f;
432 pstr_filter_section->str_filter_section_state[idx].state_in_2 = 0.0f;
433 pstr_filter_section->str_filter_section_state[idx].state_out_2 = 0.0f;
434 }
435 }
436
impd_drc_derive_matching_phase_filter_delay(ia_drc_unique_td_filter_element_struct * pstr_filter_element,ia_drc_phase_alignment_filter_struct * pstr_phase_alignment_filter)437 static VOID impd_drc_derive_matching_phase_filter_delay(
438 ia_drc_unique_td_filter_element_struct *pstr_filter_element,
439 ia_drc_phase_alignment_filter_struct *pstr_phase_alignment_filter) {
440 LOOPIDX i, j;
441 WORD32 delay = 0;
442
443 if (pstr_filter_element->eq_filter_format == FILTER_ELEMENT_FORMAT_POLE_ZERO) {
444 if (pstr_filter_element->real_zero_radius_one_count == 0) {
445 delay = pstr_filter_element->real_zero_count + 2 * pstr_filter_element->generic_zero_count -
446 pstr_filter_element->real_pole_count - 2 * pstr_filter_element->complex_pole_count;
447 delay = MAX(0, delay);
448 pstr_phase_alignment_filter->is_valid = 1;
449 }
450 }
451
452 pstr_phase_alignment_filter->str_audio_delay.delay = delay;
453 for (i = 0; i < MAX_EQ_CHANNEL_COUNT; i++) {
454 for (j = 0; j < delay; j++) {
455 pstr_phase_alignment_filter->str_audio_delay.state[i][j] = 0.0f;
456 }
457 }
458 }
459
impd_drc_derive_matching_phase_filter(ia_drc_unique_td_filter_element_struct * pstr_filter_element,WORD32 filter_element_index,ia_drc_matching_phase_filter_struct * pstr_matching_phase_filter)460 static VOID impd_drc_derive_matching_phase_filter(
461 ia_drc_unique_td_filter_element_struct *pstr_filter_element, WORD32 filter_element_index,
462 ia_drc_matching_phase_filter_struct *pstr_matching_phase_filter) {
463 LOOPIDX idx;
464
465 memset(pstr_matching_phase_filter, 0, sizeof(ia_drc_matching_phase_filter_struct));
466 pstr_matching_phase_filter->gain = 1.0f;
467
468 if (pstr_filter_element->eq_filter_format == FILTER_ELEMENT_FORMAT_POLE_ZERO) {
469 for (idx = 0; idx < pstr_filter_element->real_pole_count; idx++) {
470 impd_drc_derive_matching_phase_filter_params(CONFIG_REAL_POLE,
471 pstr_filter_element->real_pole_radius[idx],
472 0.0f, pstr_matching_phase_filter);
473 }
474 for (idx = 0; idx < pstr_filter_element->complex_pole_count; idx++) {
475 impd_drc_derive_matching_phase_filter_params(
476 CONFIG_COMPLEX_POLE, pstr_filter_element->complex_pole_radius[idx],
477 pstr_filter_element->complex_pole_angle[idx], pstr_matching_phase_filter);
478 }
479 }
480 impd_drc_derive_matching_phase_filter_delay(pstr_filter_element, pstr_matching_phase_filter);
481
482 pstr_matching_phase_filter->matches_filter_count = 1;
483 pstr_matching_phase_filter->matches_filter[0] = filter_element_index;
484 }
485
impd_drc_check_phase_filter_is_equal(ia_drc_matching_phase_filter_struct * pstr_matching_phase_filter_1,ia_drc_matching_phase_filter_struct * pstr_matching_phase_filter_2,WORD32 * is_equal)486 static VOID impd_drc_check_phase_filter_is_equal(
487 ia_drc_matching_phase_filter_struct *pstr_matching_phase_filter_1,
488 ia_drc_matching_phase_filter_struct *pstr_matching_phase_filter_2, WORD32 *is_equal) {
489 LOOPIDX idx;
490
491 *is_equal = 1;
492 if (pstr_matching_phase_filter_1->section_count ==
493 pstr_matching_phase_filter_2->section_count) {
494 for (idx = 0; idx < pstr_matching_phase_filter_1->section_count; idx++) {
495 if ((pstr_matching_phase_filter_1->str_filter_section[idx].var_a1 !=
496 pstr_matching_phase_filter_2->str_filter_section[idx].var_a1) ||
497 (pstr_matching_phase_filter_1->str_filter_section[idx].var_a2 !=
498 pstr_matching_phase_filter_2->str_filter_section[idx].var_a2) ||
499 (pstr_matching_phase_filter_1->str_filter_section[idx].var_b1 !=
500 pstr_matching_phase_filter_2->str_filter_section[idx].var_b1) ||
501 (pstr_matching_phase_filter_1->str_filter_section[idx].var_b2 !=
502 pstr_matching_phase_filter_2->str_filter_section[idx].var_b2)) {
503 *is_equal = 0;
504 break;
505 }
506 }
507 } else {
508 *is_equal = 0;
509 }
510
511 if (pstr_matching_phase_filter_1->str_audio_delay.delay !=
512 pstr_matching_phase_filter_2->str_audio_delay.delay) {
513 *is_equal = 0;
514 }
515 }
516
impd_drc_add_phase_alignment_filter(ia_drc_matching_phase_filter_struct * pstr_matching_phase_filter,ia_drc_eq_filter_element_struct * pstr_eq_filter_element)517 static IA_ERRORCODE impd_drc_add_phase_alignment_filter(
518 ia_drc_matching_phase_filter_struct *pstr_matching_phase_filter,
519 ia_drc_eq_filter_element_struct *pstr_eq_filter_element) {
520 if (pstr_matching_phase_filter->is_valid != 1) {
521 return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
522 } else {
523 pstr_eq_filter_element
524 ->str_phase_alignment_filter[pstr_eq_filter_element->phase_alignment_filter_count] =
525 *pstr_matching_phase_filter;
526 pstr_eq_filter_element->phase_alignment_filter_count++;
527 }
528
529 return IA_NO_ERROR;
530 }
531
impd_drc_derive_element_phase_alignment_filters(ia_drc_matching_phase_filter_struct * pstr_matching_phase_filter,ia_drc_eq_filter_block_struct * pstr_eq_filter_block,VOID * ptr_scratch,WORD32 * scratch_used)532 static IA_ERRORCODE impd_drc_derive_element_phase_alignment_filters(
533 ia_drc_matching_phase_filter_struct *pstr_matching_phase_filter,
534 ia_drc_eq_filter_block_struct *pstr_eq_filter_block, VOID *ptr_scratch,
535 WORD32 *scratch_used) {
536 IA_ERRORCODE err_code = IA_NO_ERROR;
537 LOOPIDX i, j, k;
538 WORD32 skip, is_equal;
539 WORD32 optimized_phase_filter_count;
540 WORD32 path_delay_min, path_delay, path_delay_new, path_delay_to_remove;
541
542 ia_drc_matching_phase_filter_struct *pstr_matching_phase_filter_opt =
543 (ia_drc_matching_phase_filter_struct *)((pUWORD8)ptr_scratch) + *scratch_used;
544 ia_drc_eq_filter_element_struct *pstr_eq_filter_element;
545
546 optimized_phase_filter_count = 0;
547 for (i = 0; i < pstr_eq_filter_block->element_count; i++) {
548 is_equal = 0;
549 for (j = 0; j < optimized_phase_filter_count; j++) {
550 impd_drc_check_phase_filter_is_equal(&pstr_matching_phase_filter[i],
551 &pstr_matching_phase_filter_opt[j], &is_equal);
552 if (is_equal == 1) {
553 break;
554 }
555 }
556 if (is_equal != 1) {
557 pstr_matching_phase_filter_opt[optimized_phase_filter_count] =
558 pstr_matching_phase_filter[i];
559 optimized_phase_filter_count++;
560 } else {
561 pstr_matching_phase_filter_opt[j]
562 .matches_filter[pstr_matching_phase_filter_opt[j].matches_filter_count] = i;
563 pstr_matching_phase_filter_opt[j].matches_filter_count++;
564 }
565 }
566
567 for (i = 0; i < pstr_eq_filter_block->element_count; i++) {
568 for (j = 0; j < optimized_phase_filter_count; j++) {
569 skip = 0;
570 for (k = 0; k < pstr_matching_phase_filter_opt[j].matches_filter_count; k++) {
571 if (pstr_matching_phase_filter_opt[j].matches_filter[k] == i) {
572 skip = 1;
573 break;
574 }
575 }
576 if (skip == 0) {
577 err_code = impd_drc_add_phase_alignment_filter(
578 &pstr_matching_phase_filter_opt[j], &pstr_eq_filter_block->str_eq_filter_element[i]);
579 if (err_code & IA_FATAL_ERROR) {
580 return err_code;
581 }
582 }
583 }
584 }
585
586 path_delay_min = 100000;
587 for (i = 0; i < pstr_eq_filter_block->element_count; i++) {
588 pstr_eq_filter_element = &pstr_eq_filter_block->str_eq_filter_element[i];
589 path_delay = 0;
590 for (k = 0; k < pstr_eq_filter_element->phase_alignment_filter_count; k++) {
591 path_delay += pstr_eq_filter_element->str_phase_alignment_filter[k].str_audio_delay.delay;
592 }
593 if (path_delay_min > path_delay) {
594 path_delay_min = path_delay;
595 }
596 }
597 if (path_delay_min > 0) {
598 for (i = 0; i < pstr_eq_filter_block->element_count; i++) {
599 pstr_eq_filter_element = &pstr_eq_filter_block->str_eq_filter_element[i];
600 path_delay_to_remove = path_delay_min;
601 for (k = 0; k < pstr_eq_filter_element->phase_alignment_filter_count; k++) {
602 path_delay = pstr_eq_filter_element->str_phase_alignment_filter[k].str_audio_delay.delay;
603 path_delay_new = MAX(0, path_delay - path_delay_to_remove);
604 path_delay_to_remove -= path_delay - path_delay_new;
605 pstr_eq_filter_element->str_phase_alignment_filter[k].str_audio_delay.delay =
606 path_delay_new;
607 }
608 }
609 }
610
611 return err_code;
612 }
613
impd_drc_convert_pole_zero_to_filter_params(const WORD32 config,FLOAT32 radius,FLOAT32 angle,WORD32 * filter_param_count,ia_drc_second_order_filter_params_struct * pstr_second_order_filter_params)614 static IA_ERRORCODE impd_drc_convert_pole_zero_to_filter_params(
615 const WORD32 config, FLOAT32 radius, FLOAT32 angle, WORD32 *filter_param_count,
616 ia_drc_second_order_filter_params_struct *pstr_second_order_filter_params) {
617 FLOAT32 z_real, angle_1, angle_2;
618 FLOAT32 *ptr_coeff;
619
620 switch (config) {
621 case CONFIG_REAL_POLE: {
622 pstr_second_order_filter_params[0].radius = radius;
623 ptr_coeff = pstr_second_order_filter_params[0].coeff;
624 ptr_coeff[0] = -2.0f * radius;
625 ptr_coeff[1] = radius * radius;
626 *filter_param_count = 1;
627 } break;
628 case CONFIG_COMPLEX_POLE: {
629 z_real = (FLOAT32)(radius * cos((FLOAT32)M_PI * angle));
630 pstr_second_order_filter_params[0].radius = radius;
631 ptr_coeff = pstr_second_order_filter_params[0].coeff;
632 ptr_coeff[0] = -2.0f * z_real;
633 ptr_coeff[1] = radius * radius;
634 pstr_second_order_filter_params[1].radius = radius;
635 pstr_second_order_filter_params[1].coeff[0] = ptr_coeff[0];
636 pstr_second_order_filter_params[1].coeff[1] = ptr_coeff[1];
637 *filter_param_count = 2;
638 } break;
639 case CONFIG_REAL_ZERO_RADIUS_ONE: {
640 angle_1 = radius;
641 angle_2 = angle;
642 pstr_second_order_filter_params[0].radius = 1.0f;
643 ptr_coeff = pstr_second_order_filter_params[0].coeff;
644
645 if (angle_1 != angle_2) {
646 ptr_coeff[0] = 0.0f;
647 ptr_coeff[1] = -1.0f;
648 } else if (angle_1 == 1.0f) {
649 ptr_coeff[0] = -2.0f;
650 ptr_coeff[1] = 1.0f;
651 } else {
652 ptr_coeff[0] = 2.0f;
653 ptr_coeff[1] = 1.0f;
654 }
655 *filter_param_count = 1;
656 } break;
657 case CONFIG_REAL_ZERO: {
658 pstr_second_order_filter_params[0].radius = radius;
659 if (fabs(radius) == 1.0f) {
660 return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
661 } else {
662 ptr_coeff = pstr_second_order_filter_params[0].coeff;
663 ptr_coeff[0] = -(radius + 1.0f / radius);
664 ptr_coeff[1] = 1.0f;
665 }
666 *filter_param_count = 1;
667 } break;
668 case CONFIG_GENERIC_ZERO: {
669 z_real = (FLOAT32)(radius * cos((FLOAT32)M_PI * angle));
670 pstr_second_order_filter_params[0].radius = radius;
671 ptr_coeff = pstr_second_order_filter_params[0].coeff;
672 ptr_coeff[0] = -2.0f * z_real;
673 ptr_coeff[1] = (FLOAT32)(radius * radius);
674 z_real = (FLOAT32)(cos((FLOAT32)M_PI * angle) / radius);
675 pstr_second_order_filter_params[1].radius = radius;
676 ptr_coeff = pstr_second_order_filter_params[1].coeff;
677 ptr_coeff[0] = -2.0f * z_real;
678 ptr_coeff[1] = 1.0f / (radius * radius);
679 *filter_param_count = 2;
680 } break;
681 default:
682 break;
683 }
684
685 return IA_NO_ERROR;
686 }
687
impd_drc_convert_fir_filter_params(const WORD32 fir_filter_order,const WORD32 fir_symmetry,FLOAT32 * fir_coefficient,ia_drc_fir_filter_struct * pstr_fir_filter)688 static VOID impd_drc_convert_fir_filter_params(const WORD32 fir_filter_order,
689 const WORD32 fir_symmetry,
690 FLOAT32 *fir_coefficient,
691 ia_drc_fir_filter_struct *pstr_fir_filter) {
692 LOOPIDX i, j;
693 FLOAT32 *ptr_coeff = pstr_fir_filter->coeff;
694
695 pstr_fir_filter->coeff_count = fir_filter_order + 1;
696 for (i = 0; i < (fir_filter_order / 2 + 1); i++) {
697 ptr_coeff[i] = fir_coefficient[i];
698 }
699 for (i = 0; i < (fir_filter_order + 1) / 2; i++) {
700 if (fir_symmetry != 1) {
701 ptr_coeff[fir_filter_order - i] = ptr_coeff[i];
702 } else {
703 ptr_coeff[fir_filter_order - i] = -ptr_coeff[i];
704 }
705 }
706 if ((fir_symmetry == 1) && ((fir_filter_order & 1) == 0)) {
707 ptr_coeff[fir_filter_order / 2] = 0.0f;
708 }
709 for (i = 0; i < MAX_EQ_CHANNEL_COUNT; i++) {
710 for (j = 0; j < (fir_filter_order + 1); j++) {
711 pstr_fir_filter->state[i][j] = 0.0f;
712 }
713 }
714 }
715
impd_drc_derive_pole_zero_filter_params(ia_drc_unique_td_filter_element_struct * pstr_filter_element,ia_drc_intermediate_filter_params_struct * pstr_intermediate_filter_params)716 static IA_ERRORCODE impd_drc_derive_pole_zero_filter_params(
717 ia_drc_unique_td_filter_element_struct *pstr_filter_element,
718 ia_drc_intermediate_filter_params_struct *pstr_intermediate_filter_params) {
719 IA_ERRORCODE err_code = IA_NO_ERROR;
720 LOOPIDX idx;
721 WORD32 param_index, filter_param_count;
722 ia_drc_second_order_filter_params_struct *pstr_second_order_filter_params_for_zeros;
723 ia_drc_second_order_filter_params_struct *pstr_second_order_filter_params_for_poles;
724
725 pstr_intermediate_filter_params->filter_format = pstr_filter_element->eq_filter_format;
726 if (pstr_filter_element->eq_filter_format != FILTER_ELEMENT_FORMAT_POLE_ZERO) {
727 pstr_intermediate_filter_params->filter_param_count_for_zeros = 0;
728 pstr_intermediate_filter_params->filter_param_count_for_poles = 0;
729
730 impd_drc_convert_fir_filter_params(
731 pstr_filter_element->fir_filter_order, pstr_filter_element->fir_symmetry,
732 pstr_filter_element->fir_coefficient, &pstr_intermediate_filter_params->str_fir_filter);
733 } else {
734 pstr_second_order_filter_params_for_zeros =
735 pstr_intermediate_filter_params->str_second_order_filter_params_for_zeros;
736 pstr_second_order_filter_params_for_poles =
737 pstr_intermediate_filter_params->str_second_order_filter_params_for_poles;
738
739 param_index = 0;
740 for (idx = 0; idx < pstr_filter_element->real_zero_radius_one_count; idx += 2) {
741 err_code = impd_drc_convert_pole_zero_to_filter_params(
742 CONFIG_REAL_ZERO_RADIUS_ONE, pstr_filter_element->zero_sign[idx],
743 pstr_filter_element->zero_sign[idx + 1], &filter_param_count,
744 &(pstr_second_order_filter_params_for_zeros[param_index]));
745 if (err_code & IA_FATAL_ERROR) {
746 return err_code;
747 }
748 param_index += filter_param_count;
749 }
750 for (idx = 0; idx < pstr_filter_element->real_zero_count; idx++) {
751 err_code = impd_drc_convert_pole_zero_to_filter_params(
752 CONFIG_REAL_ZERO, pstr_filter_element->real_zero_radius[idx], 0.0f, &filter_param_count,
753 &(pstr_second_order_filter_params_for_zeros[param_index]));
754 if (err_code & IA_FATAL_ERROR) {
755 return err_code;
756 }
757 param_index += filter_param_count;
758 }
759 for (idx = 0; idx < pstr_filter_element->generic_zero_count; idx++) {
760 err_code = impd_drc_convert_pole_zero_to_filter_params(
761 CONFIG_GENERIC_ZERO, pstr_filter_element->generic_zero_radius[idx],
762 pstr_filter_element->generic_zero_angle[idx], &filter_param_count,
763 &(pstr_second_order_filter_params_for_zeros[param_index]));
764 if (err_code & IA_FATAL_ERROR) {
765 return err_code;
766 }
767 param_index += filter_param_count;
768 }
769 pstr_intermediate_filter_params->filter_param_count_for_zeros = param_index;
770
771 param_index = 0;
772 for (idx = 0; idx < pstr_filter_element->real_pole_count; idx++) {
773 err_code = impd_drc_convert_pole_zero_to_filter_params(
774 CONFIG_REAL_POLE, pstr_filter_element->real_pole_radius[idx], 0.0f, &filter_param_count,
775 &(pstr_second_order_filter_params_for_poles[param_index]));
776 if (err_code & IA_FATAL_ERROR) {
777 return err_code;
778 }
779 param_index += filter_param_count;
780 }
781 for (idx = 0; idx < pstr_filter_element->complex_pole_count; idx++) {
782 err_code = impd_drc_convert_pole_zero_to_filter_params(
783 CONFIG_COMPLEX_POLE, pstr_filter_element->complex_pole_radius[idx],
784 pstr_filter_element->complex_pole_angle[idx], &filter_param_count,
785 &(pstr_second_order_filter_params_for_poles[param_index]));
786 if (err_code & IA_FATAL_ERROR) {
787 return err_code;
788 }
789 param_index += filter_param_count;
790 }
791 pstr_intermediate_filter_params->filter_param_count_for_poles = param_index;
792 }
793
794 return err_code;
795 }
796
impd_drc_derive_eq_filter_elements(ia_drc_intermediate_filter_params_struct * pstr_intermediate_filter_params,ia_drc_eq_filter_element_struct * pstr_eq_filter_element,pUWORD8 ptr_scratch)797 static VOID impd_drc_derive_eq_filter_elements(
798 ia_drc_intermediate_filter_params_struct *pstr_intermediate_filter_params,
799 ia_drc_eq_filter_element_struct *pstr_eq_filter_element, pUWORD8 ptr_scratch) {
800 LOOPIDX idx, ch_idx;
801 WORD32 poles_index, zeros_index, pole_order = 0, section;
802 WORD32 coeff_count, coeff_idx;
803 WORD32 *ptr_poles_done = (WORD32 *)ptr_scratch;
804 WORD32 *ptr_zeros_done =
805 (WORD32 *)(ptr_scratch +
806 ((REAL_POLE_COUNT_MAX + COMPLEX_POLE_COUNT_MAX) * sizeof(ptr_poles_done[0])));
807 FLOAT32 radius_max, radius_diff;
808 FLOAT32 temp_b1, temp_b2;
809 FLOAT32 *ptr_coeff;
810
811 for (idx = 0; idx < (REAL_ZERO_COUNT_MAX + COMPLEX_ZERO_COUNT_MAX); idx++) {
812 ptr_zeros_done[idx] = 0;
813 }
814 for (idx = 0; idx < (REAL_POLE_COUNT_MAX + COMPLEX_POLE_COUNT_MAX); idx++) {
815 ptr_poles_done[idx] = 0;
816 }
817 section = 0;
818 do {
819 poles_index = -1;
820 radius_max = -1.0;
821 for (idx = 0; idx < pstr_intermediate_filter_params->filter_param_count_for_poles; idx++) {
822 if ((ptr_poles_done[idx] == 0) && (pstr_intermediate_filter_params->filter_format == 0)) {
823 if (radius_max <
824 fabs(pstr_intermediate_filter_params->str_second_order_filter_params_for_poles[idx]
825 .radius)) {
826 radius_max = (FLOAT32)fabs(
827 pstr_intermediate_filter_params->str_second_order_filter_params_for_poles[idx]
828 .radius);
829 poles_index = idx;
830 if (pstr_intermediate_filter_params->str_second_order_filter_params_for_poles[idx]
831 .coeff[1] == 0.0f) {
832 pole_order = 1;
833 } else {
834 pole_order = 2;
835 }
836 }
837 }
838 }
839
840 if (poles_index >= 0) {
841 radius_diff = 10.0f;
842 zeros_index = -1;
843 for (idx = 0; idx < pstr_intermediate_filter_params->filter_param_count_for_zeros; idx++) {
844 if (ptr_zeros_done[idx] == 0 && pstr_intermediate_filter_params->filter_format == 0) {
845 if (pole_order == 2) {
846 if (pstr_intermediate_filter_params->str_second_order_filter_params_for_zeros[idx]
847 .coeff[1] != 0.0f) {
848 if (radius_diff > fabs(fabs(pstr_intermediate_filter_params
849 ->str_second_order_filter_params_for_zeros[idx]
850 .radius) -
851 radius_max)) {
852 radius_diff =
853 (FLOAT32)fabs(fabs(pstr_intermediate_filter_params
854 ->str_second_order_filter_params_for_zeros[idx]
855 .radius) -
856 radius_max);
857 zeros_index = idx;
858 }
859 }
860 } else {
861 if (pstr_intermediate_filter_params->str_second_order_filter_params_for_zeros[idx]
862 .coeff[1] == 0.0f) {
863 if (radius_diff > fabs(fabs(pstr_intermediate_filter_params
864 ->str_second_order_filter_params_for_zeros[idx]
865 .radius) -
866 radius_max)) {
867 radius_diff =
868 (FLOAT32)fabs(fabs(pstr_intermediate_filter_params
869 ->str_second_order_filter_params_for_zeros[idx]
870 .radius) -
871 radius_max);
872 zeros_index = idx;
873 }
874 }
875 }
876 }
877 }
878
879 if (zeros_index == -1) {
880 for (idx = 0; idx < pstr_intermediate_filter_params->filter_param_count_for_zeros;
881 idx++) {
882 if (ptr_zeros_done[idx] == 0 && pstr_intermediate_filter_params->filter_format == 0) {
883 if (pole_order == 2) {
884 if (pstr_intermediate_filter_params->str_second_order_filter_params_for_zeros[idx]
885 .coeff[1] == 0.0f) {
886 if (radius_diff > fabs(fabs(pstr_intermediate_filter_params
887 ->str_second_order_filter_params_for_zeros[idx]
888 .radius) -
889 radius_max)) {
890 radius_diff =
891 (FLOAT32)fabs(fabs(pstr_intermediate_filter_params
892 ->str_second_order_filter_params_for_zeros[idx]
893 .radius) -
894 radius_max);
895 zeros_index = idx;
896 }
897 }
898 } else {
899 if (pstr_intermediate_filter_params->str_second_order_filter_params_for_zeros[idx]
900 .coeff[1] != 0.0f) {
901 if (radius_diff > fabs(fabs(pstr_intermediate_filter_params
902 ->str_second_order_filter_params_for_zeros[idx]
903 .radius) -
904 radius_max)) {
905 radius_diff =
906 (FLOAT32)fabs(fabs(pstr_intermediate_filter_params
907 ->str_second_order_filter_params_for_zeros[idx]
908 .radius) -
909 radius_max);
910 zeros_index = idx;
911 }
912 }
913 }
914 }
915 }
916 }
917 pstr_eq_filter_element->str_pole_zero_filter.str_filter_section[section].var_a1 =
918 pstr_intermediate_filter_params->str_second_order_filter_params_for_poles[poles_index]
919 .coeff[0];
920 pstr_eq_filter_element->str_pole_zero_filter.str_filter_section[section].var_a2 =
921 pstr_intermediate_filter_params->str_second_order_filter_params_for_poles[poles_index]
922 .coeff[1];
923 if (zeros_index < 0) {
924 pstr_eq_filter_element->str_pole_zero_filter.str_filter_section[section].var_b1 = 0.0f;
925 pstr_eq_filter_element->str_pole_zero_filter.str_filter_section[section].var_b2 = 0.0f;
926 pstr_eq_filter_element->str_pole_zero_filter.str_audio_delay.delay++;
927 } else {
928 pstr_eq_filter_element->str_pole_zero_filter.str_filter_section[section].var_b1 =
929 pstr_intermediate_filter_params->str_second_order_filter_params_for_zeros[zeros_index]
930 .coeff[0];
931 pstr_eq_filter_element->str_pole_zero_filter.str_filter_section[section].var_b2 =
932 pstr_intermediate_filter_params->str_second_order_filter_params_for_zeros[zeros_index]
933 .coeff[1];
934 }
935 for (ch_idx = 0; ch_idx < MAX_EQ_CHANNEL_COUNT; ch_idx++) {
936 pstr_eq_filter_element->str_pole_zero_filter.str_filter_section[section]
937 .str_filter_section_state[ch_idx]
938 .state_in_1 = 0.0f;
939 pstr_eq_filter_element->str_pole_zero_filter.str_filter_section[section]
940 .str_filter_section_state[ch_idx]
941 .state_in_2 = 0.0f;
942 pstr_eq_filter_element->str_pole_zero_filter.str_filter_section[section]
943 .str_filter_section_state[ch_idx]
944 .state_out_1 = 0.0f;
945 pstr_eq_filter_element->str_pole_zero_filter.str_filter_section[section]
946 .str_filter_section_state[ch_idx]
947 .state_out_2 = 0.0f;
948 }
949 if (zeros_index >= 0) {
950 ptr_zeros_done[zeros_index] = 1;
951 }
952 if (poles_index >= 0) {
953 ptr_poles_done[poles_index] = 1;
954 }
955 section++;
956 }
957 } while (poles_index >= 0);
958
959 pstr_eq_filter_element->str_pole_zero_filter.section_count = section;
960
961 coeff_count = 1;
962 ptr_coeff = pstr_eq_filter_element->str_pole_zero_filter.str_fir_filter.coeff;
963 ptr_coeff[0] = 1.0f;
964 for (idx = 0; idx < pstr_intermediate_filter_params->filter_param_count_for_zeros; idx++) {
965 if (ptr_zeros_done[idx] == 0 && pstr_intermediate_filter_params->filter_format == 0) {
966 temp_b1 =
967 pstr_intermediate_filter_params->str_second_order_filter_params_for_zeros[idx].coeff[0];
968 temp_b2 =
969 pstr_intermediate_filter_params->str_second_order_filter_params_for_zeros[idx].coeff[1];
970
971 coeff_count += 2;
972 coeff_idx = coeff_count - 1;
973 ptr_coeff[coeff_idx] = temp_b2 * ptr_coeff[coeff_idx - 2];
974 coeff_idx--;
975 if (coeff_idx > 1) {
976 ptr_coeff[coeff_idx] =
977 temp_b1 * ptr_coeff[coeff_idx - 1] + temp_b2 * ptr_coeff[coeff_idx - 2];
978 coeff_idx--;
979 for (; coeff_idx > 1; coeff_idx--) {
980 ptr_coeff[coeff_idx] +=
981 temp_b1 * ptr_coeff[coeff_idx - 1] + temp_b2 * ptr_coeff[coeff_idx - 2];
982 }
983 ptr_coeff[1] += temp_b1 * ptr_coeff[0];
984 } else {
985 ptr_coeff[1] = temp_b1 * ptr_coeff[0];
986 }
987 }
988 ptr_zeros_done[idx] = 1;
989 }
990 if (coeff_count > 1) {
991 pstr_eq_filter_element->str_pole_zero_filter.fir_coeffs_present = 1;
992 pstr_eq_filter_element->str_pole_zero_filter.str_fir_filter.coeff_count = coeff_count;
993 } else {
994 pstr_eq_filter_element->str_pole_zero_filter.fir_coeffs_present = 0;
995 pstr_eq_filter_element->str_pole_zero_filter.str_fir_filter.coeff_count = 0;
996 }
997 }
998
impd_drc_derive_filter_block(ia_drc_unique_td_filter_element_struct * pstr_unique_td_filter_element,ia_drc_filter_block_struct * pstr_filter_block,ia_drc_eq_filter_block_struct * pstr_eq_filter_block,VOID * ptr_scratch,WORD32 * scratch_used)999 static IA_ERRORCODE impd_drc_derive_filter_block(
1000 ia_drc_unique_td_filter_element_struct *pstr_unique_td_filter_element,
1001 ia_drc_filter_block_struct *pstr_filter_block,
1002 ia_drc_eq_filter_block_struct *pstr_eq_filter_block, VOID *ptr_scratch,
1003 WORD32 *scratch_used) {
1004 IA_ERRORCODE err_code = IA_NO_ERROR;
1005 LOOPIDX i, j;
1006 WORD32 filter_index;
1007 WORD32 temp_scratch_used = *scratch_used;
1008 ia_drc_intermediate_filter_params_struct str_intermediate_filter_params;
1009 ia_drc_eq_filter_element_struct *pstr_eq_filter_element;
1010 ia_drc_filter_element_struct *pstr_filter_element;
1011 ia_drc_matching_phase_filter_struct *pstr_matching_phase_filter =
1012 (ia_drc_matching_phase_filter_struct *)((pUWORD8)(ptr_scratch)) + temp_scratch_used;
1013
1014 temp_scratch_used += sizeof(ia_drc_matching_phase_filter_struct) * FILTER_ELEMENT_COUNT_MAX;
1015
1016 for (i = 0; i < pstr_filter_block->filter_element_count; i++) {
1017 if ((pstr_unique_td_filter_element[pstr_filter_block->filter_element[i].filter_element_index]
1018 .eq_filter_format == FILTER_ELEMENT_FORMAT_FIR) &&
1019 (pstr_filter_block->filter_element_count > 1)) {
1020 return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
1021 }
1022 }
1023 for (i = 0; i < pstr_filter_block->filter_element_count; i++) {
1024 pstr_filter_element = &pstr_filter_block->filter_element[i];
1025 filter_index = pstr_filter_element->filter_element_index;
1026 pstr_eq_filter_element = &pstr_eq_filter_block->str_eq_filter_element[i];
1027
1028 if (pstr_unique_td_filter_element[filter_index].eq_filter_format ==
1029 FILTER_ELEMENT_FORMAT_POLE_ZERO) {
1030 err_code = impd_drc_derive_pole_zero_filter_params(
1031 &(pstr_unique_td_filter_element[filter_index]), &str_intermediate_filter_params);
1032 if (err_code & IA_FATAL_ERROR) {
1033 return err_code;
1034 }
1035
1036 impd_drc_derive_eq_filter_elements(&str_intermediate_filter_params, pstr_eq_filter_element,
1037 (pUWORD8)(ptr_scratch) + temp_scratch_used);
1038 pstr_eq_filter_element->format = FILTER_ELEMENT_FORMAT_POLE_ZERO;
1039 } else {
1040 impd_drc_convert_fir_filter_params(
1041 pstr_unique_td_filter_element[filter_index].fir_filter_order,
1042 pstr_unique_td_filter_element[filter_index].fir_symmetry,
1043 pstr_unique_td_filter_element[filter_index].fir_coefficient,
1044 &pstr_eq_filter_element->str_fir_filter);
1045 pstr_eq_filter_element->format = FILTER_ELEMENT_FORMAT_FIR;
1046 }
1047 if (pstr_filter_element->filter_element_gain_present != 1) {
1048 pstr_eq_filter_element->element_gain_linear = 1.0f;
1049 } else {
1050 pstr_eq_filter_element->element_gain_linear =
1051 (FLOAT32)pow(10.0f, 0.05f * pstr_filter_element->filter_element_gain);
1052 }
1053 for (j = 0; j < pstr_unique_td_filter_element[filter_index].real_zero_count; j++) {
1054 if (pstr_unique_td_filter_element[filter_index].real_zero_radius[j] > 0.0f) {
1055 pstr_eq_filter_element->element_gain_linear =
1056 -pstr_eq_filter_element->element_gain_linear;
1057 }
1058 }
1059 impd_drc_derive_matching_phase_filter(&(pstr_unique_td_filter_element[filter_index]), i,
1060 &pstr_matching_phase_filter[i]);
1061 }
1062 pstr_eq_filter_block->str_matching_phase_filter_element_0 = pstr_matching_phase_filter[0];
1063 pstr_eq_filter_block->element_count = pstr_filter_block->filter_element_count;
1064
1065 err_code = impd_drc_derive_element_phase_alignment_filters(
1066 pstr_matching_phase_filter, pstr_eq_filter_block, ptr_scratch, &temp_scratch_used);
1067 if (err_code & IA_FATAL_ERROR) {
1068 return err_code;
1069 }
1070
1071 return err_code;
1072 }
1073
impd_drc_derive_cascade_phase_alignment_filters(ia_drc_td_filter_cascade_struct * pstr_td_filter_cascade,const WORD32 channel_group_count,ia_drc_filter_cascade_t_domain_struct * pstr_filter_cascade_t_domain,VOID * ptr_scratch,WORD32 * scratch_used)1074 static IA_ERRORCODE impd_drc_derive_cascade_phase_alignment_filters(
1075 ia_drc_td_filter_cascade_struct *pstr_td_filter_cascade, const WORD32 channel_group_count,
1076 ia_drc_filter_cascade_t_domain_struct *pstr_filter_cascade_t_domain, VOID *ptr_scratch,
1077 WORD32 *scratch_used) {
1078 IA_ERRORCODE err_code = IA_NO_ERROR;
1079 WORD32 cascade_alignment_group_count = 0;
1080 ia_drc_cascade_alignment_group_struct *pstr_cascade_alignment_group =
1081 (ia_drc_cascade_alignment_group_struct *)ptr_scratch;
1082 *scratch_used +=
1083 sizeof(ia_drc_cascade_alignment_group_struct) * (EQ_MAX_CHANNEL_GROUP_COUNT / 2);
1084
1085 impd_drc_derive_cascade_alignment_groups(
1086 channel_group_count, pstr_td_filter_cascade->eq_phase_alignment_present,
1087 (const WORD32(*)[EQ_MAX_CHANNEL_GROUP_COUNT])pstr_td_filter_cascade->eq_phase_alignment,
1088 &cascade_alignment_group_count, pstr_cascade_alignment_group);
1089
1090 if (cascade_alignment_group_count > 0) {
1091 err_code = impd_drc_phase_align_cascade_group(
1092 cascade_alignment_group_count, pstr_cascade_alignment_group, pstr_filter_cascade_t_domain,
1093 ptr_scratch, scratch_used);
1094 if (err_code & IA_FATAL_ERROR) {
1095 return err_code;
1096 }
1097 }
1098
1099 return err_code;
1100 }
1101
impd_drc_derive_filter_cascade(ia_drc_unique_td_filter_element_struct * pstr_unique_td_filter_element,ia_drc_filter_block_struct * pstr_filter_block,ia_drc_td_filter_cascade_struct * pstr_td_filter_cascade,WORD32 channel_group_count,ia_drc_filter_cascade_t_domain_struct * pstr_filter_cascade_t_domain,VOID * ptr_scratch,WORD32 * scratch_used)1102 static IA_ERRORCODE impd_drc_derive_filter_cascade(
1103 ia_drc_unique_td_filter_element_struct *pstr_unique_td_filter_element,
1104 ia_drc_filter_block_struct *pstr_filter_block,
1105 ia_drc_td_filter_cascade_struct *pstr_td_filter_cascade, WORD32 channel_group_count,
1106 ia_drc_filter_cascade_t_domain_struct *pstr_filter_cascade_t_domain, VOID *ptr_scratch,
1107 WORD32 *scratch_used) {
1108 IA_ERRORCODE err_code = IA_NO_ERROR;
1109 LOOPIDX i, j;
1110
1111 for (i = 0; i < channel_group_count; i++) {
1112 for (j = 0; j < pstr_td_filter_cascade->str_filter_block_refs[i].filter_block_count; j++) {
1113 err_code = impd_drc_derive_filter_block(
1114 pstr_unique_td_filter_element,
1115 &(pstr_filter_block[pstr_td_filter_cascade->str_filter_block_refs[i]
1116 .filter_block_index[j]]),
1117 &(pstr_filter_cascade_t_domain[i].str_eq_filter_block[j]), ptr_scratch, scratch_used);
1118 if (err_code & IA_FATAL_ERROR) {
1119 return err_code;
1120 }
1121 }
1122 pstr_filter_cascade_t_domain[i].cascade_gain_linear =
1123 (FLOAT32)pow(10.0f, 0.05f * pstr_td_filter_cascade->eq_cascade_gain[i]);
1124 pstr_filter_cascade_t_domain[i].block_count = j;
1125 }
1126
1127 err_code = impd_drc_derive_cascade_phase_alignment_filters(
1128 pstr_td_filter_cascade, channel_group_count, pstr_filter_cascade_t_domain, ptr_scratch,
1129 scratch_used);
1130 if (err_code & IA_FATAL_ERROR) {
1131 return err_code;
1132 }
1133
1134 return err_code;
1135 }
1136
impd_drc_derive_subband_eq(ia_drc_eq_subband_gain_vector_struct * pstr_eq_subband_gain_vector,const WORD32 eq_subband_gain_count,ia_drc_subband_filter_struct * pstr_subband_filter)1137 static VOID impd_drc_derive_subband_eq(
1138 ia_drc_eq_subband_gain_vector_struct *pstr_eq_subband_gain_vector,
1139 const WORD32 eq_subband_gain_count, ia_drc_subband_filter_struct *pstr_subband_filter) {
1140 LOOPIDX idx;
1141
1142 for (idx = 0; idx < eq_subband_gain_count; idx++) {
1143 pstr_subband_filter->subband_coeff[idx] =
1144 (FLOAT32)pstr_eq_subband_gain_vector->eq_subband_gain[idx];
1145 }
1146 pstr_subband_filter->coeff_count = eq_subband_gain_count;
1147 }
1148
impd_drc_decode_eq_node_freq(const WORD32 eq_node_freq_index)1149 static FLOAT32 impd_drc_decode_eq_node_freq(const WORD32 eq_node_freq_index) {
1150 FLOAT32 eq_node_frequency;
1151
1152 eq_node_frequency =
1153 (FLOAT32)(pow(STEP_RATIO_F_LOW, 1.0f + eq_node_freq_index * STEP_RATIO_COMPUTED));
1154
1155 return eq_node_frequency;
1156 }
1157
impd_drc_warp_freq_delta(const FLOAT32 f_subband,const FLOAT32 node_frequency_0,const WORD32 eq_node_freq_index)1158 static FLOAT32 impd_drc_warp_freq_delta(const FLOAT32 f_subband, const FLOAT32 node_frequency_0,
1159 const WORD32 eq_node_freq_index) {
1160 FLOAT32 wraped_delta_frequency;
1161
1162 wraped_delta_frequency =
1163 (FLOAT32)((log10(f_subband) / log10(node_frequency_0) - 1.0f) / STEP_RATIO_COMPUTED -
1164 (FLOAT32)eq_node_freq_index);
1165
1166 return wraped_delta_frequency;
1167 }
1168
impd_drc_interpolate_eq_gain(const WORD32 band_step,const FLOAT32 eq_gain_0,const FLOAT32 eq_gain_1,const FLOAT32 eq_slope_0,const FLOAT32 eq_slope_1,const FLOAT32 wrap_delta_freq,FLOAT32 * interpolated_gain)1169 static VOID impd_drc_interpolate_eq_gain(const WORD32 band_step, const FLOAT32 eq_gain_0,
1170 const FLOAT32 eq_gain_1, const FLOAT32 eq_slope_0,
1171 const FLOAT32 eq_slope_1, const FLOAT32 wrap_delta_freq,
1172 FLOAT32 *interpolated_gain) {
1173 FLOAT32 k1, k2, val_a, val_b;
1174 FLOAT32 nodes_per_octave_count = 3.128f;
1175 FLOAT32 gain_left = eq_gain_0;
1176 FLOAT32 gain_right = eq_gain_1;
1177 FLOAT32 slope_left = eq_slope_0 / nodes_per_octave_count;
1178 FLOAT32 slope_right = eq_slope_1 / nodes_per_octave_count;
1179 FLOAT32 band_step_inv = (FLOAT32)(1.0 / (FLOAT32)band_step);
1180 FLOAT32 band_step_inv_square = band_step_inv * band_step_inv;
1181
1182 k1 = (gain_right - gain_left) * band_step_inv_square;
1183 k2 = slope_right + slope_left;
1184 val_a = (FLOAT32)(band_step_inv * (band_step_inv * k2 - 2.0 * k1));
1185 val_b = (FLOAT32)(3.0 * k1 - band_step_inv * (k2 + slope_left));
1186
1187 *interpolated_gain =
1188 (((val_a * wrap_delta_freq + val_b) * wrap_delta_freq + slope_left) * wrap_delta_freq) +
1189 gain_left;
1190 }
1191
impd_drc_interpolate_subband_spline(ia_drc_eq_subband_gain_spline_struct * pstr_eq_subband_gain_spline,const WORD32 eq_subband_gain_count,const WORD32 eq_subband_gain_format,const FLOAT32 audio_sample_rate,ia_drc_subband_filter_struct * pstr_subband_filter,VOID * ptr_scratch)1192 static IA_ERRORCODE impd_drc_interpolate_subband_spline(
1193 ia_drc_eq_subband_gain_spline_struct *pstr_eq_subband_gain_spline,
1194 const WORD32 eq_subband_gain_count, const WORD32 eq_subband_gain_format,
1195 const FLOAT32 audio_sample_rate, ia_drc_subband_filter_struct *pstr_subband_filter,
1196 VOID *ptr_scratch) {
1197 IA_ERRORCODE err_code = IA_NO_ERROR;
1198 LOOPIDX i, j;
1199 WORD32 eq_node_freq_index[32] = {0};
1200 WORD32 n_eq_nodes = pstr_eq_subband_gain_spline->n_eq_nodes;
1201 WORD32 eq_node_count_max = 33;
1202 WORD32 eq_node_index_max = eq_node_count_max - 1;
1203 WORD32 *ptr_eq_freq_delta = pstr_eq_subband_gain_spline->eq_freq_delta;
1204 FLOAT32 eq_gain[32] = {0}, eq_node_freq[32] = {0};
1205 FLOAT32 freq_subband, warped_delta_freq, g_eq_subband_db;
1206 FLOAT32 eq_gain_initial = pstr_eq_subband_gain_spline->eq_gain_initial;
1207 FLOAT32 *ptr_subband_center_freq = (FLOAT32 *)ptr_scratch;
1208 FLOAT32 *ptr_eq_slope = pstr_eq_subband_gain_spline->eq_slope;
1209 FLOAT32 *ptr_eq_gain_delta = pstr_eq_subband_gain_spline->eq_gain_delta;
1210 FLOAT32 *ptr_subband_coeff = pstr_subband_filter->subband_coeff;
1211
1212 eq_gain[0] = eq_gain_initial;
1213 eq_node_freq_index[0] = 0;
1214 eq_node_freq[0] = impd_drc_decode_eq_node_freq(eq_node_freq_index[0]);
1215 for (i = 1; i < n_eq_nodes; i++) {
1216 eq_gain[i] = eq_gain[i - 1] + ptr_eq_gain_delta[i];
1217 eq_node_freq_index[i] = eq_node_freq_index[i - 1] + ptr_eq_freq_delta[i];
1218 eq_node_freq[i] = impd_drc_decode_eq_node_freq(eq_node_freq_index[i]);
1219 }
1220 if ((eq_node_freq[n_eq_nodes - 1] < audio_sample_rate * 0.5f) &&
1221 (eq_node_freq_index[n_eq_nodes - 1] < eq_node_index_max)) {
1222 ptr_eq_slope[n_eq_nodes] = 0;
1223 eq_gain[n_eq_nodes] = eq_gain[n_eq_nodes - 1];
1224 ptr_eq_freq_delta[n_eq_nodes] = eq_node_index_max - eq_node_freq_index[n_eq_nodes - 1];
1225 eq_node_freq_index[n_eq_nodes] = eq_node_index_max;
1226 eq_node_freq[n_eq_nodes] = impd_drc_decode_eq_node_freq(eq_node_freq_index[n_eq_nodes]);
1227 n_eq_nodes += 1;
1228 }
1229
1230 err_code = impd_drc_derive_subband_center_freq(eq_subband_gain_count, eq_subband_gain_format,
1231 audio_sample_rate, ptr_subband_center_freq);
1232 if (err_code & IA_FATAL_ERROR) {
1233 return err_code;
1234 }
1235
1236 for (i = 0; i < n_eq_nodes - 1; i++) {
1237 for (j = 0; j < eq_subband_gain_count; j++) {
1238 freq_subband = MAX(ptr_subband_center_freq[j], eq_node_freq[0]);
1239 freq_subband = MIN(freq_subband, eq_node_freq[n_eq_nodes - 1]);
1240 if ((freq_subband >= eq_node_freq[i]) && (freq_subband <= eq_node_freq[i + 1])) {
1241 warped_delta_freq =
1242 impd_drc_warp_freq_delta(freq_subband, eq_node_freq[0], eq_node_freq_index[i]);
1243 impd_drc_interpolate_eq_gain(ptr_eq_freq_delta[i + 1], eq_gain[i], eq_gain[i + 1],
1244 ptr_eq_slope[i], ptr_eq_slope[i + 1], warped_delta_freq,
1245 &g_eq_subband_db);
1246
1247 ptr_subband_coeff[j] = (FLOAT32)pow(2.0, (FLOAT32)(g_eq_subband_db / 6.0f));
1248 }
1249 }
1250 }
1251 pstr_subband_filter->coeff_count = eq_subband_gain_count;
1252
1253 return err_code;
1254 }
1255
impd_drc_derive_subband_gains(ia_drc_eq_coefficients_struct * pstr_eq_coefficients,const WORD32 eq_channel_group_count,const WORD32 * subband_gains_index,const FLOAT32 audio_sample_rate,const WORD32 eq_frame_size_subband,ia_drc_subband_filter_struct * pstr_subband_filter,VOID * ptr_scratch)1256 static IA_ERRORCODE impd_drc_derive_subband_gains(
1257 ia_drc_eq_coefficients_struct *pstr_eq_coefficients, const WORD32 eq_channel_group_count,
1258 const WORD32 *subband_gains_index, const FLOAT32 audio_sample_rate,
1259 const WORD32 eq_frame_size_subband, ia_drc_subband_filter_struct *pstr_subband_filter,
1260 VOID *ptr_scratch) {
1261 IA_ERRORCODE err_code = IA_NO_ERROR;
1262 LOOPIDX idx;
1263
1264 for (idx = 0; idx < eq_channel_group_count; idx++) {
1265 if (pstr_eq_coefficients->eq_subband_gain_representation != 1) {
1266 impd_drc_derive_subband_eq(
1267 &(pstr_eq_coefficients->str_eq_subband_gain_vector[subband_gains_index[idx]]),
1268 pstr_eq_coefficients->eq_subband_gain_count, &(pstr_subband_filter[idx]));
1269 } else {
1270 err_code = impd_drc_interpolate_subband_spline(
1271 &(pstr_eq_coefficients->str_eq_subband_gain_spline[subband_gains_index[idx]]),
1272 pstr_eq_coefficients->eq_subband_gain_count,
1273 pstr_eq_coefficients->eq_subband_gain_format, audio_sample_rate,
1274 &(pstr_subband_filter[idx]), ptr_scratch);
1275 if (err_code & IA_FATAL_ERROR) {
1276 return err_code;
1277 }
1278 }
1279 pstr_subband_filter[idx].eq_frame_size_subband = eq_frame_size_subband;
1280 }
1281
1282 return err_code;
1283 }
1284
impd_drc_get_eq_complexity(ia_drc_eq_set_struct * pstr_eq_set,WORD32 * eq_complexity_level)1285 IA_ERRORCODE impd_drc_get_eq_complexity(ia_drc_eq_set_struct *pstr_eq_set,
1286 WORD32 *eq_complexity_level) {
1287 LOOPIDX idx_c, idx_b, i, j;
1288 WORD32 group;
1289 WORD32 fir_order_complexity = 0;
1290 WORD32 zero_pole_pair_count_complexity = 0;
1291 WORD32 subband_filter_complexity = 0;
1292 FLOAT32 complexity;
1293 ia_drc_filter_cascade_t_domain_struct *pstr_filter_cascade_t_domain;
1294 ia_drc_eq_filter_block_struct *pstr_eq_filter_block;
1295 ia_drc_eq_filter_element_struct *pstr_eq_filter_element;
1296
1297 for (idx_c = 0; idx_c < pstr_eq_set->audio_channel_count; idx_c++) {
1298 group = pstr_eq_set->eq_channel_group_for_channel[idx_c];
1299 if (group >= 0) {
1300 switch (pstr_eq_set->domain) {
1301 case EQ_FILTER_DOMAIN_TIME: {
1302 pstr_filter_cascade_t_domain = &pstr_eq_set->str_filter_cascade_t_domain[group];
1303 for (idx_b = 0; idx_b < pstr_filter_cascade_t_domain->block_count; idx_b++) {
1304 pstr_eq_filter_block = &pstr_filter_cascade_t_domain->str_eq_filter_block[idx_b];
1305 for (i = 0; i < pstr_eq_filter_block->element_count; i++) {
1306 pstr_eq_filter_element = &pstr_eq_filter_block->str_eq_filter_element[i];
1307 switch (pstr_eq_filter_element->format) {
1308 case FILTER_ELEMENT_FORMAT_POLE_ZERO:
1309 zero_pole_pair_count_complexity +=
1310 pstr_eq_filter_element->str_pole_zero_filter.section_count * 2;
1311 if (pstr_eq_filter_element->str_pole_zero_filter.fir_coeffs_present) {
1312 fir_order_complexity +=
1313 pstr_eq_filter_element->str_pole_zero_filter.str_fir_filter.coeff_count -
1314 1;
1315 }
1316 break;
1317 case FILTER_ELEMENT_FORMAT_FIR:
1318 fir_order_complexity += pstr_eq_filter_element->str_fir_filter.coeff_count - 1;
1319 break;
1320 default:
1321 break;
1322 }
1323 for (j = 0; j < pstr_eq_filter_element->phase_alignment_filter_count; j++) {
1324 zero_pole_pair_count_complexity +=
1325 pstr_eq_filter_element->str_phase_alignment_filter[j].section_count * 2;
1326 }
1327 }
1328 }
1329 for (idx_b = 0; idx_b < pstr_filter_cascade_t_domain->phase_alignment_filter_count;
1330 idx_b++) {
1331 zero_pole_pair_count_complexity +=
1332 pstr_filter_cascade_t_domain->str_phase_alignment_filter[idx_b].section_count * 2;
1333 }
1334 } break;
1335 case EQ_FILTER_DOMAIN_SUBBAND:
1336 subband_filter_complexity++;
1337 break;
1338 case EQ_FILTER_DOMAIN_NONE:
1339 default:
1340 break;
1341 }
1342 }
1343 }
1344 complexity = COMPLEXITY_W_SUBBAND_EQ * subband_filter_complexity;
1345 complexity += COMPLEXITY_W_FIR * fir_order_complexity;
1346 complexity += COMPLEXITY_W_IIR * zero_pole_pair_count_complexity;
1347 complexity = (FLOAT32)(log10(complexity / pstr_eq_set->audio_channel_count) / log10(2.0f));
1348 *eq_complexity_level = (WORD32)MAX(0, ceil(complexity));
1349 if (*eq_complexity_level > EQ_COMPLEXITY_LEVEL_MAX) {
1350 return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
1351 }
1352
1353 return IA_NO_ERROR;
1354 }
1355
impd_drc_derive_eq_set(ia_drc_eq_coefficients_struct * pstr_eq_coefficients,ia_drc_eq_instructions_struct * pstr_eq_instructions,const FLOAT32 audio_sample_rate,const WORD32 drc_frame_size,const WORD32 sub_band_domain_mode,ia_drc_eq_set_struct * pstr_eq_set,VOID * ptr_scratch,WORD32 * scratch_used)1356 IA_ERRORCODE impd_drc_derive_eq_set(ia_drc_eq_coefficients_struct *pstr_eq_coefficients,
1357 ia_drc_eq_instructions_struct *pstr_eq_instructions,
1358 const FLOAT32 audio_sample_rate, const WORD32 drc_frame_size,
1359 const WORD32 sub_band_domain_mode,
1360 ia_drc_eq_set_struct *pstr_eq_set, VOID *ptr_scratch,
1361 WORD32 *scratch_used) {
1362 IA_ERRORCODE err_code = IA_NO_ERROR;
1363 LOOPIDX idx;
1364 WORD32 eq_frame_size_subband;
1365
1366 pstr_eq_set->domain = EQ_FILTER_DOMAIN_NONE;
1367
1368 if (sub_band_domain_mode != SUBBAND_DOMAIN_MODE_OFF) {
1369 switch (sub_band_domain_mode) {
1370 case SUBBAND_DOMAIN_MODE_STFT256:
1371 if (pstr_eq_coefficients->eq_subband_gain_count != STFT256_AUDIO_CODEC_SUBBAND_COUNT) {
1372 return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
1373 }
1374 eq_frame_size_subband = drc_frame_size / STFT256_AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR;
1375 break;
1376 case SUBBAND_DOMAIN_MODE_QMF71:
1377 if (pstr_eq_coefficients->eq_subband_gain_count != QMF71_AUDIO_CODEC_SUBBAND_COUNT) {
1378 return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
1379 }
1380 eq_frame_size_subband = drc_frame_size / QMF71_AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR;
1381 break;
1382 case SUBBAND_DOMAIN_MODE_QMF64:
1383 if (pstr_eq_coefficients->eq_subband_gain_count != QMF64_AUDIO_CODEC_SUBBAND_COUNT) {
1384 return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
1385 }
1386 eq_frame_size_subband = drc_frame_size / QMF64_AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR;
1387 break;
1388 default:
1389 return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
1390 break;
1391 }
1392 if (pstr_eq_instructions->subband_gains_present == 1) {
1393 err_code = impd_drc_derive_subband_gains(
1394 pstr_eq_coefficients, pstr_eq_instructions->eq_channel_group_count,
1395 pstr_eq_instructions->subband_gains_index, audio_sample_rate, eq_frame_size_subband,
1396 pstr_eq_set->str_subband_filter, ptr_scratch);
1397 if (err_code & IA_FATAL_ERROR) {
1398 return err_code;
1399 }
1400 } else {
1401 if (pstr_eq_instructions->td_filter_cascade_present == 1) {
1402 err_code = impd_drc_derive_subband_gains_from_td_cascade(
1403 pstr_eq_coefficients->str_unique_td_filter_element,
1404 pstr_eq_coefficients->str_filter_block, &pstr_eq_instructions->str_td_filter_cascade,
1405 pstr_eq_coefficients->eq_subband_gain_format,
1406 pstr_eq_instructions->eq_channel_group_count, audio_sample_rate,
1407 eq_frame_size_subband, pstr_eq_set->str_subband_filter, ptr_scratch);
1408 if (err_code & IA_FATAL_ERROR) {
1409 return err_code;
1410 }
1411 } else {
1412 err_code = IA_EXHEAACE_CONFIG_NONFATAL_DRC_MISSING_CONFIG;
1413 }
1414 }
1415 pstr_eq_set->domain |= EQ_FILTER_DOMAIN_SUBBAND;
1416 } else {
1417 if (pstr_eq_instructions->td_filter_cascade_present == 1) {
1418 err_code = impd_drc_derive_filter_cascade(
1419 pstr_eq_coefficients->str_unique_td_filter_element,
1420 pstr_eq_coefficients->str_filter_block, &pstr_eq_instructions->str_td_filter_cascade,
1421 pstr_eq_instructions->eq_channel_group_count, pstr_eq_set->str_filter_cascade_t_domain,
1422 ptr_scratch, scratch_used);
1423 if (err_code & IA_FATAL_ERROR) {
1424 return err_code;
1425 }
1426 }
1427 pstr_eq_set->domain |= EQ_FILTER_DOMAIN_TIME;
1428 }
1429
1430 pstr_eq_set->audio_channel_count = pstr_eq_instructions->eq_channel_count;
1431 pstr_eq_set->eq_channel_group_count = pstr_eq_instructions->eq_channel_group_count;
1432
1433 for (idx = 0; idx < pstr_eq_instructions->eq_channel_count; idx++) {
1434 pstr_eq_set->eq_channel_group_for_channel[idx] =
1435 pstr_eq_instructions->eq_channel_group_for_channel[idx];
1436 }
1437
1438 return err_code;
1439 }
1440