• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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