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 "impd_type_def.h" 22 #include "impd_memory_standards.h" 23 #include "impd_drc_bitbuffer.h" 24 #include "impd_drc_extr_delta_coded_info.h" 25 #include "impd_drc_common.h" 26 #include "impd_drc_struct.h" 27 #include "impd_drc_interface.h" 28 #include "impd_drc_peak_limiter.h" 29 #include "impd_drc_bitstream_dec_api.h" 30 #include "impd_drc_gain_dec.h" 31 #include "impd_drc_filter_bank.h" 32 #include "impd_drc_multi_band.h" 33 #include "impd_drc_process_audio.h" 34 #include "impd_parametric_drc_dec.h" 35 #include "impd_drc_eq.h" 36 #include "impd_drc_gain_decoder.h" 37 #include "impd_drc_selection_process.h" 38 #include "impd_drc_api_struct_def.h" 39 40 #define BITSTREAM_FILE_FORMAT_SPLIT 1 41 42 static WORD32 impd_down_mix( 43 ia_drc_sel_proc_output_struct *uni_drc_sel_proc_output, 44 FLOAT32 **input_audio, WORD32 frame_len) { 45 WORD32 num_base_ch = uni_drc_sel_proc_output->base_channel_count; 46 WORD32 num_target_ch = uni_drc_sel_proc_output->target_channel_count; 47 WORD32 i, i_ch, o_ch; 48 FLOAT32 tmp_out[MAX_CHANNEL_COUNT]; 49 50 if (uni_drc_sel_proc_output->downmix_matrix_present == 0) return 0; 51 52 if (input_audio == 0) return 0; 53 54 if (num_target_ch > MAX_CHANNEL_COUNT) return -1; 55 56 if (num_target_ch > num_base_ch) return -1; 57 58 for (i = 0; i < frame_len; i++) { 59 for (o_ch = 0; o_ch < num_target_ch; o_ch++) { 60 tmp_out[o_ch] = 0.0f; 61 for (i_ch = 0; i_ch < num_base_ch; i_ch++) { 62 tmp_out[o_ch] += input_audio[i_ch][i] * 63 uni_drc_sel_proc_output->downmix_matrix[i_ch][o_ch]; 64 } 65 } 66 for (o_ch = 0; o_ch < num_target_ch; o_ch++) { 67 input_audio[o_ch][i] = tmp_out[o_ch]; 68 } 69 for (; o_ch < num_base_ch; o_ch++) { 70 input_audio[o_ch][i] = 0.0f; 71 } 72 } 73 74 return 0; 75 } 76 77 WORD32 impd_init_process_audio_main_stft(ia_drc_api_struct *p_obj_drc) 78 79 { 80 WORD32 error = 0, i, j, num_samples_per_channel; 81 FLOAT32 *input_buffer; 82 FLOAT32 *output_buffer; 83 FLOAT32 *audio_io_buf_real[10]; 84 FLOAT32 *audio_io_buf_imag[10]; 85 FLOAT32 *scratch_buffer; 86 WORD32 last_frame = 0; 87 scratch_buffer = (FLOAT32 *)p_obj_drc->pp_mem[1]; 88 input_buffer = (FLOAT32 *)p_obj_drc->pp_mem[2]; 89 output_buffer = (FLOAT32 *)p_obj_drc->pp_mem[3]; 90 91 if (p_obj_drc->p_state->ui_in_bytes <= 0) { 92 p_obj_drc->p_state->ui_out_bytes = 0; 93 return 0; 94 } 95 96 if ((p_obj_drc->p_state->ui_in_bytes / p_obj_drc->str_config.num_ch_in / 97 (p_obj_drc->str_config.pcm_size >> 3)) < 98 (UWORD32)p_obj_drc->str_config.frame_size) 99 last_frame = 1; 100 for (i = 0; i < p_obj_drc->str_config.num_ch_in; i++) { 101 audio_io_buf_real[i] = 102 scratch_buffer + i * (p_obj_drc->str_config.frame_size + 32); 103 audio_io_buf_imag[i] = 104 scratch_buffer + 105 p_obj_drc->str_config.num_ch_in * p_obj_drc->str_config.frame_size + 106 p_obj_drc->str_config.num_ch_in * 64 + 107 i * (p_obj_drc->str_config.frame_size + 64); 108 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) { 109 audio_io_buf_real[i][j] = 110 input_buffer[j * p_obj_drc->str_config.num_ch_in + i]; 111 audio_io_buf_imag[i][j] = 112 input_buffer[p_obj_drc->str_config.num_ch_in * 113 p_obj_drc->str_config.frame_size + 114 j * p_obj_drc->str_config.num_ch_in + i]; 115 } 116 } 117 118 error = impd_process_drc_bitstream_dec_gain( 119 p_obj_drc->str_payload.pstr_bitstream_dec, p_obj_drc->pstr_bit_buf, 120 p_obj_drc->str_payload.pstr_drc_config, 121 p_obj_drc->str_payload.pstr_drc_gain, 122 &p_obj_drc->str_bit_handler 123 .it_bit_buf[p_obj_drc->str_bit_handler.byte_index_bs], 124 p_obj_drc->str_bit_handler.num_bytes_bs, 125 p_obj_drc->str_bit_handler.num_bits_offset_bs, 126 &p_obj_drc->str_bit_handler.num_bits_read_bs); 127 128 if (error > PROC_COMPLETE) return -1; 129 130 p_obj_drc->str_bit_handler.num_bytes_read_bs = 131 (p_obj_drc->str_bit_handler.num_bits_read_bs >> 3); 132 p_obj_drc->str_bit_handler.num_bits_offset_bs = 133 (p_obj_drc->str_bit_handler.num_bits_read_bs & 7); 134 p_obj_drc->str_bit_handler.byte_index_bs += 135 p_obj_drc->str_bit_handler.num_bytes_read_bs; 136 if (p_obj_drc->str_bit_handler.gain_stream_flag == 137 0) // ITTIAM: Flag for applying gain frame by frame 138 { 139 p_obj_drc->str_bit_handler.num_bytes_bs -= 140 p_obj_drc->str_bit_handler.num_bytes_read_bs; 141 } 142 143 if (p_obj_drc->str_config.bitstream_file_format == 144 BITSTREAM_FILE_FORMAT_SPLIT) { 145 if (p_obj_drc->str_bit_handler.num_bits_offset_bs != 0) { 146 p_obj_drc->str_bit_handler.num_bits_read_bs = 147 p_obj_drc->str_bit_handler.num_bits_read_bs + 8 - 148 p_obj_drc->str_bit_handler.num_bits_offset_bs; 149 p_obj_drc->str_bit_handler.num_bytes_read_bs = 150 p_obj_drc->str_bit_handler.num_bytes_read_bs + 1; 151 p_obj_drc->str_bit_handler.num_bits_offset_bs = 0; 152 p_obj_drc->str_bit_handler.byte_index_bs = 153 p_obj_drc->str_bit_handler.byte_index_bs + 1; 154 if (p_obj_drc->str_bit_handler.gain_stream_flag == 155 0) // ITTIAM: Flag for applying gain frame by frame 156 { 157 p_obj_drc->str_bit_handler.num_bytes_bs = 158 p_obj_drc->str_bit_handler.num_bytes_bs - 1; 159 } 160 } 161 } 162 163 error = impd_drc_process_freq_domain( 164 p_obj_drc->str_payload.pstr_gain_dec[0], 165 p_obj_drc->str_payload.pstr_drc_config, 166 p_obj_drc->str_payload.pstr_drc_gain, audio_io_buf_real, 167 audio_io_buf_imag, p_obj_drc->str_payload.pstr_drc_sel_proc_output 168 ->loudness_normalization_gain_db, 169 p_obj_drc->str_payload.pstr_drc_sel_proc_output->boost, 170 p_obj_drc->str_payload.pstr_drc_sel_proc_output->compress, 171 p_obj_drc->str_payload.pstr_drc_sel_proc_output 172 ->drc_characteristic_target); 173 if (error) return -1; 174 175 error = impd_down_mix(p_obj_drc->str_payload.pstr_drc_sel_proc_output, 176 audio_io_buf_real, p_obj_drc->str_config.frame_size); 177 if (error) return -1; 178 179 error = impd_down_mix(p_obj_drc->str_payload.pstr_drc_sel_proc_output, 180 audio_io_buf_imag, p_obj_drc->str_config.frame_size); 181 if (error) return -1; 182 183 error = impd_drc_process_freq_domain( 184 p_obj_drc->str_payload.pstr_gain_dec[1], 185 p_obj_drc->str_payload.pstr_drc_config, 186 p_obj_drc->str_payload.pstr_drc_gain, audio_io_buf_real, 187 audio_io_buf_imag, p_obj_drc->str_payload.pstr_drc_sel_proc_output 188 ->loudness_normalization_gain_db, 189 p_obj_drc->str_payload.pstr_drc_sel_proc_output->boost, 190 p_obj_drc->str_payload.pstr_drc_sel_proc_output->compress, 191 p_obj_drc->str_payload.pstr_drc_sel_proc_output 192 ->drc_characteristic_target); 193 if (error) return -1; 194 195 if (p_obj_drc->str_payload.pstr_drc_sel_proc_output 196 ->loudness_normalization_gain_db != 0.0f) { 197 FLOAT32 loudness_normalization_gain = 198 (FLOAT32)pow(10.0, p_obj_drc->str_payload.pstr_drc_sel_proc_output 199 ->loudness_normalization_gain_db / 200 20.0); 201 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) { 202 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) { 203 audio_io_buf_real[i][j] *= loudness_normalization_gain; 204 audio_io_buf_imag[i][j] *= loudness_normalization_gain; 205 } 206 } 207 } 208 209 num_samples_per_channel = p_obj_drc->str_config.frame_size; 210 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 output_buffer[j * p_obj_drc->str_config.num_ch_out + i] = 214 audio_io_buf_real[i][j]; 215 output_buffer[p_obj_drc->str_config.frame_size * 216 p_obj_drc->str_config.num_ch_in + 217 j * p_obj_drc->str_config.num_ch_out + i] = 218 audio_io_buf_imag[i][j]; 219 } 220 } 221 p_obj_drc->p_state->ui_out_bytes = 222 p_obj_drc->str_config.num_ch_out * (p_obj_drc->str_config.frame_size) * 4; 223 p_obj_drc->p_state->ui_out_bytes = 224 p_obj_drc->str_config.num_ch_out * 225 (p_obj_drc->p_state->ui_in_bytes / p_obj_drc->str_config.num_ch_in); 226 227 if (last_frame == 0) { 228 if (p_obj_drc->str_config.bitstream_file_format != 229 BITSTREAM_FILE_FORMAT_SPLIT) { 230 error = impd_process_drc_bitstream_dec( 231 p_obj_drc->str_payload.pstr_bitstream_dec, p_obj_drc->pstr_bit_buf, 232 p_obj_drc->str_payload.pstr_drc_config, 233 p_obj_drc->str_payload.pstr_loudness_info, 234 &p_obj_drc->str_bit_handler 235 .it_bit_buf[p_obj_drc->str_bit_handler.byte_index_bs], 236 p_obj_drc->str_bit_handler.num_bytes_bs, 237 p_obj_drc->str_bit_handler.num_bits_offset_bs, 238 &p_obj_drc->str_bit_handler.num_bits_read_bs); 239 240 if (error > PROC_COMPLETE) return -1; 241 242 p_obj_drc->str_bit_handler.num_bytes_read_bs = 243 (p_obj_drc->str_bit_handler.num_bits_read_bs >> 3); 244 p_obj_drc->str_bit_handler.num_bits_offset_bs = 245 (p_obj_drc->str_bit_handler.num_bits_read_bs & 7); 246 p_obj_drc->str_bit_handler.byte_index_bs += 247 p_obj_drc->str_bit_handler.num_bytes_read_bs; 248 p_obj_drc->str_bit_handler.num_bytes_bs -= 249 p_obj_drc->str_bit_handler.num_bytes_read_bs; 250 } 251 } 252 253 return error; 254 } 255