• 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 <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_parametric_drc_dec.h"
30 #include "impd_drc_filter_bank.h"
31 #include "impd_drc_multi_band.h"
32 #include "impd_drc_gain_dec.h"
33 #include "impd_drc_process_audio.h"
34 #include "impd_drc_interface.h"
35 #include "impd_drc_gain_dec.h"
36 #include "impd_drc_eq.h"
37 #include "impd_drc_gain_decoder.h"
38 #include "impd_drc_rom.h"
39 
impd_shape_filt_block_adapt(const FLOAT32 drc_gain,shape_filter_block * shape_filter_block)40 VOID impd_shape_filt_block_adapt(const FLOAT32 drc_gain,
41                                  shape_filter_block* shape_filter_block) {
42   //    WORD32 err = 0;
43   WORD32 i;
44   FLOAT32 warpedGain, x1, y1;
45   shape_filter_block->drc_gain_last = drc_gain;
46   for (i = 0; i < 4; i++) {
47     if (shape_filter_block->shape_filter[i].type == SHAPE_FILTER_TYPE_OFF)
48       continue;
49     else if (shape_filter_block->shape_filter[i].type ==
50                  SHAPE_FILTER_TYPE_LF_CUT ||
51              shape_filter_block->shape_filter[i].type ==
52                  SHAPE_FILTER_TYPE_HF_CUT) {
53       if (drc_gain < 1.0f)
54         warpedGain = -1.0f;
55       else
56         warpedGain =
57             (drc_gain - 1.0f) /
58             (drc_gain - 1.0f + shape_filter_block->shape_filter[i].gain_offset);
59       x1 = shape_filter_block->shape_filter[i].a1;
60     } else if (shape_filter_block->shape_filter[i].type ==
61                    SHAPE_FILTER_TYPE_LF_BOOST ||
62                shape_filter_block->shape_filter[i].type ==
63                    SHAPE_FILTER_TYPE_HF_BOOST) {
64       if (drc_gain >= 1.0f)
65         warpedGain = -1.0f;
66       else
67         warpedGain =
68             (1.0f - drc_gain) /
69             (1.0f +
70              drc_gain *
71                  (shape_filter_block->shape_filter[i].gain_offset - 1.0f));
72       x1 = shape_filter_block->shape_filter[i].b1;
73     }
74 
75     if (warpedGain <= 0.0f) {
76       y1 = x1;
77     } else if (warpedGain <
78                shape_filter_block->shape_filter[i].warped_gain_max) {
79       y1 = x1 + shape_filter_block->shape_filter[i].factor * warpedGain;
80     } else {
81       y1 = shape_filter_block->shape_filter[i].y1_bound;
82     }
83     if (shape_filter_block->shape_filter[i].type == SHAPE_FILTER_TYPE_LF_CUT) {
84       shape_filter_block->shape_filter[i].b1 = y1;
85     } else if (shape_filter_block->shape_filter[i].type ==
86                SHAPE_FILTER_TYPE_HF_CUT) {
87       shape_filter_block->shape_filter[i].g_norm =
88           shape_filter_block->shape_filter[i].coeff_sum /
89           (shape_filter_block->shape_filter[i].partial_coeff_sum + y1);
90       shape_filter_block->shape_filter[i].b1 = y1;
91     } else if (shape_filter_block->shape_filter[i].type ==
92                SHAPE_FILTER_TYPE_HF_BOOST) {
93       shape_filter_block->shape_filter[i].g_norm =
94           (shape_filter_block->shape_filter[i].partial_coeff_sum + y1) /
95           shape_filter_block->shape_filter[i].coeff_sum;
96       shape_filter_block->shape_filter[i].a1 = y1;
97     } else if (shape_filter_block->shape_filter[i].type ==
98                SHAPE_FILTER_TYPE_LF_BOOST) {
99       shape_filter_block->shape_filter[i].a1 = y1;
100     }
101   }
102   return;
103 }
104 
resetshape_flter_block(shape_filter_block * shape_filter_block)105 VOID resetshape_flter_block(shape_filter_block* shape_filter_block) {
106   WORD32 i, c;
107   shape_filter_block->drc_gain_last = -1.0f;
108   impd_shape_filt_block_adapt(1.0f, shape_filter_block);
109   for (i = 0; i < 4; i++) {
110     for (c = 0; c < MAX_CHANNEL_COUNT; c++) {
111       shape_filter_block->shape_filter[i].audio_in_state_1[c] = 0.0f;
112       shape_filter_block->shape_filter[i].audio_in_state_2[c] = 0.0f;
113       shape_filter_block->shape_filter[i].audio_out_state_1[c] = 0.0f;
114       shape_filter_block->shape_filter[i].audio_out_state_2[c] = 0.0f;
115     }
116   }
117   return;
118 }
119 
impd_shape_filt_block_init(ia_shape_filter_block_params_struct * shape_flter_block_params,shape_filter_block * shape_filter_block)120 VOID impd_shape_filt_block_init(
121     ia_shape_filter_block_params_struct* shape_flter_block_params,
122     shape_filter_block* shape_filter_block) {
123   // WORD32 err = 0;
124   FLOAT32 x1;
125   FLOAT32 x2 = 0.0f;
126   FLOAT32 radius;
127   if (shape_flter_block_params->lf_cut_filter_present) {
128     ia_shape_filter_params_struct* params =
129         &shape_flter_block_params->str_lf_cut_params;
130     shape_filter_block->shape_filter[0].type = SHAPE_FILTER_TYPE_LF_CUT;
131     shape_filter_block->shape_filter[0].gain_offset =
132         shape_filt_lf_gain_offset_tbl[params->corner_freq_index]
133                                      [params->filter_strength_index];
134     shape_filter_block->shape_filter[0].y1_bound =
135         shape_filt_lf_y1_bound_tbl[params->corner_freq_index]
136                                   [params->filter_strength_index];
137     x1 = -shape_filt_lf_radius_tbl[params->corner_freq_index];
138     shape_filter_block->shape_filter[0].warped_gain_max =
139         SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE /
140         (SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE +
141          shape_filter_block->shape_filter[0].gain_offset);
142     shape_filter_block->shape_filter[0].factor =
143         (shape_filter_block->shape_filter[0].y1_bound - x1) /
144         shape_filter_block->shape_filter[0].warped_gain_max;
145     shape_filter_block->shape_filter[0].a1 = x1;
146 
147   } else {
148     shape_filter_block->shape_filter[0].type = SHAPE_FILTER_TYPE_OFF;
149   }
150   if (shape_flter_block_params->lf_boost_filter_present) {
151     ia_shape_filter_params_struct* params =
152         &shape_flter_block_params->str_lf_boost_params;
153     shape_filter_block->shape_filter[1].type = SHAPE_FILTER_TYPE_LF_BOOST;
154     shape_filter_block->shape_filter[1].gain_offset =
155         shape_filt_lf_gain_offset_tbl[params->corner_freq_index]
156                                      [params->filter_strength_index];
157     shape_filter_block->shape_filter[1].y1_bound =
158         shape_filt_lf_y1_bound_tbl[params->corner_freq_index]
159                                   [params->filter_strength_index];
160     x1 = -shape_filt_lf_radius_tbl[params->corner_freq_index];
161     shape_filter_block->shape_filter[1].warped_gain_max =
162         SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE /
163         (SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE +
164          shape_filter_block->shape_filter[1].gain_offset);
165     shape_filter_block->shape_filter[1].factor =
166         (shape_filter_block->shape_filter[1].y1_bound - x1) /
167         shape_filter_block->shape_filter[1].warped_gain_max;
168     shape_filter_block->shape_filter[1].b1 = x1;
169 
170   } else {
171     shape_filter_block->shape_filter[1].type = SHAPE_FILTER_TYPE_OFF;
172   }
173   if (shape_flter_block_params->hf_cut_filter_present) {
174     ia_shape_filter_params_struct* params =
175         &shape_flter_block_params->str_hfCutParams;
176     shape_filter_block->shape_filter[2].type = SHAPE_FILTER_TYPE_HF_CUT;
177     shape_filter_block->shape_filter[2].gain_offset =
178         shape_filt_hf_gain_offset_tbl[params->corner_freq_index]
179                                      [params->filter_strength_index];
180     shape_filter_block->shape_filter[2].y1_bound =
181         shape_filt_hf_y1_bound_tbl[params->corner_freq_index]
182                                   [params->filter_strength_index];
183     radius = shape_filt_hf_radius_tbl[params->corner_freq_index];
184     x1 = (FLOAT32)(
185         -2.0f * radius *
186         cos(2.0f * M_PI *
187             shape_filt_cutoff_freq_norm_hf_tbl[params->corner_freq_index]));
188     x2 = radius * radius;
189     shape_filter_block->shape_filter[2].warped_gain_max =
190         SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE /
191         (SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE +
192          shape_filter_block->shape_filter[2].gain_offset);
193     shape_filter_block->shape_filter[2].factor =
194         (shape_filter_block->shape_filter[2].y1_bound - x1) /
195         shape_filter_block->shape_filter[2].warped_gain_max;
196     shape_filter_block->shape_filter[2].coeff_sum = 1.0f + x1 + x2;
197     shape_filter_block->shape_filter[2].partial_coeff_sum = 1.0f + x2;
198     shape_filter_block->shape_filter[2].a1 = x1;
199     shape_filter_block->shape_filter[2].a2 = x2;
200     shape_filter_block->shape_filter[2].b2 = x2;
201   } else {
202     shape_filter_block->shape_filter[2].type = SHAPE_FILTER_TYPE_OFF;
203   }
204   if (shape_flter_block_params->hf_boost_filter_present) {
205     ia_shape_filter_params_struct* params =
206         &shape_flter_block_params->str_hf_boost_params;
207     shape_filter_block->shape_filter[3].type = SHAPE_FILTER_TYPE_HF_BOOST;
208     shape_filter_block->shape_filter[3].gain_offset =
209         shape_filt_hf_gain_offset_tbl[params->corner_freq_index]
210                                      [params->filter_strength_index];
211     shape_filter_block->shape_filter[3].y1_bound =
212         shape_filt_hf_y1_bound_tbl[params->corner_freq_index]
213                                   [params->filter_strength_index];
214     radius = shape_filt_hf_radius_tbl[params->corner_freq_index];
215     x1 = (FLOAT32)(
216         -2.0f * radius *
217         cos(2.0f * M_PI *
218             shape_filt_cutoff_freq_norm_hf_tbl[params->corner_freq_index]));
219     x2 = radius * radius;
220     shape_filter_block->shape_filter[3].warped_gain_max =
221         SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE /
222         (SHAPE_FILTER_DRC_GAIN_MAX_MINUS_ONE +
223          shape_filter_block->shape_filter[3].gain_offset);
224     shape_filter_block->shape_filter[3].factor =
225         (shape_filter_block->shape_filter[3].y1_bound - x1) /
226         shape_filter_block->shape_filter[3].warped_gain_max;
227     shape_filter_block->shape_filter[3].coeff_sum = 1.0f + x1 + x2;
228     shape_filter_block->shape_filter[3].partial_coeff_sum = 1.0f + x2;
229     shape_filter_block->shape_filter[3].b1 = x1;
230     shape_filter_block->shape_filter[3].b2 = x2;
231     shape_filter_block->shape_filter[3].a2 = x2;
232 
233   } else {
234     shape_filter_block->shape_filter[3].type = SHAPE_FILTER_TYPE_OFF;
235   }
236   resetshape_flter_block(shape_filter_block);
237   shape_filter_block->shape_flter_block_flag = 1;
238   return;
239 }
240 
impd_shape_filt_block_time_process(shape_filter_block * shape_filter_block,FLOAT32 * drc_gain,const WORD32 channel,FLOAT32 * audio_in,WORD32 start,WORD32 end)241 VOID impd_shape_filt_block_time_process(shape_filter_block* shape_filter_block,
242                                         FLOAT32* drc_gain, const WORD32 channel,
243                                         FLOAT32* audio_in, WORD32 start,
244                                         WORD32 end) {
245   WORD32 i, j;
246   FLOAT32 audio_out;
247 
248   if (shape_filter_block->shape_flter_block_flag) {
249     for (i = start; i < end; i++) {
250       FLOAT32 tmp = audio_in[i];
251       for (j = 0; j < 4; j++) {
252         if (shape_filter_block->shape_filter[j].type ==
253                 SHAPE_FILTER_TYPE_LF_CUT ||
254             shape_filter_block->shape_filter[j].type ==
255                 SHAPE_FILTER_TYPE_LF_BOOST) {
256           audio_out = tmp +
257                       shape_filter_block->shape_filter[j].b1 *
258                           shape_filter_block->shape_filter[j]
259                               .audio_in_state_1[channel] -
260                       shape_filter_block->shape_filter[j].a1 *
261                           shape_filter_block->shape_filter[j]
262                               .audio_out_state_1[channel];
263           shape_filter_block->shape_filter[j].audio_in_state_1[channel] = tmp;
264           shape_filter_block->shape_filter[j].audio_out_state_1[channel] =
265               audio_out;
266 
267         } else if (shape_filter_block->shape_filter[j].type ==
268                        SHAPE_FILTER_TYPE_HF_CUT ||
269                    shape_filter_block->shape_filter[j].type ==
270                        SHAPE_FILTER_TYPE_HF_BOOST) {
271           audio_out = shape_filter_block->shape_filter[j].g_norm * tmp +
272                       shape_filter_block->shape_filter[j].b1 *
273                           shape_filter_block->shape_filter[j]
274                               .audio_in_state_1[channel] +
275                       shape_filter_block->shape_filter[j].b2 *
276                           shape_filter_block->shape_filter[j]
277                               .audio_in_state_2[channel] -
278                       shape_filter_block->shape_filter[j].a1 *
279                           shape_filter_block->shape_filter[j]
280                               .audio_out_state_1[channel] -
281                       shape_filter_block->shape_filter[j].a2 *
282                           shape_filter_block->shape_filter[j]
283                               .audio_out_state_2[channel];
284           shape_filter_block->shape_filter[j].audio_in_state_2[channel] =
285               shape_filter_block->shape_filter[j].audio_in_state_1[channel];
286           shape_filter_block->shape_filter[j].audio_in_state_1[channel] =
287               shape_filter_block->shape_filter[j].g_norm * tmp;
288           shape_filter_block->shape_filter[j].audio_out_state_2[channel] =
289               shape_filter_block->shape_filter[j].audio_out_state_1[channel];
290           shape_filter_block->shape_filter[j].audio_out_state_1[channel] =
291               audio_out;
292         } else {
293           audio_out = tmp;
294         }
295         tmp = audio_out;
296       }
297 
298       audio_in[i] = audio_out * drc_gain[i];
299     }
300 
301   } else {
302     for (i = start; i < end; i++) {
303       audio_in[i] = audio_in[i] * drc_gain[i];
304     }
305   }
306 
307   return;
308 }
309