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