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