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 <stdio.h>
21 #include <stdlib.h>
22 #include <math.h>
23 #include <string.h>
24 
25 #include "impd_type_def.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_filter_bank.h"
30 #include "impd_drc_multi_band.h"
31 #include "impd_drc_gain_dec.h"
32 #include "impd_drc_process_audio.h"
33 
impd_apply_gains_and_add(ia_drc_instructions_struct * pstr_drc_instruction_arr,const WORD32 drc_instructions_index,ia_drc_params_struct * ia_drc_params_struct,ia_gain_buffer_struct * pstr_gain_buf,shape_filter_block shape_filter_block[],FLOAT32 * deinterleaved_audio[],FLOAT32 * channel_audio[],WORD32 impd_apply_gains)34 VOID impd_apply_gains_and_add(
35     ia_drc_instructions_struct* pstr_drc_instruction_arr,
36     const WORD32 drc_instructions_index,
37     ia_drc_params_struct* ia_drc_params_struct,
38     ia_gain_buffer_struct* pstr_gain_buf,
39     shape_filter_block shape_filter_block[], FLOAT32* deinterleaved_audio[],
40 
41     FLOAT32* channel_audio[], WORD32 impd_apply_gains) {
42   WORD32 c, b, g, i;
43   WORD32 offset = 0, signalIndex = 0;
44   WORD32 gainIndexForGroup[CHANNEL_GROUP_COUNT_MAX];
45   WORD32 signalIndexForChannel[MAX_CHANNEL_COUNT];
46   FLOAT32* lpcm_gains;
47   FLOAT32 sum;
48   FLOAT32 drc_gain_last, gainThr;
49   WORD32 iEnd, iStart;
50   ia_drc_instructions_struct* str_drc_instruction_str =
51       &(pstr_drc_instruction_arr[drc_instructions_index]);
52 
53   if (drc_instructions_index >= 0) {
54     str_drc_instruction_str =
55         &(pstr_drc_instruction_arr[drc_instructions_index]);
56     {
57       if (str_drc_instruction_str->drc_set_id > 0) {
58         if (ia_drc_params_struct->delay_mode == DELAY_MODE_LOW_DELAY) {
59           offset = ia_drc_params_struct->drc_frame_size;
60         }
61         gainIndexForGroup[0] = 0;
62         for (g = 0; g < str_drc_instruction_str->num_drc_ch_groups - 1; g++) {
63           gainIndexForGroup[g + 1] =
64               gainIndexForGroup[g] +
65               str_drc_instruction_str->band_count_of_ch_group[g];
66         }
67         signalIndexForChannel[0] = 0;
68         for (c = 0; c < str_drc_instruction_str->audio_num_chan - 1; c++) {
69           if (str_drc_instruction_str->channel_group_of_ch[c] >= 0) {
70             signalIndexForChannel[c + 1] =
71                 signalIndexForChannel[c] +
72                 str_drc_instruction_str->band_count_of_ch_group
73                     [str_drc_instruction_str->channel_group_of_ch[c]];
74           } else {
75             signalIndexForChannel[c + 1] = signalIndexForChannel[c] + 1;
76           }
77         }
78 
79         for (g = 0; g < str_drc_instruction_str->num_drc_ch_groups; g++) {
80           for (b = 0; b < str_drc_instruction_str->band_count_of_ch_group[g];
81                b++) {
82             if (str_drc_instruction_str->ch_group_parametric_drc_flag[g] == 0) {
83               lpcm_gains =
84                   pstr_gain_buf->buf_interpolation[gainIndexForGroup[g] + b]
85                       .lpcm_gains +
86                   MAX_SIGNAL_DELAY - ia_drc_params_struct->gain_delay_samples -
87                   ia_drc_params_struct->audio_delay_samples + offset;
88             } else {
89               lpcm_gains =
90                   pstr_gain_buf->buf_interpolation[gainIndexForGroup[g] + b]
91                       .lpcm_gains +
92                   MAX_SIGNAL_DELAY +
93                   str_drc_instruction_str
94                       ->parametric_drc_look_ahead_samples[g] -
95                   ia_drc_params_struct->audio_delay_samples;
96             }
97             iEnd = 0;
98             iStart = 0;
99             while (iEnd < ia_drc_params_struct->drc_frame_size) {
100               if (shape_filter_block[g].shape_flter_block_flag) {
101                 drc_gain_last = shape_filter_block[g].drc_gain_last;
102                 gainThr = 0.0001f * drc_gain_last;
103                 while ((iEnd < ia_drc_params_struct->drc_frame_size) &&
104                        (fabs(lpcm_gains[iEnd] - drc_gain_last) <= gainThr))
105                   iEnd++;
106               } else {
107                 iEnd = ia_drc_params_struct->drc_frame_size;
108               }
109 
110               for (c = 0; c < str_drc_instruction_str->audio_num_chan; c++)
111 
112               {
113                 if (g == str_drc_instruction_str->channel_group_of_ch[c]) {
114                   signalIndex = signalIndexForChannel[c] + b;
115 
116                   if (impd_apply_gains == 1) {
117                     impd_shape_filt_block_time_process(
118                         &shape_filter_block[g], &lpcm_gains[0], signalIndex,
119                         &deinterleaved_audio[signalIndex][0], iStart, iEnd);
120 
121                   } else {
122                     for (i = iStart; i < iEnd; i++) {
123                       deinterleaved_audio[signalIndex][i] = lpcm_gains[i];
124                     }
125                   }
126                 }
127               }
128               if ((iEnd < ia_drc_params_struct->drc_frame_size) &&
129                   (shape_filter_block[g].shape_flter_block_flag)) {
130                 impd_shape_filt_block_adapt(lpcm_gains[iEnd],
131                                             &shape_filter_block[g]);
132               }
133               if ((iEnd == iStart) &&
134                   (drc_gain_last == shape_filter_block[g].drc_gain_last))
135                 break;
136               iStart = iEnd;
137             }
138           }
139         }
140       }
141     }
142   }
143 
144   signalIndex = 0;
145 
146   if (str_drc_instruction_str->drc_set_id > 0) {
147     for (c = 0; c < str_drc_instruction_str->audio_num_chan; c++)
148 
149     {
150       g = str_drc_instruction_str->channel_group_of_ch[c];
151       if (g >= 0) {
152         for (i = 0; i < ia_drc_params_struct->drc_frame_size; i++) {
153           sum = 0.0f;
154           for (b = 0; b < str_drc_instruction_str->band_count_of_ch_group[g];
155                b++) {
156             sum += deinterleaved_audio[signalIndex + b][i];
157           }
158 
159           channel_audio[c][i] = sum;
160         }
161         signalIndex += str_drc_instruction_str->band_count_of_ch_group[g];
162       } else {
163         for (i = 0; i < ia_drc_params_struct->drc_frame_size; i++) {
164           channel_audio[c][i] = deinterleaved_audio[signalIndex][i];
165         }
166         signalIndex++;
167       }
168     }
169   } else {
170     for (c = 0; c < str_drc_instruction_str->audio_num_chan; c++)
171 
172     {
173       for (i = 0; i < ia_drc_params_struct->drc_frame_size; i++) {
174         channel_audio[c][i] = deinterleaved_audio[c][i];
175       }
176     }
177   }
178 
179   return;
180 }
181 
182 WORD32
impd_filter_banks_process(ia_drc_instructions_struct * pstr_drc_instruction_arr,const WORD32 drc_instructions_index,ia_drc_params_struct * ia_drc_params_struct,FLOAT32 * audio_io_buf[],ia_audio_band_buffer_struct * audio_band_buffer,ia_filter_banks_struct * ia_filter_banks_struct,const WORD32 passThru)183 impd_filter_banks_process(ia_drc_instructions_struct* pstr_drc_instruction_arr,
184                           const WORD32 drc_instructions_index,
185                           ia_drc_params_struct* ia_drc_params_struct,
186                           FLOAT32* audio_io_buf[],
187                           ia_audio_band_buffer_struct* audio_band_buffer,
188                           ia_filter_banks_struct* ia_filter_banks_struct,
189                           const WORD32 passThru) {
190   WORD32 c, g, e, i, num_bands;
191   // WORD32 err = 0;
192   FLOAT32* audio_in;
193   FLOAT32** audio_out;
194   ia_drc_filter_bank_struct* str_drc_filter_bank;
195   ia_drc_instructions_struct* str_drc_instruction_str;
196   WORD32 drc_frame_size = ia_drc_params_struct->drc_frame_size;
197 
198   if (drc_instructions_index >= 0) {
199     str_drc_instruction_str =
200         &(pstr_drc_instruction_arr[drc_instructions_index]);
201   } else {
202     return -1;
203   }
204 
205   e = 0;
206 
207   for (c = 0; c < str_drc_instruction_str->audio_num_chan; c++)
208 
209   {
210     str_drc_filter_bank = NULL;
211 
212     audio_in = audio_io_buf[c];
213 
214     audio_out = &(audio_band_buffer->non_interleaved_audio[e]);
215     if ((passThru == 0) && (drc_instructions_index >= 0)) {
216       if (str_drc_instruction_str->drc_set_id < 0) {
217         num_bands = 1;
218       } else {
219         g = str_drc_instruction_str->channel_group_of_ch[c];
220         if (g == -1) {
221           num_bands = 1;
222           // if (ia_filter_banks_struct->str_drc_filter_bank != NULL)
223           //{
224           str_drc_filter_bank =
225               &(ia_filter_banks_struct->str_drc_filter_bank
226                     [str_drc_instruction_str->num_drc_ch_groups]);
227           //}
228         } else {
229           num_bands = str_drc_instruction_str->band_count_of_ch_group[g];
230           // if (ia_filter_banks_struct->str_drc_filter_bank != NULL)
231           //{
232           str_drc_filter_bank =
233               &(ia_filter_banks_struct->str_drc_filter_bank[g]);
234           //}
235         }
236         // if (ia_filter_banks_struct->str_drc_filter_bank != NULL)
237         //{
238         // if (&str_drc_filter_bank->str_all_pass_cascade != NULL)
239         //{
240         impd_all_pass_cascade_process(
241             &str_drc_filter_bank->str_all_pass_cascade, c, drc_frame_size,
242             audio_in);
243         //}
244         //}
245       }
246     } else {
247       num_bands = 1;
248     }
249     switch (num_bands) {
250       case 1:
251         for (i = 0; i < drc_frame_size; i++) {
252           audio_out[0][i] = audio_in[i];
253         }
254         e++;
255         break;
256       case 2:
257         impd_two_band_filter_process(&str_drc_filter_bank->str_two_band_bank, c,
258                                      drc_frame_size, audio_in, audio_out);
259         e += 2;
260         break;
261       case 3:
262         impd_three_band_filter_process(
263             &str_drc_filter_bank->str_three_band_bank, c, drc_frame_size,
264             audio_in, audio_out);
265         e += 3;
266         break;
267       case 4:
268         impd_four_band_filter_process(&str_drc_filter_bank->str_four_band_bank,
269                                       c, drc_frame_size, audio_in, audio_out);
270         e += 4;
271         break;
272       default:
273         return (PARAM_ERROR);
274         break;
275     }
276   }
277 
278   return (0);
279 }
280 
impd_store_audio_io_buffer_time(FLOAT32 * audio_in_out_buf[],ia_audio_in_out_buf * audio_io_buf_internal)281 VOID impd_store_audio_io_buffer_time(
282     FLOAT32* audio_in_out_buf[], ia_audio_in_out_buf* audio_io_buf_internal) {
283   WORD32 i, j;
284 
285   if (audio_io_buf_internal->audio_delay_samples) {
286     for (i = 0; i < audio_io_buf_internal->audio_num_chan; i++) {
287       for (j = 0; j < audio_io_buf_internal->frame_size; j++) {
288         audio_io_buf_internal->audio_io_buffer_delayed
289             [i][audio_io_buf_internal->audio_delay_samples + j] =
290             audio_in_out_buf[i][j];
291       }
292     }
293   } else {
294     audio_io_buf_internal->audio_io_buffer_delayed = audio_in_out_buf;
295     audio_io_buf_internal->audio_in_out_buf = audio_in_out_buf;
296   }
297 
298   return;
299 }
300 
impd_retrieve_audio_io_buffer_time(FLOAT32 * audio_in_out_buf[],ia_audio_in_out_buf * audio_io_buf_internal)301 VOID impd_retrieve_audio_io_buffer_time(
302     FLOAT32* audio_in_out_buf[], ia_audio_in_out_buf* audio_io_buf_internal) {
303   WORD32 i, j;
304 
305   if (audio_io_buf_internal->audio_delay_samples) {
306     for (i = 0; i < audio_io_buf_internal->audio_num_chan; i++) {
307       for (j = 0; j < audio_io_buf_internal->frame_size; j++) {
308         audio_in_out_buf[i][j] =
309             audio_io_buf_internal->audio_io_buffer_delayed[i][j];
310       }
311     }
312   }
313 
314   return;
315 }
316 
impd_advance_audio_io_buffer_time(ia_audio_in_out_buf * audio_io_buf_internal)317 VOID impd_advance_audio_io_buffer_time(
318     ia_audio_in_out_buf* audio_io_buf_internal) {
319   WORD32 i;
320   if (audio_io_buf_internal->audio_delay_samples) {
321     for (i = 0; i < audio_io_buf_internal->audio_num_chan; i++) {
322       memmove(
323           audio_io_buf_internal->audio_io_buffer_delayed[i],
324           &audio_io_buf_internal
325                ->audio_io_buffer_delayed[i][audio_io_buf_internal->frame_size],
326           sizeof(FLOAT32) * audio_io_buf_internal->audio_delay_samples);
327     }
328   }
329 
330   return;
331 }
332