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 #include <math.h>
21 #include <float.h>
22 #include "ixheaac_type_def.h"
23 #include "ixheaac_error_standards.h"
24 #include "ixheaace_error_codes.h"
25
26 #include "iusace_cnst.h"
27 #include "iusace_block_switch_const.h"
28 #include "iusace_bitbuffer.h"
29
30 #include "impd_drc_common_enc.h"
31 #include "impd_drc_uni_drc.h"
32 #include "impd_drc_tables.h"
33 #include "impd_drc_api.h"
34
35 #include "iusace_tns_usac.h"
36 #include "iusace_psy_mod.h"
37 #include "ixheaace_sbr_header.h"
38 #include "ixheaace_config.h"
39 #include "iusace_config.h"
40
41 #include "iusace_rom.h"
42 #include "iusace_fft.h"
43
44 #include "impd_drc_uni_drc_eq.h"
45 #include "impd_drc_uni_drc_filter_bank.h"
46 #include "impd_drc_gain_enc.h"
47 #include "impd_drc_struct_def.h"
48 #include "impd_drc_enc.h"
49 #include "ixheaace_common_utils.h"
50
impd_drc_compand_update_volume(ia_drc_compand_chan_param_struct * pstr_channel_param,FLOAT64 in_value)51 static VOID impd_drc_compand_update_volume(ia_drc_compand_chan_param_struct *pstr_channel_param,
52 FLOAT64 in_value) {
53 FLOAT64 delta = in_value - pstr_channel_param->volume;
54
55 if (delta <= 0.0) {
56 pstr_channel_param->volume += delta * pstr_channel_param->decay;
57 } else {
58 pstr_channel_param->volume += delta * pstr_channel_param->attack;
59 }
60 }
61
impd_drc_compand_get_volume(ia_drc_compand_struct * pstr_drc_compand,FLOAT64 in_lin)62 static FLOAT64 impd_drc_compand_get_volume(ia_drc_compand_struct *pstr_drc_compand,
63 FLOAT64 in_lin) {
64 ULOOPIDX idx;
65 FLOAT64 in_log, out_log;
66 ia_drc_compand_segment_struct *pstr_compand_segment;
67
68 if (in_lin < pstr_drc_compand->in_min_lin) {
69 return pstr_drc_compand->out_min_lin;
70 }
71
72 if (fabs(in_lin) <= FLT_EPSILON) {
73 in_log = log(FLT_EPSILON);
74 }
75 else {
76 in_log = log(fabs(in_lin));
77 }
78
79 for (idx = 1; idx < pstr_drc_compand->nb_segments; idx++) {
80 if (in_log <= pstr_drc_compand->str_segment[idx].x) {
81 break;
82 }
83 }
84
85 pstr_compand_segment = &pstr_drc_compand->str_segment[idx - 1];
86 in_log -= pstr_compand_segment->x;
87 out_log = pstr_compand_segment->y +
88 in_log * (pstr_compand_segment->a * in_log + pstr_compand_segment->b);
89
90 return exp(out_log);
91 }
92
impd_drc_td_drc_gain_calc_process(ia_drc_gain_enc_struct * pstr_drc_gain_enc,WORD32 drc_coefficients_uni_drc_idx,WORD32 gain_set_idx,WORD32 num_samples,FLOAT32 * in_buff,FLOAT32 * out_buff)93 VOID impd_drc_td_drc_gain_calc_process(ia_drc_gain_enc_struct *pstr_drc_gain_enc,
94 WORD32 drc_coefficients_uni_drc_idx, WORD32 gain_set_idx,
95 WORD32 num_samples, FLOAT32 *in_buff, FLOAT32 *out_buff) {
96 LOOPIDX idx;
97 FLOAT64 gain;
98 ia_drc_compand_chan_param_struct *pstr_channel_param;
99 ia_drc_compand_struct *pstr_drc_compand =
100 &pstr_drc_gain_enc->str_drc_compand[drc_coefficients_uni_drc_idx][gain_set_idx];
101
102 pstr_channel_param = &pstr_drc_compand->str_channel_param;
103
104 for (idx = 0; idx < num_samples; idx++) {
105 impd_drc_compand_update_volume(pstr_channel_param, fabs((FLOAT64)in_buff[idx] / 32768.0));
106
107 gain = impd_drc_compand_get_volume(pstr_drc_compand, pstr_channel_param->volume);
108 out_buff[idx] = (FLOAT32)(20.0 * log10(gain));
109 }
110 }
111
impd_drc_td_drc_gain_calc_init(ia_drc_gain_enc_struct * pstr_drc_gain_enc,WORD32 drc_coefficients_uni_drc_idx,WORD32 gain_set_idx)112 IA_ERRORCODE impd_drc_td_drc_gain_calc_init(ia_drc_gain_enc_struct *pstr_drc_gain_enc,
113 WORD32 drc_coefficients_uni_drc_idx,
114 WORD32 gain_set_idx) {
115 ULOOPIDX i, j;
116 UWORD32 num_points;
117 FLOAT64 g1, g2;
118 FLOAT64 x, y, cx, cy, r;
119 FLOAT64 inp_1, inp_2, out_1, out_2, theta, length, radius;
120 ia_drc_compand_struct *pstr_drc_compand;
121 ia_drc_compand_chan_param_struct *pstr_chan_param;
122
123 if ((drc_coefficients_uni_drc_idx >= MAX_DRC_COEFF_COUNT) ||
124 (gain_set_idx >= GAIN_SET_COUNT_MAX)) {
125 return IA_EXHEAACE_CONFIG_FATAL_DRC_COMPAND_FAILED;
126 }
127
128 pstr_drc_compand =
129 &pstr_drc_gain_enc->str_drc_compand[drc_coefficients_uni_drc_idx][gain_set_idx];
130
131 for (i = 0; i < pstr_drc_compand->nb_points; i++) {
132 if (i && pstr_drc_compand->str_segment[2 * ((i - 1) + 1)].x >
133 pstr_drc_compand->str_segment[2 * ((i) + 1)].x) {
134 return IA_EXHEAACE_CONFIG_FATAL_DRC_COMPAND_FAILED;
135 }
136 pstr_drc_compand->str_segment[2 * (i + 1)].y -= pstr_drc_compand->str_segment[2 * (i + 1)].x;
137 }
138 num_points = pstr_drc_compand->nb_points;
139
140 if (num_points == 0 || pstr_drc_compand->str_segment[2 * ((num_points - 1) + 1)].x) {
141 num_points++;
142 }
143
144 pstr_drc_compand->str_segment[0].x =
145 pstr_drc_compand->str_segment[2].x - 2 * pstr_drc_compand->width_db;
146 pstr_drc_compand->str_segment[0].y = pstr_drc_compand->str_segment[2].y;
147 num_points++;
148
149 radius = pstr_drc_compand->width_db * M_LN10_DIV_20;
150
151 for (i = 2; i < num_points; i++) {
152 g1 = (pstr_drc_compand->str_segment[2 * (i - 1)].y -
153 pstr_drc_compand->str_segment[2 * (i - 2)].y) *
154 (pstr_drc_compand->str_segment[2 * i].x - pstr_drc_compand->str_segment[2 * (i - 1)].x);
155 g2 = (pstr_drc_compand->str_segment[2 * i].y - pstr_drc_compand->str_segment[2 * (i - 1)].y) *
156 (pstr_drc_compand->str_segment[2 * (i - 1)].x -
157 pstr_drc_compand->str_segment[2 * (i - 2)].x);
158
159 if (fabs(g1 - g2)) {
160 continue;
161 }
162 num_points--;
163
164 for (j = --i; j < num_points; j++) {
165 pstr_drc_compand->str_segment[2 * j] = pstr_drc_compand->str_segment[2 * (j + 1)];
166 }
167 }
168
169 pstr_drc_compand->nb_segments = num_points * 2;
170 for (i = 0; i < pstr_drc_compand->nb_segments; i += 2) {
171 pstr_drc_compand->str_segment[i].y += pstr_drc_compand->gain_db;
172 pstr_drc_compand->str_segment[i].x *= M_LN10_DIV_20;
173 pstr_drc_compand->str_segment[i].y *= M_LN10_DIV_20;
174 }
175
176 for (i = 4; i < pstr_drc_compand->nb_segments; i += 2) {
177 FLOAT64 num = 0.0;
178 FLOAT64 den = 0.0f;
179
180 num = pstr_drc_compand->str_segment[i - 2].y - pstr_drc_compand->str_segment[i - 4].y;
181 den = pstr_drc_compand->str_segment[i - 2].x - pstr_drc_compand->str_segment[i - 4].x;
182 length = hypot(num, den);
183 if (length < FLT_EPSILON) {
184 return IA_EXHEAACE_EXE_NONFATAL_USAC_INVALID_GAIN_POINTS;
185 }
186 pstr_drc_compand->str_segment[i - 4].a = 0;
187 pstr_drc_compand->str_segment[i - 4].b = ixheaace_div64(num, den);
188 theta = atan2(num, den);
189 r = MIN(radius, length);
190 pstr_drc_compand->str_segment[i - 3].x =
191 pstr_drc_compand->str_segment[i - 2].x - r * cos(theta);
192 pstr_drc_compand->str_segment[i - 3].y =
193 pstr_drc_compand->str_segment[i - 2].y - r * sin(theta);
194
195 num = pstr_drc_compand->str_segment[i].y - pstr_drc_compand->str_segment[i - 2].y;
196 den = pstr_drc_compand->str_segment[i].x - pstr_drc_compand->str_segment[i - 2].x;
197 length = hypot(num, den);
198 if (length < FLT_EPSILON) {
199 return IA_EXHEAACE_EXE_NONFATAL_USAC_INVALID_GAIN_POINTS;
200 }
201 pstr_drc_compand->str_segment[i - 2].a = 0;
202 pstr_drc_compand->str_segment[i - 2].b = ixheaace_div64(num, den);
203 theta = atan2(num, den);
204 r = MIN(radius, length / 2);
205 x = pstr_drc_compand->str_segment[i - 2].x + r * cos(theta);
206 y = pstr_drc_compand->str_segment[i - 2].y + r * sin(theta);
207
208 cx =
209 (pstr_drc_compand->str_segment[i - 3].x + pstr_drc_compand->str_segment[i - 2].x + x) / 3;
210 cy =
211 (pstr_drc_compand->str_segment[i - 3].y + pstr_drc_compand->str_segment[i - 2].y + y) / 3;
212
213 pstr_drc_compand->str_segment[i - 2].x = x;
214 pstr_drc_compand->str_segment[i - 2].y = y;
215
216 inp_1 = cx - pstr_drc_compand->str_segment[i - 3].x;
217 out_1 = cy - pstr_drc_compand->str_segment[i - 3].y;
218 inp_2 = pstr_drc_compand->str_segment[i - 2].x - pstr_drc_compand->str_segment[i - 3].x;
219 out_2 = pstr_drc_compand->str_segment[i - 2].y - pstr_drc_compand->str_segment[i - 3].y;
220
221 num = (out_2 * inp_1) - (inp_2 * out_1);
222 den = (inp_2 - inp_1) * inp_1 * inp_2;
223 pstr_drc_compand->str_segment[i - 3].a = ixheaace_div64(num, den);
224
225 num = out_1 - (pstr_drc_compand->str_segment[i - 3].a * inp_1 * inp_1);
226 den = inp_1;
227 pstr_drc_compand->str_segment[i - 3].b = ixheaace_div64(num, den);
228 }
229 pstr_drc_compand->str_segment[i - 3].x = 0;
230 pstr_drc_compand->str_segment[i - 3].y = pstr_drc_compand->str_segment[i - 3].y;
231
232 pstr_drc_compand->in_min_lin = exp(pstr_drc_compand->str_segment[1].x);
233 pstr_drc_compand->out_min_lin = exp(pstr_drc_compand->str_segment[1].y);
234
235 pstr_chan_param = &pstr_drc_compand->str_channel_param;
236
237 if (pstr_chan_param->attack < 1.0 / pstr_drc_gain_enc->sample_rate) {
238 pstr_chan_param->attack = 1.0;
239 } else {
240 pstr_chan_param->attack =
241 1.0 - exp(-1.0 / (pstr_drc_gain_enc->sample_rate * pstr_chan_param->attack));
242 }
243
244 if (pstr_chan_param->decay < 1.0 / pstr_drc_gain_enc->sample_rate) {
245 pstr_chan_param->decay = 1.0;
246 } else {
247 pstr_chan_param->decay =
248 1.0 - exp(-1.0 / (pstr_drc_gain_enc->sample_rate * pstr_chan_param->decay));
249 }
250 pstr_chan_param->volume = EXP10(pstr_drc_compand->initial_volume / 20);
251
252 return IA_NO_ERROR;
253 }
254
impd_drc_stft_drc_compand_get_volume(ia_drc_stft_gain_calc_struct * pstr_drc_stft_gain_handle,FLOAT32 in_db)255 static FLOAT32 impd_drc_stft_drc_compand_get_volume(
256 ia_drc_stft_gain_calc_struct *pstr_drc_stft_gain_handle, FLOAT32 in_db) {
257 ULOOPIDX idx;
258 FLOAT32 in_log, out_log;
259 ia_drc_compand_segment_struct *pstr_compand_segment;
260
261 if (in_db < pstr_drc_stft_gain_handle->in_min_db) {
262 return pstr_drc_stft_gain_handle->out_min_db;
263 }
264
265 in_log = (FLOAT32)(in_db * M_LN10_DIV_20);
266
267 for (idx = 1; idx < pstr_drc_stft_gain_handle->nb_segments; idx++) {
268 if (in_log <= pstr_drc_stft_gain_handle->str_segment[idx].x) {
269 break;
270 }
271 }
272
273 pstr_compand_segment = &pstr_drc_stft_gain_handle->str_segment[idx - 1];
274 in_log -= (FLOAT32)(pstr_compand_segment->x);
275 out_log = (FLOAT32)(pstr_compand_segment->y +
276 in_log * (pstr_compand_segment->a * in_log + pstr_compand_segment->b));
277
278 return (FLOAT32)(out_log * M_LOG10_E * 20.0f);
279 }
280
impd_drc_stft_drc_gain_calc_process(ia_drc_gain_enc_struct * pstr_drc_gain_enc,WORD32 drc_coefficients_uni_drc_idx,WORD32 gain_set_idx,WORD32 band_idx,WORD32 start_sub_band_index,WORD32 stop_sub_band_index,UWORD32 num_frames,FLOAT32 * in_buff,FLOAT32 * gain_values)281 VOID impd_drc_stft_drc_gain_calc_process(ia_drc_gain_enc_struct *pstr_drc_gain_enc,
282 WORD32 drc_coefficients_uni_drc_idx, WORD32 gain_set_idx,
283 WORD32 band_idx, WORD32 start_sub_band_index,
284 WORD32 stop_sub_band_index, UWORD32 num_frames,
285 FLOAT32 *in_buff, FLOAT32 *gain_values) {
286 ULOOPIDX idx;
287 LOOPIDX band;
288 FLOAT32 xg, xl, yl, cdb;
289 FLOAT32 in_real, in_imag;
290 FLOAT32 abs_val_sqr;
291 UWORD32 num_time_slot = num_frames / STFT256_HOP_SIZE;
292
293 ia_drc_stft_gain_calc_struct *pstr_drc_stft_gain_handle =
294 &pstr_drc_gain_enc
295 ->str_drc_stft_gain_handle[drc_coefficients_uni_drc_idx][gain_set_idx][band_idx];
296
297 for (idx = 0; idx < num_time_slot; idx++) {
298 abs_val_sqr = 0.0f;
299 for (band = start_sub_band_index; band <= stop_sub_band_index; band++) {
300 in_imag = in_buff[((idx * STFT256_HOP_SIZE + band) << 1) + 1];
301 in_real = in_buff[(idx * STFT256_HOP_SIZE + band) << 1];
302
303 abs_val_sqr += sqrtf(powf(in_real, 2.0f) + powf(in_imag, 2.0f));
304 }
305
306 abs_val_sqr /= (FLOAT32)((stop_sub_band_index - start_sub_band_index + 1) << 4);
307
308 abs_val_sqr = powf(abs_val_sqr, 2.0f);
309 xg = 10.0f * log10f((abs_val_sqr) + 2e-13f);
310
311 xl = -impd_drc_stft_drc_compand_get_volume(pstr_drc_stft_gain_handle, xg);
312
313 if (xl > pstr_drc_stft_gain_handle->yl_z1[band]) {
314 yl = (pstr_drc_stft_gain_handle->alpha_a * pstr_drc_stft_gain_handle->yl_z1[band]) +
315 ((1.0f - pstr_drc_stft_gain_handle->alpha_a) * xl);
316 } else {
317 yl = (pstr_drc_stft_gain_handle->alpha_r * pstr_drc_stft_gain_handle->yl_z1[band]) +
318 ((1.0f - pstr_drc_stft_gain_handle->alpha_r) * xl);
319 }
320
321 pstr_drc_stft_gain_handle->yl_z1[band] = yl;
322 cdb = -yl;
323 cdb = MAX(IMPD_DRCSPECTRAL_FLOOR, (powf(10.0f, cdb / 20.0f)));
324 cdb = 20.0f * log10f(cdb);
325
326 for (band = 0; band < STFT256_HOP_SIZE; band++) {
327 gain_values[idx * STFT256_HOP_SIZE + band] = cdb;
328 }
329 }
330 }
331
impd_drc_stft_drc_gain_calc_init(ia_drc_gain_enc_struct * pstr_drc_gain_enc,WORD32 drc_coefficients_uni_drc_idx,WORD32 gain_set_idx,WORD32 band_idx)332 IA_ERRORCODE impd_drc_stft_drc_gain_calc_init(ia_drc_gain_enc_struct *pstr_drc_gain_enc,
333 WORD32 drc_coefficients_uni_drc_idx,
334 WORD32 gain_set_idx, WORD32 band_idx) {
335 ULOOPIDX i, j;
336 UWORD32 num_points;
337 FLOAT32 width_e, tmp;
338 FLOAT64 g1, g2;
339 FLOAT64 x, y, cx, cy, r;
340 FLOAT64 inp_1, inp_2, out_1, out_2, theta, len;
341 ia_drc_compand_chan_param_struct *pstr_chan_param;
342 ia_drc_stft_gain_calc_struct *pstr_drc_stft_gain_handle;
343
344 if ((drc_coefficients_uni_drc_idx >= MAX_DRC_COEFF_COUNT) ||
345 (gain_set_idx >= GAIN_SET_COUNT_MAX) || (band_idx >= MAX_BAND_COUNT)) {
346 return IA_EXHEAACE_CONFIG_FATAL_DRC_COMPAND_FAILED;
347 }
348
349 pstr_drc_stft_gain_handle =
350 &pstr_drc_gain_enc
351 ->str_drc_stft_gain_handle[drc_coefficients_uni_drc_idx][gain_set_idx][band_idx];
352
353 width_e = (FLOAT32)(pstr_drc_stft_gain_handle->width_db * M_LN10_DIV_20);
354
355 for (i = 0; i < pstr_drc_stft_gain_handle->nb_points; i++) {
356 if (i && pstr_drc_stft_gain_handle->str_segment[2 * ((i - 1) + 1)].x >
357 pstr_drc_stft_gain_handle->str_segment[2 * (i + 1)].x) {
358 return IA_EXHEAACE_CONFIG_FATAL_DRC_COMPAND_FAILED;
359 }
360 pstr_drc_stft_gain_handle->str_segment[2 * (i + 1)].y -=
361 pstr_drc_stft_gain_handle->str_segment[2 * (i + 1)].x;
362 }
363 num_points = pstr_drc_stft_gain_handle->nb_points;
364
365 if (num_points == 0 || pstr_drc_stft_gain_handle->str_segment[2 * ((num_points - 1) + 1)].x) {
366 num_points++;
367 }
368
369 pstr_drc_stft_gain_handle->str_segment[0].x =
370 pstr_drc_stft_gain_handle->str_segment[2].x - pstr_drc_stft_gain_handle->width_db;
371 pstr_drc_stft_gain_handle->str_segment[0].y = pstr_drc_stft_gain_handle->str_segment[2].y;
372 num_points++;
373
374 for (i = 2; i < num_points; i++) {
375 g1 = (pstr_drc_stft_gain_handle->str_segment[2 * (i - 1)].y -
376 pstr_drc_stft_gain_handle->str_segment[2 * (i - 2)].y) *
377 (pstr_drc_stft_gain_handle->str_segment[2 * i].x -
378 pstr_drc_stft_gain_handle->str_segment[2 * (i - 1)].x);
379 g2 = (pstr_drc_stft_gain_handle->str_segment[2 * i].y -
380 pstr_drc_stft_gain_handle->str_segment[2 * (i - 1)].y) *
381 (pstr_drc_stft_gain_handle->str_segment[2 * (i - 1)].x -
382 pstr_drc_stft_gain_handle->str_segment[2 * (i - 2)].x);
383
384 if (fabs(g1 - g2)) {
385 continue;
386 }
387 num_points--;
388
389 for (j = --i; j < num_points; j++) {
390 pstr_drc_stft_gain_handle->str_segment[2 * j] =
391 pstr_drc_stft_gain_handle->str_segment[2 * (j + 1)];
392 }
393 }
394 pstr_drc_stft_gain_handle->nb_segments = num_points * 2;
395 for (i = 0; i < pstr_drc_stft_gain_handle->nb_segments; i += 2) {
396 pstr_drc_stft_gain_handle->str_segment[i].y += pstr_drc_stft_gain_handle->gain_db;
397 pstr_drc_stft_gain_handle->str_segment[i].x *= M_LN10_DIV_20;
398 pstr_drc_stft_gain_handle->str_segment[i].y *= M_LN10_DIV_20;
399 }
400
401 for (i = 4; i < pstr_drc_stft_gain_handle->nb_segments; i += 2) {
402 FLOAT64 denominator;
403 FLOAT64 numerator;
404
405 denominator = pstr_drc_stft_gain_handle->str_segment[i - 2].x -
406 pstr_drc_stft_gain_handle->str_segment[i - 4].x;
407 numerator = pstr_drc_stft_gain_handle->str_segment[i - 2].y -
408 pstr_drc_stft_gain_handle->str_segment[i - 4].y;
409 len = hypot(denominator , numerator);
410 if (len < FLT_EPSILON) {
411 return IA_EXHEAACE_EXE_NONFATAL_USAC_INVALID_GAIN_POINTS;
412 }
413 pstr_drc_stft_gain_handle->str_segment[i - 4].a = 0;
414 pstr_drc_stft_gain_handle->str_segment[i - 4].b = ixheaace_div64(numerator, denominator);
415 theta = atan2(numerator, denominator);
416 r = MIN(width_e / (2.0f * cos(theta)), len / 2);
417
418 pstr_drc_stft_gain_handle->str_segment[i - 3].x =
419 pstr_drc_stft_gain_handle->str_segment[i - 2].x - r * cos(theta);
420 pstr_drc_stft_gain_handle->str_segment[i - 3].y =
421 pstr_drc_stft_gain_handle->str_segment[i - 2].y - r * sin(theta);
422
423 denominator = pstr_drc_stft_gain_handle->str_segment[i].x -
424 pstr_drc_stft_gain_handle->str_segment[i - 2].x;
425 numerator = pstr_drc_stft_gain_handle->str_segment[i].y -
426 pstr_drc_stft_gain_handle->str_segment[i - 2].y;
427 len = hypot(denominator, numerator);
428 if (len < FLT_EPSILON) {
429 return IA_EXHEAACE_EXE_NONFATAL_USAC_INVALID_GAIN_POINTS;
430 }
431 pstr_drc_stft_gain_handle->str_segment[i - 2].a = 0;
432 pstr_drc_stft_gain_handle->str_segment[i - 2].b = ixheaace_div64(numerator, denominator);
433
434 theta = atan2(numerator, denominator);
435 r = MIN(width_e / (2.0f * cos(theta)), len / 2);
436 x = pstr_drc_stft_gain_handle->str_segment[i - 2].x + r * cos(theta);
437 y = pstr_drc_stft_gain_handle->str_segment[i - 2].y + r * sin(theta);
438
439 cx = (pstr_drc_stft_gain_handle->str_segment[i - 3].x +
440 pstr_drc_stft_gain_handle->str_segment[i - 2].x + x) /
441 3;
442 cy = (pstr_drc_stft_gain_handle->str_segment[i - 3].y +
443 pstr_drc_stft_gain_handle->str_segment[i - 2].y + y) /
444 3;
445
446 pstr_drc_stft_gain_handle->str_segment[i - 2].x = x;
447 pstr_drc_stft_gain_handle->str_segment[i - 2].y = y;
448
449 inp_1 = cx - pstr_drc_stft_gain_handle->str_segment[i - 3].x;
450 out_1 = cy - pstr_drc_stft_gain_handle->str_segment[i - 3].y;
451 inp_2 = pstr_drc_stft_gain_handle->str_segment[i - 2].x -
452 pstr_drc_stft_gain_handle->str_segment[i - 3].x;
453 out_2 = pstr_drc_stft_gain_handle->str_segment[i - 2].y -
454 pstr_drc_stft_gain_handle->str_segment[i - 3].y;
455 numerator = (out_2 * inp_1) - (inp_2 * out_1);
456 denominator = (inp_2 - inp_1) * inp_2 * inp_1;
457 pstr_drc_stft_gain_handle->str_segment[i - 3].a = ixheaace_div64(numerator, denominator);
458
459 numerator = out_1 - (pstr_drc_stft_gain_handle->str_segment[i - 3].a * inp_1 * inp_1);
460 denominator = inp_1;
461 pstr_drc_stft_gain_handle->str_segment[i - 3].b = ixheaace_div64(numerator, denominator);
462 }
463 pstr_drc_stft_gain_handle->str_segment[i - 3].x = 0;
464 pstr_drc_stft_gain_handle->str_segment[i - 3].y =
465 pstr_drc_stft_gain_handle->str_segment[i - 2].y;
466
467 pstr_drc_stft_gain_handle->in_min_db =
468 (FLOAT32)(pstr_drc_stft_gain_handle->str_segment[1].x * M_LOG10_E * 20.0f);
469 pstr_drc_stft_gain_handle->out_min_db =
470 (FLOAT32)(pstr_drc_stft_gain_handle->str_segment[1].y * M_LOG10_E * 20.0f);
471
472 pstr_chan_param = &pstr_drc_stft_gain_handle->str_channel_param;
473
474 pstr_chan_param->volume = EXP10(pstr_drc_stft_gain_handle->initial_volume / 20.0f);
475
476 for (i = 0; i < STFT256_HOP_SIZE; i++) {
477 pstr_drc_stft_gain_handle->yl_z1[i] = 0.0f;
478 }
479
480 tmp = (pstr_drc_stft_gain_handle->attack_ms / STFT256_HOP_SIZE) *
481 pstr_drc_gain_enc->sample_rate * 0.001f;
482 if ((fabs(tmp) < FLT_EPSILON) && (tmp >= 0.0f)) {
483 pstr_drc_stft_gain_handle->alpha_a = 0;
484 }
485 else {
486 pstr_drc_stft_gain_handle->alpha_a = expf(ixheaace_div32(-1.0f, tmp));
487 }
488
489 tmp = (pstr_drc_stft_gain_handle->release_ms / STFT256_HOP_SIZE) *
490 pstr_drc_gain_enc->sample_rate * 0.001f;
491 if ((fabs(tmp) < FLT_EPSILON) && (tmp >= 0.0f)) {
492 pstr_drc_stft_gain_handle->alpha_r = 0;
493 }
494 else {
495 pstr_drc_stft_gain_handle->alpha_r = expf(ixheaace_div32(-1.0f, tmp));
496 }
497
498 return IA_NO_ERROR;
499 }
500
impd_drc_stft_drc_convert_to_fd(ia_drc_gain_enc_struct * pstr_drc_gain_enc,FLOAT32 * ptr_input,UWORD32 ch_idx,UWORD32 frame_size,FLOAT32 * ptr_output,VOID * pstr_scratch)501 VOID impd_drc_stft_drc_convert_to_fd(ia_drc_gain_enc_struct *pstr_drc_gain_enc,
502 FLOAT32 *ptr_input, UWORD32 ch_idx, UWORD32 frame_size,
503 FLOAT32 *ptr_output, VOID *pstr_scratch) {
504 ULOOPIDX i, j;
505 UWORD32 num_time_slot = frame_size / STFT256_HOP_SIZE;
506 FLOAT32 time_sample_vector;
507 iusace_scratch_mem *ptr_scratch = (iusace_scratch_mem *)(pstr_scratch);
508 pFLOAT32 scratch_buff = ptr_scratch->ptr_drc_scratch_buf;
509
510 for (i = 0; i < num_time_slot; i++) {
511 for (j = 0; j < STFT256_HOP_SIZE; j++) {
512 time_sample_vector = (FLOAT32)(ptr_input[i * STFT256_HOP_SIZE + j] / (32768.0));
513
514 scratch_buff[(j << 1)] =
515 (FLOAT32)(pstr_drc_gain_enc->stft_tmp_in_buf_time[ch_idx][j] * iusace_sine_win_256[j]);
516 scratch_buff[(j << 1) + 1] = 0.0f;
517
518 scratch_buff[(STFT256_HOP_SIZE + j) << 1] =
519 (FLOAT32)(iusace_sine_win_256[STFT256_HOP_SIZE - 1 - j] * time_sample_vector);
520 scratch_buff[((STFT256_HOP_SIZE + j) << 1) + 1] = 0.0f;
521
522 pstr_drc_gain_enc->stft_tmp_in_buf_time[ch_idx][j] = time_sample_vector;
523 }
524
525 iusace_complex_fft(scratch_buff, STFT256_HOP_SIZE << 1, ptr_scratch);
526
527 ptr_output[(i * STFT256_HOP_SIZE) << 1] = scratch_buff[0];
528 ptr_output[((i * STFT256_HOP_SIZE) << 1) + 1] = scratch_buff[STFT256_HOP_SIZE << 1];
529
530 for (j = 1; j < STFT256_HOP_SIZE; j++) {
531 ptr_output[(i * STFT256_HOP_SIZE + j) << 1] = scratch_buff[j << 1];
532 ptr_output[((i * STFT256_HOP_SIZE + j) << 1) + 1] = scratch_buff[(j << 1) + 1];
533 }
534 }
535 }
536