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_filter_bank.h"
30 #include "impd_drc_gain_dec.h"
31 #include "impd_parametric_drc_dec.h"
32 #include "impd_drc_multi_band.h"
33 #include "impd_drc_process_audio.h"
34 #include "impd_drc_eq.h"
35 #include "impd_drc_gain_decoder.h"
36
37 extern const ia_cicp_sigmoid_characteristic_param_struct
38 pstr_cicp_sigmoid_characteristic_param[];
39
impd_gain_db_to_lin(ia_interp_params_struct * interp_params_str,WORD32 drc_band,FLOAT32 in_param_db_gain,FLOAT32 in_param_db_slope,FLOAT32 * out_param_lin_gain,FLOAT32 * out_param_lin_slope)40 VOID impd_gain_db_to_lin(ia_interp_params_struct* interp_params_str,
41 WORD32 drc_band, FLOAT32 in_param_db_gain,
42 FLOAT32 in_param_db_slope, FLOAT32* out_param_lin_gain,
43 FLOAT32* out_param_lin_slope) {
44 FLOAT32 loc_db_gain = in_param_db_gain;
45 FLOAT32 gain_ratio = 1.0;
46
47 ia_gain_modifiers_struct* pstr_gain_modifiers =
48 interp_params_str->pstr_gain_modifiers;
49 if (interp_params_str->gain_modification_flag) {
50 if ((interp_params_str->characteristic_index > 0) &&
51 (loc_db_gain != 0.0f)) {
52 gain_ratio = 1.0f;
53 }
54
55 if (loc_db_gain < 0.0f) {
56 gain_ratio *= interp_params_str->compress;
57 } else {
58 gain_ratio *= interp_params_str->boost;
59 }
60 }
61 if (pstr_gain_modifiers->gain_scaling_flag[drc_band] == 1) {
62 if (loc_db_gain < 0.0) {
63 gain_ratio *= pstr_gain_modifiers->attn_scaling[drc_band];
64 } else {
65 gain_ratio *= pstr_gain_modifiers->ampl_scaling[drc_band];
66 }
67 }
68 if ((interp_params_str->pstr_ducking_modifiers->ducking_scaling_flag == 1) &&
69 (interp_params_str->ducking_flag == 1)) {
70 gain_ratio *= interp_params_str->pstr_ducking_modifiers->ducking_scaling;
71 }
72
73 {
74 *out_param_lin_gain =
75 (FLOAT32)pow(2.0, (FLOAT64)(gain_ratio * loc_db_gain / 6.0f));
76 *out_param_lin_slope = SLOPE_FACTOR_DB_TO_LINEAR * gain_ratio *
77 *out_param_lin_gain * in_param_db_slope;
78
79 if (pstr_gain_modifiers->gain_offset_flag[drc_band] == 1) {
80 *out_param_lin_gain *= (FLOAT32)pow(
81 2.0, (FLOAT64)(pstr_gain_modifiers->gain_offset[drc_band] / 6.0f));
82 }
83 if ((interp_params_str->limiter_peak_target_present == 1) &&
84 (interp_params_str->clipping_flag == 1)) {
85 *out_param_lin_gain *= (FLOAT32)pow(
86 2.0, max(0.0, -interp_params_str->limiter_peak_target -
87 interp_params_str->loudness_normalization_gain_db) /
88 6.0);
89 if (*out_param_lin_gain >= 1.0) {
90 *out_param_lin_gain = 1.0;
91 *out_param_lin_slope = 0.0;
92 }
93 }
94 }
95 return;
96 }
97
98 WORD32
impd_compressor_io_sigmoid(ia_split_drc_characteristic_struct * split_drc_characteristic,FLOAT32 in_db_level,FLOAT32 * out_db_gain)99 impd_compressor_io_sigmoid(
100 ia_split_drc_characteristic_struct* split_drc_characteristic,
101 FLOAT32 in_db_level, FLOAT32* out_db_gain) {
102 FLOAT32 tmp;
103 FLOAT32 in_out_ratio = split_drc_characteristic->in_out_ratio;
104 FLOAT32 gainDbLimit = split_drc_characteristic->gain;
105 FLOAT32 exp = split_drc_characteristic->exp;
106
107 tmp = (DRC_INPUT_LOUDNESS_TARGET - in_db_level) * in_out_ratio;
108 if (exp < 1000.0f) {
109 FLOAT32 x = tmp / gainDbLimit;
110 if (x < 0.0f) {
111 return (UNEXPECTED_ERROR);
112 }
113 *out_db_gain = (FLOAT32)(tmp / pow(1.0f + pow(x, exp), 1.0f / exp));
114 } else {
115 *out_db_gain = tmp;
116 }
117 if (split_drc_characteristic->flip_sign == 1) {
118 *out_db_gain = -*out_db_gain;
119 }
120 return (0);
121 }
122
123 WORD32
impd_compressor_io_sigmoid_inv(ia_split_drc_characteristic_struct * split_drc_characteristic,FLOAT32 loc_db_gain,FLOAT32 * in_level)124 impd_compressor_io_sigmoid_inv(
125 ia_split_drc_characteristic_struct* split_drc_characteristic,
126 FLOAT32 loc_db_gain, FLOAT32* in_level) {
127 FLOAT32 in_out_ratio = split_drc_characteristic->in_out_ratio;
128 FLOAT32 gainDbLimit = split_drc_characteristic->gain;
129 FLOAT32 exp = split_drc_characteristic->exp;
130 FLOAT32 tmp = loc_db_gain;
131
132 if (split_drc_characteristic->flip_sign == 1) {
133 tmp = -loc_db_gain;
134 }
135 if (exp < 1000.0f) {
136 FLOAT32 x = tmp / gainDbLimit;
137 if (x < 0.0f) {
138 return (UNEXPECTED_ERROR);
139 }
140 tmp = (FLOAT32)(tmp / pow(1.0f - pow(x, exp), 1.0f / exp));
141 }
142 *in_level = DRC_INPUT_LOUDNESS_TARGET - tmp / in_out_ratio;
143
144 return (0);
145 }
146
147 WORD32
impd_compressor_io_nodes_lt(ia_split_drc_characteristic_struct * split_drc_characteristic,FLOAT32 in_db_level,FLOAT32 * out_db_gain)148 impd_compressor_io_nodes_lt(
149 ia_split_drc_characteristic_struct* split_drc_characteristic,
150 FLOAT32 in_db_level, FLOAT32* out_db_gain) {
151 WORD32 n;
152 FLOAT32 w;
153 FLOAT32* node_level = split_drc_characteristic->node_level;
154 FLOAT32* node_gain = split_drc_characteristic->node_gain;
155
156 if (in_db_level > DRC_INPUT_LOUDNESS_TARGET) {
157 return (UNEXPECTED_ERROR);
158 }
159 for (n = 1; n <= split_drc_characteristic->characteristic_node_count; n++) {
160 if ((in_db_level <= node_level[n - 1]) && (in_db_level > node_level[n])) {
161 w = (node_level[n] - in_db_level) / (node_level[n] - node_level[n - 1]);
162 *out_db_gain = (FLOAT32)(w * node_gain[n - 1] + (1.0 - w) * node_gain[n]);
163 }
164 }
165 *out_db_gain = node_gain[split_drc_characteristic->characteristic_node_count];
166 return (0);
167 }
168
169 WORD32
impd_compressor_io_nodes_rt(ia_split_drc_characteristic_struct * split_drc_characteristic,FLOAT32 in_db_level,FLOAT32 * out_db_gain)170 impd_compressor_io_nodes_rt(
171 ia_split_drc_characteristic_struct* split_drc_characteristic,
172 FLOAT32 in_db_level, FLOAT32* out_db_gain) {
173 WORD32 n;
174 FLOAT32 w;
175 FLOAT32* node_level = split_drc_characteristic->node_level;
176 FLOAT32* node_gain = split_drc_characteristic->node_gain;
177
178 if (in_db_level < DRC_INPUT_LOUDNESS_TARGET) {
179 return (UNEXPECTED_ERROR);
180 }
181 for (n = 1; n <= split_drc_characteristic->characteristic_node_count; n++) {
182 if ((in_db_level >= node_level[n - 1]) && (in_db_level < node_level[n])) {
183 w = (FLOAT32)(node_level[n] - in_db_level) /
184 (node_level[n] - node_level[n - 1]);
185 *out_db_gain = (FLOAT32)(w * node_gain[n - 1] + (1.0 - w) * node_gain[n]);
186 }
187 }
188 *out_db_gain =
189 (node_gain[split_drc_characteristic->characteristic_node_count]);
190 return (0);
191 }
192
impd_compressor_io_nodes_inverse(ia_split_drc_characteristic_struct * split_drc_characteristic,FLOAT32 loc_db_gain,FLOAT32 * in_level)193 VOID impd_compressor_io_nodes_inverse(
194 ia_split_drc_characteristic_struct* split_drc_characteristic,
195 FLOAT32 loc_db_gain, FLOAT32* in_level) {
196 WORD32 n;
197 FLOAT32 w;
198 FLOAT32* node_level = split_drc_characteristic->node_level;
199 FLOAT32* node_gain = split_drc_characteristic->node_gain;
200 WORD32 node_count = split_drc_characteristic->characteristic_node_count;
201
202 if (node_gain[1] < 0.0f) {
203 if (loc_db_gain <= node_gain[node_count]) {
204 *in_level = node_level[node_count];
205 } else {
206 if (loc_db_gain >= 0.0f) {
207 *in_level = DRC_INPUT_LOUDNESS_TARGET;
208 } else {
209 for (n = 1; n <= node_count; n++) {
210 if ((loc_db_gain <= node_gain[n - 1]) &&
211 (loc_db_gain > node_gain[n])) {
212 w = (node_gain[n] - loc_db_gain) /
213 (node_gain[n] - node_gain[n - 1]);
214 *in_level =
215 (FLOAT32)(w * node_level[n - 1] + (1.0 - w) * node_level[n]);
216 }
217 }
218 }
219 }
220 } else {
221 if (loc_db_gain >= node_gain[node_count]) {
222 *in_level = node_level[node_count];
223 } else {
224 if (loc_db_gain <= 0.0f) {
225 *in_level = DRC_INPUT_LOUDNESS_TARGET;
226 } else {
227 for (n = 1; n <= node_count; n++) {
228 if ((loc_db_gain >= node_gain[n - 1]) &&
229 (loc_db_gain < node_gain[n])) {
230 w = (FLOAT32)(node_gain[n] - loc_db_gain) /
231 (node_gain[n] - node_gain[n - 1]);
232 *in_level =
233 (FLOAT32)(w * node_level[n - 1] + (1.0 - w) * node_level[n]);
234 }
235 }
236 }
237 }
238 }
239 return;
240 }
241
242 WORD32
impd_map_gain(ia_split_drc_characteristic_struct * split_drc_characteristic_source,ia_split_drc_characteristic_struct * split_drc_characteristic_target,FLOAT32 gain_in_db,FLOAT32 * gain_out_db)243 impd_map_gain(
244 ia_split_drc_characteristic_struct* split_drc_characteristic_source,
245 ia_split_drc_characteristic_struct* split_drc_characteristic_target,
246 FLOAT32 gain_in_db, FLOAT32* gain_out_db) {
247 FLOAT32 in_level=0;
248 WORD32 err = 0;
249
250 switch (split_drc_characteristic_source->characteristic_format) {
251 case CHARACTERISTIC_SIGMOID:
252 err = impd_compressor_io_sigmoid_inv(split_drc_characteristic_source,
253 gain_in_db, &in_level);
254 if (err) return (err);
255 break;
256 case CHARACTERISTIC_NODES:
257 impd_compressor_io_nodes_inverse(split_drc_characteristic_source,
258 gain_in_db, &in_level);
259
260 break;
261 case CHARACTERISTIC_PASS_THRU:
262 in_level = gain_in_db;
263 break;
264 default:
265 return (UNEXPECTED_ERROR);
266 break;
267 }
268 switch (split_drc_characteristic_target->characteristic_format) {
269 case CHARACTERISTIC_SIGMOID:
270 err = impd_compressor_io_sigmoid(split_drc_characteristic_target, in_level,
271 gain_out_db);
272 if (err) return (err);
273 break;
274 case CHARACTERISTIC_NODES:
275 if (in_level < DRC_INPUT_LOUDNESS_TARGET) {
276 err = impd_compressor_io_nodes_lt(split_drc_characteristic_target,
277 in_level, gain_out_db);
278 if (err) return (err);
279 } else {
280 err = impd_compressor_io_nodes_rt(split_drc_characteristic_target,
281 in_level, gain_out_db);
282 if (err) return (err);
283 }
284 break;
285 case CHARACTERISTIC_PASS_THRU:
286 *gain_out_db = in_level;
287 break;
288 default:
289 break;
290 }
291 return (0);
292 }
293
294 WORD32
impd_conv_to_linear_domain(ia_interp_params_struct * interp_params_str,WORD32 drc_band,FLOAT32 in_param_db_gain,FLOAT32 in_param_db_slope,FLOAT32 * out_param_lin_gain,FLOAT32 * out_param_lin_slope)295 impd_conv_to_linear_domain(ia_interp_params_struct* interp_params_str,
296 WORD32 drc_band, FLOAT32 in_param_db_gain,
297 FLOAT32 in_param_db_slope,
298 FLOAT32* out_param_lin_gain,
299 FLOAT32* out_param_lin_slope) {
300 WORD32 err = 0;
301 FLOAT32 loc_db_gain = in_param_db_gain;
302 FLOAT32 gain_ratio = 1.0;
303 FLOAT32 mapped_db_gain;
304 ia_gain_modifiers_struct* pstr_gain_modifiers =
305 interp_params_str->pstr_gain_modifiers;
306 if (interp_params_str->gain_modification_flag) {
307 ia_split_drc_characteristic_struct* split_drc_characteristic_source;
308
309 WORD32 slopeIsNegative;
310
311 if (interp_params_str->drc_characteristic_present) {
312 if (interp_params_str->drc_source_characteristic_cicp_format) {
313 } else {
314 slopeIsNegative = 0;
315 split_drc_characteristic_source =
316 interp_params_str->split_source_characteristic_left;
317 if (split_drc_characteristic_source->characteristic_format == 0) {
318 slopeIsNegative = 1;
319 } else {
320 if (split_drc_characteristic_source->node_gain[1] > 0.0f) {
321 slopeIsNegative = 1;
322 }
323 }
324 if (loc_db_gain == 0.0f) {
325 if (((pstr_gain_modifiers
326 ->target_characteristic_left_present[drc_band] == 1) &&
327 (interp_params_str->split_target_characteristic_left
328 ->characteristic_format == CHARACTERISTIC_PASS_THRU)) ||
329 ((pstr_gain_modifiers
330 ->target_characteristic_right_present[drc_band] == 1) &&
331 (interp_params_str->split_target_characteristic_right
332 ->characteristic_format == CHARACTERISTIC_PASS_THRU))) {
333 mapped_db_gain = DRC_INPUT_LOUDNESS_TARGET;
334 loc_db_gain = DRC_INPUT_LOUDNESS_TARGET;
335 }
336 } else {
337 if (((loc_db_gain > 0.0f) && (slopeIsNegative == 1)) ||
338 ((loc_db_gain < 0.0f) && (slopeIsNegative == 0))) {
339 if (pstr_gain_modifiers
340 ->target_characteristic_left_present[drc_band] == 1) {
341 err = impd_map_gain(
342 split_drc_characteristic_source,
343 interp_params_str->split_target_characteristic_left,
344 loc_db_gain, &mapped_db_gain);
345 if (err) return (err);
346 gain_ratio = mapped_db_gain / loc_db_gain;
347 }
348
349 } else if (((loc_db_gain < 0.0f) && (slopeIsNegative == 1)) ||
350 ((loc_db_gain > 0.0f) && (slopeIsNegative == 0))) {
351 if (pstr_gain_modifiers
352 ->target_characteristic_right_present[drc_band] == 1) {
353 split_drc_characteristic_source =
354 interp_params_str->split_source_characteristic_right;
355 err = impd_map_gain(
356 split_drc_characteristic_source,
357 interp_params_str->split_target_characteristic_right,
358 loc_db_gain, &mapped_db_gain);
359 if (err) return (err);
360 gain_ratio = mapped_db_gain / loc_db_gain;
361 }
362 }
363 }
364 }
365 }
366
367 if (loc_db_gain < 0.0f) {
368 gain_ratio *= interp_params_str->compress;
369 } else {
370 gain_ratio *= interp_params_str->boost;
371 }
372 }
373 if (pstr_gain_modifiers->gain_scaling_flag[drc_band] == 1) {
374 if (loc_db_gain < 0.0) {
375 gain_ratio *= pstr_gain_modifiers->attn_scaling[drc_band];
376 } else {
377 gain_ratio *= pstr_gain_modifiers->ampl_scaling[drc_band];
378 }
379 }
380 if ((interp_params_str->pstr_ducking_modifiers->ducking_scaling_flag == 1) &&
381 (interp_params_str->ducking_flag == 1)) {
382 gain_ratio *= interp_params_str->pstr_ducking_modifiers->ducking_scaling;
383 }
384
385 if (interp_params_str->interpolation_loud_eq == 1) {
386 *out_param_lin_gain =
387 gain_ratio * loc_db_gain + pstr_gain_modifiers->gain_offset[drc_band];
388 *out_param_lin_slope = 0.0f;
389 } else {
390 *out_param_lin_gain =
391 (FLOAT32)pow(2.0, (FLOAT64)(gain_ratio * loc_db_gain / 6.0f));
392 *out_param_lin_slope = SLOPE_FACTOR_DB_TO_LINEAR * gain_ratio *
393 *out_param_lin_gain * in_param_db_slope;
394
395 if (pstr_gain_modifiers->gain_offset_flag[drc_band] == 1) {
396 *out_param_lin_gain *= (FLOAT32)pow(
397 2.0, (FLOAT64)(pstr_gain_modifiers->gain_offset[drc_band] / 6.0f));
398 }
399 if ((interp_params_str->limiter_peak_target_present == 1) &&
400 (interp_params_str->clipping_flag == 1)) {
401 *out_param_lin_gain *= (FLOAT32)pow(
402 2.0, max(0.0, -interp_params_str->limiter_peak_target -
403 interp_params_str->loudness_normalization_gain_db) /
404 6.0);
405 if (*out_param_lin_gain >= 1.0) {
406 *out_param_lin_gain = 1.0;
407 *out_param_lin_slope = 0.0;
408 }
409 }
410 }
411 return (0);
412 }
413
impd_interpolate_drc_gain(ia_interp_params_struct * interp_params_str,WORD32 drc_band,WORD32 gain_step_tdomain,FLOAT32 gain0,FLOAT32 gain1,FLOAT32 slope0,FLOAT32 slope1,FLOAT32 * result)414 WORD32 impd_interpolate_drc_gain(ia_interp_params_struct* interp_params_str,
415 WORD32 drc_band, WORD32 gain_step_tdomain,
416 FLOAT32 gain0, FLOAT32 gain1, FLOAT32 slope0,
417 FLOAT32 slope1, FLOAT32* result) {
418 WORD32 err = 0;
419 WORD32 n;
420 FLOAT32 k1, k2, a, b, c, d;
421 FLOAT32 slope_t1;
422 FLOAT32 slope_t2;
423 FLOAT32 gain_t1;
424 FLOAT32 gain_t2;
425
426 WORD32 cubic_interpolation = 1;
427 WORD32 node_inser;
428 FLOAT32 node_inser_float;
429
430 if (gain_step_tdomain <= 0) {
431 return (UNEXPECTED_ERROR);
432 }
433
434 err = impd_conv_to_linear_domain(interp_params_str, drc_band, gain0, slope0,
435 &gain_t1, &slope_t1);
436 if (err) return (err);
437 err = impd_conv_to_linear_domain(interp_params_str, drc_band, gain1, slope1,
438 &gain_t2, &slope_t2);
439 if (err) return (err);
440
441 if (interp_params_str->gain_interpolation_type ==
442 GAIN_INTERPOLATION_TYPE_SPLINE) {
443 slope_t1 = slope_t1 / (FLOAT32)interp_params_str->delta_tmin;
444 slope_t2 = slope_t2 / (FLOAT32)interp_params_str->delta_tmin;
445 if ((FLOAT32)fabs((FLOAT64)slope_t1) > (FLOAT32)fabs((FLOAT64)slope_t2)) {
446 node_inser_float = 2.0f *
447 (gain_t2 - gain_t1 - slope_t2 * gain_step_tdomain) /
448 (slope_t1 - slope_t2);
449 node_inser = (WORD32)(0.5f + node_inser_float);
450 if ((node_inser >= 0) && (node_inser < gain_step_tdomain)) {
451 cubic_interpolation = 0;
452
453 result[0] = gain_t1;
454 result[gain_step_tdomain] = gain_t2;
455
456 a = 0.5f * (slope_t2 - slope_t1) / node_inser_float;
457 b = slope_t1;
458 c = gain_t1;
459 for (n = 1; n < node_inser; n++) {
460 FLOAT32 t = (FLOAT32)n;
461 result[n] = (a * t + b) * t + c;
462 result[n] = max(0.0f, result[n]);
463 }
464 a = slope_t2;
465 b = gain_t2;
466 for (; n < gain_step_tdomain; n++) {
467 FLOAT32 t = (FLOAT32)(n - gain_step_tdomain);
468 result[n] = a * t + b;
469 }
470 }
471 } else if ((FLOAT32)fabs((FLOAT64)slope_t1) <
472 (FLOAT32)fabs((FLOAT64)slope_t2)) {
473 node_inser_float = 2.0f *
474 (gain_t1 - gain_t2 + slope_t1 * gain_step_tdomain) /
475 (slope_t1 - slope_t2);
476 node_inser_float = gain_step_tdomain - node_inser_float;
477 node_inser = (WORD32)(0.5f + node_inser_float);
478 if ((node_inser >= 0) && (node_inser < gain_step_tdomain)) {
479 cubic_interpolation = 0;
480
481 result[0] = gain_t1;
482 result[gain_step_tdomain] = gain_t2;
483
484 a = slope_t1;
485 b = gain_t1;
486 for (n = 1; n < node_inser; n++) {
487 FLOAT32 t = (FLOAT32)n;
488 result[n] = a * t + b;
489 }
490 a = (slope_t2 - slope_t1) /
491 (2.0f * (gain_step_tdomain - node_inser_float));
492 b = -slope_t2;
493 c = gain_t2;
494 for (; n < gain_step_tdomain; n++) {
495 FLOAT32 t = (FLOAT32)(gain_step_tdomain - n);
496 result[n] = (a * t + b) * t + c;
497 result[n] = max(0.0f, result[n]);
498 }
499 }
500 }
501
502 if (cubic_interpolation == 1) {
503 FLOAT32 gain_step_inv = 1.0f / (FLOAT32)gain_step_tdomain;
504 FLOAT32 gain_step_inv2 = gain_step_inv * gain_step_inv;
505
506 k1 = (gain_t2 - gain_t1) * gain_step_inv2;
507 k2 = slope_t2 + slope_t1;
508
509 a = gain_step_inv * (gain_step_inv * k2 - 2.0f * k1);
510 b = 3.0f * k1 - gain_step_inv * (k2 + slope_t1);
511 c = slope_t1;
512 d = gain_t1;
513
514 result[0] = gain_t1;
515 result[gain_step_tdomain] = gain_t2;
516 for (n = 1; n < gain_step_tdomain; n++) {
517 FLOAT32 t = (FLOAT32)n;
518 result[n] = (((a * t + b) * t + c) * t) + d;
519 result[n] = max(0.0f, result[n]);
520 }
521 }
522 } else {
523 a = (gain_t2 - gain_t1) / (FLOAT32)gain_step_tdomain;
524 b = gain_t1;
525 result[0] = gain_t1;
526 result[gain_step_tdomain] = gain_t2;
527 for (n = 1; n < gain_step_tdomain; n++) {
528 FLOAT32 t = (FLOAT32)n;
529 result[n] = a * t + b;
530 }
531 }
532 return 0;
533 }
534
impd_advance_buf(WORD32 drc_frame_size,ia_gain_buffer_struct * pstr_gain_buf)535 VOID impd_advance_buf(WORD32 drc_frame_size,
536 ia_gain_buffer_struct* pstr_gain_buf) {
537 WORD32 n;
538 ia_interp_buf_struct* buf_interpolation;
539
540 for (n = 0; n < pstr_gain_buf->buf_interpolation_count; n++) {
541 buf_interpolation = &(pstr_gain_buf->buf_interpolation[n]);
542 buf_interpolation->prev_node = buf_interpolation->str_node;
543 buf_interpolation->prev_node.time -= drc_frame_size;
544 memmove(buf_interpolation->lpcm_gains,
545 buf_interpolation->lpcm_gains + drc_frame_size,
546 sizeof(FLOAT32) * (drc_frame_size + MAX_SIGNAL_DELAY));
547 }
548 return;
549 }
550 WORD32
impd_concatenate_segments(WORD32 drc_frame_size,WORD32 drc_band,ia_interp_params_struct * interp_params_str,ia_spline_nodes_struct * str_spline_nodes,ia_interp_buf_struct * buf_interpolation,WORD32 sel_drc_index,WORD32 is_config_changed,WORD32 loudness_changed)551 impd_concatenate_segments(WORD32 drc_frame_size, WORD32 drc_band,
552 ia_interp_params_struct* interp_params_str,
553 ia_spline_nodes_struct* str_spline_nodes,
554 ia_interp_buf_struct* buf_interpolation,
555 WORD32 sel_drc_index, WORD32 is_config_changed,
556 WORD32 loudness_changed) {
557 WORD32 time_prev, duration, n, err = 0;
558 FLOAT32 loc_db_gain = 0.0f, prev_db_gain, slope = 0.0f, slope_prev;
559
560 time_prev = buf_interpolation->prev_node.time;
561 prev_db_gain = buf_interpolation->prev_node.loc_db_gain;
562 slope_prev = buf_interpolation->prev_node.slope;
563 for (n = 0; n < str_spline_nodes->num_nodes; n++) {
564 duration = str_spline_nodes->str_node[n].time - time_prev;
565 loc_db_gain = str_spline_nodes->str_node[n].loc_db_gain;
566 if (loudness_changed) {
567 if (sel_drc_index == 0 && is_config_changed == 1) {
568 loc_db_gain = str_spline_nodes->str_node[n].loc_db_gain +
569 interp_params_str->loudness_normalization_gain_db;
570 if (prev_db_gain == 0) {
571 prev_db_gain = buf_interpolation->prev_node.loc_db_gain +
572 interp_params_str->loudness_normalization_gain_db;
573 }
574 }
575 }
576 slope = str_spline_nodes->str_node[n].slope;
577
578 err = impd_interpolate_drc_gain(
579 interp_params_str, drc_band, duration, prev_db_gain, loc_db_gain,
580 slope_prev, slope, buf_interpolation->lpcm_gains + MAX_SIGNAL_DELAY +
581 drc_frame_size + time_prev);
582 if (err) return (err);
583
584 time_prev = str_spline_nodes->str_node[n].time;
585 prev_db_gain = loc_db_gain;
586 slope_prev = slope;
587 }
588
589 buf_interpolation->str_node.loc_db_gain = loc_db_gain;
590 buf_interpolation->str_node.slope = slope;
591 buf_interpolation->str_node.time = time_prev;
592
593 return (0);
594 }
595
596 WORD32
impd_get_drc_gain(ia_drc_gain_dec_struct * p_drc_gain_dec_structs,ia_drc_config * pstr_drc_config,ia_drc_gain_struct * pstr_drc_gain,FLOAT32 compress,FLOAT32 boost,WORD32 characteristic_index,FLOAT32 loudness_normalization_gain_db,WORD32 sel_drc_index,ia_drc_gain_buffers_struct * drc_gain_buffers)597 impd_get_drc_gain(ia_drc_gain_dec_struct* p_drc_gain_dec_structs,
598 ia_drc_config* pstr_drc_config,
599 ia_drc_gain_struct* pstr_drc_gain, FLOAT32 compress,
600 FLOAT32 boost, WORD32 characteristic_index,
601 FLOAT32 loudness_normalization_gain_db, WORD32 sel_drc_index,
602 ia_drc_gain_buffers_struct* drc_gain_buffers) {
603 ia_drc_params_struct* ia_drc_params_struct =
604 &(p_drc_gain_dec_structs->ia_drc_params_struct);
605 WORD32 drc_instructions_index =
606 ia_drc_params_struct->sel_drc_array[sel_drc_index].drc_instructions_index;
607 if (drc_instructions_index >= 0) {
608 WORD32 b, g, gain_element_index, err = 0;
609 WORD32 parametric_drc_instance_index = 0;
610 ia_interp_params_struct interp_params_str = {0};
611
612 ia_drc_instructions_struct* str_drc_instruction_str =
613 &(pstr_drc_config->str_drc_instruction_str[drc_instructions_index]);
614 WORD32 drc_set_effect = str_drc_instruction_str->drc_set_effect;
615 WORD32 num_drc_ch_groups = str_drc_instruction_str->num_drc_ch_groups;
616 ia_uni_drc_coeffs_struct* str_p_loc_drc_coefficients_uni_drc = NULL;
617 WORD32 drc_coeff_idx =
618 ia_drc_params_struct->sel_drc_array[sel_drc_index].drc_coeff_idx;
619 if (drc_coeff_idx >= 0) {
620 str_p_loc_drc_coefficients_uni_drc =
621 &(pstr_drc_config->str_p_loc_drc_coefficients_uni_drc[drc_coeff_idx]);
622 interp_params_str.interpolation_loud_eq = 0;
623 } else {
624 return (UNEXPECTED_ERROR);
625 }
626
627 interp_params_str.loudness_normalization_gain_db =
628 loudness_normalization_gain_db;
629 interp_params_str.characteristic_index = characteristic_index;
630 interp_params_str.compress = compress;
631 interp_params_str.boost = boost;
632 interp_params_str.limiter_peak_target_present =
633 str_drc_instruction_str->limiter_peak_target_present;
634 interp_params_str.limiter_peak_target =
635 str_drc_instruction_str->limiter_peak_target;
636
637 if (((drc_set_effect & (EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) ==
638 0) &&
639 (drc_set_effect != EFFECT_BIT_FADE) &&
640 (drc_set_effect != EFFECT_BIT_CLIPPING)) {
641 interp_params_str.gain_modification_flag = 1;
642 } else {
643 interp_params_str.gain_modification_flag = 0;
644 }
645 if (drc_set_effect & (EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) {
646 interp_params_str.ducking_flag = 1;
647 } else {
648 interp_params_str.ducking_flag = 0;
649 }
650 if (drc_set_effect == EFFECT_BIT_CLIPPING) {
651 interp_params_str.clipping_flag = 1;
652 } else {
653 interp_params_str.clipping_flag = 0;
654 }
655
656 impd_advance_buf(ia_drc_params_struct->drc_frame_size,
657 &(drc_gain_buffers->pstr_gain_buf[sel_drc_index]));
658
659 gain_element_index = 0;
660 for (g = 0; g < num_drc_ch_groups; g++) {
661 WORD32 gainSet = 0;
662 WORD32 num_drc_bands = 0;
663 interp_params_str.gain_interpolation_type =
664 str_drc_instruction_str->gain_interpolation_type_for_channel_group[g];
665 interp_params_str.delta_tmin =
666 str_drc_instruction_str->time_delta_min_for_channel_group[g];
667 interp_params_str.pstr_ducking_modifiers = &(
668 str_drc_instruction_str->str_ducking_modifiers_for_channel_group[g]);
669 interp_params_str.pstr_gain_modifiers =
670 &(str_drc_instruction_str->str_gain_modifiers_of_ch_group[g]);
671 if (str_drc_instruction_str->ch_group_parametric_drc_flag[g] == 0) {
672 gainSet = str_drc_instruction_str->gain_set_index_for_channel_group[g];
673 num_drc_bands = str_drc_instruction_str->band_count_of_ch_group[g];
674 for (b = 0; b < num_drc_bands; b++) {
675 ia_gain_params_struct* gain_params =
676 &(str_p_loc_drc_coefficients_uni_drc->gain_set_params[gainSet]
677 .gain_params[b]);
678 WORD32 seq = gain_params->gain_seq_idx;
679 interp_params_str.drc_characteristic_present =
680 gain_params->drc_characteristic_present;
681 interp_params_str.drc_source_characteristic_cicp_format =
682 gain_params->drc_characteristic_format_is_cicp;
683 interp_params_str.source_drc_characteristic =
684 gain_params->drc_characteristic;
685 interp_params_str.split_source_characteristic_left = &(
686 str_p_loc_drc_coefficients_uni_drc->str_split_characteristic_left
687 [gain_params->drc_characteristic_left_index]);
688 interp_params_str.split_source_characteristic_right = &(
689 str_p_loc_drc_coefficients_uni_drc->str_split_characteristic_right
690 [gain_params->drc_characteristic_right_index]);
691 interp_params_str.split_target_characteristic_left = &(
692 str_p_loc_drc_coefficients_uni_drc->str_split_characteristic_left
693 [interp_params_str.pstr_gain_modifiers
694 ->target_characteristic_left_index[b]]);
695 interp_params_str.split_target_characteristic_right = &(
696 str_p_loc_drc_coefficients_uni_drc->str_split_characteristic_right
697 [interp_params_str.pstr_gain_modifiers
698 ->target_characteristic_right_index[b]]);
699 err = impd_concatenate_segments(
700 ia_drc_params_struct->drc_frame_size, b, &interp_params_str,
701 &(pstr_drc_gain->drc_gain_sequence[seq].str_spline_nodes[0]),
702 &(drc_gain_buffers->pstr_gain_buf[sel_drc_index]
703 .buf_interpolation[gain_element_index]),
704 sel_drc_index, pstr_drc_config->is_config_changed,
705 pstr_drc_config->ln_gain_changed);
706 if (err) return (err);
707 gain_element_index++;
708 }
709 } else {
710 if (ia_drc_params_struct->sub_band_domain_mode ==
711 SUBBAND_DOMAIN_MODE_OFF &&
712 !(p_drc_gain_dec_structs->parametricdrc_params
713 .str_parametric_drc_instance_params
714 [parametric_drc_instance_index]
715 .parametric_drc_type == PARAM_DRC_TYPE_LIM)) {
716 err = impd_parametric_drc_instance_process(
717 p_drc_gain_dec_structs->audio_in_out_buf.audio_in_out_buf, NULL,
718 NULL, &p_drc_gain_dec_structs->parametricdrc_params,
719 &p_drc_gain_dec_structs->parametricdrc_params
720 .str_parametric_drc_instance_params
721 [parametric_drc_instance_index]);
722 if (err) return (err);
723
724 err = impd_concatenate_segments(
725 ia_drc_params_struct->drc_frame_size, 0, &interp_params_str,
726 &p_drc_gain_dec_structs->parametricdrc_params
727 .str_parametric_drc_instance_params
728 [parametric_drc_instance_index]
729 .str_spline_nodes,
730 &(drc_gain_buffers->pstr_gain_buf[sel_drc_index]
731 .buf_interpolation[gain_element_index]),
732 sel_drc_index, pstr_drc_config->is_config_changed,
733 pstr_drc_config->ln_gain_changed);
734 if (err) return (err);
735 } else if (ia_drc_params_struct->sub_band_domain_mode ==
736 SUBBAND_DOMAIN_MODE_OFF &&
737 p_drc_gain_dec_structs->parametricdrc_params
738 .str_parametric_drc_instance_params
739 [parametric_drc_instance_index]
740 .parametric_drc_type == PARAM_DRC_TYPE_LIM) {
741 FLOAT32* lpcm_gains = (drc_gain_buffers->pstr_gain_buf[sel_drc_index]
742 .buf_interpolation[gain_element_index])
743 .lpcm_gains +
744 MAX_SIGNAL_DELAY;
745 impd_parametric_lim_type_drc_process(
746 p_drc_gain_dec_structs->audio_in_out_buf.audio_in_out_buf,
747 loudness_normalization_gain_db,
748 &p_drc_gain_dec_structs->parametricdrc_params
749 .str_parametric_drc_instance_params
750 [parametric_drc_instance_index]
751 .str_parametric_drc_type_lim_params,
752 lpcm_gains);
753
754 } else if (ia_drc_params_struct->sub_band_domain_mode !=
755 SUBBAND_DOMAIN_MODE_OFF &&
756 !(p_drc_gain_dec_structs->parametricdrc_params
757 .str_parametric_drc_instance_params
758 [parametric_drc_instance_index]
759 .parametric_drc_type == PARAM_DRC_TYPE_LIM)) {
760 err = impd_parametric_drc_instance_process(
761 NULL, p_drc_gain_dec_structs->audio_in_out_buf.audio_real_buff,
762 p_drc_gain_dec_structs->audio_in_out_buf.audio_imag_buff,
763 &p_drc_gain_dec_structs->parametricdrc_params,
764 &p_drc_gain_dec_structs->parametricdrc_params
765 .str_parametric_drc_instance_params
766 [parametric_drc_instance_index]);
767 if (err) return (err);
768
769 err = impd_concatenate_segments(
770 ia_drc_params_struct->drc_frame_size, 0, &interp_params_str,
771 &p_drc_gain_dec_structs->parametricdrc_params
772 .str_parametric_drc_instance_params
773 [parametric_drc_instance_index]
774 .str_spline_nodes,
775 &(drc_gain_buffers->pstr_gain_buf[sel_drc_index]
776 .buf_interpolation[gain_element_index]),
777 sel_drc_index, pstr_drc_config->is_config_changed,
778 pstr_drc_config->ln_gain_changed);
779 if (err) return (err);
780
781 } else {
782 return (UNEXPECTED_ERROR);
783 }
784 gain_element_index++;
785 parametric_drc_instance_index++;
786 }
787 }
788 }
789 return (0);
790 }
791