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 IA_ERRORCODE impd_drc_set_default_bitstream_config(
44 ia_drc_config *pstr_drc_config);
45
impd_down_mix(ia_drc_sel_proc_output_struct * uni_drc_sel_proc_output,FLOAT32 ** input_audio,WORD32 frame_len)46 static IA_ERRORCODE impd_down_mix(
47 ia_drc_sel_proc_output_struct *uni_drc_sel_proc_output,
48 FLOAT32 **input_audio, WORD32 frame_len) {
49 WORD32 num_base_ch = uni_drc_sel_proc_output->base_channel_count;
50 WORD32 num_target_ch = uni_drc_sel_proc_output->target_channel_count;
51 WORD32 i, i_ch, o_ch;
52 FLOAT32 tmp_out[MAX_CHANNEL_COUNT];
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 IA_NO_ERROR;
75 }
76
impd_process_time_domain(ia_drc_api_struct * p_obj_drc)77 IA_ERRORCODE impd_process_time_domain(ia_drc_api_struct *p_obj_drc) {
78 IA_ERRORCODE err_code = IA_NO_ERROR;
79 WORD32 i, j;
80 FLOAT32 *audio_buff[10];
81 WORD32 last_frame = 0;
82 WORD32 num_sample_to_process;
83
84 if (p_obj_drc->p_state->ui_in_bytes <= 0) {
85 p_obj_drc->p_state->ui_out_bytes = 0;
86 return IA_NO_ERROR;
87 }
88
89 p_obj_drc->str_payload.pstr_loudness_info->loudness_info_album_count = 0;
90 p_obj_drc->str_payload.pstr_loudness_info->loudness_info_count = 0;
91 p_obj_drc->str_payload.pstr_loudness_info->loudness_info_set_ext_present = 0;
92 p_obj_drc->str_payload.pstr_drc_config->is_config_changed =
93 p_obj_drc->str_config.is_config_changed;
94
95 if (p_obj_drc->str_config.is_config_changed == 1) {
96 err_code = impd_process_drc_bitstream_dec_loudness_info_set(
97 p_obj_drc->pstr_bit_buf, p_obj_drc->str_payload.pstr_loudness_info,
98 &p_obj_drc->str_bit_handler.bitstream_loudness_info[0],
99 p_obj_drc->str_bit_handler.num_bytes_bs_loudness_info);
100 if (err_code != IA_NO_ERROR) return err_code;
101
102 err_code = impd_drc_uni_sel_proc_process(
103 p_obj_drc->str_payload.pstr_selection_proc,
104 p_obj_drc->str_payload.pstr_drc_config,
105 p_obj_drc->str_payload.pstr_loudness_info,
106 p_obj_drc->str_payload.pstr_drc_sel_proc_output);
107 if (err_code != IA_NO_ERROR) return err_code;
108
109 err_code = impd_process_drc_bitstream_dec_config(
110 p_obj_drc->str_payload.pstr_bitstream_dec, p_obj_drc->pstr_bit_buf,
111 p_obj_drc->str_payload.pstr_drc_config,
112 &p_obj_drc->str_bit_handler.bitstream_drc_config[0],
113 p_obj_drc->str_bit_handler.num_bytes_bs_drc_config);
114 if (err_code == 1) {
115 memset(p_obj_drc->str_payload.pstr_drc_config, 0, sizeof(ia_drc_config));
116 err_code = impd_drc_set_default_bitstream_config(
117 p_obj_drc->str_payload.pstr_drc_config);
118 p_obj_drc->str_payload.pstr_drc_config->channel_layout
119 .base_channel_count = p_obj_drc->str_config.num_ch_in;
120 }
121
122 if (err_code != IA_NO_ERROR) return err_code;
123 }
124
125 if (p_obj_drc->frame_count == 0) {
126 p_obj_drc->str_config.ln_dbgain_prev =
127 (WORD32)p_obj_drc->str_payload.pstr_drc_sel_proc_output
128 ->loudness_normalization_gain_db;
129 }
130
131 if (!p_obj_drc->str_payload.pstr_drc_config->ln_gain_changed) {
132 if (p_obj_drc->str_payload.pstr_drc_sel_proc_output
133 ->loudness_normalization_gain_db !=
134 p_obj_drc->str_config.ln_dbgain_prev) {
135 p_obj_drc->str_payload.pstr_drc_config->ln_gain_changed = 1;
136 }
137 }
138
139 err_code = impd_process_drc_bitstream_dec_gain(
140 p_obj_drc->str_payload.pstr_bitstream_dec, p_obj_drc->pstr_bit_buf,
141 p_obj_drc->str_payload.pstr_drc_config,
142 p_obj_drc->str_payload.pstr_drc_gain,
143 p_obj_drc->str_bit_handler.it_bit_buf,
144 p_obj_drc->str_bit_handler.num_bytes_bs,
145 p_obj_drc->str_bit_handler.num_bits_offset_bs,
146 &p_obj_drc->str_bit_handler.num_bits_read_bs);
147
148 if (err_code > PROC_COMPLETE) return -1;
149
150 p_obj_drc->str_bit_handler.num_bytes_read_bs =
151 (p_obj_drc->str_bit_handler.num_bits_read_bs >> 3);
152 p_obj_drc->str_bit_handler.num_bits_offset_bs =
153 (p_obj_drc->str_bit_handler.num_bits_read_bs & 7);
154 p_obj_drc->str_bit_handler.byte_index_bs +=
155 p_obj_drc->str_bit_handler.num_bytes_read_bs;
156
157 if (p_obj_drc->str_bit_handler.num_bits_offset_bs != 0) {
158 p_obj_drc->str_bit_handler.num_bits_read_bs =
159 p_obj_drc->str_bit_handler.num_bits_read_bs + 8 -
160 p_obj_drc->str_bit_handler.num_bits_offset_bs;
161 p_obj_drc->str_bit_handler.num_bytes_read_bs =
162 p_obj_drc->str_bit_handler.num_bytes_read_bs + 1;
163 p_obj_drc->str_bit_handler.num_bits_offset_bs = 0;
164 p_obj_drc->str_bit_handler.byte_index_bs =
165 p_obj_drc->str_bit_handler.byte_index_bs + 1;
166 }
167
168 num_sample_to_process =
169 (p_obj_drc->p_state->ui_in_bytes / p_obj_drc->str_config.num_ch_in /
170 (p_obj_drc->str_config.pcm_size >> 3));
171
172 p_obj_drc->str_config.frame_size = num_sample_to_process;
173
174 if (num_sample_to_process < p_obj_drc->str_config.frame_size) last_frame = 1;
175
176 if (p_obj_drc->str_config.pcm_size == 16) {
177 FLOAT32 *scratch_buffer = (FLOAT32 *)p_obj_drc->pp_mem[1];
178 WORD16 *input_buffer16 = (WORD16 *)p_obj_drc->pp_mem[2];
179 for (i = 0; i < p_obj_drc->str_config.num_ch_in; i++) {
180 audio_buff[i] =
181 scratch_buffer + i * (p_obj_drc->str_config.frame_size + 32);
182
183 for (j = 0; j < num_sample_to_process; j++) {
184 audio_buff[i][j] =
185 ((FLOAT32)input_buffer16[j * p_obj_drc->str_config.num_ch_in + i]) /
186 32767.0f;
187 }
188 }
189 } else if (p_obj_drc->str_config.pcm_size == 24) {
190 FLOAT32 *scratch_buffer = (FLOAT32 *)p_obj_drc->pp_mem[1];
191 WORD8 *input_buffer8 = (WORD8 *)p_obj_drc->pp_mem[2];
192 for (i = 0; i < p_obj_drc->str_config.num_ch_in; i++) {
193 audio_buff[i] =
194 scratch_buffer + i * (p_obj_drc->str_config.frame_size + 32);
195
196 for (j = 0; j < num_sample_to_process; j++) {
197 WORD32 temp;
198
199 WORD8 *addr =
200 (WORD8 *)(&input_buffer8[3 * j * p_obj_drc->str_config.num_ch_in +
201 3 * i]);
202 temp = (WORD8)(*(addr + 2));
203 temp = (temp << 8) | ((WORD8)(*(addr + 1)) & 0xff);
204 temp = (temp << 8) | (((WORD8) * (addr)) & 0xff);
205
206 audio_buff[i][j] = (FLOAT32)((temp) / 8388607.0f);
207 }
208 }
209 } else {
210 FLOAT32 *scratch_buffer = (FLOAT32 *)p_obj_drc->pp_mem[1];
211 FLOAT32 *input_buffer = (FLOAT32 *)p_obj_drc->pp_mem[2];
212 for (i = 0; i < p_obj_drc->str_config.num_ch_in; i++) {
213 audio_buff[i] =
214 scratch_buffer + i * (p_obj_drc->str_config.frame_size + 32);
215
216 for (j = 0; j < num_sample_to_process; j++) {
217 audio_buff[i][j] =
218 input_buffer[j * p_obj_drc->str_config.num_ch_in + i];
219 }
220 }
221 }
222
223 err_code = impd_drc_process_time_domain(
224 p_obj_drc->str_payload.pstr_gain_dec[0],
225 p_obj_drc->str_payload.pstr_drc_config,
226 p_obj_drc->str_payload.pstr_drc_gain, audio_buff,
227 p_obj_drc->str_payload.pstr_drc_sel_proc_output
228 ->loudness_normalization_gain_db,
229 p_obj_drc->str_payload.pstr_drc_sel_proc_output->boost,
230 p_obj_drc->str_payload.pstr_drc_sel_proc_output->compress,
231 p_obj_drc->str_payload.pstr_drc_sel_proc_output
232 ->drc_characteristic_target);
233
234 if (err_code != IA_NO_ERROR) return err_code;
235
236 if (p_obj_drc->str_payload.pstr_drc_sel_proc_output->downmix_matrix_present !=
237 0)
238 err_code = impd_down_mix(p_obj_drc->str_payload.pstr_drc_sel_proc_output,
239 audio_buff, p_obj_drc->str_config.frame_size);
240
241 if (err_code != IA_NO_ERROR) return err_code;
242
243 err_code = impd_drc_process_time_domain(
244 p_obj_drc->str_payload.pstr_gain_dec[1],
245 p_obj_drc->str_payload.pstr_drc_config,
246 p_obj_drc->str_payload.pstr_drc_gain, audio_buff,
247 p_obj_drc->str_payload.pstr_drc_sel_proc_output
248 ->loudness_normalization_gain_db,
249 p_obj_drc->str_payload.pstr_drc_sel_proc_output->boost,
250 p_obj_drc->str_payload.pstr_drc_sel_proc_output->compress,
251 p_obj_drc->str_payload.pstr_drc_sel_proc_output
252 ->drc_characteristic_target);
253
254 if (err_code != IA_NO_ERROR) return err_code;
255
256 if (p_obj_drc->str_payload.pstr_drc_config->apply_drc == 0 ||
257 p_obj_drc->str_payload.pstr_drc_config->is_config_changed == 0 ||
258 p_obj_drc->str_payload.pstr_drc_config->ln_gain_changed == 0) {
259 if (p_obj_drc->str_payload.pstr_drc_sel_proc_output
260 ->loudness_normalization_gain_db != 0.0f) {
261 FLOAT32 gain_value =
262 (FLOAT32)pow(10.0, p_obj_drc->str_payload.pstr_drc_sel_proc_output
263 ->loudness_normalization_gain_db /
264 20.0);
265 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) {
266 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
267 audio_buff[i][j] *= gain_value;
268 }
269 }
270 }
271 }
272
273 if (p_obj_drc->str_config.peak_limiter) {
274 FLOAT32 *output_buffer = (FLOAT32 *)p_obj_drc->pp_mem[3];
275 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) {
276 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
277 output_buffer[j * p_obj_drc->str_config.num_ch_out + i] =
278 audio_buff[i][j];
279 }
280 }
281
282 impd_limiter_process(p_obj_drc->str_payload.pstr_peak_limiter,
283 output_buffer, p_obj_drc->str_config.frame_size);
284
285 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) {
286 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
287 audio_buff[i][j] =
288 output_buffer[j * p_obj_drc->str_config.num_ch_out + i];
289 }
290 }
291 }
292
293 if (p_obj_drc->str_config.pcm_size == 16) {
294 WORD16 *output_buffer16 = (WORD16 *)p_obj_drc->pp_mem[3];
295 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) {
296 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
297 if (audio_buff[i][j] < -1.0f)
298 output_buffer16[j * p_obj_drc->str_config.num_ch_out + i] = -32767;
299
300 else if (audio_buff[i][j] > 1.0f)
301 output_buffer16[j * p_obj_drc->str_config.num_ch_out + i] = 32767;
302
303 else
304 output_buffer16[j * p_obj_drc->str_config.num_ch_out + i] =
305 (WORD16)(audio_buff[i][j] * 32767.0f);
306 }
307 }
308 } else if (p_obj_drc->str_config.pcm_size == 24) {
309 WORD8 *output_buffer8 = (WORD8 *)p_obj_drc->pp_mem[3];
310 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) {
311 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
312 WORD32 temp = 0;
313 WORD8 *temp_addr =
314 &output_buffer8[3 * j * p_obj_drc->str_config.num_ch_out + 3 * i];
315
316 if (audio_buff[i][j] < -1.0f)
317 temp = -8388607;
318
319 else if (audio_buff[i][j] > 1.0f)
320 temp = 8388607;
321
322 else
323 temp = (WORD32)(audio_buff[i][j] * 8388607.0f);
324
325 *temp_addr++ = (WORD8)(temp & 0xff);
326 *temp_addr++ = (WORD8)((WORD32)temp >> 8) & 0xff;
327 *temp_addr = (WORD8)((WORD32)temp >> 16) & 0xff;
328 }
329 }
330 } else {
331 FLOAT32 *output_buffer = (FLOAT32 *)p_obj_drc->pp_mem[3];
332 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) {
333 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
334 output_buffer[j * p_obj_drc->str_config.num_ch_out + i] =
335 audio_buff[i][j];
336 }
337 }
338 }
339
340 p_obj_drc->p_state->ui_out_bytes =
341 p_obj_drc->str_config.num_ch_out *
342 (p_obj_drc->p_state->ui_in_bytes / p_obj_drc->str_config.num_ch_in);
343
344 if (p_obj_drc->p_state->delay_in_output != 0) {
345 FLOAT32 *output_buffer = (FLOAT32 *)p_obj_drc->pp_mem[3];
346 WORD16 *output_buffer16 = (WORD16 *)p_obj_drc->pp_mem[3];
347 p_obj_drc->p_state->ui_out_bytes = p_obj_drc->str_config.num_ch_out *
348 (p_obj_drc->str_config.frame_size -
349 p_obj_drc->p_state->delay_in_output) *
350 (p_obj_drc->str_config.pcm_size >> 3);
351 if (p_obj_drc->str_config.pcm_size == 16)
352 memcpy(output_buffer16,
353 (output_buffer16 + (p_obj_drc->p_state->delay_in_output *
354 p_obj_drc->str_config.num_ch_out)),
355 p_obj_drc->p_state->ui_out_bytes);
356 else
357 memcpy(output_buffer,
358 (output_buffer + (p_obj_drc->p_state->delay_in_output *
359 p_obj_drc->str_config.num_ch_out)),
360 p_obj_drc->p_state->ui_out_bytes);
361
362 p_obj_drc->p_state->delay_adjust_samples =
363 p_obj_drc->p_state->delay_in_output;
364 p_obj_drc->p_state->delay_in_output = 0;
365 }
366 if (last_frame == 1) {
367 if ((num_sample_to_process + p_obj_drc->p_state->delay_adjust_samples) <=
368 p_obj_drc->str_config.frame_size)
369 p_obj_drc->p_state->ui_out_bytes =
370 (num_sample_to_process + p_obj_drc->p_state->delay_adjust_samples) *
371 p_obj_drc->str_config.num_ch_out *
372 (p_obj_drc->str_config.pcm_size >> 3);
373 else
374 p_obj_drc->p_state->ui_out_bytes = (p_obj_drc->str_config.frame_size) *
375 p_obj_drc->str_config.num_ch_out *
376 (p_obj_drc->str_config.pcm_size >> 3);
377 }
378 p_obj_drc->frame_count++;
379 return err_code;
380 }
381