• 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 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