• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *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     impd_limiter_process(p_obj_drc->str_payload.pstr_peak_limiter,
228                          output_buffer, p_obj_drc->str_config.frame_size);
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     WORD16 *output_buffer16 = (WORD16 *)p_obj_drc->pp_mem[3];
240     for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) {
241       for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
242         if (audio_buff[i][j] < -1.0f)
243           output_buffer16[j * p_obj_drc->str_config.num_ch_out + i] = -32767;
244 
245         else if (audio_buff[i][j] > 1.0f)
246           output_buffer16[j * p_obj_drc->str_config.num_ch_out + i] = 32767;
247 
248         else
249           output_buffer16[j * p_obj_drc->str_config.num_ch_out + i] =
250               (WORD16)(audio_buff[i][j] * 32767.0f);
251       }
252     }
253   } else if (p_obj_drc->str_config.pcm_size == 24) {
254     WORD8 *output_buffer8 = (WORD8 *)p_obj_drc->pp_mem[3];
255     for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) {
256       for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
257         WORD32 temp = 0;
258         WORD8 *temp_addr =
259             &output_buffer8[3 * j * p_obj_drc->str_config.num_ch_out + 3 * i];
260 
261         if (audio_buff[i][j] < -1.0f)
262           temp = -8388607;
263 
264         else if (audio_buff[i][j] > 1.0f)
265           temp = 8388607;
266 
267         else
268           temp = (WORD32)(audio_buff[i][j] * 8388607.0f);
269 
270         *temp_addr++ = (WORD8)(temp & 0xff);
271         *temp_addr++ = (WORD8)((WORD32)temp >> 8) & 0xff;
272         *temp_addr = (WORD8)((WORD32)temp >> 16) & 0xff;
273       }
274     }
275   } else {
276     FLOAT32 *output_buffer = (FLOAT32 *)p_obj_drc->pp_mem[3];
277     for (i = 0; i < p_obj_drc->str_config.num_ch_out; i++) {
278       for (j = 0; j < p_obj_drc->str_config.frame_size; j++) {
279         output_buffer[j * p_obj_drc->str_config.num_ch_out + i] =
280             audio_buff[i][j];
281       }
282     }
283   }
284 
285   p_obj_drc->p_state->ui_out_bytes =
286       p_obj_drc->str_config.num_ch_out *
287       (p_obj_drc->p_state->ui_in_bytes / p_obj_drc->str_config.num_ch_in);
288 
289   if (p_obj_drc->p_state->delay_in_output != 0) {
290     FLOAT32 *output_buffer = (FLOAT32 *)p_obj_drc->pp_mem[3];
291     WORD16 *output_buffer16 = (WORD16 *)p_obj_drc->pp_mem[3];
292     p_obj_drc->p_state->ui_out_bytes = p_obj_drc->str_config.num_ch_out *
293                                        (p_obj_drc->str_config.frame_size -
294                                         p_obj_drc->p_state->delay_in_output) *
295                                        (p_obj_drc->str_config.pcm_size >> 3);
296     if (p_obj_drc->str_config.pcm_size == 16)
297       memcpy(output_buffer16,
298              (output_buffer16 + (p_obj_drc->p_state->delay_in_output *
299                                  p_obj_drc->str_config.num_ch_out)),
300              p_obj_drc->p_state->ui_out_bytes);
301     else
302       memcpy(output_buffer,
303              (output_buffer + (p_obj_drc->p_state->delay_in_output *
304                                p_obj_drc->str_config.num_ch_out)),
305              p_obj_drc->p_state->ui_out_bytes);
306 
307     p_obj_drc->p_state->delay_adjust_samples =
308         p_obj_drc->p_state->delay_in_output;
309     p_obj_drc->p_state->delay_in_output = 0;
310   }
311   if (last_frame == 1) {
312     if ((num_sample_to_process + p_obj_drc->p_state->delay_adjust_samples) <=
313         p_obj_drc->str_config.frame_size)
314       p_obj_drc->p_state->ui_out_bytes =
315           (num_sample_to_process + p_obj_drc->p_state->delay_adjust_samples) *
316           p_obj_drc->str_config.num_ch_out *
317           (p_obj_drc->str_config.pcm_size >> 3);
318     else
319       p_obj_drc->p_state->ui_out_bytes = (p_obj_drc->str_config.frame_size) *
320                                          p_obj_drc->str_config.num_ch_out *
321                                          (p_obj_drc->str_config.pcm_size >> 3);
322   }
323   return err_code;
324 }
325