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 <math.h> 21 #include <string.h> 22 #include "impd_type_def.h" 23 #include "impd_error_standards.h" 24 #include "impd_memory_standards.h" 25 #include "impd_drc_peak_limiter.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_drc_interface.h" 30 #include "impd_drc_bitbuffer.h" 31 #include "impd_drc_bitstream_dec_api.h" 32 #include "impd_drc_gain_dec.h" 33 #include "impd_drc_filter_bank.h" 34 #include "impd_drc_multi_band.h" 35 #include "impd_drc_process_audio.h" 36 #include "impd_parametric_drc_dec.h" 37 #include "impd_drc_eq.h" 38 #include "impd_drc_gain_decoder.h" 39 #include "impd_drc_selection_process.h" 40 #include "impd_drc_api_struct_def.h" 41 #include "impd_drc_hashdefines.h" 42 #include "impd_drc_peak_limiter.h" 43 44 static IA_ERRORCODE impd_down_mix( 45 ia_drc_sel_proc_output_struct *uni_drc_sel_proc_output, 46 FLOAT32 **input_audio, WORD32 frame_len) { 47 WORD32 num_base_ch = uni_drc_sel_proc_output->base_channel_count; 48 WORD32 num_target_ch = uni_drc_sel_proc_output->target_channel_count; 49 WORD32 i, i_ch, o_ch; 50 FLOAT32 tmp_out[MAX_CHANNEL_COUNT]; 51 52 if (num_target_ch > MAX_CHANNEL_COUNT) return -1; 53 54 if (num_target_ch > num_base_ch) return -1; 55 56 for (i = 0; i < frame_len; i++) { 57 for (o_ch = 0; o_ch < num_target_ch; o_ch++) { 58 tmp_out[o_ch] = 0.0f; 59 for (i_ch = 0; i_ch < num_base_ch; i_ch++) { 60 tmp_out[o_ch] += input_audio[i_ch][i] * 61 uni_drc_sel_proc_output->downmix_matrix[i_ch][o_ch]; 62 } 63 } 64 for (o_ch = 0; o_ch < num_target_ch; o_ch++) { 65 input_audio[o_ch][i] = tmp_out[o_ch]; 66 } 67 for (; o_ch < num_base_ch; o_ch++) { 68 input_audio[o_ch][i] = 0.0f; 69 } 70 } 71 72 return IA_NO_ERROR; 73 } 74 75 IA_ERRORCODE impd_process_time_domain(ia_drc_api_struct *p_obj_drc) { 76 IA_ERRORCODE err_code = IA_NO_ERROR; 77 WORD32 i, j; 78 FLOAT32 *audio_buff[10]; 79 WORD32 last_frame = 0; 80 WORD32 num_sample_to_process; 81 82 if (p_obj_drc->p_state->ui_in_bytes <= 0) { 83 p_obj_drc->p_state->ui_out_bytes = 0; 84 return IA_NO_ERROR; 85 } 86 87 err_code = impd_process_drc_bitstream_dec_gain( 88 p_obj_drc->str_payload.pstr_bitstream_dec, p_obj_drc->pstr_bit_buf, 89 p_obj_drc->str_payload.pstr_drc_config, 90 p_obj_drc->str_payload.pstr_drc_gain, 91 &p_obj_drc->str_bit_handler 92 .it_bit_buf[p_obj_drc->str_bit_handler.byte_index_bs], 93 p_obj_drc->str_bit_handler.num_bytes_bs, 94 p_obj_drc->str_bit_handler.num_bits_offset_bs, 95 &p_obj_drc->str_bit_handler.num_bits_read_bs); 96 97 if (err_code > PROC_COMPLETE) return -1; 98 99 p_obj_drc->str_bit_handler.num_bytes_read_bs = 100 (p_obj_drc->str_bit_handler.num_bits_read_bs >> 3); 101 p_obj_drc->str_bit_handler.num_bits_offset_bs = 102 (p_obj_drc->str_bit_handler.num_bits_read_bs & 7); 103 p_obj_drc->str_bit_handler.byte_index_bs += 104 p_obj_drc->str_bit_handler.num_bytes_read_bs; 105 106 if (p_obj_drc->str_bit_handler.num_bits_offset_bs != 0) { 107 p_obj_drc->str_bit_handler.num_bits_read_bs = 108 p_obj_drc->str_bit_handler.num_bits_read_bs + 8 - 109 p_obj_drc->str_bit_handler.num_bits_offset_bs; 110 p_obj_drc->str_bit_handler.num_bytes_read_bs = 111 p_obj_drc->str_bit_handler.num_bytes_read_bs + 1; 112 p_obj_drc->str_bit_handler.num_bits_offset_bs = 0; 113 p_obj_drc->str_bit_handler.byte_index_bs = 114 p_obj_drc->str_bit_handler.byte_index_bs + 1; 115 } 116 117 num_sample_to_process = 118 (p_obj_drc->p_state->ui_in_bytes / p_obj_drc->str_config.num_ch_in / 119 (p_obj_drc->str_config.pcm_size >> 3)); 120 121 p_obj_drc->str_config.frame_size = num_sample_to_process; 122 123 if (num_sample_to_process < p_obj_drc->str_config.frame_size) last_frame = 1; 124 125 if (p_obj_drc->str_config.pcm_size == 16) { 126 FLOAT32 *scratch_buffer = (FLOAT32 *)p_obj_drc->pp_mem[1]; 127 WORD16 *input_buffer16 = (WORD16 *)p_obj_drc->pp_mem[2]; 128 for (i = 0; i < p_obj_drc->str_config.num_ch_in; i++) { 129 audio_buff[i] = 130 scratch_buffer + i * (p_obj_drc->str_config.frame_size + 32); 131 132 for (j = 0; j < num_sample_to_process; j++) { 133 audio_buff[i][j] = 134 ((FLOAT32)input_buffer16[j * p_obj_drc->str_config.num_ch_in + i]) / 135 32767.0f; 136 } 137 } 138 } else if (p_obj_drc->str_config.pcm_size == 24) { 139 FLOAT32 *scratch_buffer = (FLOAT32 *)p_obj_drc->pp_mem[1]; 140 WORD8 *input_buffer8 = (WORD8 *)p_obj_drc->pp_mem[2]; 141 for (i = 0; i < p_obj_drc->str_config.num_ch_in; i++) { 142 audio_buff[i] = 143 scratch_buffer + i * (p_obj_drc->str_config.frame_size + 32); 144 145 for (j = 0; j < num_sample_to_process; j++) { 146 WORD32 temp; 147 148 WORD8 *addr = 149 (WORD8 *)(&input_buffer8[3 * j * p_obj_drc->str_config.num_ch_in + 150 3 * i]); 151 temp = (WORD8)(*(addr + 2)); 152 temp = (temp << 8) | ((WORD8)(*(addr + 1)) & 0xff); 153 temp = (temp << 8) | (((WORD8) * (addr)) & 0xff); 154 155 audio_buff[i][j] = (FLOAT32)((temp) / 8388607.0f); 156 } 157 } 158 } else { 159 FLOAT32 *scratch_buffer = (FLOAT32 *)p_obj_drc->pp_mem[1]; 160 FLOAT32 *input_buffer = (FLOAT32 *)p_obj_drc->pp_mem[2]; 161 for (i = 0; i < p_obj_drc->str_config.num_ch_in; i++) { 162 audio_buff[i] = 163 scratch_buffer + i * (p_obj_drc->str_config.frame_size + 32); 164 165 for (j = 0; j < num_sample_to_process; j++) { 166 audio_buff[i][j] = 167 input_buffer[j * p_obj_drc->str_config.num_ch_in + i]; 168 } 169 } 170 } 171 172 err_code = impd_drc_process_time_domain( 173 p_obj_drc->str_payload.pstr_gain_dec[0], 174 p_obj_drc->str_payload.pstr_drc_config, 175 p_obj_drc->str_payload.pstr_drc_gain, audio_buff, 176 p_obj_drc->str_payload.pstr_drc_sel_proc_output 177 ->loudness_normalization_gain_db, 178 p_obj_drc->str_payload.pstr_drc_sel_proc_output->boost, 179 p_obj_drc->str_payload.pstr_drc_sel_proc_output->compress, 180 p_obj_drc->str_payload.pstr_drc_sel_proc_output 181 ->drc_characteristic_target); 182 183 if (err_code != IA_NO_ERROR) return err_code; 184 185 if (p_obj_drc->str_payload.pstr_drc_sel_proc_output->downmix_matrix_present != 186 0) 187 err_code = impd_down_mix(p_obj_drc->str_payload.pstr_drc_sel_proc_output, 188 audio_buff, p_obj_drc->str_config.frame_size); 189 190 if (err_code != IA_NO_ERROR) return err_code; 191 192 err_code = impd_drc_process_time_domain( 193 p_obj_drc->str_payload.pstr_gain_dec[1], 194 p_obj_drc->str_payload.pstr_drc_config, 195 p_obj_drc->str_payload.pstr_drc_gain, audio_buff, 196 p_obj_drc->str_payload.pstr_drc_sel_proc_output 197 ->loudness_normalization_gain_db, 198 p_obj_drc->str_payload.pstr_drc_sel_proc_output->boost, 199 p_obj_drc->str_payload.pstr_drc_sel_proc_output->compress, 200 p_obj_drc->str_payload.pstr_drc_sel_proc_output 201 ->drc_characteristic_target); 202 203 if (err_code != IA_NO_ERROR) return err_code; 204 205 if (p_obj_drc->str_payload.pstr_drc_sel_proc_output 206 ->loudness_normalization_gain_db != 0.0f) { 207 FLOAT32 gain_value = 208 (FLOAT32)pow(10.0, p_obj_drc->str_payload.pstr_drc_sel_proc_output 209 ->loudness_normalization_gain_db / 210 20.0); 211 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) { 212 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) { 213 audio_buff[i][j] *= gain_value; 214 } 215 } 216 } 217 218 if (p_obj_drc->str_config.peak_limiter) { 219 FLOAT32 *output_buffer = (FLOAT32 *)p_obj_drc->pp_mem[3]; 220 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) { 221 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) { 222 output_buffer[j * p_obj_drc->str_config.num_ch_out + i] = 223 audio_buff[i][j]; 224 } 225 } 226 227 err_code = 228 impd_limiter_process(p_obj_drc->str_payload.pstr_peak_limiter, 229 output_buffer, p_obj_drc->str_config.frame_size); 230 231 if (err_code != IA_NO_ERROR) return err_code; 232 233 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) { 234 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) { 235 audio_buff[i][j] = 236 output_buffer[j * p_obj_drc->str_config.num_ch_out + i]; 237 } 238 } 239 } 240 241 if (p_obj_drc->str_config.pcm_size == 16) { 242 WORD16 *output_buffer16 = (WORD16 *)p_obj_drc->pp_mem[3]; 243 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) { 244 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) { 245 if (audio_buff[i][j] < -1.0f) 246 output_buffer16[j * p_obj_drc->str_config.num_ch_out + i] = -32767; 247 248 else if (audio_buff[i][j] > 1.0f) 249 output_buffer16[j * p_obj_drc->str_config.num_ch_out + i] = 32767; 250 251 else 252 output_buffer16[j * p_obj_drc->str_config.num_ch_out + i] = 253 (WORD16)(audio_buff[i][j] * 32767.0f); 254 } 255 } 256 } else if (p_obj_drc->str_config.pcm_size == 24) { 257 WORD8 *output_buffer8 = (WORD8 *)p_obj_drc->pp_mem[3]; 258 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) { 259 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) { 260 WORD32 temp = 0; 261 WORD8 *temp_addr = 262 &output_buffer8[3 * j * p_obj_drc->str_config.num_ch_out + 3 * i]; 263 264 if (audio_buff[i][j] < -1.0f) 265 temp = -8388607; 266 267 else if (audio_buff[i][j] > 1.0f) 268 temp = 8388607; 269 270 else 271 temp = (WORD32)(audio_buff[i][j] * 8388607.0f); 272 273 *temp_addr++ = (WORD8)(temp & 0xff); 274 *temp_addr++ = (WORD8)((WORD32)temp >> 8) & 0xff; 275 *temp_addr = (WORD8)((WORD32)temp >> 16) & 0xff; 276 } 277 } 278 } else { 279 FLOAT32 *output_buffer = (FLOAT32 *)p_obj_drc->pp_mem[3]; 280 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) { 281 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) { 282 output_buffer[j * p_obj_drc->str_config.num_ch_out + i] = 283 audio_buff[i][j]; 284 } 285 } 286 } 287 288 p_obj_drc->p_state->ui_out_bytes = 289 p_obj_drc->str_config.num_ch_out * 290 (p_obj_drc->p_state->ui_in_bytes / p_obj_drc->str_config.num_ch_in); 291 292 if (p_obj_drc->p_state->delay_in_output != 0) { 293 FLOAT32 *output_buffer = (FLOAT32 *)p_obj_drc->pp_mem[3]; 294 WORD16 *output_buffer16 = (WORD16 *)p_obj_drc->pp_mem[3]; 295 p_obj_drc->p_state->ui_out_bytes = p_obj_drc->str_config.num_ch_out * 296 (p_obj_drc->str_config.frame_size - 297 p_obj_drc->p_state->delay_in_output) * 298 (p_obj_drc->str_config.pcm_size >> 3); 299 if (p_obj_drc->str_config.pcm_size == 16) 300 memcpy(output_buffer16, 301 (output_buffer16 + (p_obj_drc->p_state->delay_in_output * 302 p_obj_drc->str_config.num_ch_out)), 303 p_obj_drc->p_state->ui_out_bytes); 304 else 305 memcpy(output_buffer, 306 (output_buffer + (p_obj_drc->p_state->delay_in_output * 307 p_obj_drc->str_config.num_ch_out)), 308 p_obj_drc->p_state->ui_out_bytes); 309 310 p_obj_drc->p_state->delay_adjust_samples = 311 p_obj_drc->p_state->delay_in_output; 312 p_obj_drc->p_state->delay_in_output = 0; 313 } 314 if (last_frame == 1) { 315 if ((num_sample_to_process + p_obj_drc->p_state->delay_adjust_samples) <= 316 p_obj_drc->str_config.frame_size) 317 p_obj_drc->p_state->ui_out_bytes = 318 (num_sample_to_process + p_obj_drc->p_state->delay_adjust_samples) * 319 p_obj_drc->str_config.num_ch_out * 320 (p_obj_drc->str_config.pcm_size >> 3); 321 else 322 p_obj_drc->p_state->ui_out_bytes = (p_obj_drc->str_config.frame_size) * 323 p_obj_drc->str_config.num_ch_out * 324 (p_obj_drc->str_config.pcm_size >> 3); 325 } 326 return err_code; 327 } 328