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 25 #include "impd_type_def.h" 26 #include "impd_drc_extr_delta_coded_info.h" 27 #include "impd_drc_common.h" 28 #include "impd_drc_struct.h" 29 #include "impd_parametric_drc_dec.h" 30 #include "impd_drc_filter_bank.h" 31 #include "impd_drc_multi_band.h" 32 #include "impd_drc_gain_dec.h" 33 #include "impd_drc_process_audio.h" 34 #include "impd_drc_interface.h" 35 #include "impd_drc_gain_dec.h" 36 #include "impd_drc_eq.h" 37 #include "impd_drc_gain_decoder.h" 38 #include "impd_drc_rom.h" 39 40 WORD32 impd_shape_filt_block_adapt(const FLOAT32 drc_gain, 41 shape_filter_block* shape_filter_block) { 42 // WORD32 err = 0; 43 WORD32 i; 44 FLOAT32 warpedGain, x1, y1; 45 shape_filter_block->drc_gain_last = drc_gain; 46 for (i = 0; i < 4; i++) { 47 if (shape_filter_block->shape_filter[i].type == SHAPE_FILTER_TYPE_OFF) 48 continue; 49 else if (shape_filter_block->shape_filter[i].type == 50 SHAPE_FILTER_TYPE_LF_CUT || 51 shape_filter_block->shape_filter[i].type == 52 SHAPE_FILTER_TYPE_HF_CUT) { 53 if (drc_gain < 1.0f) 54 warpedGain = -1.0f; 55 else 56 warpedGain = 57 (drc_gain - 1.0f) / 58 (drc_gain - 1.0f + shape_filter_block->shape_filter[i].gain_offset); 59 x1 = shape_filter_block->shape_filter[i].a1; 60 } else if (shape_filter_block->shape_filter[i].type == 61 SHAPE_FILTER_TYPE_LF_BOOST || 62 shape_filter_block->shape_filter[i].type == 63 SHAPE_FILTER_TYPE_HF_BOOST) { 64 if (drc_gain >= 1.0f) 65 warpedGain = -1.0f; 66 else 67 warpedGain = 68 (1.0f - drc_gain) / 69 (1.0f + 70 drc_gain * 71 (shape_filter_block->shape_filter[i].gain_offset - 1.0f)); 72 x1 = shape_filter_block->shape_filter[i].b1; 73 } 74 75 if (warpedGain <= 0.0f) { 76 y1 = x1; 77 } else if (warpedGain < 78 shape_filter_block->shape_filter[i].warped_gain_max) { 79 y1 = x1 + shape_filter_block->shape_filter[i].factor * warpedGain; 80 } else { 81 y1 = shape_filter_block->shape_filter[i].y1_bound; 82 } 83 if (shape_filter_block->shape_filter[i].type == SHAPE_FILTER_TYPE_LF_CUT) { 84 shape_filter_block->shape_filter[i].b1 = y1; 85 } else if (shape_filter_block->shape_filter[i].type == 86 SHAPE_FILTER_TYPE_HF_CUT) { 87 shape_filter_block->shape_filter[i].g_norm = 88 shape_filter_block->shape_filter[i].coeff_sum / 89 (shape_filter_block->shape_filter[i].partial_coeff_sum + y1); 90 shape_filter_block->shape_filter[i].b1 = y1; 91 } else if (shape_filter_block->shape_filter[i].type == 92 SHAPE_FILTER_TYPE_HF_BOOST) { 93 shape_filter_block->shape_filter[i].g_norm = 94 (shape_filter_block->shape_filter[i].partial_coeff_sum + y1) / 95 shape_filter_block->shape_filter[i].coeff_sum; 96 shape_filter_block->shape_filter[i].a1 = y1; 97 } else if (shape_filter_block->shape_filter[i].type == 98 SHAPE_FILTER_TYPE_LF_BOOST) { 99 shape_filter_block->shape_filter[i].a1 = y1; 100 } 101 } 102 return (0); 103 } 104 105 WORD32 resetshape_flter_block(shape_filter_block* shape_filter_block) { 106 WORD32 i, c; 107 shape_filter_block->drc_gain_last = -1.0f; 108 impd_shape_filt_block_adapt(1.0f, shape_filter_block); 109 for (i = 0; i < 4; i++) { 110 for (c = 0; c < MAX_CHANNEL_COUNT; c++) { 111 shape_filter_block->shape_filter[i].audio_in_state_1[c] = 0.0f; 112 shape_filter_block->shape_filter[i].audio_in_state_2[c] = 0.0f; 113 shape_filter_block->shape_filter[i].audio_out_state_1[c] = 0.0f; 114 shape_filter_block->shape_filter[i].audio_out_state_2[c] = 0.0f; 115 } 116 } 117 return (0); 118 } 119 120 WORD32 impd_shape_filt_block_init( 121 ia_shape_filter_block_params_struct* shape_flter_block_params, 122 shape_filter_block* shape_filter_block) { 123 // WORD32 err = 0; 124 FLOAT32 x1; 125 FLOAT32 x2 = 0.0f; 126 FLOAT32 radius; 127 if (shape_flter_block_params->lf_cut_filter_present) { 128 ia_shape_filter_params_struct* params = 129 &shape_flter_block_params->str_lf_cut_params; 130 shape_filter_block->shape_filter[0].type = SHAPE_FILTER_TYPE_LF_CUT; 131 shape_filter_block->shape_filter[0].gain_offset = 132 shape_filt_lf_gain_offset_tbl[params->corner_freq_index] 133 [params->filter_strength_index]; 134 shape_filter_block->shape_filter[0].y1_bound = 135 shape_filt_lf_y1_bound_tbl[params->corner_freq_index] 136 [params->filter_strength_index]; 137 x1 = -shape_filt_lf_radius_tbl[params->corner_freq_index]; 138 shape_filter_block->shape_filter[0].warped_gain_max = 139 SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE / 140 (SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE + 141 shape_filter_block->shape_filter[0].gain_offset); 142 shape_filter_block->shape_filter[0].factor = 143 (shape_filter_block->shape_filter[0].y1_bound - x1) / 144 shape_filter_block->shape_filter[0].warped_gain_max; 145 shape_filter_block->shape_filter[0].a1 = x1; 146 147 } else { 148 shape_filter_block->shape_filter[0].type = SHAPE_FILTER_TYPE_OFF; 149 } 150 if (shape_flter_block_params->lf_boost_filter_present) { 151 ia_shape_filter_params_struct* params = 152 &shape_flter_block_params->str_lf_boost_params; 153 shape_filter_block->shape_filter[1].type = SHAPE_FILTER_TYPE_LF_BOOST; 154 shape_filter_block->shape_filter[1].gain_offset = 155 shape_filt_lf_gain_offset_tbl[params->corner_freq_index] 156 [params->filter_strength_index]; 157 shape_filter_block->shape_filter[1].y1_bound = 158 shape_filt_lf_y1_bound_tbl[params->corner_freq_index] 159 [params->filter_strength_index]; 160 x1 = -shape_filt_lf_radius_tbl[params->corner_freq_index]; 161 shape_filter_block->shape_filter[1].warped_gain_max = 162 SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE / 163 (SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE + 164 shape_filter_block->shape_filter[1].gain_offset); 165 shape_filter_block->shape_filter[1].factor = 166 (shape_filter_block->shape_filter[1].y1_bound - x1) / 167 shape_filter_block->shape_filter[1].warped_gain_max; 168 shape_filter_block->shape_filter[1].b1 = x1; 169 170 } else { 171 shape_filter_block->shape_filter[1].type = SHAPE_FILTER_TYPE_OFF; 172 } 173 if (shape_flter_block_params->hf_cut_filter_present) { 174 ia_shape_filter_params_struct* params = 175 &shape_flter_block_params->str_hfCutParams; 176 shape_filter_block->shape_filter[2].type = SHAPE_FILTER_TYPE_HF_CUT; 177 shape_filter_block->shape_filter[2].gain_offset = 178 shape_filt_hf_gain_offset_tbl[params->corner_freq_index] 179 [params->filter_strength_index]; 180 shape_filter_block->shape_filter[2].y1_bound = 181 shape_filt_hf_y1_bound_tbl[params->corner_freq_index] 182 [params->filter_strength_index]; 183 radius = shape_filt_hf_radius_tbl[params->corner_freq_index]; 184 x1 = (FLOAT32)( 185 -2.0f * radius * 186 cos(2.0f * M_PI * 187 shape_filt_cutoff_freq_norm_hf_tbl[params->corner_freq_index])); 188 x2 = radius * radius; 189 shape_filter_block->shape_filter[2].warped_gain_max = 190 SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE / 191 (SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE + 192 shape_filter_block->shape_filter[2].gain_offset); 193 shape_filter_block->shape_filter[2].factor = 194 (shape_filter_block->shape_filter[2].y1_bound - x1) / 195 shape_filter_block->shape_filter[2].warped_gain_max; 196 shape_filter_block->shape_filter[2].coeff_sum = 1.0f + x1 + x2; 197 shape_filter_block->shape_filter[2].partial_coeff_sum = 1.0f + x2; 198 shape_filter_block->shape_filter[2].a1 = x1; 199 shape_filter_block->shape_filter[2].a2 = x2; 200 shape_filter_block->shape_filter[2].b2 = x2; 201 } else { 202 shape_filter_block->shape_filter[2].type = SHAPE_FILTER_TYPE_OFF; 203 } 204 if (shape_flter_block_params->hf_boost_filter_present) { 205 ia_shape_filter_params_struct* params = 206 &shape_flter_block_params->str_hf_boost_params; 207 shape_filter_block->shape_filter[3].type = SHAPE_FILTER_TYPE_HF_BOOST; 208 shape_filter_block->shape_filter[3].gain_offset = 209 shape_filt_hf_gain_offset_tbl[params->corner_freq_index] 210 [params->filter_strength_index]; 211 shape_filter_block->shape_filter[3].y1_bound = 212 shape_filt_hf_y1_bound_tbl[params->corner_freq_index] 213 [params->filter_strength_index]; 214 radius = shape_filt_hf_radius_tbl[params->corner_freq_index]; 215 x1 = (FLOAT32)( 216 -2.0f * radius * 217 cos(2.0f * M_PI * 218 shape_filt_cutoff_freq_norm_hf_tbl[params->corner_freq_index])); 219 x2 = radius * radius; 220 shape_filter_block->shape_filter[3].warped_gain_max = 221 SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE / 222 (SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE + 223 shape_filter_block->shape_filter[3].gain_offset); 224 shape_filter_block->shape_filter[3].factor = 225 (shape_filter_block->shape_filter[3].y1_bound - x1) / 226 shape_filter_block->shape_filter[3].warped_gain_max; 227 shape_filter_block->shape_filter[3].coeff_sum = 1.0f + x1 + x2; 228 shape_filter_block->shape_filter[3].partial_coeff_sum = 1.0f + x2; 229 shape_filter_block->shape_filter[3].b1 = x1; 230 shape_filter_block->shape_filter[3].b2 = x2; 231 shape_filter_block->shape_filter[3].a2 = x2; 232 233 } else { 234 shape_filter_block->shape_filter[3].type = SHAPE_FILTER_TYPE_OFF; 235 } 236 resetshape_flter_block(shape_filter_block); 237 shape_filter_block->shape_flter_block_flag = 1; 238 return (0); 239 } 240 241 WORD32 impd_shape_filt_block_time_process( 242 shape_filter_block* shape_filter_block, FLOAT32* drc_gain, 243 const WORD32 channel, FLOAT32* audio_in, WORD32 start, WORD32 end) { 244 WORD32 i, j, err = 0; 245 FLOAT32 audio_out; 246 247 if (shape_filter_block->shape_flter_block_flag) { 248 for (i = start; i < end; i++) { 249 FLOAT32 tmp = audio_in[i]; 250 for (j = 0; j < 4; j++) { 251 if (shape_filter_block->shape_filter[j].type == 252 SHAPE_FILTER_TYPE_LF_CUT || 253 shape_filter_block->shape_filter[j].type == 254 SHAPE_FILTER_TYPE_LF_BOOST) { 255 audio_out = tmp + 256 shape_filter_block->shape_filter[j].b1 * 257 shape_filter_block->shape_filter[j] 258 .audio_in_state_1[channel] - 259 shape_filter_block->shape_filter[j].a1 * 260 shape_filter_block->shape_filter[j] 261 .audio_out_state_1[channel]; 262 shape_filter_block->shape_filter[j].audio_in_state_1[channel] = tmp; 263 shape_filter_block->shape_filter[j].audio_out_state_1[channel] = 264 audio_out; 265 266 } else if (shape_filter_block->shape_filter[j].type == 267 SHAPE_FILTER_TYPE_HF_CUT || 268 shape_filter_block->shape_filter[j].type == 269 SHAPE_FILTER_TYPE_HF_BOOST) { 270 audio_out = shape_filter_block->shape_filter[j].g_norm * tmp + 271 shape_filter_block->shape_filter[j].b1 * 272 shape_filter_block->shape_filter[j] 273 .audio_in_state_1[channel] + 274 shape_filter_block->shape_filter[j].b2 * 275 shape_filter_block->shape_filter[j] 276 .audio_in_state_2[channel] - 277 shape_filter_block->shape_filter[j].a1 * 278 shape_filter_block->shape_filter[j] 279 .audio_out_state_1[channel] - 280 shape_filter_block->shape_filter[j].a2 * 281 shape_filter_block->shape_filter[j] 282 .audio_out_state_2[channel]; 283 shape_filter_block->shape_filter[j].audio_in_state_2[channel] = 284 shape_filter_block->shape_filter[j].audio_in_state_1[channel]; 285 shape_filter_block->shape_filter[j].audio_in_state_1[channel] = 286 shape_filter_block->shape_filter[j].g_norm * tmp; 287 shape_filter_block->shape_filter[j].audio_out_state_2[channel] = 288 shape_filter_block->shape_filter[j].audio_out_state_1[channel]; 289 shape_filter_block->shape_filter[j].audio_out_state_1[channel] = 290 audio_out; 291 } else { 292 audio_out = tmp; 293 } 294 tmp = audio_out; 295 } 296 297 audio_in[i] = audio_out * drc_gain[i]; 298 } 299 300 } else { 301 for (i = start; i < end; i++) { 302 audio_in[i] = audio_in[i] * drc_gain[i]; 303 } 304 } 305 306 return err; 307 } 308