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 warped_gain = 0, x1 = 0, 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 warped_gain = -1.0f;
55 else
56 warped_gain =
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 warped_gain = -1.0f;
66 else
67 warped_gain =
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 (warped_gain <= 0.0f) {
76 y1 = x1;
77 } else if (warped_gain <
78 shape_filter_block->shape_filter[i].warped_gain_max) {
79 y1 = x1 + shape_filter_block->shape_filter[i].factor * warped_gain;
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