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
impd_down_mix(ia_drc_sel_proc_output_struct * uni_drc_sel_proc_output,FLOAT32 ** input_audio,WORD32 frame_len)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
impd_process_time_domain(ia_drc_api_struct * p_obj_drc)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 *input_buffer;
79 WORD16 *input_buffer16, *output_buffer16;
80 FLOAT32 *output_buffer;
81 FLOAT32 *audio_buff[10];
82 FLOAT32 *scratch_buffer;
83 WORD32 last_frame = 0;
84 WORD32 num_sample_to_process;
85 scratch_buffer = (FLOAT32 *)p_obj_drc->pp_mem[1];
86 input_buffer = (FLOAT32 *)p_obj_drc->pp_mem[2];
87 output_buffer = (FLOAT32 *)p_obj_drc->pp_mem[3];
88 input_buffer16 = (WORD16 *)p_obj_drc->pp_mem[2];
89 output_buffer16 = (WORD16 *)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 IA_NO_ERROR;
94 }
95
96 err_code = impd_process_drc_bitstream_dec_gain(
97 p_obj_drc->str_payload.pstr_bitstream_dec, p_obj_drc->pstr_bit_buf,
98 p_obj_drc->str_payload.pstr_drc_config,
99 p_obj_drc->str_payload.pstr_drc_gain,
100 &p_obj_drc->str_bit_handler
101 .it_bit_buf[p_obj_drc->str_bit_handler.byte_index_bs],
102 p_obj_drc->str_bit_handler.num_bytes_bs,
103 p_obj_drc->str_bit_handler.num_bits_offset_bs,
104 &p_obj_drc->str_bit_handler.num_bits_read_bs);
105
106 if (err_code > PROC_COMPLETE) return -1;
107
108 p_obj_drc->str_bit_handler.num_bytes_read_bs =
109 (p_obj_drc->str_bit_handler.num_bits_read_bs >> 3);
110 p_obj_drc->str_bit_handler.num_bits_offset_bs =
111 (p_obj_drc->str_bit_handler.num_bits_read_bs & 7);
112 p_obj_drc->str_bit_handler.byte_index_bs +=
113 p_obj_drc->str_bit_handler.num_bytes_read_bs;
114 if (p_obj_drc->str_bit_handler.gain_stream_flag ==
115 0) // ITTIAM: Flag for applying gain frame by frame
116 {
117 p_obj_drc->str_bit_handler.num_bytes_bs -=
118 p_obj_drc->str_bit_handler.num_bytes_read_bs;
119 }
120
121 if (p_obj_drc->str_config.bitstream_file_format ==
122 BITSTREAM_FILE_FORMAT_SPLIT) {
123 if (p_obj_drc->str_bit_handler.num_bits_offset_bs != 0) {
124 p_obj_drc->str_bit_handler.num_bits_read_bs =
125 p_obj_drc->str_bit_handler.num_bits_read_bs + 8 -
126 p_obj_drc->str_bit_handler.num_bits_offset_bs;
127 p_obj_drc->str_bit_handler.num_bytes_read_bs =
128 p_obj_drc->str_bit_handler.num_bytes_read_bs + 1;
129 p_obj_drc->str_bit_handler.num_bits_offset_bs = 0;
130 p_obj_drc->str_bit_handler.byte_index_bs =
131 p_obj_drc->str_bit_handler.byte_index_bs + 1;
132 if (p_obj_drc->str_bit_handler.gain_stream_flag == 0) {
133 p_obj_drc->str_bit_handler.num_bytes_bs =
134 p_obj_drc->str_bit_handler.num_bytes_bs - 1;
135 }
136 }
137 }
138
139 num_sample_to_process =
140 (p_obj_drc->p_state->ui_in_bytes / p_obj_drc->str_config.num_ch_in /
141 (p_obj_drc->str_config.pcm_size >> 3));
142
143 p_obj_drc->str_config.frame_size = num_sample_to_process;
144
145 if (num_sample_to_process < p_obj_drc->str_config.frame_size) last_frame = 1;
146
147 if (p_obj_drc->str_config.pcm_size == 16) {
148 for (i = 0; i < p_obj_drc->str_config.num_ch_in; i++) {
149 audio_buff[i] =
150 scratch_buffer + i * (p_obj_drc->str_config.frame_size + 32);
151
152 for (j = 0; j < num_sample_to_process; j++) {
153 audio_buff[i][j] =
154 ((FLOAT32)input_buffer16[j * p_obj_drc->str_config.num_ch_in + i]) /
155 32767.0f;
156 }
157 }
158 } else {
159 for (i = 0; i < p_obj_drc->str_config.num_ch_in; i++) {
160 audio_buff[i] =
161 scratch_buffer + i * (p_obj_drc->str_config.frame_size + 32);
162
163 for (j = 0; j < num_sample_to_process; j++) {
164 audio_buff[i][j] =
165 input_buffer[j * p_obj_drc->str_config.num_ch_in + i];
166 }
167 }
168 }
169
170 err_code = impd_drc_process_time_domain(
171 p_obj_drc->str_payload.pstr_gain_dec[0],
172 p_obj_drc->str_payload.pstr_drc_config,
173 p_obj_drc->str_payload.pstr_drc_gain, audio_buff,
174 p_obj_drc->str_payload.pstr_drc_sel_proc_output
175 ->loudness_normalization_gain_db,
176 p_obj_drc->str_payload.pstr_drc_sel_proc_output->boost,
177 p_obj_drc->str_payload.pstr_drc_sel_proc_output->compress,
178 p_obj_drc->str_payload.pstr_drc_sel_proc_output
179 ->drc_characteristic_target);
180
181 if (err_code != IA_NO_ERROR) return err_code;
182
183 if (p_obj_drc->str_payload.pstr_drc_sel_proc_output->downmix_matrix_present !=
184 0)
185 err_code = impd_down_mix(p_obj_drc->str_payload.pstr_drc_sel_proc_output,
186 audio_buff, p_obj_drc->str_config.frame_size);
187
188 if (err_code != IA_NO_ERROR) return err_code;
189
190 err_code = impd_drc_process_time_domain(
191 p_obj_drc->str_payload.pstr_gain_dec[1],
192 p_obj_drc->str_payload.pstr_drc_config,
193 p_obj_drc->str_payload.pstr_drc_gain, audio_buff,
194 p_obj_drc->str_payload.pstr_drc_sel_proc_output
195 ->loudness_normalization_gain_db,
196 p_obj_drc->str_payload.pstr_drc_sel_proc_output->boost,
197 p_obj_drc->str_payload.pstr_drc_sel_proc_output->compress,
198 p_obj_drc->str_payload.pstr_drc_sel_proc_output
199 ->drc_characteristic_target);
200
201 if (err_code != IA_NO_ERROR) return err_code;
202
203 if (p_obj_drc->str_payload.pstr_drc_sel_proc_output
204 ->loudness_normalization_gain_db != 0.0f) {
205 FLOAT32 gain_value =
206 (FLOAT32)pow(10.0, p_obj_drc->str_payload.pstr_drc_sel_proc_output
207 ->loudness_normalization_gain_db /
208 20.0);
209 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) {
210 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
211 audio_buff[i][j] *= gain_value;
212 }
213 }
214 }
215
216 if (p_obj_drc->str_config.peak_limiter) {
217 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) {
218 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
219 output_buffer[j * p_obj_drc->str_config.num_ch_out + i] =
220 audio_buff[i][j];
221 }
222 }
223
224 err_code =
225 impd_limiter_process(p_obj_drc->str_payload.pstr_peak_limiter,
226 output_buffer, p_obj_drc->str_config.frame_size);
227
228 if (err_code != IA_NO_ERROR) return err_code;
229
230 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) {
231 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
232 audio_buff[i][j] =
233 output_buffer[j * p_obj_drc->str_config.num_ch_out + i];
234 }
235 }
236 }
237
238 if (p_obj_drc->str_config.pcm_size == 16) {
239 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) {
240 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
241 if (audio_buff[i][j] < -1.0f)
242 output_buffer16[j * p_obj_drc->str_config.num_ch_out + i] = -32767;
243
244 else if (audio_buff[i][j] > 1.0f)
245 output_buffer16[j * p_obj_drc->str_config.num_ch_out + i] = 32767;
246
247 else
248 output_buffer16[j * p_obj_drc->str_config.num_ch_out + i] =
249 (WORD16)(audio_buff[i][j] * 32767.0f);
250 }
251 }
252 } else {
253 for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) {
254 for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
255 output_buffer[j * p_obj_drc->str_config.num_ch_out + i] =
256 audio_buff[i][j];
257 }
258 }
259 }
260
261 p_obj_drc->p_state->ui_out_bytes =
262 p_obj_drc->str_config.num_ch_out *
263 (p_obj_drc->p_state->ui_in_bytes / p_obj_drc->str_config.num_ch_in);
264
265 if (p_obj_drc->p_state->delay_in_output != 0) {
266 p_obj_drc->p_state->ui_out_bytes = p_obj_drc->str_config.num_ch_out *
267 (p_obj_drc->str_config.frame_size -
268 p_obj_drc->p_state->delay_in_output) *
269 (p_obj_drc->str_config.pcm_size >> 3);
270 if (p_obj_drc->str_config.pcm_size == 16)
271 memcpy(output_buffer16,
272 (output_buffer16 + (p_obj_drc->p_state->delay_in_output *
273 p_obj_drc->str_config.num_ch_out)),
274 p_obj_drc->p_state->ui_out_bytes);
275 else
276 memcpy(output_buffer,
277 (output_buffer + (p_obj_drc->p_state->delay_in_output *
278 p_obj_drc->str_config.num_ch_out)),
279 p_obj_drc->p_state->ui_out_bytes);
280
281 p_obj_drc->p_state->delay_adjust_samples =
282 p_obj_drc->p_state->delay_in_output;
283 p_obj_drc->p_state->delay_in_output = 0;
284 }
285 if (last_frame == 1) {
286 if ((num_sample_to_process + p_obj_drc->p_state->delay_adjust_samples) <=
287 p_obj_drc->str_config.frame_size)
288 p_obj_drc->p_state->ui_out_bytes =
289 (num_sample_to_process + p_obj_drc->p_state->delay_adjust_samples) *
290 p_obj_drc->str_config.num_ch_out *
291 (p_obj_drc->str_config.pcm_size >> 3);
292 else
293 p_obj_drc->p_state->ui_out_bytes = (p_obj_drc->str_config.frame_size) *
294 p_obj_drc->str_config.num_ch_out *
295 (p_obj_drc->str_config.pcm_size >> 3);
296 }
297
298 if (last_frame == 0) {
299 if (p_obj_drc->str_config.bitstream_file_format !=
300 BITSTREAM_FILE_FORMAT_SPLIT) {
301 err_code = impd_process_drc_bitstream_dec(
302 p_obj_drc->str_payload.pstr_bitstream_dec, p_obj_drc->pstr_bit_buf,
303 p_obj_drc->str_payload.pstr_drc_config,
304 p_obj_drc->str_payload.pstr_loudness_info,
305 &p_obj_drc->str_bit_handler
306 .it_bit_buf[p_obj_drc->str_bit_handler.byte_index_bs],
307 p_obj_drc->str_bit_handler.num_bytes_bs,
308 p_obj_drc->str_bit_handler.num_bits_offset_bs,
309 &p_obj_drc->str_bit_handler.num_bits_read_bs);
310
311 if (err_code > PROC_COMPLETE) return -1;
312
313 p_obj_drc->str_bit_handler.num_bytes_read_bs =
314 (p_obj_drc->str_bit_handler.num_bits_read_bs >> 3);
315 p_obj_drc->str_bit_handler.num_bits_offset_bs =
316 (p_obj_drc->str_bit_handler.num_bits_read_bs & 7);
317 p_obj_drc->str_bit_handler.byte_index_bs +=
318 p_obj_drc->str_bit_handler.num_bytes_read_bs;
319 p_obj_drc->str_bit_handler.num_bytes_bs -=
320 p_obj_drc->str_bit_handler.num_bytes_read_bs;
321 }
322 }
323
324 return err_code;
325 }
326