• 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 WORD32 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 (0);
103 }
104 
resetshape_flter_block(shape_filter_block * shape_filter_block)105 WORD32 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 (0);
118 }
119 
impd_shape_filt_block_init(ia_shape_filter_block_params_struct * shape_flter_block_params,shape_filter_block * shape_filter_block)120 WORD32 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 (0);
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 WORD32 impd_shape_filt_block_time_process(
242     shape_filter_block* shape_filter_block, FLOAT32* drc_gain,
243     const WORD32 channel, FLOAT32* audio_in, WORD32 start, WORD32 end) {
244   WORD32 i, j, err = 0;
245   FLOAT32 audio_out;
246 
247   if (shape_filter_block->shape_flter_block_flag) {
248     for (i = start; i < end; i++) {
249       FLOAT32 tmp = audio_in[i];
250       for (j = 0; j < 4; j++) {
251         if (shape_filter_block->shape_filter[j].type ==
252                 SHAPE_FILTER_TYPE_LF_CUT ||
253             shape_filter_block->shape_filter[j].type ==
254                 SHAPE_FILTER_TYPE_LF_BOOST) {
255           audio_out = tmp +
256                       shape_filter_block->shape_filter[j].b1 *
257                           shape_filter_block->shape_filter[j]
258                               .audio_in_state_1[channel] -
259                       shape_filter_block->shape_filter[j].a1 *
260                           shape_filter_block->shape_filter[j]
261                               .audio_out_state_1[channel];
262           shape_filter_block->shape_filter[j].audio_in_state_1[channel] = tmp;
263           shape_filter_block->shape_filter[j].audio_out_state_1[channel] =
264               audio_out;
265 
266         } else if (shape_filter_block->shape_filter[j].type ==
267                        SHAPE_FILTER_TYPE_HF_CUT ||
268                    shape_filter_block->shape_filter[j].type ==
269                        SHAPE_FILTER_TYPE_HF_BOOST) {
270           audio_out = shape_filter_block->shape_filter[j].g_norm * tmp +
271                       shape_filter_block->shape_filter[j].b1 *
272                           shape_filter_block->shape_filter[j]
273                               .audio_in_state_1[channel] +
274                       shape_filter_block->shape_filter[j].b2 *
275                           shape_filter_block->shape_filter[j]
276                               .audio_in_state_2[channel] -
277                       shape_filter_block->shape_filter[j].a1 *
278                           shape_filter_block->shape_filter[j]
279                               .audio_out_state_1[channel] -
280                       shape_filter_block->shape_filter[j].a2 *
281                           shape_filter_block->shape_filter[j]
282                               .audio_out_state_2[channel];
283           shape_filter_block->shape_filter[j].audio_in_state_2[channel] =
284               shape_filter_block->shape_filter[j].audio_in_state_1[channel];
285           shape_filter_block->shape_filter[j].audio_in_state_1[channel] =
286               shape_filter_block->shape_filter[j].g_norm * tmp;
287           shape_filter_block->shape_filter[j].audio_out_state_2[channel] =
288               shape_filter_block->shape_filter[j].audio_out_state_1[channel];
289           shape_filter_block->shape_filter[j].audio_out_state_1[channel] =
290               audio_out;
291         } else {
292           audio_out = tmp;
293         }
294         tmp = audio_out;
295       }
296 
297       audio_in[i] = audio_out * drc_gain[i];
298     }
299 
300   } else {
301     for (i = start; i < end; i++) {
302       audio_in[i] = audio_in[i] * drc_gain[i];
303     }
304   }
305 
306   return err;
307 }
308