/src/libxaac/encoder/drc_src/impd_drc_enc.c
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * * |
3 | | * Copyright (C) 2023 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 | | |
21 | | #include <string.h> |
22 | | #include "ixheaac_type_def.h" |
23 | | #include "ixheaac_error_standards.h" |
24 | | #include "ixheaace_error_codes.h" |
25 | | |
26 | | #include "iusace_bitbuffer.h" |
27 | | #include "impd_drc_common_enc.h" |
28 | | #include "impd_drc_uni_drc.h" |
29 | | #include "impd_drc_tables.h" |
30 | | #include "impd_drc_api.h" |
31 | | #include "impd_drc_uni_drc_eq.h" |
32 | | #include "impd_drc_uni_drc_filter_bank.h" |
33 | | #include "impd_drc_gain_enc.h" |
34 | | #include "impd_drc_struct_def.h" |
35 | | #include "impd_drc_enc.h" |
36 | | |
37 | | static VOID impd_drc_util_stft_read_gain_config( |
38 | | ia_drc_stft_gain_calc_struct *pstr_stft_drc_gain_handle, WORD32 band_count, |
39 | 321 | ia_drc_gain_set_params_struct *str_gain_set_params) { |
40 | 321 | LOOPIDX i, j; |
41 | 321 | WORD32 num_points; |
42 | | |
43 | 964 | for (i = 0; i < band_count; i++) { |
44 | 643 | num_points = str_gain_set_params->gain_params[i].nb_points; |
45 | 643 | pstr_stft_drc_gain_handle[i].nb_points = num_points; |
46 | 2.42k | for (j = 0; j < num_points; j++) { |
47 | 1.78k | pstr_stft_drc_gain_handle[i].str_segment[2 * (j + 1)].x = |
48 | 1.78k | str_gain_set_params->gain_params[i].gain_points[j].x; |
49 | 1.78k | pstr_stft_drc_gain_handle[i].str_segment[2 * (j + 1)].y = |
50 | 1.78k | str_gain_set_params->gain_params[i].gain_points[j].y; |
51 | 1.78k | } |
52 | | |
53 | 643 | pstr_stft_drc_gain_handle[i].width_db = str_gain_set_params->gain_params[i].width; |
54 | 643 | pstr_stft_drc_gain_handle[i].attack_ms = str_gain_set_params->gain_params[i].attack; |
55 | 643 | pstr_stft_drc_gain_handle[i].release_ms = str_gain_set_params->gain_params[i].decay; |
56 | 643 | } |
57 | 321 | } |
58 | | |
59 | | static VOID impd_drc_util_td_read_gain_config( |
60 | 1.17k | ia_drc_compand_struct *pstr_drc_compand, ia_drc_gain_set_params_struct *str_gain_set_params) { |
61 | 1.17k | LOOPIDX idx; |
62 | 1.17k | WORD32 num_points; |
63 | | |
64 | 1.17k | num_points = str_gain_set_params->gain_params[0].nb_points; |
65 | 1.17k | pstr_drc_compand->nb_points = num_points; |
66 | 8.15k | for (idx = 0; idx < num_points; idx++) { |
67 | 6.98k | pstr_drc_compand->str_segment[2 * (idx + 1)].x = |
68 | 6.98k | str_gain_set_params->gain_params[0].gain_points[idx].x; |
69 | 6.98k | pstr_drc_compand->str_segment[2 * (idx + 1)].y = |
70 | 6.98k | str_gain_set_params->gain_params[0].gain_points[idx].y; |
71 | 6.98k | } |
72 | | |
73 | 1.17k | pstr_drc_compand->width_db = str_gain_set_params->gain_params[0].width; |
74 | 1.17k | pstr_drc_compand->str_channel_param.attack = str_gain_set_params->gain_params[0].attack; |
75 | 1.17k | pstr_drc_compand->str_channel_param.decay = str_gain_set_params->gain_params[0].decay; |
76 | | |
77 | 1.17k | pstr_drc_compand->str_channel_param.attack /= 1000.0; |
78 | 1.17k | pstr_drc_compand->str_channel_param.decay /= 1000.0; |
79 | 1.17k | } |
80 | | |
81 | | IA_ERRORCODE impd_drc_gain_enc_init(ia_drc_gain_enc_struct *pstr_gain_enc, |
82 | | ia_drc_uni_drc_config_struct *pstr_uni_drc_config, |
83 | | ia_drc_loudness_info_set_struct *pstr_loudness_info_set, |
84 | | const WORD32 frame_size, const WORD32 sample_rate, |
85 | 1.42k | const WORD32 delay_mode, const WORD32 domain) { |
86 | 1.42k | IA_ERRORCODE err_code = IA_NO_ERROR; |
87 | 1.42k | LOOPIDX i, j, k, l, m, ch; |
88 | 1.42k | WORD32 num_gain_values_max; |
89 | 1.42k | UWORD8 found_ch_idx; |
90 | 1.42k | UWORD32 ch_idx; |
91 | | |
92 | 1.42k | ia_drc_uni_drc_config_ext_struct *pstr_uni_drc_config_ext = |
93 | 1.42k | &pstr_uni_drc_config->str_uni_drc_config_ext; |
94 | 1.42k | ia_drc_coefficients_uni_drc_struct *pstr_drc_coefficients_uni_drc = |
95 | 1.42k | &pstr_uni_drc_config->str_drc_coefficients_uni_drc[0]; |
96 | 1.42k | ia_drc_coefficients_uni_drc_struct *pstr_drc_coefficients_uni_drc_v1 = |
97 | 1.42k | &pstr_uni_drc_config_ext->str_drc_coefficients_uni_drc_v1[0]; |
98 | | |
99 | 1.42k | if (pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count <= 0) { |
100 | 1.05k | WORD32 all_band_gain_count = 0; |
101 | 1.05k | WORD32 gain_set_count = pstr_drc_coefficients_uni_drc->gain_set_count; |
102 | 2.97k | for (i = 0; i < gain_set_count; i++) { |
103 | 1.92k | all_band_gain_count += pstr_drc_coefficients_uni_drc->str_gain_set_params[i].band_count; |
104 | 1.92k | } |
105 | 1.05k | pstr_gain_enc->n_sequences = all_band_gain_count; |
106 | 1.05k | } else { |
107 | 1.04k | for (i = 0; i < pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count; i++) { |
108 | 672 | WORD32 all_band_gain_count = 0; |
109 | 2.01k | for (j = 0; j < pstr_drc_coefficients_uni_drc_v1[i].gain_set_count; j++) { |
110 | 1.34k | all_band_gain_count += |
111 | 1.34k | pstr_drc_coefficients_uni_drc_v1[i].str_gain_set_params[j].band_count; |
112 | 1.34k | } |
113 | 672 | pstr_drc_coefficients_uni_drc_v1[i].gain_sequence_count = all_band_gain_count; |
114 | 672 | pstr_gain_enc->n_sequences += all_band_gain_count; |
115 | 672 | } |
116 | 372 | } |
117 | | |
118 | 1.42k | if (pstr_gain_enc->n_sequences > IMPD_DRCMAX_NSEQ) { |
119 | 0 | return IA_EXHEAACE_CONFIG_FATAL_DRC_PARAM_OUT_OF_RANGE; |
120 | 0 | } |
121 | | |
122 | 1.42k | if ((pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count > 0) && |
123 | 372 | (pstr_drc_coefficients_uni_drc_v1->drc_frame_size_present)) { |
124 | 0 | pstr_gain_enc->drc_frame_size = pstr_drc_coefficients_uni_drc_v1->drc_frame_size; |
125 | 1.42k | } else if ((pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) && |
126 | 525 | (pstr_drc_coefficients_uni_drc->drc_frame_size_present)) { |
127 | 110 | pstr_gain_enc->drc_frame_size = pstr_drc_coefficients_uni_drc->drc_frame_size; |
128 | 1.31k | } else { |
129 | 1.31k | pstr_gain_enc->drc_frame_size = frame_size; |
130 | 1.31k | } |
131 | | |
132 | 1.42k | if (pstr_gain_enc->drc_frame_size > IMPD_DRCMAX_FRAMESIZE) { |
133 | 0 | return IA_EXHEAACE_CONFIG_FATAL_DRC_PARAM_OUT_OF_RANGE; |
134 | 0 | } |
135 | 1.42k | if (pstr_gain_enc->drc_frame_size < 1) { |
136 | 0 | return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG; |
137 | 0 | } |
138 | | |
139 | 1.42k | if (!pstr_uni_drc_config->sample_rate_present) { |
140 | 245 | pstr_gain_enc->sample_rate = sample_rate; |
141 | 1.17k | } else { |
142 | 1.17k | pstr_gain_enc->sample_rate = pstr_uni_drc_config->sample_rate; |
143 | 1.17k | } |
144 | | |
145 | 1.42k | pstr_gain_enc->domain = domain; |
146 | 1.42k | pstr_gain_enc->delay_mode = delay_mode; |
147 | 1.42k | pstr_gain_enc->delta_tmin_default = impd_drc_get_delta_t_min(pstr_gain_enc->sample_rate); |
148 | | |
149 | 1.42k | if ((pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count > 0) && |
150 | 372 | (pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[0].time_delta_min_present == 1)) { |
151 | 293 | pstr_gain_enc->delta_tmin = |
152 | 293 | pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[0].delta_tmin; |
153 | 1.13k | } else if ((pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) && |
154 | 525 | (pstr_drc_coefficients_uni_drc->str_gain_set_params[0].time_delta_min_present == |
155 | 525 | 1)) { |
156 | 370 | pstr_gain_enc->delta_tmin = pstr_drc_coefficients_uni_drc->str_gain_set_params[0].delta_tmin; |
157 | 761 | } else { |
158 | 761 | pstr_gain_enc->delta_tmin = impd_drc_get_delta_t_min(pstr_gain_enc->sample_rate); |
159 | 761 | } |
160 | | |
161 | 1.42k | num_gain_values_max = pstr_gain_enc->drc_frame_size / pstr_gain_enc->delta_tmin; |
162 | 1.42k | pstr_gain_enc->base_ch_count = pstr_uni_drc_config->str_channel_layout.base_ch_count; |
163 | | |
164 | 1.42k | memcpy(&pstr_gain_enc->str_uni_drc_config, pstr_uni_drc_config, |
165 | 1.42k | sizeof(ia_drc_uni_drc_config_struct)); |
166 | 1.42k | memcpy(&pstr_gain_enc->str_loudness_info_set, pstr_loudness_info_set, |
167 | 1.42k | sizeof(ia_drc_loudness_info_set_struct)); |
168 | | |
169 | 1.42k | k = 0; |
170 | 1.42k | if (pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) { |
171 | 2.36k | for (j = 0; j < pstr_drc_coefficients_uni_drc->gain_set_count; j++) { |
172 | 1.86k | ch_idx = 0; |
173 | 1.86k | found_ch_idx = 0; |
174 | 1.86k | ia_drc_gain_set_params_struct *pstr_gain_set_params = |
175 | 1.86k | &pstr_drc_coefficients_uni_drc->str_gain_set_params[j]; |
176 | | |
177 | 2.86k | for (m = 0; m < pstr_uni_drc_config->drc_instructions_uni_drc_count; m++) { |
178 | 1.03k | if (pstr_uni_drc_config->str_drc_instructions_uni_drc[m].drc_location == |
179 | 1.03k | pstr_drc_coefficients_uni_drc->drc_location) { |
180 | 3.01k | for (ch = 0; ch < MAX_CHANNEL_COUNT; ch++) { |
181 | 2.68k | if (pstr_uni_drc_config->str_drc_instructions_uni_drc[m].gain_set_index[ch] == j) { |
182 | 42 | ch_idx = ch; |
183 | 42 | found_ch_idx = 1; |
184 | 42 | break; |
185 | 42 | } |
186 | 2.68k | } |
187 | 367 | } |
188 | 1.03k | if (found_ch_idx) { |
189 | 42 | break; |
190 | 42 | } |
191 | 1.03k | } |
192 | 1.86k | if (ch_idx >= (UWORD32)pstr_gain_enc->base_ch_count) { |
193 | 10 | return IA_EXHEAACE_INIT_FATAL_DRC_INVALID_CHANNEL_INDEX; |
194 | 10 | } |
195 | 1.85k | if (pstr_gain_set_params->band_count > 1) { |
196 | 30 | impd_drc_util_stft_read_gain_config(pstr_gain_enc->str_drc_stft_gain_handle[0][j], |
197 | 30 | pstr_gain_set_params->band_count, |
198 | 30 | pstr_gain_set_params); |
199 | | |
200 | 82 | for (l = 0; l < pstr_gain_set_params->band_count; l++) { |
201 | 57 | err_code = impd_drc_stft_drc_gain_calc_init(pstr_gain_enc, 0, j, l); |
202 | 57 | if (err_code) { |
203 | 5 | return err_code; |
204 | 5 | } |
205 | 52 | pstr_gain_enc->str_drc_stft_gain_handle[0][j][l].ch_idx = ch_idx; |
206 | 52 | pstr_gain_enc->str_drc_stft_gain_handle[0][j][l].is_valid = 1; |
207 | 52 | } |
208 | 1.82k | } else if (pstr_gain_set_params->band_count == 1) { |
209 | 509 | impd_drc_util_td_read_gain_config(&pstr_gain_enc->str_drc_compand[0][j], |
210 | 509 | pstr_gain_set_params); |
211 | | |
212 | 509 | pstr_gain_enc->str_drc_compand[0][j].initial_volume = 0.0f; |
213 | | |
214 | 509 | err_code = impd_drc_td_drc_gain_calc_init(pstr_gain_enc, 0, j); |
215 | 509 | if (err_code) { |
216 | 12 | return err_code; |
217 | 12 | } |
218 | 497 | pstr_gain_enc->str_drc_compand[0][j].ch_idx = ch_idx; |
219 | 497 | pstr_gain_enc->str_drc_compand[0][j].is_valid = 1; |
220 | 497 | } |
221 | | |
222 | 2.38k | for (l = 0; l < pstr_gain_set_params->band_count; l++) { |
223 | 547 | pstr_gain_enc->str_drc_gain_seq_buf[k].str_drc_group.n_gain_values = 1; |
224 | 547 | pstr_gain_enc->str_drc_gain_seq_buf[k].str_gain_set_params = |
225 | 547 | pstr_drc_coefficients_uni_drc->str_gain_set_params[j]; |
226 | 547 | k++; |
227 | 547 | } |
228 | 1.83k | } |
229 | 525 | } |
230 | 1.39k | k = 0; |
231 | 2.03k | for (i = 0; i < pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count; i++) { |
232 | 668 | pstr_drc_coefficients_uni_drc_v1 = |
233 | 668 | &pstr_uni_drc_config_ext->str_drc_coefficients_uni_drc_v1[i]; |
234 | 1.94k | for (j = 0; j < pstr_drc_coefficients_uni_drc_v1->gain_set_count; j++) { |
235 | 1.30k | ch_idx = 0; |
236 | 1.30k | found_ch_idx = 0; |
237 | 1.30k | ia_drc_gain_set_params_struct *pstr_gain_set_params = |
238 | 1.30k | &pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[j]; |
239 | | |
240 | 2.78k | for (m = 0; m < pstr_uni_drc_config_ext->drc_instructions_uni_drc_v1_count; m++) { |
241 | 1.49k | if (pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1[m].drc_location == |
242 | 1.49k | pstr_drc_coefficients_uni_drc_v1->drc_location) { |
243 | 231 | for (ch = 0; ch < MAX_CHANNEL_COUNT; ch++) { |
244 | 210 | if (pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1[m].gain_set_index[ch] == |
245 | 210 | j) { |
246 | 14 | ch_idx = ch; |
247 | 14 | found_ch_idx = 1; |
248 | 14 | break; |
249 | 14 | } |
250 | 210 | } |
251 | 35 | } |
252 | 1.49k | if (found_ch_idx) { |
253 | 14 | break; |
254 | 14 | } |
255 | 1.49k | } |
256 | | |
257 | 1.30k | if (ch_idx >= (UWORD32)pstr_gain_enc->base_ch_count) { |
258 | 8 | return IA_EXHEAACE_INIT_FATAL_DRC_INVALID_CHANNEL_INDEX; |
259 | 8 | } |
260 | | |
261 | 1.29k | if (pstr_gain_set_params->band_count > 1) { |
262 | 291 | impd_drc_util_stft_read_gain_config(pstr_gain_enc->str_drc_stft_gain_handle[i][j], |
263 | 291 | pstr_gain_set_params->band_count, |
264 | 291 | pstr_gain_set_params); |
265 | | |
266 | 866 | for (l = 0; l < pstr_gain_set_params->band_count; l++) { |
267 | 580 | err_code = impd_drc_stft_drc_gain_calc_init(pstr_gain_enc, i, j, l); |
268 | 580 | if (err_code) { |
269 | 5 | return err_code; |
270 | 5 | } |
271 | 575 | pstr_gain_enc->str_drc_stft_gain_handle[i][j][l].ch_idx = ch_idx; |
272 | 575 | pstr_gain_enc->str_drc_stft_gain_handle[i][j][l].is_valid = 1; |
273 | 575 | } |
274 | 1.00k | } else if (pstr_gain_set_params->band_count == 1) { |
275 | 666 | impd_drc_util_td_read_gain_config(&pstr_gain_enc->str_drc_compand[i][j], |
276 | 666 | pstr_gain_set_params); |
277 | | |
278 | 666 | pstr_gain_enc->str_drc_compand[i][j].initial_volume = 0.0f; |
279 | | |
280 | 666 | err_code = impd_drc_td_drc_gain_calc_init(pstr_gain_enc, i, j); |
281 | 666 | if (err_code) { |
282 | 15 | return err_code; |
283 | 15 | } |
284 | 651 | pstr_gain_enc->str_drc_compand[i][j].ch_idx = ch_idx; |
285 | 651 | pstr_gain_enc->str_drc_compand[i][j].is_valid = 1; |
286 | 651 | } |
287 | | |
288 | 2.50k | for (l = 0; l < pstr_gain_set_params->band_count; l++) { |
289 | 1.22k | pstr_gain_enc->str_drc_gain_seq_buf[k].str_drc_group.n_gain_values = 1; |
290 | 1.22k | pstr_gain_enc->str_drc_gain_seq_buf[k].str_gain_set_params = |
291 | 1.22k | pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[j]; |
292 | 1.22k | k++; |
293 | 1.22k | } |
294 | 1.27k | } |
295 | 668 | } |
296 | | |
297 | 1.36k | impd_drc_generate_delta_time_code_table(num_gain_values_max, |
298 | 1.36k | pstr_gain_enc->str_delta_time_code_table); |
299 | | |
300 | 100k | for (i = num_gain_values_max - 1; i >= 0; i--) { |
301 | 98.9k | pstr_gain_enc->delta_time_quant_table[i] = pstr_gain_enc->delta_tmin * (i + 1); |
302 | 98.9k | } |
303 | | |
304 | 1.36k | return err_code; |
305 | 1.39k | } |
306 | | |
307 | | IA_ERRORCODE impd_drc_encode_uni_drc_gain(ia_drc_gain_enc_struct *pstr_gain_enc, |
308 | 55.9k | FLOAT32 *ptr_gain_buffer, VOID *pstr_scratch) { |
309 | 55.9k | LOOPIDX idx; |
310 | 55.9k | IA_ERRORCODE err_code = IA_NO_ERROR; |
311 | 146k | for (idx = 0; idx < pstr_gain_enc->n_sequences; idx++) { |
312 | 90.6k | err_code = impd_drc_quantize_and_encode_drc_gain( |
313 | 90.6k | pstr_gain_enc, &ptr_gain_buffer[idx * MAX_DRC_FRAME_SIZE], |
314 | 90.6k | &(pstr_gain_enc->drc_gain_per_sample_with_prev_frame[idx][0]), |
315 | 90.6k | pstr_gain_enc->str_delta_time_code_table, &(pstr_gain_enc->str_drc_gain_seq_buf[idx]), |
316 | 90.6k | pstr_scratch); |
317 | | |
318 | 90.6k | if (err_code) { |
319 | 0 | return err_code; |
320 | 0 | } |
321 | 90.6k | } |
322 | 55.9k | return err_code; |
323 | 55.9k | } |
324 | | |
325 | 5.68k | WORD32 impd_drc_get_delta_t_min(const WORD32 sample_rate) { |
326 | 5.68k | WORD32 lower_bound; |
327 | 5.68k | WORD32 result = 1; |
328 | 5.68k | WORD32 sample_rate_local = sample_rate; |
329 | | |
330 | 5.68k | if (sample_rate_local < 1000) { |
331 | 0 | sample_rate_local = 1000; |
332 | 0 | } |
333 | 5.68k | lower_bound = (WORD32)((0.0005f * sample_rate_local) + 0.5f); |
334 | | |
335 | 32.5k | while (result <= lower_bound) { |
336 | 26.8k | result = result << 1; |
337 | 26.8k | } |
338 | 5.68k | return result; |
339 | 5.68k | } |