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 inLevel;
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, &inLevel);
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, &inLevel);
259
260 break;
261 case CHARACTERISTIC_PASS_THRU:
262 inLevel = 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, inLevel,
271 gain_out_db);
272 if (err) return (err);
273 break;
274 case CHARACTERISTIC_NODES:
275 if (inLevel < DRC_INPUT_LOUDNESS_TARGET) {
276 err = impd_compressor_io_nodes_lt(split_drc_characteristic_target,
277 inLevel, gain_out_db);
278 if (err) return (err);
279 } else {
280 err = impd_compressor_io_nodes_rt(split_drc_characteristic_target,
281 inLevel, gain_out_db);
282 if (err) return (err);
283 }
284 break;
285 case CHARACTERISTIC_PASS_THRU:
286 *gain_out_db = inLevel;
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)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 timePrev, duration, n, err = 0;
556 FLOAT32 loc_db_gain = 0.0f, prev_db_gain, slope = 0.0f, slopePrev;
557
558 timePrev = buf_interpolation->prev_node.time;
559 prev_db_gain = buf_interpolation->prev_node.loc_db_gain;
560 slopePrev = buf_interpolation->prev_node.slope;
561 for (n = 0; n < str_spline_nodes->num_nodes; n++) {
562 duration = str_spline_nodes->str_node[n].time - timePrev;
563 loc_db_gain = str_spline_nodes->str_node[n].loc_db_gain;
564 slope = str_spline_nodes->str_node[n].slope;
565
566 err = impd_interpolate_drc_gain(
567 interp_params_str, drc_band, duration, prev_db_gain, loc_db_gain,
568 slopePrev, slope, buf_interpolation->lpcm_gains + MAX_SIGNAL_DELAY +
569 drc_frame_size + timePrev);
570 if (err) return (err);
571
572 timePrev = str_spline_nodes->str_node[n].time;
573 prev_db_gain = loc_db_gain;
574 slopePrev = slope;
575 }
576
577 buf_interpolation->str_node.loc_db_gain = loc_db_gain;
578 buf_interpolation->str_node.slope = slope;
579 buf_interpolation->str_node.time = timePrev;
580
581 return (0);
582 }
583
584 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)585 impd_get_drc_gain(ia_drc_gain_dec_struct* p_drc_gain_dec_structs,
586 ia_drc_config* pstr_drc_config,
587 ia_drc_gain_struct* pstr_drc_gain, FLOAT32 compress,
588 FLOAT32 boost, WORD32 characteristic_index,
589 FLOAT32 loudness_normalization_gain_db, WORD32 sel_drc_index,
590 ia_drc_gain_buffers_struct* drc_gain_buffers) {
591 ia_drc_params_struct* ia_drc_params_struct =
592 &(p_drc_gain_dec_structs->ia_drc_params_struct);
593 WORD32 drc_instructions_index =
594 ia_drc_params_struct->sel_drc_array[sel_drc_index].drc_instructions_index;
595 if (drc_instructions_index >= 0) {
596 WORD32 b, g, gainElementIndex, err = 0;
597 WORD32 parametricDrcInstanceIndex = 0;
598 ia_interp_params_struct interp_params_str = {0};
599
600 ia_drc_instructions_struct* str_drc_instruction_str =
601 &(pstr_drc_config->str_drc_instruction_str[drc_instructions_index]);
602 WORD32 drc_set_effect = str_drc_instruction_str->drc_set_effect;
603 WORD32 num_drc_ch_groups = str_drc_instruction_str->num_drc_ch_groups;
604 ia_uni_drc_coeffs_struct* str_p_loc_drc_coefficients_uni_drc = NULL;
605 WORD32 drc_coeff_idx =
606 ia_drc_params_struct->sel_drc_array[sel_drc_index].drc_coeff_idx;
607 if (drc_coeff_idx >= 0) {
608 str_p_loc_drc_coefficients_uni_drc =
609 &(pstr_drc_config->str_p_loc_drc_coefficients_uni_drc[drc_coeff_idx]);
610 interp_params_str.interpolation_loud_eq = 0;
611 } else {
612 return (UNEXPECTED_ERROR);
613 }
614
615 interp_params_str.loudness_normalization_gain_db =
616 loudness_normalization_gain_db;
617 interp_params_str.characteristic_index = characteristic_index;
618 interp_params_str.compress = compress;
619 interp_params_str.boost = boost;
620 interp_params_str.limiter_peak_target_present =
621 str_drc_instruction_str->limiter_peak_target_present;
622 interp_params_str.limiter_peak_target =
623 str_drc_instruction_str->limiter_peak_target;
624
625 if (((drc_set_effect & (EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) ==
626 0) &&
627 (drc_set_effect != EFFECT_BIT_FADE) &&
628 (drc_set_effect != EFFECT_BIT_CLIPPING)) {
629 interp_params_str.gain_modification_flag = 1;
630 } else {
631 interp_params_str.gain_modification_flag = 0;
632 }
633 if (drc_set_effect & (EFFECT_BIT_DUCK_OTHER | EFFECT_BIT_DUCK_SELF)) {
634 interp_params_str.ducking_flag = 1;
635 } else {
636 interp_params_str.ducking_flag = 0;
637 }
638 if (drc_set_effect == EFFECT_BIT_CLIPPING) {
639 interp_params_str.clipping_flag = 1;
640 } else {
641 interp_params_str.clipping_flag = 0;
642 }
643
644 impd_advance_buf(ia_drc_params_struct->drc_frame_size,
645 &(drc_gain_buffers->pstr_gain_buf[sel_drc_index]));
646
647 gainElementIndex = 0;
648 for (g = 0; g < num_drc_ch_groups; g++) {
649 WORD32 gainSet = 0;
650 WORD32 num_drc_bands = 0;
651 interp_params_str.gain_interpolation_type =
652 str_drc_instruction_str->gain_interpolation_type_for_channel_group[g];
653 interp_params_str.delta_tmin =
654 str_drc_instruction_str->time_delta_min_for_channel_group[g];
655 interp_params_str.pstr_ducking_modifiers = &(
656 str_drc_instruction_str->str_ducking_modifiers_for_channel_group[g]);
657 interp_params_str.pstr_gain_modifiers =
658 &(str_drc_instruction_str->str_gain_modifiers_of_ch_group[g]);
659 if (str_drc_instruction_str->ch_group_parametric_drc_flag[g] == 0) {
660 gainSet = str_drc_instruction_str->gain_set_index_for_channel_group[g];
661 num_drc_bands = str_drc_instruction_str->band_count_of_ch_group[g];
662 for (b = 0; b < num_drc_bands; b++) {
663 ia_gain_params_struct* gain_params =
664 &(str_p_loc_drc_coefficients_uni_drc->gain_set_params[gainSet]
665 .gain_params[b]);
666 WORD32 seq = gain_params->gain_seq_idx;
667 interp_params_str.drc_characteristic_present =
668 gain_params->drc_characteristic_present;
669 interp_params_str.drc_source_characteristic_cicp_format =
670 gain_params->drc_characteristic_format_is_cicp;
671 interp_params_str.source_drc_characteristic =
672 gain_params->drc_characteristic;
673 interp_params_str.split_source_characteristic_left = &(
674 str_p_loc_drc_coefficients_uni_drc->str_split_characteristic_left
675 [gain_params->drc_characteristic_left_index]);
676 interp_params_str.split_source_characteristic_right = &(
677 str_p_loc_drc_coefficients_uni_drc->str_split_characteristic_right
678 [gain_params->drc_characteristic_right_index]);
679 interp_params_str.split_target_characteristic_left = &(
680 str_p_loc_drc_coefficients_uni_drc->str_split_characteristic_left
681 [interp_params_str.pstr_gain_modifiers
682 ->target_characteristic_left_index[b]]);
683 interp_params_str.split_target_characteristic_right = &(
684 str_p_loc_drc_coefficients_uni_drc->str_split_characteristic_right
685 [interp_params_str.pstr_gain_modifiers
686 ->target_characteristic_right_index[b]]);
687 err = impd_concatenate_segments(
688 ia_drc_params_struct->drc_frame_size, b, &interp_params_str,
689 &(pstr_drc_gain->drc_gain_sequence[seq].str_spline_nodes[0]),
690 &(drc_gain_buffers->pstr_gain_buf[sel_drc_index]
691 .buf_interpolation[gainElementIndex]));
692 if (err) return (err);
693 gainElementIndex++;
694 }
695 } else {
696 if (ia_drc_params_struct->sub_band_domain_mode ==
697 SUBBAND_DOMAIN_MODE_OFF &&
698 !(p_drc_gain_dec_structs->parametricdrc_params
699 .str_parametric_drc_instance_params
700 [parametricDrcInstanceIndex]
701 .parametric_drc_type == PARAM_DRC_TYPE_LIM)) {
702 err = impd_parametric_drc_instance_process(
703 p_drc_gain_dec_structs->audio_in_out_buf.audio_in_out_buf, NULL,
704 NULL, &p_drc_gain_dec_structs->parametricdrc_params,
705 &p_drc_gain_dec_structs->parametricdrc_params
706 .str_parametric_drc_instance_params
707 [parametricDrcInstanceIndex]);
708 if (err) return (err);
709
710 err = impd_concatenate_segments(
711 ia_drc_params_struct->drc_frame_size, 0, &interp_params_str,
712 &p_drc_gain_dec_structs->parametricdrc_params
713 .str_parametric_drc_instance_params
714 [parametricDrcInstanceIndex]
715 .str_spline_nodes,
716 &(drc_gain_buffers->pstr_gain_buf[sel_drc_index]
717 .buf_interpolation[gainElementIndex]));
718 if (err) return (err);
719 } else if (ia_drc_params_struct->sub_band_domain_mode ==
720 SUBBAND_DOMAIN_MODE_OFF &&
721 p_drc_gain_dec_structs->parametricdrc_params
722 .str_parametric_drc_instance_params
723 [parametricDrcInstanceIndex]
724 .parametric_drc_type == PARAM_DRC_TYPE_LIM) {
725 FLOAT32* lpcm_gains = (drc_gain_buffers->pstr_gain_buf[sel_drc_index]
726 .buf_interpolation[gainElementIndex])
727 .lpcm_gains +
728 MAX_SIGNAL_DELAY;
729 impd_parametric_lim_type_drc_process(
730 p_drc_gain_dec_structs->audio_in_out_buf.audio_in_out_buf,
731 loudness_normalization_gain_db,
732 &p_drc_gain_dec_structs->parametricdrc_params
733 .str_parametric_drc_instance_params
734 [parametricDrcInstanceIndex]
735 .str_parametric_drc_type_lim_params,
736 lpcm_gains);
737
738 } else if (ia_drc_params_struct->sub_band_domain_mode !=
739 SUBBAND_DOMAIN_MODE_OFF &&
740 !(p_drc_gain_dec_structs->parametricdrc_params
741 .str_parametric_drc_instance_params
742 [parametricDrcInstanceIndex]
743 .parametric_drc_type == PARAM_DRC_TYPE_LIM)) {
744 err = impd_parametric_drc_instance_process(
745 NULL, p_drc_gain_dec_structs->audio_in_out_buf.audio_real_buff,
746 p_drc_gain_dec_structs->audio_in_out_buf.audio_imag_buff,
747 &p_drc_gain_dec_structs->parametricdrc_params,
748 &p_drc_gain_dec_structs->parametricdrc_params
749 .str_parametric_drc_instance_params
750 [parametricDrcInstanceIndex]);
751 if (err) return (err);
752
753 err = impd_concatenate_segments(
754 ia_drc_params_struct->drc_frame_size, 0, &interp_params_str,
755 &p_drc_gain_dec_structs->parametricdrc_params
756 .str_parametric_drc_instance_params
757 [parametricDrcInstanceIndex]
758 .str_spline_nodes,
759 &(drc_gain_buffers->pstr_gain_buf[sel_drc_index]
760 .buf_interpolation[gainElementIndex]));
761 if (err) return (err);
762
763 } else {
764 return (UNEXPECTED_ERROR);
765 }
766 gainElementIndex++;
767 parametricDrcInstanceIndex++;
768 }
769 }
770 }
771 return (0);
772 }
773