Coverage Report

Created: 2024-06-21 06:45

/src/libxaac/decoder/drc_src/impd_drc_eq.c
Line
Count
Source (jump to first uncovered line)
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
#include <string.h>
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_interface.h"
29
#include "impd_drc_gain_dec.h"
30
#include "impd_drc_eq.h"
31
32
0
#define CONFIG_REAL_POLE 0
33
0
#define CONFIG_COMPLEX_POLE 1
34
#define CONFIG_REAL_ZERO_RADIUS_ONE 2
35
#define CONFIG_REAL_ZERO 3
36
#define CONFIG_GENERIC_ZERO 4
37
38
0
#define STEP_RATIO_F_LO 20.0f
39
#define STEP_RATIO_F_HI 24000.0f
40
#define STEP_RATIO_EQ_NODE_COUNT_MAX 33
41
42
0
#define FILTER_ELEMENT_FORMAT_POLE_ZERO 0
43
0
#define FILTER_ELEMENT_FORMAT_FIR 1
44
45
#ifndef M_PI
46
#define M_PI (3.14159265358979323846)
47
#endif
48
49
WORD32 impd_derive_subband_center_freq(WORD32 eq_subband_gain_count,
50
                                       WORD32 eq_subband_gain_format,
51
                                       FLOAT32 sample_rate,
52
0
                                       FLOAT32* subband_center_freq) {
53
0
  WORD32 i;
54
0
  FLOAT32 width, offset;
55
0
  switch (eq_subband_gain_format) {
56
0
    case GAINFORMAT_QMF32:
57
0
    case GAINFORMAT_QMF64:
58
0
    case GAINFORMAT_QMF128:
59
0
    case GAINFORMAT_UNIFORM:
60
0
      width = 0.5f * sample_rate / (FLOAT32)eq_subband_gain_count;
61
0
      offset = 0.5f * width;
62
0
      for (i = 0; i < eq_subband_gain_count; i++) {
63
0
        subband_center_freq[i] = offset;
64
0
        offset = offset + width;
65
0
      }
66
0
      break;
67
0
    case GAINFORMAT_QMFHYBRID39:
68
0
    case GAINFORMAT_QMFHYBRID71:
69
0
    case GAINFORMAT_QMFHYBRID135:
70
0
      return (UNEXPECTED_ERROR);
71
0
      break;
72
0
    default:
73
0
      break;
74
0
  }
75
0
  return (0);
76
0
}
77
78
VOID impd_calc_fir_filt_response(WORD32 fir_order, WORD32 fir_symmetry,
79
                                 FLOAT32* coeff, FLOAT32 frequency_radian,
80
0
                                 FLOAT32* response) {
81
0
  WORD32 m;
82
0
  FLOAT32 sum = 0.0f;
83
0
  WORD32 o2;
84
85
0
  if ((fir_order & 0x1) == 0) {
86
0
    o2 = fir_order / 2;
87
0
    if (fir_symmetry == 0) {
88
      /*ITTIAM: sum is been over written after the loop
89
                None of the conformance streams with us entering this function*/
90
0
      for (m = 1; m <= o2; m++) {
91
0
        sum += coeff[o2 - m] * (FLOAT32)cos(m * frequency_radian);
92
0
      }
93
0
      sum += sum;
94
0
      sum = coeff[o2];
95
0
    } else {
96
0
      for (m = 1; m <= o2; m++) {
97
0
        sum += coeff[o2 - m] * (FLOAT32)sin(m * frequency_radian);
98
0
      }
99
0
      sum += sum;
100
0
    }
101
0
  } else {
102
0
    o2 = (fir_order + 1) / 2;
103
0
    if (fir_symmetry == 0) {
104
0
      for (m = 1; m <= o2; m++) {
105
0
        sum += coeff[o2 - m] * (FLOAT32)cos((m - 0.5f) * frequency_radian);
106
0
      }
107
0
    } else {
108
0
      for (m = 1; m <= o2; m++) {
109
0
        sum += coeff[o2 - m] * (FLOAT32)sin((m - 0.5f) * frequency_radian);
110
0
      }
111
0
    }
112
0
    sum += sum;
113
0
  }
114
0
  *response = sum;
115
0
  return;
116
0
}
117
118
VOID impd_calc_filt_ele_response(ia_unique_td_filt_element* element,
119
0
                                 FLOAT32 frequency_radian, FLOAT32* response) {
120
0
  WORD32 i;
121
0
  FLOAT32 part_response, radius, angle_radian;
122
0
  FLOAT64 total_response = 1.0;
123
124
0
  if (element->eq_filter_format == FILTER_ELEMENT_FORMAT_POLE_ZERO) {
125
0
    for (i = 0; i < element->bs_real_zero_radius_one_count; i++) {
126
0
      part_response =
127
0
          1.0f + 1.0f -
128
0
          2.0f * 1.0f *
129
0
              (FLOAT32)cos(frequency_radian - (FLOAT32)element->zero_sign[i]);
130
0
      total_response *= part_response;
131
0
    }
132
0
    for (i = 0; i < element->real_zero_count; i++) {
133
0
      if (element->real_zero_radius[i] < 0.0f) {
134
0
        radius = -element->real_zero_radius[i];
135
0
        angle_radian = (FLOAT32)M_PI;
136
0
      } else {
137
0
        radius = element->real_zero_radius[i];
138
0
        angle_radian = 0.0f;
139
0
      }
140
0
      part_response =
141
0
          1.0f + radius * radius -
142
0
          2.0f * radius * (FLOAT32)cos(frequency_radian - angle_radian);
143
0
      total_response *= part_response;
144
0
      part_response =
145
0
          1.0f + radius * radius -
146
0
          2.0f * radius * (FLOAT32)cos(frequency_radian - angle_radian);
147
0
      total_response *= part_response;
148
0
    }
149
150
0
    total_response = sqrt(total_response);
151
152
0
    for (i = 0; i < element->generic_zero_count; i++) {
153
0
      radius = element->generic_zero_radius[i];
154
0
      part_response =
155
0
          1.0f + radius * radius -
156
0
          2.0f * radius *
157
0
              (FLOAT32)cos(frequency_radian - element->generic_zero_angle[i]);
158
0
      total_response *= part_response;
159
0
      part_response =
160
0
          1.0f + radius * radius -
161
0
          2.0f * radius *
162
0
              (FLOAT32)cos(frequency_radian - element->generic_zero_angle[i]);
163
0
      total_response *= part_response;
164
0
    }
165
0
    for (i = 0; i < element->real_pole_count; i++) {
166
0
      if (element->real_pole_radius[i] < 0.0f) {
167
0
        radius = -element->real_pole_radius[i];
168
0
        angle_radian = (FLOAT32)(-M_PI);
169
0
      } else {
170
0
        radius = element->real_pole_radius[i];
171
0
        angle_radian = 0.0f;
172
0
      }
173
0
      part_response =
174
0
          1 / (1.0f + radius * radius -
175
0
               2.0f * radius * (FLOAT32)cos(frequency_radian - angle_radian));
176
0
      total_response *= part_response;
177
0
    }
178
0
    for (i = 0; i < element->cmplx_pole_count; i++) {
179
0
      part_response =
180
0
          1 /
181
0
          (1.0f + element->real_pole_radius[i] * element->real_pole_radius[i] -
182
0
           2.0f * element->real_pole_radius[i] *
183
0
               (FLOAT32)cos(frequency_radian - element->complex_pole_angle[i]));
184
0
      total_response *= part_response * part_response;
185
0
    }
186
0
  } else {
187
0
    impd_calc_fir_filt_response(element->fir_filt_order, element->fir_symmetry,
188
0
                                element->fir_coeff, frequency_radian,
189
0
                                &part_response);
190
191
0
    total_response *= part_response;
192
0
  }
193
0
  *response = (FLOAT32)total_response;
194
0
  return;
195
0
}
196
197
VOID impd_calc_filt_block_response(
198
    ia_unique_td_filt_element* unique_td_filt_ele,
199
    ia_filt_block_struct* str_filter_block, FLOAT32 frequency_radian,
200
0
    FLOAT32* response) {
201
0
  WORD32 i;
202
0
  FLOAT32 part_response;
203
0
  FLOAT64 total_response = 1.0;
204
0
  for (i = 0; i < str_filter_block->filter_element_count; i++) {
205
0
    ia_filt_ele_struct* str_filter_element =
206
0
        &str_filter_block->str_filter_element[i];
207
208
0
    impd_calc_filt_ele_response(
209
0
        &(unique_td_filt_ele[str_filter_element->filt_ele_idx]),
210
0
        frequency_radian, &part_response);
211
0
    total_response *= part_response;
212
213
0
    if (str_filter_element->filt_ele_gain_flag == 1) {
214
0
      total_response *= pow(10.0f, 0.05f * str_filter_element->filt_ele_gain);
215
0
    }
216
0
  }
217
0
  *response = (FLOAT32)total_response;
218
0
  return;
219
0
}
220
221
WORD32 impd_calc_subband_gains_td_cascade(
222
    ia_unique_td_filt_element* unique_td_filt_ele,
223
    ia_filt_block_struct* str_filter_block,
224
    ia_td_filter_cascade_struct* str_td_filter_cascade,
225
    WORD32 eq_subband_gain_format, WORD32 eq_ch_group_count,
226
    FLOAT32 sample_rate, WORD32 eq_frame_size_subband,
227
0
    ia_subband_filt_struct* subband_filt) {
228
0
  WORD32 i, err = 0, g, b;
229
0
  FLOAT32 response, frequency_radian;
230
0
  FLOAT32 subband_center_freq[256];
231
0
  FLOAT64 total_response;
232
233
0
  WORD32 eq_subband_gain_count = subband_filt->coeff_count;
234
235
0
  err = impd_derive_subband_center_freq(eq_subband_gain_count,
236
0
                                        eq_subband_gain_format, sample_rate,
237
0
                                        subband_center_freq);
238
0
  if (err) return (err);
239
240
0
  for (g = 0; g < eq_ch_group_count; g++) {
241
0
    for (b = 0; b < eq_subband_gain_count; b++) {
242
0
      total_response =
243
0
          pow(10.0f, 0.05f * str_td_filter_cascade->eq_cascade_gain[g]);
244
0
      frequency_radian =
245
0
          (FLOAT32)(2.0f * M_PI * subband_center_freq[b] / sample_rate);
246
0
      for (i = 0;
247
0
           i <
248
0
           str_td_filter_cascade->str_filter_block_refs[g].filter_block_count;
249
0
           i++) {
250
0
        impd_calc_filt_block_response(
251
0
            unique_td_filt_ele,
252
0
            &(str_filter_block[str_td_filter_cascade->str_filter_block_refs[g]
253
0
                                   .filter_block_index[i]]),
254
0
            frequency_radian, &response);
255
0
        total_response *= response;
256
0
      }
257
0
      subband_filt[g].subband_coeff[b] = (FLOAT32)total_response;
258
0
    }
259
0
    subband_filt[g].eq_frame_size_subband = eq_frame_size_subband;
260
0
  }
261
0
  return (0);
262
0
}
263
264
VOID impd_add_cascade(ia_cascade_align_group_struct* pstr_cascade_align_grp,
265
0
                      WORD32 c1, WORD32 c2, WORD32* done) {
266
0
  WORD32 m, n;
267
268
0
  *done = 0;
269
0
  for (m = 0; m < pstr_cascade_align_grp->member_count; m++) {
270
0
    if (pstr_cascade_align_grp->member_idx[m] == c1) {
271
0
      for (n = 0; n < pstr_cascade_align_grp->member_count; n++) {
272
0
        if (pstr_cascade_align_grp->member_idx[n] == c2) {
273
0
          *done = 1;
274
0
        }
275
0
      }
276
0
      if (*done == 0) {
277
0
        pstr_cascade_align_grp
278
0
            ->member_idx[pstr_cascade_align_grp->member_count] = c2;
279
0
        pstr_cascade_align_grp->member_count++;
280
0
        *done = 1;
281
0
      }
282
0
    }
283
0
  }
284
0
  return;
285
0
}
286
287
VOID impd_calc_cascade_align_groups(
288
    WORD32 eq_ch_group_count, WORD32 eq_phase_alignment_present,
289
    WORD32 eq_phase_alignment[][EQ_CHANNEL_GROUP_COUNT_MAX],
290
    WORD32* cascade_align_grp_cnt,
291
0
    ia_cascade_align_group_struct* pstr_cascade_align_grp) {
292
0
  WORD32 i, k, g, group_count, done;
293
294
0
  group_count = 0;
295
296
0
  if (eq_phase_alignment_present == 0) {
297
0
    if (eq_ch_group_count > 1) {
298
0
      for (i = 0; i < eq_ch_group_count; i++) {
299
0
        pstr_cascade_align_grp[group_count].member_idx[i] = i;
300
0
      }
301
0
      pstr_cascade_align_grp[group_count].member_count = eq_ch_group_count;
302
0
      group_count = 1;
303
0
    }
304
0
  } else {
305
0
    for (i = 0; i < eq_ch_group_count; i++) {
306
0
      for (k = i + 1; k < eq_ch_group_count; k++) {
307
0
        if (eq_phase_alignment[i][k] == 1) {
308
0
          done = 0;
309
0
          for (g = 0; g < group_count; g++) {
310
0
            impd_add_cascade(&pstr_cascade_align_grp[g], i, k, &done);
311
312
0
            if (done == 0) {
313
0
              impd_add_cascade(&pstr_cascade_align_grp[g], k, i, &done);
314
0
            }
315
0
          }
316
0
          if (done == 0) {
317
0
            pstr_cascade_align_grp[group_count].member_idx[0] = i;
318
0
            pstr_cascade_align_grp[group_count].member_idx[1] = k;
319
0
            pstr_cascade_align_grp[group_count].member_count = 2;
320
0
            group_count++;
321
0
          }
322
0
        }
323
0
      }
324
0
    }
325
0
  }
326
0
  *cascade_align_grp_cnt = group_count;
327
0
  return;
328
0
}
329
330
VOID impd_calc_phase_filt_params(
331
    WORD32 config, FLOAT32 radius, FLOAT32 angle,
332
0
    ia_ph_alignment_filt_struct* ph_alignment_filt) {
333
0
  WORD32 channel;
334
0
  FLOAT32 zReal, zImag;
335
0
  FLOAT32 prod;
336
0
  WORD32 section = ph_alignment_filt->section_count;
337
0
  ia_filt_sect_struct* filt_section = &ph_alignment_filt->filt_section[section];
338
0
  switch (config) {
339
0
    case CONFIG_REAL_POLE:
340
0
      ph_alignment_filt->gain *= (-radius);
341
0
      filt_section->a1 = -radius;
342
0
      filt_section->a2 = 0.0f;
343
0
      filt_section->b1 = -1.0f / radius;
344
0
      filt_section->b2 = 0.0f;
345
0
      ph_alignment_filt->section_count++;
346
0
      break;
347
0
    case CONFIG_COMPLEX_POLE:
348
0
      zReal = radius * (FLOAT32)cos(M_PI * angle);
349
0
      zImag = radius * (FLOAT32)sin(M_PI * angle);
350
0
      prod = zReal * zReal + zImag * zImag;
351
0
      ph_alignment_filt->gain *= prod;
352
0
      filt_section->a1 = -2.0f * zReal;
353
0
      filt_section->a2 = prod;
354
0
      filt_section->b1 = -2.0f * zReal / prod;
355
0
      filt_section->b2 = 1.0f / prod;
356
0
      ph_alignment_filt->section_count++;
357
0
      break;
358
0
    default:
359
0
      break;
360
0
  }
361
0
  for (channel = 0; channel < EQ_CHANNEL_COUNT_MAX; channel++) {
362
0
    filt_section->filt_sect_state[channel].in_state_1 = 0.0f;
363
0
    filt_section->filt_sect_state[channel].in_state_2 = 0.0f;
364
0
    filt_section->filt_sect_state[channel].out_state_1 = 0.0f;
365
0
    filt_section->filt_sect_state[channel].out_state_2 = 0.0f;
366
0
  }
367
368
0
  return;
369
0
}
370
371
VOID impd_calc_phase_filt_delay(
372
    ia_unique_td_filt_element* element,
373
0
    ia_ph_alignment_filt_struct* ph_alignment_filt) {
374
0
  WORD32 i, delay = 0, channel;
375
0
  if (element->eq_filter_format == FILTER_ELEMENT_FORMAT_POLE_ZERO) {
376
0
    if (element->bs_real_zero_radius_one_count == 0) {
377
0
      delay = element->real_zero_count + 2 * element->generic_zero_count -
378
0
              element->real_pole_count - 2 * element->cmplx_pole_count;
379
0
      delay = max(0, delay);
380
0
      ph_alignment_filt->validity_flag = 1;
381
0
    }
382
0
  }
383
0
  ph_alignment_filt->audio_delay.delay = delay;
384
0
  for (channel = 0; channel < EQ_CHANNEL_COUNT_MAX; channel++) {
385
0
    for (i = 0; i < delay; i++) {
386
0
      ph_alignment_filt->audio_delay.state[channel][i] = 0.0f;
387
0
    }
388
0
  }
389
390
0
  return;
391
0
}
392
393
VOID impd_calc_phase_filt(ia_unique_td_filt_element* element,
394
                          WORD32 filt_ele_idx,
395
0
                          ia_matching_ph_filt_struct* matching_ph_filt) {
396
0
  WORD32 i;
397
398
0
  memset(matching_ph_filt, 0, sizeof(ia_matching_ph_filt_struct));
399
0
  matching_ph_filt->gain = 1.0f;
400
401
0
  if (element->eq_filter_format == FILTER_ELEMENT_FORMAT_POLE_ZERO) {
402
0
    for (i = 0; i < element->real_pole_count; i++) {
403
0
      impd_calc_phase_filt_params(CONFIG_REAL_POLE,
404
0
                                  element->real_pole_radius[i], 0.0f,
405
0
                                  matching_ph_filt);
406
0
    }
407
0
    for (i = 0; i < element->cmplx_pole_count; i++) {
408
0
      impd_calc_phase_filt_params(
409
0
          CONFIG_COMPLEX_POLE, element->complex_pole_radius[i],
410
0
          element->complex_pole_angle[i], matching_ph_filt);
411
0
    }
412
0
  }
413
0
  impd_calc_phase_filt_delay(element, matching_ph_filt);
414
415
0
  matching_ph_filt->num_matches_filter = 1;
416
0
  matching_ph_filt->matches_filter[0] = filt_ele_idx;
417
418
0
  return;
419
0
}
420
421
WORD32 impd_calc_filt_params(ia_unique_td_filt_element* element,
422
0
                             ia_interm_filt_params_struct* interm_filt_params) {
423
0
  FLOAT32 zReal;
424
0
  FLOAT32* coeff;
425
  // WORD32   offset_idx = 0;
426
0
  WORD32 i;
427
0
  WORD32 param_idx = 0;
428
429
0
  ia_2nd_order_filt_params_struct* pstr_2nd_oder_filt_params =
430
0
      &interm_filt_params->ord_2_filt_params_of_zeros[0];
431
432
0
  for (i = 0; i < element->bs_real_zero_radius_one_count; i += 2) {
433
0
    FLOAT32 radius = (FLOAT32)element->zero_sign[i + 0];
434
0
    FLOAT32 angle = (FLOAT32)element->zero_sign[i + 1];
435
0
    FLOAT32 angle1 = radius;
436
0
    FLOAT32 angle2 = angle;
437
0
    pstr_2nd_oder_filt_params->radius = 1.0f;
438
0
    coeff = pstr_2nd_oder_filt_params->coeff;
439
440
0
    if (angle1 != angle2) {
441
0
      coeff[0] = 0.0f;
442
0
      coeff[1] = -1.0f;
443
0
    } else if (angle1 == 1.0f) {
444
0
      coeff[0] = -2.0f;
445
0
      coeff[1] = 1.0f;
446
0
    } else {
447
0
      coeff[0] = 2.0f;
448
0
      coeff[1] = 1.0f;
449
0
    }
450
0
    pstr_2nd_oder_filt_params += 1;
451
0
    param_idx += 1;
452
0
  }
453
0
  for (i = 0; i < element->real_zero_count; i++) {
454
0
    FLOAT32 radius = element->real_zero_radius[i];
455
    // FLOAT32  angle  = 0.0f;
456
457
0
    pstr_2nd_oder_filt_params->radius = radius;
458
0
    if (fabs(radius) == 1.0f) {
459
0
      return (-1);
460
0
    } else {
461
0
      coeff = pstr_2nd_oder_filt_params->coeff;
462
0
      coeff[0] = -(radius + 1.0f / radius);
463
0
      coeff[1] = 1.0f;
464
0
    }
465
0
    pstr_2nd_oder_filt_params += 1;
466
0
    param_idx += 1;
467
0
  }
468
469
0
  for (i = 0; i < element->generic_zero_count; i++) {
470
0
    FLOAT32 radius = element->generic_zero_radius[i];
471
0
    FLOAT32 angle = element->generic_zero_angle[i];
472
0
    zReal = radius * (FLOAT32)cos(M_PI * angle);
473
0
    pstr_2nd_oder_filt_params->radius = radius;
474
0
    coeff = pstr_2nd_oder_filt_params->coeff;
475
0
    coeff[0] = -2.0f * zReal;
476
0
    coeff[1] = radius * radius;
477
478
0
    pstr_2nd_oder_filt_params += 1;
479
480
0
    zReal = (FLOAT32)cos(M_PI * angle) / radius;
481
0
    pstr_2nd_oder_filt_params->radius = radius;
482
0
    coeff = pstr_2nd_oder_filt_params->coeff;
483
0
    coeff[0] = -2.0f * zReal;
484
0
    coeff[1] = 1.0f / (radius * radius);
485
486
0
    pstr_2nd_oder_filt_params += 1;
487
488
0
    param_idx += 2;
489
0
  }
490
491
0
  interm_filt_params->filter_param_count_of_zeros = param_idx;
492
0
  param_idx = 0;
493
494
0
  pstr_2nd_oder_filt_params =
495
0
      &interm_filt_params->ord_2_filt_params_of_poles[0];
496
497
0
  for (i = 0; i < element->real_pole_count; i++) {
498
0
    FLOAT32 radius = element->real_pole_radius[i];
499
0
    pstr_2nd_oder_filt_params->radius = radius;
500
0
    coeff = pstr_2nd_oder_filt_params->coeff;
501
0
    coeff[0] = -2.0f * radius;
502
0
    coeff[1] = radius * radius;
503
0
    param_idx += 1;
504
0
    pstr_2nd_oder_filt_params += 1;
505
0
  }
506
507
0
  for (i = 0; i < element->cmplx_pole_count; i++) {
508
0
    FLOAT32 radius = element->complex_pole_radius[i];
509
0
    FLOAT32 angle = element->complex_pole_angle[i];
510
511
0
    zReal = radius * (FLOAT32)cos(M_PI * angle);
512
0
    pstr_2nd_oder_filt_params->radius = radius;
513
0
    coeff = pstr_2nd_oder_filt_params->coeff;
514
0
    coeff[0] = -2.0f * zReal;
515
0
    coeff[1] = radius * radius;
516
517
0
    pstr_2nd_oder_filt_params += 1;
518
519
0
    pstr_2nd_oder_filt_params->radius = radius;
520
0
    pstr_2nd_oder_filt_params->coeff[0] = coeff[0];
521
0
    pstr_2nd_oder_filt_params->coeff[1] = coeff[1];
522
523
0
    pstr_2nd_oder_filt_params += 1;
524
0
    param_idx += 2;
525
0
  }
526
0
  interm_filt_params->filter_param_count_of_poles = param_idx;
527
0
  return 0;
528
0
}
529
530
VOID impd_convert_fir_filt_params(WORD32 fir_filt_order, WORD32 fir_symmetry,
531
                                  FLOAT32* fir_coeff,
532
0
                                  ia_fir_filter_struct* fir_filter) {
533
0
  WORD32 i, channel;
534
0
  FLOAT32* coeff = fir_filter->coeff;
535
536
0
  fir_filter->coeff_count = fir_filt_order + 1;
537
0
  for (i = 0; i < fir_filt_order / 2 + 1; i++) {
538
0
    coeff[i] = fir_coeff[i];
539
0
  }
540
541
0
  if (fir_symmetry == 1) {
542
0
    for (i = 0; i < (fir_filt_order + 1) / 2; i++) {
543
0
      coeff[fir_filt_order - i] = -coeff[i];
544
0
    }
545
546
0
    if ((fir_filt_order & 1) == 0) {
547
0
      coeff[fir_filt_order / 2] = 0.0f;
548
0
    }
549
0
  } else {
550
0
    for (i = 0; i < (fir_filt_order + 1) / 2; i++) {
551
0
      coeff[fir_filt_order - i] = coeff[i];
552
0
    }
553
0
  }
554
555
0
  for (channel = 0; channel < EQ_CHANNEL_COUNT_MAX; channel++) {
556
0
    for (i = 0; i < fir_filt_order + 1; i++) {
557
0
      fir_filter->state[channel][i] = 0.0f;
558
0
    }
559
0
  }
560
0
  return;
561
0
}
562
563
WORD32 impd_calc_filt_params_all(
564
    ia_unique_td_filt_element* element,
565
0
    ia_interm_filt_params_struct* interm_filt_params) {
566
0
  WORD32 err = 0;
567
568
0
  interm_filt_params->filter_format = element->eq_filter_format;
569
0
  if (element->eq_filter_format == FILTER_ELEMENT_FORMAT_POLE_ZERO) {
570
0
    err = impd_calc_filt_params(element, interm_filt_params);
571
0
    if (err) return err;
572
0
  } else {
573
0
    interm_filt_params->filter_param_count_of_zeros = 0;
574
0
    interm_filt_params->filter_param_count_of_poles = 0;
575
576
0
    impd_convert_fir_filt_params(element->fir_filt_order, element->fir_symmetry,
577
0
                                 element->fir_coeff,
578
0
                                 &interm_filt_params->fir_filter);
579
0
  }
580
0
  return (0);
581
0
}
582
583
VOID impd_calc_eq_filt_elements(
584
    ia_interm_filt_params_struct* interm_filt_params,
585
0
    ia_eq_filt_ele_struct* eq_filt_element) {
586
0
  WORD32 i, poles_idx, zeros_idx, pole_order = 0, section, channel;
587
0
  WORD32 poles_over[REAL_POLE_COUNT_MAX + COMPLEX_POLE_COUNT_MAX];
588
0
  WORD32 zeros_over[REAL_ZERO_COUNT_MAX + COMPLEX_ZERO_COUNT_MAX];
589
0
  FLOAT32 max_radius, diff_radius;
590
0
  WORD32 coeff_count;
591
0
  FLOAT32* coeff;
592
593
0
  for (i = 0; i < REAL_POLE_COUNT_MAX + COMPLEX_POLE_COUNT_MAX; i++) {
594
0
    poles_over[i] = 0;
595
0
  }
596
0
  for (i = 0; i < REAL_ZERO_COUNT_MAX + COMPLEX_ZERO_COUNT_MAX; i++) {
597
0
    zeros_over[i] = 0;
598
0
  }
599
0
  section = 0;
600
0
  do {
601
0
    max_radius = -1.0;
602
0
    poles_idx = -1;
603
0
    for (i = 0; i < interm_filt_params->filter_param_count_of_poles; i++) {
604
0
      if (poles_over[i] == 0) {
605
0
        if (interm_filt_params->filter_format == 0) {
606
0
          if (max_radius <
607
0
              fabs(interm_filt_params->ord_2_filt_params_of_poles[i].radius)) {
608
0
            max_radius = (FLOAT32)fabs(
609
0
                interm_filt_params->ord_2_filt_params_of_poles[i].radius);
610
0
            poles_idx = i;
611
0
            if (interm_filt_params->ord_2_filt_params_of_poles[i].coeff[1] !=
612
0
                0.0f) {
613
0
              pole_order = 2;
614
0
            } else {
615
0
              pole_order = 1;
616
0
            }
617
0
          }
618
0
        }
619
0
      }
620
0
    }
621
0
    if (poles_idx >= 0) {
622
0
      diff_radius = 10.0f;
623
0
      zeros_idx = -1;
624
0
      for (i = 0; i < interm_filt_params->filter_param_count_of_zeros; i++) {
625
0
        if (zeros_over[i] == 0) {
626
0
          if (interm_filt_params->filter_format == 0) {
627
0
            if (pole_order == 2) {
628
0
              if (interm_filt_params->ord_2_filt_params_of_zeros[i].coeff[1] !=
629
0
                  0.0f) {
630
0
                if (diff_radius >
631
0
                    fabs(fabs(interm_filt_params->ord_2_filt_params_of_zeros[i]
632
0
                                  .radius) -
633
0
                         max_radius)) {
634
0
                  diff_radius = (FLOAT32)fabs(
635
0
                      fabs(interm_filt_params->ord_2_filt_params_of_zeros[i]
636
0
                               .radius) -
637
0
                      max_radius);
638
0
                  zeros_idx = i;
639
0
                }
640
0
              }
641
0
            } else {
642
0
              if (interm_filt_params->ord_2_filt_params_of_zeros[i].coeff[1] ==
643
0
                  0.0f) {
644
0
                if (diff_radius >
645
0
                    (FLOAT32)(fabs(
646
0
                        fabs(interm_filt_params->ord_2_filt_params_of_zeros[i]
647
0
                                 .radius) -
648
0
                        max_radius))) {
649
0
                  diff_radius = (FLOAT32)(fabs(
650
0
                      fabs(interm_filt_params->ord_2_filt_params_of_zeros[i]
651
0
                               .radius) -
652
0
                      max_radius));
653
0
                  zeros_idx = i;
654
0
                }
655
0
              }
656
0
            }
657
0
          }
658
0
        }
659
0
      }
660
0
      if (zeros_idx == -1) {
661
0
        for (i = 0; i < interm_filt_params->filter_param_count_of_zeros; i++) {
662
0
          if (zeros_over[i] == 0) {
663
0
            if (interm_filt_params->filter_format == 0) {
664
0
              if (pole_order == 2) {
665
0
                if (interm_filt_params->ord_2_filt_params_of_zeros[i]
666
0
                        .coeff[1] == 0.0f) {
667
0
                  if (diff_radius >
668
0
                      (FLOAT32)(fabs(
669
0
                          fabs(interm_filt_params->ord_2_filt_params_of_zeros[i]
670
0
                                   .radius) -
671
0
                          max_radius))) {
672
0
                    diff_radius = (FLOAT32)(fabs(
673
0
                        fabs(interm_filt_params->ord_2_filt_params_of_zeros[i]
674
0
                                 .radius) -
675
0
                        max_radius));
676
0
                    zeros_idx = i;
677
0
                  }
678
0
                }
679
0
              } else {
680
0
                if (interm_filt_params->ord_2_filt_params_of_zeros[i]
681
0
                        .coeff[1] != 0.0f) {
682
0
                  if (diff_radius >
683
0
                      (FLOAT32)(fabs(
684
0
                          fabs(interm_filt_params->ord_2_filt_params_of_zeros[i]
685
0
                                   .radius) -
686
0
                          max_radius))) {
687
0
                    diff_radius = (FLOAT32)(fabs(
688
0
                        fabs(interm_filt_params->ord_2_filt_params_of_zeros[i]
689
0
                                 .radius) -
690
0
                        max_radius));
691
0
                    zeros_idx = i;
692
0
                  }
693
0
                }
694
0
              }
695
0
            }
696
0
          }
697
0
        }
698
0
      }
699
0
      eq_filt_element->pstr_pole_zero_filt.filt_section[section].a1 =
700
0
          interm_filt_params->ord_2_filt_params_of_poles[poles_idx].coeff[0];
701
0
      eq_filt_element->pstr_pole_zero_filt.filt_section[section].a2 =
702
0
          interm_filt_params->ord_2_filt_params_of_poles[poles_idx].coeff[1];
703
0
      if (zeros_idx >= 0) {
704
0
        eq_filt_element->pstr_pole_zero_filt.filt_section[section].b1 =
705
0
            interm_filt_params->ord_2_filt_params_of_zeros[zeros_idx].coeff[0];
706
0
        eq_filt_element->pstr_pole_zero_filt.filt_section[section].b2 =
707
0
            interm_filt_params->ord_2_filt_params_of_zeros[zeros_idx].coeff[1];
708
0
      } else {
709
0
        eq_filt_element->pstr_pole_zero_filt.filt_section[section].b1 = 0.0f;
710
0
        eq_filt_element->pstr_pole_zero_filt.filt_section[section].b2 = 0.0f;
711
0
        eq_filt_element->pstr_pole_zero_filt.audio_delay.delay++;
712
0
      }
713
0
      for (channel = 0; channel < EQ_CHANNEL_COUNT_MAX; channel++) {
714
0
        eq_filt_element->pstr_pole_zero_filt.filt_section[section]
715
0
            .filt_sect_state[channel]
716
0
            .in_state_1 = 0.0f;
717
0
        eq_filt_element->pstr_pole_zero_filt.filt_section[section]
718
0
            .filt_sect_state[channel]
719
0
            .in_state_2 = 0.0f;
720
0
        eq_filt_element->pstr_pole_zero_filt.filt_section[section]
721
0
            .filt_sect_state[channel]
722
0
            .out_state_1 = 0.0f;
723
0
        eq_filt_element->pstr_pole_zero_filt.filt_section[section]
724
0
            .filt_sect_state[channel]
725
0
            .out_state_2 = 0.0f;
726
0
      }
727
0
      if (zeros_idx >= 0) zeros_over[zeros_idx] = 1;
728
0
      if (poles_idx >= 0) poles_over[poles_idx] = 1;
729
0
      section++;
730
0
    }
731
0
  } while (poles_idx >= 0);
732
733
0
  eq_filt_element->pstr_pole_zero_filt.section_count = section;
734
735
0
  coeff_count = 1;
736
0
  coeff = eq_filt_element->pstr_pole_zero_filt.fir_filter.coeff;
737
0
  coeff[0] = 1.0f;
738
0
  for (i = 0; i < interm_filt_params->filter_param_count_of_zeros; i++) {
739
0
    if (zeros_over[i] == 0) {
740
0
      if (interm_filt_params->filter_format == 0) {
741
0
        WORD32 k;
742
0
        FLOAT32 b1, b2;
743
0
        b1 = interm_filt_params->ord_2_filt_params_of_zeros[i].coeff[0];
744
0
        b2 = interm_filt_params->ord_2_filt_params_of_zeros[i].coeff[1];
745
746
0
        coeff_count += 2;
747
0
        k = coeff_count - 1;
748
0
        coeff[k] = b2 * coeff[k - 2];
749
0
        k--;
750
0
        if (k > 1) {
751
0
          coeff[k] = b1 * coeff[k - 1] + b2 * coeff[k - 2];
752
0
          k--;
753
0
          for (; k > 1; k--) {
754
0
            coeff[k] += b1 * coeff[k - 1] + b2 * coeff[k - 2];
755
0
          }
756
0
          coeff[1] += b1 * coeff[0];
757
0
        } else {
758
0
          coeff[1] = b1 * coeff[0];
759
0
        }
760
0
      }
761
0
    }
762
0
    zeros_over[i] = 1;
763
0
  }
764
0
  if (coeff_count > 1) {
765
0
    eq_filt_element->pstr_pole_zero_filt.filt_coeffs_flag = 1;
766
0
    eq_filt_element->pstr_pole_zero_filt.fir_filter.coeff_count = coeff_count;
767
0
  } else {
768
0
    eq_filt_element->pstr_pole_zero_filt.filt_coeffs_flag = 0;
769
0
    eq_filt_element->pstr_pole_zero_filt.fir_filter.coeff_count = 0;
770
0
  }
771
772
0
  return;
773
0
}
774
775
WORD32 impd_calc_filt_block(ia_unique_td_filt_element* unique_td_filt_ele,
776
                            ia_filt_block_struct* str_filter_block,
777
0
                            ia_eq_filt_block_struct* pstr_eq_filt_block) {
778
0
  WORD32 i, k, err;
779
0
  ia_interm_filt_params_struct interm_filt_params;
780
0
  ia_matching_ph_filt_struct matching_ph_filt[FILTER_ELEMENT_COUNT_MAX];
781
782
0
  for (i = 0; i < str_filter_block->filter_element_count; i++) {
783
0
    if ((unique_td_filt_ele[str_filter_block->str_filter_element[i]
784
0
                                .filt_ele_idx]
785
0
             .eq_filter_format == FILTER_ELEMENT_FORMAT_FIR) &&
786
0
        (str_filter_block->filter_element_count > 1)) {
787
0
      return (-1);
788
0
    }
789
0
  }
790
0
  for (i = 0; i < str_filter_block->filter_element_count; i++) {
791
0
    ia_eq_filt_ele_struct* eq_filt_element =
792
0
        &pstr_eq_filt_block->eq_filt_element[i];
793
0
    ia_filt_ele_struct* str_filter_element =
794
0
        &str_filter_block->str_filter_element[i];
795
0
    WORD32 filterIndex = str_filter_element->filt_ele_idx;
796
797
0
    if (unique_td_filt_ele[filterIndex].eq_filter_format ==
798
0
        FILTER_ELEMENT_FORMAT_POLE_ZERO) {
799
0
      err = impd_calc_filt_params_all(&(unique_td_filt_ele[filterIndex]),
800
0
                                      &interm_filt_params);
801
0
      if (err) return (err);
802
803
0
      impd_calc_eq_filt_elements(&interm_filt_params, eq_filt_element);
804
805
0
      eq_filt_element->format = FILTER_ELEMENT_FORMAT_POLE_ZERO;
806
0
    } else {
807
0
      impd_convert_fir_filt_params(
808
0
          unique_td_filt_ele[filterIndex].fir_filt_order,
809
0
          unique_td_filt_ele[filterIndex].fir_symmetry,
810
0
          unique_td_filt_ele[filterIndex].fir_coeff,
811
0
          &eq_filt_element->fir_filter);
812
813
0
      eq_filt_element->format = FILTER_ELEMENT_FORMAT_FIR;
814
0
    }
815
0
    if (str_filter_element->filt_ele_gain_flag == 1) {
816
0
      eq_filt_element->elementGainLinear =
817
0
          (FLOAT32)(pow(10.0f, 0.05f * str_filter_element->filt_ele_gain));
818
0
    } else {
819
0
      eq_filt_element->elementGainLinear = 1.0f;
820
0
    }
821
0
    for (k = 0; k < unique_td_filt_ele[filterIndex].real_zero_count; k++) {
822
0
      if (unique_td_filt_ele[filterIndex].real_zero_radius[k] > 0.0f) {
823
0
        eq_filt_element->elementGainLinear =
824
0
            -eq_filt_element->elementGainLinear;
825
0
      }
826
0
    }
827
0
    impd_calc_phase_filt(&(unique_td_filt_ele[filterIndex]), i,
828
0
                         &matching_ph_filt[i]);
829
0
  }
830
0
  pstr_eq_filt_block->element_count = str_filter_block->filter_element_count;
831
832
0
  pstr_eq_filt_block->matching_ph_filt_ele_0 = matching_ph_filt[0];
833
834
0
  return (0);
835
0
}
836
837
VOID impd_calc_cascade_phase_align_filt(
838
0
    ia_td_filter_cascade_struct* str_td_filter_cascade, WORD32 ch_group_cnt) {
839
  // WORD32 err = 0;
840
0
  WORD32 cascade_align_grp_cnt = 0;
841
0
  ia_cascade_align_group_struct
842
0
      pstr_cascade_align_grp[EQ_CHANNEL_GROUP_COUNT_MAX / 2];
843
844
0
  impd_calc_cascade_align_groups(
845
0
      ch_group_cnt, str_td_filter_cascade->eq_phase_alignment_present,
846
0
      str_td_filter_cascade->eq_phase_alignment, &cascade_align_grp_cnt,
847
0
      pstr_cascade_align_grp);
848
0
  return;
849
0
}
850
851
WORD32 impd_calc_filt_cascade(
852
    ia_unique_td_filt_element* unique_td_filt_ele,
853
    ia_filt_block_struct* str_filter_block,
854
    ia_td_filter_cascade_struct* str_td_filter_cascade, WORD32 ch_group_cnt,
855
0
    ia_filt_cascade_td_struct filt_cascade_td[]) {
856
0
  WORD32 i, err, g;
857
858
0
  for (g = 0; g < ch_group_cnt; g++) {
859
0
    for (i = 0;
860
0
         i < str_td_filter_cascade->str_filter_block_refs[g].filter_block_count;
861
0
         i++) {
862
0
      err = impd_calc_filt_block(
863
0
          unique_td_filt_ele,
864
0
          &(str_filter_block[str_td_filter_cascade->str_filter_block_refs[g]
865
0
                                 .filter_block_index[i]]),
866
0
          &(filt_cascade_td[g].pstr_eq_filt_block[i]));
867
0
      if (err) return (err);
868
0
    }
869
0
    filt_cascade_td[g].block_count = i;
870
0
    filt_cascade_td[g].cascade_gain_linear = (FLOAT32)(
871
0
        pow(10.0f, 0.05f * str_td_filter_cascade->eq_cascade_gain[g]));
872
0
  }
873
874
0
  impd_calc_cascade_phase_align_filt(str_td_filter_cascade, ch_group_cnt);
875
0
  return (0);
876
0
}
877
878
VOID impd_calc_subband_eq(ia_eq_subband_gain_vector* str_eq_subband_gain_vector,
879
                          WORD32 eq_subband_gain_count,
880
0
                          ia_subband_filt_struct* subband_filt) {
881
0
  WORD32 i;
882
883
0
  for (i = 0; i < eq_subband_gain_count; i++) {
884
0
    subband_filt->subband_coeff[i] =
885
0
        str_eq_subband_gain_vector->eq_subband_gain[i];
886
0
  }
887
0
  subband_filt->coeff_count = eq_subband_gain_count;
888
0
  return;
889
0
}
890
891
0
FLOAT32 impd_decode_eq_node_freq(WORD32 eq_node_freq_idx) {
892
  /*((FLOAT32)((log10(STEP_RATIO_F_HI) / log10(STEP_RATIO_F_LO) - 1.0f) /
893
   * (STEP_RATIO_EQ_NODE_COUNT_MAX - 1.0f)))*/
894
0
  FLOAT32 step_ratio = 0.0739601809794f;
895
0
  return (
896
0
      (FLOAT32)(pow(STEP_RATIO_F_LO, 1.0f + eq_node_freq_idx * step_ratio)));
897
0
}
898
899
FLOAT32 impd_calc_warp_freq_delta(FLOAT32 fsubband, FLOAT32 node_freq,
900
0
                                  WORD32 eq_node_freq_idx) {
901
  /*((FLOAT32)((log10(STEP_RATIO_F_HI) / log10(STEP_RATIO_F_LO) - 1.0f) /
902
   * (STEP_RATIO_EQ_NODE_COUNT_MAX - 1.0f)))*/
903
0
  FLOAT32 step_ratio = 0.0739601809794f;
904
0
  return ((FLOAT32)((log10(fsubband) / log10(node_freq) - 1.0f) / step_ratio -
905
0
                    (FLOAT32)eq_node_freq_idx));
906
0
}
907
908
VOID impd_interpolate_eq_gain(WORD32 band_step, FLOAT32 left_gain,
909
                              FLOAT32 right_gain, FLOAT32 left_slope,
910
                              FLOAT32 right_slope, FLOAT32 f,
911
0
                              FLOAT32* interpolated_gain) {
912
0
  FLOAT32 k1, k2, a, b, c, d;
913
0
  FLOAT32 inv_band_step = (FLOAT32)(1.0 / (FLOAT32)band_step);
914
0
  FLOAT32 inv_band_step_sqr = inv_band_step * inv_band_step;
915
0
  k1 = (right_gain - left_gain) * inv_band_step_sqr;
916
0
  left_slope = (FLOAT32)(left_slope / 3.128f);
917
0
  right_slope = (FLOAT32)(right_slope / 3.128f);
918
919
0
  k2 = right_slope + left_slope;
920
0
  a = inv_band_step * (inv_band_step * k2 - 2.0f * k1);
921
0
  b = 3.0f * k1 - inv_band_step * (k2 + left_slope);
922
0
  c = left_slope;
923
0
  d = left_gain;
924
0
  *interpolated_gain = (((a * f + b) * f + c) * f) + d;
925
0
  return;
926
0
}
927
928
WORD32 impd_interpolate_subband_spline(
929
    ia_eq_subband_gain_spline_struct* str_eq_subband_gain_spline,
930
    WORD32 eq_subband_gain_count, WORD32 eq_subband_gain_format,
931
0
    FLOAT32 sample_rate, ia_subband_filt_struct* subband_filt) {
932
0
  WORD32 b, n, err;
933
934
0
  FLOAT32 eq_gain[32];
935
0
  WORD32 eq_node_freq_idx[32];
936
0
  FLOAT32 eq_node_freq[32];
937
0
  FLOAT32 subband_center_freq[256];
938
0
  WORD32 num_eq_nodes = str_eq_subband_gain_spline->num_eq_nodes;
939
940
0
  FLOAT32* eq_slope = str_eq_subband_gain_spline->eq_slope;
941
0
  WORD32* eq_freq_delta = str_eq_subband_gain_spline->eq_freq_delta;
942
0
  FLOAT32 eq_gain_initial = str_eq_subband_gain_spline->eq_gain_initial;
943
0
  FLOAT32* eq_gain_delta = str_eq_subband_gain_spline->eq_gain_delta;
944
945
0
  FLOAT32* subband_coeff = subband_filt->subband_coeff;
946
0
  WORD32 max_eq_node_idx = 32;
947
948
0
  eq_gain[0] = eq_gain_initial;
949
0
  eq_node_freq_idx[0] = 0;
950
0
  eq_node_freq[0] = impd_decode_eq_node_freq(eq_node_freq_idx[0]);
951
0
  for (n = 1; n < num_eq_nodes; n++) {
952
0
    eq_gain[n] = eq_gain[n - 1] + eq_gain_delta[n];
953
0
    eq_node_freq_idx[n] = eq_node_freq_idx[n - 1] + eq_freq_delta[n];
954
0
    eq_node_freq[n] = impd_decode_eq_node_freq(eq_node_freq_idx[n]);
955
0
  }
956
0
  if ((eq_node_freq[num_eq_nodes - 1] < sample_rate * 0.5f) &&
957
0
      (eq_node_freq_idx[num_eq_nodes - 1] < max_eq_node_idx)) {
958
0
    eq_slope[num_eq_nodes] = 0;
959
0
    eq_gain[num_eq_nodes] = eq_gain[num_eq_nodes - 1];
960
0
    eq_freq_delta[num_eq_nodes] =
961
0
        max_eq_node_idx - eq_node_freq_idx[num_eq_nodes - 1];
962
0
    eq_node_freq_idx[num_eq_nodes] = max_eq_node_idx;
963
0
    eq_node_freq[num_eq_nodes] =
964
0
        impd_decode_eq_node_freq(eq_node_freq_idx[num_eq_nodes]);
965
0
    num_eq_nodes += 1;
966
0
  }
967
968
0
  err = impd_derive_subband_center_freq(eq_subband_gain_count,
969
0
                                        eq_subband_gain_format, sample_rate,
970
0
                                        subband_center_freq);
971
0
  if (err) return (err);
972
973
0
  for (n = 0; n < num_eq_nodes - 1; n++) {
974
0
    for (b = 0; b < eq_subband_gain_count; b++) {
975
0
      FLOAT32 fSub;
976
0
      fSub = max(subband_center_freq[b], eq_node_freq[0]);
977
0
      fSub = min(fSub, eq_node_freq[num_eq_nodes - 1]);
978
0
      if ((fSub >= eq_node_freq[n]) && (fSub <= eq_node_freq[n + 1])) {
979
0
        FLOAT32 warpedDeltaFreq = impd_calc_warp_freq_delta(
980
0
            fSub, eq_node_freq[0], eq_node_freq_idx[n]);
981
0
        FLOAT32 gEqSubbandDb;
982
0
        impd_interpolate_eq_gain(eq_freq_delta[n + 1], eq_gain[n],
983
0
                                 eq_gain[n + 1], eq_slope[n], eq_slope[n + 1],
984
0
                                 warpedDeltaFreq, &gEqSubbandDb);
985
986
0
        subband_coeff[b] = (FLOAT32)pow(2.0, gEqSubbandDb / 6.0f);
987
0
      }
988
0
    }
989
0
  }
990
0
  subband_filt->coeff_count = eq_subband_gain_count;
991
0
  return (0);
992
0
}
993
994
WORD32 impd_calc_subband_gains(ia_eq_coeff_struct* str_eq_coeff,
995
                               WORD32 eq_ch_group_count,
996
                               WORD32* subband_gains_index, FLOAT32 sample_rate,
997
                               WORD32 eq_frame_size_subband,
998
0
                               ia_subband_filt_struct* subband_filt) {
999
0
  WORD32 g, err;
1000
0
  WORD32 eq_subband_gain_representation =
1001
0
      str_eq_coeff->eq_subband_gain_representation;
1002
0
  WORD32 eq_subband_gain_count = str_eq_coeff->eq_subband_gain_count;
1003
0
  WORD32 eq_subband_gain_format = str_eq_coeff->eq_subband_gain_format;
1004
1005
0
  for (g = 0; g < eq_ch_group_count; g++) {
1006
0
    if (eq_subband_gain_representation == 1) {
1007
0
      err = impd_interpolate_subband_spline(
1008
0
          &(str_eq_coeff->str_eq_subband_gain_spline[subband_gains_index[g]]),
1009
0
          eq_subband_gain_count, eq_subband_gain_format, sample_rate,
1010
0
          &(subband_filt[g]));
1011
0
      if (err) return (err);
1012
0
    } else {
1013
0
      impd_calc_subband_eq(
1014
0
          &(str_eq_coeff->str_eq_subband_gain_vector[subband_gains_index[g]]),
1015
0
          eq_subband_gain_count, &(subband_filt[g]));
1016
0
    }
1017
0
    subband_filt[g].eq_frame_size_subband = eq_frame_size_subband;
1018
0
  }
1019
0
  return (0);
1020
0
}
1021
1022
VOID impd_calc_filt_sect_delay(WORD32 section_count,
1023
                               ia_filt_sect_struct* filt_section,
1024
0
                               FLOAT32* delay) {
1025
0
  WORD32 i;
1026
0
  FLOAT32 d = 0.0f;
1027
0
  for (i = 0; i < section_count; i++) {
1028
0
    if (filt_section[i].b2 != 0.0f) {
1029
0
      d += 1.0f;
1030
0
    } else if (filt_section[i].b1 != 0.0f) {
1031
0
      d += 0.5f;
1032
0
    }
1033
0
  }
1034
0
  *delay = d;
1035
0
  return;
1036
0
}
1037
1038
0
VOID impd_get_eq_set_delay(ia_eq_set_struct* eq_set, WORD32* cascade_delay) {
1039
0
  FLOAT32 delay, sect_delay;
1040
0
  WORD32 k, g, b;
1041
1042
0
  delay = 0;
1043
0
  g = eq_set->eq_ch_group_of_channel[0];
1044
0
  if (g >= 0) {
1045
0
    switch (eq_set->domain) {
1046
0
      case EQ_FILTER_DOMAIN_TIME: {
1047
0
        ia_filt_cascade_td_struct* filt_cascade_td =
1048
0
            &eq_set->filt_cascade_td[g];
1049
0
        for (b = 0; b < filt_cascade_td->block_count; b++) {
1050
0
          ia_eq_filt_ele_struct* eq_filt_element =
1051
0
              &filt_cascade_td->pstr_eq_filt_block[b].eq_filt_element[0];
1052
0
          switch (eq_filt_element->format) {
1053
0
            case FILTER_ELEMENT_FORMAT_POLE_ZERO:
1054
0
              impd_calc_filt_sect_delay(
1055
0
                  eq_filt_element->pstr_pole_zero_filt.section_count,
1056
0
                  eq_filt_element->pstr_pole_zero_filt.filt_section,
1057
0
                  &sect_delay);
1058
0
              delay += sect_delay;
1059
0
              if (eq_filt_element->pstr_pole_zero_filt.filt_coeffs_flag) {
1060
0
                delay += 0.5f * (eq_filt_element->pstr_pole_zero_filt.fir_filter
1061
0
                                     .coeff_count -
1062
0
                                 1);
1063
0
              }
1064
0
              break;
1065
0
            case FILTER_ELEMENT_FORMAT_FIR:
1066
0
              delay += 0.5f * (eq_filt_element->fir_filter.coeff_count - 1);
1067
0
              break;
1068
0
            default:
1069
0
              break;
1070
0
          }
1071
0
          for (k = 0; k < eq_filt_element->num_ph_align_filt; k++) {
1072
0
            ia_ph_alignment_filt_struct* ph_alignment_filt =
1073
0
                &eq_filt_element->ph_alignment_filt[k];
1074
0
            impd_calc_filt_sect_delay(ph_alignment_filt->section_count,
1075
0
                                      ph_alignment_filt->filt_section,
1076
0
                                      &sect_delay);
1077
0
            delay += sect_delay;
1078
0
          }
1079
0
        }
1080
0
        for (b = 0; b < filt_cascade_td->num_ph_align_filt; b++) {
1081
0
          ia_ph_alignment_filt_struct* ph_alignment_filt =
1082
0
              &filt_cascade_td->ph_alignment_filt[b];
1083
0
          impd_calc_filt_sect_delay(ph_alignment_filt->section_count,
1084
0
                                    ph_alignment_filt->filt_section,
1085
0
                                    &sect_delay);
1086
0
          delay += sect_delay;
1087
0
        }
1088
0
      } break;
1089
0
      case EQ_FILTER_DOMAIN_SUBBAND:
1090
0
      case EQ_FILTER_DOMAIN_NONE:
1091
0
      default:
1092
0
        break;
1093
0
    }
1094
0
  }
1095
0
  *cascade_delay = (WORD32)delay;
1096
0
  return;
1097
0
}
1098
1099
WORD32 impd_derive_eq_set(ia_eq_coeff_struct* str_eq_coeff,
1100
                          ia_eq_instructions_struct* str_eq_instructions,
1101
                          FLOAT32 sample_rate, WORD32 drc_frame_size,
1102
                          WORD32 sub_band_domain_mode,
1103
0
                          ia_eq_set_struct* eq_set) {
1104
0
  WORD32 err, i, eq_frame_size_subband;
1105
1106
0
  eq_set->domain = EQ_FILTER_DOMAIN_NONE;
1107
1108
0
  if (sub_band_domain_mode == SUBBAND_DOMAIN_MODE_OFF) {
1109
0
    if (str_eq_instructions->td_filter_cascade_present == 1) {
1110
0
      err = impd_calc_filt_cascade(
1111
0
          str_eq_coeff->unique_td_filt_ele, str_eq_coeff->str_filter_block,
1112
0
          &str_eq_instructions->str_td_filter_cascade,
1113
0
          str_eq_instructions->eq_ch_group_count, eq_set->filt_cascade_td);
1114
0
      if (err) return (err);
1115
0
    }
1116
1117
0
    eq_set->domain |= EQ_FILTER_DOMAIN_TIME;
1118
0
  }
1119
0
  if (sub_band_domain_mode != SUBBAND_DOMAIN_MODE_OFF) {
1120
0
    switch (sub_band_domain_mode) {
1121
0
      case SUBBAND_DOMAIN_MODE_QMF64:
1122
0
        if (str_eq_coeff->eq_subband_gain_count !=
1123
0
            AUDIO_CODEC_SUBBAND_COUNT_QMF64) {
1124
0
          return (-1);
1125
0
        }
1126
0
        eq_frame_size_subband =
1127
0
            drc_frame_size / AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR_QMF64;
1128
0
        break;
1129
0
      case SUBBAND_DOMAIN_MODE_QMF71:
1130
0
        if (str_eq_coeff->eq_subband_gain_count !=
1131
0
            AUDIO_CODEC_SUBBAND_COUNT_QMF71) {
1132
0
          return (-1);
1133
0
        }
1134
0
        eq_frame_size_subband =
1135
0
            drc_frame_size / AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR_QMF71;
1136
0
        break;
1137
0
      case SUBBAND_DOMAIN_MODE_STFT256:
1138
0
        if (str_eq_coeff->eq_subband_gain_count !=
1139
0
            AUDIO_CODEC_SUBBAND_COUNT_STFT256) {
1140
0
          return (-1);
1141
0
        }
1142
0
        eq_frame_size_subband =
1143
0
            drc_frame_size / AUDIO_CODEC_SUBBAND_DOWNSAMPLING_FACTOR_STFT256;
1144
0
        break;
1145
0
      default:
1146
0
        return (-1);
1147
0
        break;
1148
0
    }
1149
0
    if (str_eq_instructions->subband_gains_present == 1) {
1150
0
      err = impd_calc_subband_gains(
1151
0
          str_eq_coeff, str_eq_instructions->eq_ch_group_count,
1152
0
          str_eq_instructions->subband_gains_index, sample_rate,
1153
0
          eq_frame_size_subband, eq_set->subband_filt);
1154
0
      if (err) return (err);
1155
0
    } else {
1156
0
      if (str_eq_instructions->td_filter_cascade_present == 1) {
1157
0
        err = impd_calc_subband_gains_td_cascade(
1158
0
            str_eq_coeff->unique_td_filt_ele, str_eq_coeff->str_filter_block,
1159
0
            &str_eq_instructions->str_td_filter_cascade,
1160
0
            str_eq_coeff->eq_subband_gain_format,
1161
0
            str_eq_instructions->eq_ch_group_count, sample_rate,
1162
0
            eq_frame_size_subband, eq_set->subband_filt);
1163
0
        if (err) return (err);
1164
0
      }
1165
0
    }
1166
0
    eq_set->domain |= EQ_FILTER_DOMAIN_SUBBAND;
1167
0
  }
1168
0
  eq_set->audio_num_chan = str_eq_instructions->eq_channel_count;
1169
0
  eq_set->eq_ch_group_count = str_eq_instructions->eq_ch_group_count;
1170
1171
0
  for (i = 0; i < str_eq_instructions->eq_channel_count; i++) {
1172
0
    eq_set->eq_ch_group_of_channel[i] =
1173
0
        str_eq_instructions->eq_ch_group_of_channel[i];
1174
0
  }
1175
1176
0
  return (0);
1177
0
}
1178
1179
VOID impd_process_filt_sect(
1180
    ia_filt_sect_struct filt_section[EQ_FILTER_SECTION_COUNT_MAX],
1181
0
    WORD32 channel, FLOAT32* audio_out, WORD32 section_count) {
1182
0
  WORD32 i;
1183
1184
0
  for (i = 0; i < section_count; i++) {
1185
0
    ia_filt_sect_state_struct* filt_sect_state =
1186
0
        &filt_section[i].filt_sect_state[channel];
1187
0
    FLOAT32 audio_in = *audio_out;
1188
0
    *audio_out = audio_in + filt_section[i].b1 * filt_sect_state->in_state_1 +
1189
0
                 filt_section[i].b2 * filt_sect_state->in_state_2 -
1190
0
                 filt_section[i].a1 * filt_sect_state->out_state_1 -
1191
0
                 filt_section[i].a2 * filt_sect_state->out_state_2;
1192
1193
0
    filt_sect_state->in_state_2 = filt_sect_state->in_state_1;
1194
0
    filt_sect_state->in_state_1 = audio_in;
1195
0
    filt_sect_state->out_state_2 = filt_sect_state->out_state_1;
1196
0
    filt_sect_state->out_state_1 = *audio_out;
1197
0
  }
1198
0
  return;
1199
0
}
1200
1201
VOID impd_fir_filt_process(ia_fir_filter_struct* fir_filter, WORD32 channel,
1202
0
                           FLOAT32 audio_in, FLOAT32* audio_out) {
1203
0
  WORD32 i;
1204
0
  FLOAT32* coeff = fir_filter->coeff;
1205
0
  FLOAT32* state = fir_filter->state[channel];
1206
0
  FLOAT32 sum;
1207
0
  sum = coeff[0] * audio_in;
1208
0
  for (i = 1; i < fir_filter->coeff_count; i++) {
1209
0
    sum += coeff[i] * state[i - 1];
1210
0
  }
1211
0
  *audio_out = sum;
1212
0
  for (i = fir_filter->coeff_count - 2; i > 0; i--) {
1213
0
    state[i] = state[i - 1];
1214
0
  }
1215
0
  state[0] = audio_in;
1216
0
  return;
1217
0
}
1218
1219
VOID impd_audio_delay_process(ia_audio_delay_struct* audio_delay,
1220
                              WORD32 channel, FLOAT32 audio_in,
1221
0
                              FLOAT32* ptr_audio_out) {
1222
0
  WORD32 i;
1223
0
  FLOAT32* state = audio_delay->state[channel];
1224
0
  if (audio_delay->delay > 0) {
1225
0
    *ptr_audio_out = state[audio_delay->delay - 1];
1226
0
    for (i = audio_delay->delay - 1; i > 0; i--) {
1227
0
      state[i] = state[i - 1];
1228
0
    }
1229
0
    state[0] = audio_in;
1230
0
  } else {
1231
0
    *ptr_audio_out = audio_in;
1232
0
  }
1233
0
  return;
1234
0
}
1235
1236
VOID impd_pole_zero_filt_process(ia_pole_zero_filt_struct* pstr_pole_zero_filt,
1237
                                 WORD32 channel, FLOAT32 audio_in,
1238
0
                                 FLOAT32* ptr_audio_out) {
1239
0
  FLOAT32 inp = audio_in;
1240
0
  FLOAT32 out = inp;
1241
1242
0
  impd_process_filt_sect(pstr_pole_zero_filt->filt_section, channel, &out,
1243
0
                         pstr_pole_zero_filt->section_count);
1244
0
  inp = out;
1245
1246
0
  if (pstr_pole_zero_filt->filt_coeffs_flag == 1) {
1247
0
    impd_fir_filt_process(&pstr_pole_zero_filt->fir_filter, channel, inp, &out);
1248
0
    inp = out;
1249
0
  }
1250
0
  impd_audio_delay_process(&pstr_pole_zero_filt->audio_delay, channel, inp,
1251
0
                           &out);
1252
1253
0
  *ptr_audio_out = out;
1254
0
  return;
1255
0
}
1256
1257
VOID impd_phase_align_filt_process(
1258
    ia_ph_alignment_filt_struct* ph_alignment_filt, WORD32 channel,
1259
0
    FLOAT32* ptr_audio_out) {
1260
0
  FLOAT32 audio_in = *ptr_audio_out;
1261
0
  FLOAT32 inp = audio_in;
1262
0
  FLOAT32 out = inp;
1263
1264
0
  impd_process_filt_sect(ph_alignment_filt->filt_section, channel, &out,
1265
0
                         ph_alignment_filt->section_count);
1266
0
  inp = out;
1267
1268
0
  impd_audio_delay_process(&ph_alignment_filt->audio_delay, channel, inp, &out);
1269
1270
0
  *ptr_audio_out = out * ph_alignment_filt->gain;
1271
0
  return;
1272
0
}
1273
1274
VOID impd_eq_filt_element_process(
1275
    ia_eq_filt_block_struct str_eq_filt_block[EQ_FILTER_BLOCK_COUNT_MAX],
1276
    WORD32 channel, FLOAT32 audio_in, FLOAT32* ptr_audio_out,
1277
0
    WORD32 block_count) {
1278
0
  WORD32 i;
1279
0
  FLOAT32 inp = audio_in;
1280
0
  FLOAT32 out = inp;
1281
0
  WORD32 k, j;
1282
0
  WORD32 element_count;
1283
0
  for (j = 0; j < block_count; j++) {
1284
0
    FLOAT32 sum = 0.0f;
1285
0
    element_count = str_eq_filt_block[j].element_count;
1286
0
    for (k = 0; k < element_count; k++) {
1287
0
      switch (str_eq_filt_block[j].eq_filt_element[k].format) {
1288
0
        case FILTER_ELEMENT_FORMAT_POLE_ZERO:
1289
0
          impd_pole_zero_filt_process(
1290
0
              &str_eq_filt_block[j].eq_filt_element[k].pstr_pole_zero_filt,
1291
0
              channel, inp, &out);
1292
0
          break;
1293
0
        case FILTER_ELEMENT_FORMAT_FIR:
1294
0
          impd_fir_filt_process(
1295
0
              &str_eq_filt_block[j].eq_filt_element[k].fir_filter, channel, inp,
1296
0
              &out);
1297
0
          break;
1298
0
        default:
1299
0
          break;
1300
0
      }
1301
0
      out *= str_eq_filt_block[j].eq_filt_element[k].elementGainLinear;
1302
1303
0
      for (i = 0; i < str_eq_filt_block[j].eq_filt_element[k].num_ph_align_filt;
1304
0
           i++) {
1305
0
        inp = out;
1306
0
        impd_phase_align_filt_process(
1307
0
            &str_eq_filt_block[j].eq_filt_element[k].ph_alignment_filt[i],
1308
0
            channel, &out);
1309
0
      }
1310
0
      sum += out;
1311
0
    }
1312
0
    inp = sum;
1313
0
  }
1314
0
  *ptr_audio_out = inp;
1315
0
  return;
1316
0
}
1317
1318
WORD32 impd_process_eq_set_time_domain(ia_eq_set_struct* pstr_eq_set,
1319
                                       WORD32 channel, FLOAT32* ptr_audio_in,
1320
                                       FLOAT32* ptr_audio_out,
1321
0
                                       WORD32 frame_size) {
1322
0
  WORD32 i, j, g = 0;
1323
1324
0
  if (pstr_eq_set == NULL) return 0;
1325
1326
0
  g = pstr_eq_set->eq_ch_group_of_channel[channel];
1327
1328
0
  if (g < 0) return 0;
1329
1330
0
  for (i = 0; i < frame_size; i++) {
1331
0
    impd_eq_filt_element_process(
1332
0
        (pstr_eq_set->filt_cascade_td[g].pstr_eq_filt_block), channel,
1333
0
        ptr_audio_in[i], &ptr_audio_out[i],
1334
0
        pstr_eq_set->filt_cascade_td[g].block_count);
1335
1336
0
    for (j = 0; j < pstr_eq_set->filt_cascade_td[g].num_ph_align_filt; j++) {
1337
0
      impd_phase_align_filt_process(
1338
0
          &pstr_eq_set->filt_cascade_td[g].ph_alignment_filt[j], channel,
1339
0
          &ptr_audio_out[i]);
1340
0
    }
1341
1342
0
    ptr_audio_out[i] =
1343
0
        ptr_audio_out[i] * pstr_eq_set->filt_cascade_td[g].cascade_gain_linear;
1344
0
  }
1345
0
  return 0;
1346
0
}
1347