/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 | 220 | ia_drc_gain_set_params_struct *str_gain_set_params) { |
40 | 220 | LOOPIDX i, j; |
41 | 220 | WORD32 num_points; |
42 | | |
43 | 670 | for (i = 0; i < band_count; i++) { |
44 | 450 | num_points = str_gain_set_params->gain_params[i].nb_points; |
45 | 450 | pstr_stft_drc_gain_handle[i].nb_points = num_points; |
46 | 1.32k | for (j = 0; j < num_points; j++) { |
47 | 872 | pstr_stft_drc_gain_handle[i].str_segment[2 * (j + 1)].x = |
48 | 872 | str_gain_set_params->gain_params[i].gain_points[j].x; |
49 | 872 | pstr_stft_drc_gain_handle[i].str_segment[2 * (j + 1)].y = |
50 | 872 | str_gain_set_params->gain_params[i].gain_points[j].y; |
51 | 872 | } |
52 | | |
53 | 450 | pstr_stft_drc_gain_handle[i].width_db = str_gain_set_params->gain_params[i].width; |
54 | 450 | pstr_stft_drc_gain_handle[i].attack_ms = str_gain_set_params->gain_params[i].attack; |
55 | 450 | pstr_stft_drc_gain_handle[i].release_ms = str_gain_set_params->gain_params[i].decay; |
56 | 450 | } |
57 | 220 | } |
58 | | |
59 | | static VOID impd_drc_util_td_read_gain_config( |
60 | 962 | ia_drc_compand_struct *pstr_drc_compand, ia_drc_gain_set_params_struct *str_gain_set_params) { |
61 | 962 | LOOPIDX idx; |
62 | 962 | WORD32 num_points; |
63 | | |
64 | 962 | num_points = str_gain_set_params->gain_params[0].nb_points; |
65 | 962 | pstr_drc_compand->nb_points = num_points; |
66 | 6.70k | for (idx = 0; idx < num_points; idx++) { |
67 | 5.74k | pstr_drc_compand->str_segment[2 * (idx + 1)].x = |
68 | 5.74k | str_gain_set_params->gain_params[0].gain_points[idx].x; |
69 | 5.74k | pstr_drc_compand->str_segment[2 * (idx + 1)].y = |
70 | 5.74k | str_gain_set_params->gain_params[0].gain_points[idx].y; |
71 | 5.74k | } |
72 | | |
73 | 962 | pstr_drc_compand->width_db = str_gain_set_params->gain_params[0].width; |
74 | 962 | pstr_drc_compand->str_channel_param.attack = str_gain_set_params->gain_params[0].attack; |
75 | 962 | pstr_drc_compand->str_channel_param.decay = str_gain_set_params->gain_params[0].decay; |
76 | | |
77 | 962 | pstr_drc_compand->str_channel_param.attack /= 1000.0; |
78 | 962 | pstr_drc_compand->str_channel_param.decay /= 1000.0; |
79 | 962 | } |
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.12k | const WORD32 delay_mode, const WORD32 domain) { |
86 | 1.12k | IA_ERRORCODE err_code = IA_NO_ERROR; |
87 | 1.12k | LOOPIDX i, j, k, l, m, ch; |
88 | 1.12k | WORD32 num_gain_values_max; |
89 | 1.12k | UWORD8 found_ch_idx; |
90 | 1.12k | UWORD32 ch_idx; |
91 | | |
92 | 1.12k | ia_drc_uni_drc_config_ext_struct *pstr_uni_drc_config_ext = |
93 | 1.12k | &pstr_uni_drc_config->str_uni_drc_config_ext; |
94 | 1.12k | ia_drc_coefficients_uni_drc_struct *pstr_drc_coefficients_uni_drc = |
95 | 1.12k | &pstr_uni_drc_config->str_drc_coefficients_uni_drc[0]; |
96 | 1.12k | ia_drc_coefficients_uni_drc_struct *pstr_drc_coefficients_uni_drc_v1 = |
97 | 1.12k | &pstr_uni_drc_config_ext->str_drc_coefficients_uni_drc_v1[0]; |
98 | | |
99 | 1.12k | if (pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count <= 0) { |
100 | 881 | WORD32 all_band_gain_count = 0; |
101 | 881 | WORD32 gain_set_count = pstr_drc_coefficients_uni_drc->gain_set_count; |
102 | 2.57k | for (i = 0; i < gain_set_count; i++) { |
103 | 1.69k | all_band_gain_count += pstr_drc_coefficients_uni_drc->str_gain_set_params[i].band_count; |
104 | 1.69k | } |
105 | 881 | pstr_gain_enc->n_sequences = all_band_gain_count; |
106 | 881 | } else { |
107 | 659 | for (i = 0; i < pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count; i++) { |
108 | 417 | WORD32 all_band_gain_count = 0; |
109 | 1.31k | for (j = 0; j < pstr_drc_coefficients_uni_drc_v1[i].gain_set_count; j++) { |
110 | 900 | all_band_gain_count += |
111 | 900 | pstr_drc_coefficients_uni_drc_v1[i].str_gain_set_params[j].band_count; |
112 | 900 | } |
113 | 417 | pstr_drc_coefficients_uni_drc_v1[i].gain_sequence_count = all_band_gain_count; |
114 | 417 | pstr_gain_enc->n_sequences += all_band_gain_count; |
115 | 417 | } |
116 | 242 | } |
117 | | |
118 | 1.12k | 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.12k | if ((pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count > 0) && |
123 | 242 | (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.12k | } else if ((pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) && |
126 | 459 | (pstr_drc_coefficients_uni_drc->drc_frame_size_present)) { |
127 | 94 | pstr_gain_enc->drc_frame_size = pstr_drc_coefficients_uni_drc->drc_frame_size; |
128 | 1.02k | } else { |
129 | 1.02k | pstr_gain_enc->drc_frame_size = frame_size; |
130 | 1.02k | } |
131 | | |
132 | 1.12k | 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.12k | if (pstr_gain_enc->drc_frame_size < 1) { |
136 | 0 | return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG; |
137 | 0 | } |
138 | | |
139 | 1.12k | if (!pstr_uni_drc_config->sample_rate_present) { |
140 | 156 | pstr_gain_enc->sample_rate = sample_rate; |
141 | 967 | } else { |
142 | 967 | pstr_gain_enc->sample_rate = pstr_uni_drc_config->sample_rate; |
143 | 967 | } |
144 | | |
145 | 1.12k | pstr_gain_enc->domain = domain; |
146 | 1.12k | pstr_gain_enc->delay_mode = delay_mode; |
147 | 1.12k | pstr_gain_enc->delta_tmin_default = impd_drc_get_delta_t_min(pstr_gain_enc->sample_rate); |
148 | | |
149 | 1.12k | if ((pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count > 0) && |
150 | 242 | (pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[0].time_delta_min_present == 1)) { |
151 | 181 | pstr_gain_enc->delta_tmin = |
152 | 181 | pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[0].delta_tmin; |
153 | 942 | } else if ((pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) && |
154 | 459 | (pstr_drc_coefficients_uni_drc->str_gain_set_params[0].time_delta_min_present == |
155 | 459 | 1)) { |
156 | 333 | pstr_gain_enc->delta_tmin = pstr_drc_coefficients_uni_drc->str_gain_set_params[0].delta_tmin; |
157 | 609 | } else { |
158 | 609 | pstr_gain_enc->delta_tmin = impd_drc_get_delta_t_min(pstr_gain_enc->sample_rate); |
159 | 609 | } |
160 | | |
161 | 1.12k | num_gain_values_max = pstr_gain_enc->drc_frame_size / pstr_gain_enc->delta_tmin; |
162 | 1.12k | pstr_gain_enc->base_ch_count = pstr_uni_drc_config->str_channel_layout.base_ch_count; |
163 | | |
164 | 1.12k | memcpy(&pstr_gain_enc->str_uni_drc_config, pstr_uni_drc_config, |
165 | 1.12k | sizeof(ia_drc_uni_drc_config_struct)); |
166 | 1.12k | memcpy(&pstr_gain_enc->str_loudness_info_set, pstr_loudness_info_set, |
167 | 1.12k | sizeof(ia_drc_loudness_info_set_struct)); |
168 | | |
169 | 1.12k | k = 0; |
170 | 1.12k | if (pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) { |
171 | 2.09k | for (j = 0; j < pstr_drc_coefficients_uni_drc->gain_set_count; j++) { |
172 | 1.65k | ch_idx = 0; |
173 | 1.65k | found_ch_idx = 0; |
174 | 1.65k | ia_drc_gain_set_params_struct *pstr_gain_set_params = |
175 | 1.65k | &pstr_drc_coefficients_uni_drc->str_gain_set_params[j]; |
176 | | |
177 | 2.58k | for (m = 0; m < pstr_uni_drc_config->drc_instructions_uni_drc_count; m++) { |
178 | 958 | if (pstr_uni_drc_config->str_drc_instructions_uni_drc[m].drc_location == |
179 | 958 | pstr_drc_coefficients_uni_drc->drc_location) { |
180 | 2.81k | for (ch = 0; ch < MAX_CHANNEL_COUNT; ch++) { |
181 | 2.51k | if (pstr_uni_drc_config->str_drc_instructions_uni_drc[m].gain_set_index[ch] == j) { |
182 | 33 | ch_idx = ch; |
183 | 33 | found_ch_idx = 1; |
184 | 33 | break; |
185 | 33 | } |
186 | 2.51k | } |
187 | 339 | } |
188 | 958 | if (found_ch_idx) { |
189 | 33 | break; |
190 | 33 | } |
191 | 958 | } |
192 | 1.65k | if (ch_idx >= (UWORD32)pstr_gain_enc->base_ch_count) { |
193 | 6 | return IA_EXHEAACE_INIT_FATAL_DRC_INVALID_CHANNEL_INDEX; |
194 | 6 | } |
195 | 1.65k | if (pstr_gain_set_params->band_count > 1) { |
196 | 51 | impd_drc_util_stft_read_gain_config(pstr_gain_enc->str_drc_stft_gain_handle[0][j], |
197 | 51 | pstr_gain_set_params->band_count, |
198 | 51 | pstr_gain_set_params); |
199 | | |
200 | 155 | for (l = 0; l < pstr_gain_set_params->band_count; l++) { |
201 | 108 | err_code = impd_drc_stft_drc_gain_calc_init(pstr_gain_enc, 0, j, l); |
202 | 108 | if (err_code) { |
203 | 4 | return err_code; |
204 | 4 | } |
205 | 104 | pstr_gain_enc->str_drc_stft_gain_handle[0][j][l].ch_idx = ch_idx; |
206 | 104 | pstr_gain_enc->str_drc_stft_gain_handle[0][j][l].is_valid = 1; |
207 | 104 | } |
208 | 1.60k | } else if (pstr_gain_set_params->band_count == 1) { |
209 | 526 | impd_drc_util_td_read_gain_config(&pstr_gain_enc->str_drc_compand[0][j], |
210 | 526 | pstr_gain_set_params); |
211 | | |
212 | 526 | pstr_gain_enc->str_drc_compand[0][j].initial_volume = 0.0f; |
213 | | |
214 | 526 | err_code = impd_drc_td_drc_gain_calc_init(pstr_gain_enc, 0, j); |
215 | 526 | if (err_code) { |
216 | 13 | return err_code; |
217 | 13 | } |
218 | 513 | pstr_gain_enc->str_drc_compand[0][j].ch_idx = ch_idx; |
219 | 513 | pstr_gain_enc->str_drc_compand[0][j].is_valid = 1; |
220 | 513 | } |
221 | | |
222 | 2.25k | for (l = 0; l < pstr_gain_set_params->band_count; l++) { |
223 | 615 | pstr_gain_enc->str_drc_gain_seq_buf[k].str_drc_group.n_gain_values = 1; |
224 | 615 | pstr_gain_enc->str_drc_gain_seq_buf[k].str_gain_set_params = |
225 | 615 | pstr_drc_coefficients_uni_drc->str_gain_set_params[j]; |
226 | 615 | k++; |
227 | 615 | } |
228 | 1.63k | } |
229 | 459 | } |
230 | 1.10k | k = 0; |
231 | 1.49k | for (i = 0; i < pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count; i++) { |
232 | 411 | pstr_drc_coefficients_uni_drc_v1 = |
233 | 411 | &pstr_uni_drc_config_ext->str_drc_coefficients_uni_drc_v1[i]; |
234 | 1.27k | for (j = 0; j < pstr_drc_coefficients_uni_drc_v1->gain_set_count; j++) { |
235 | 877 | ch_idx = 0; |
236 | 877 | found_ch_idx = 0; |
237 | 877 | ia_drc_gain_set_params_struct *pstr_gain_set_params = |
238 | 877 | &pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[j]; |
239 | | |
240 | 2.52k | for (m = 0; m < pstr_uni_drc_config_ext->drc_instructions_uni_drc_v1_count; m++) { |
241 | 1.66k | if (pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1[m].drc_location == |
242 | 1.66k | pstr_drc_coefficients_uni_drc_v1->drc_location) { |
243 | 222 | for (ch = 0; ch < MAX_CHANNEL_COUNT; ch++) { |
244 | 201 | if (pstr_uni_drc_config_ext->str_drc_instructions_uni_drc_v1[m].gain_set_index[ch] == |
245 | 201 | j) { |
246 | 12 | ch_idx = ch; |
247 | 12 | found_ch_idx = 1; |
248 | 12 | break; |
249 | 12 | } |
250 | 201 | } |
251 | 33 | } |
252 | 1.66k | if (found_ch_idx) { |
253 | 12 | break; |
254 | 12 | } |
255 | 1.66k | } |
256 | | |
257 | 877 | if (ch_idx >= (UWORD32)pstr_gain_enc->base_ch_count) { |
258 | 6 | return IA_EXHEAACE_INIT_FATAL_DRC_INVALID_CHANNEL_INDEX; |
259 | 6 | } |
260 | | |
261 | 871 | if (pstr_gain_set_params->band_count > 1) { |
262 | 169 | impd_drc_util_stft_read_gain_config(pstr_gain_enc->str_drc_stft_gain_handle[i][j], |
263 | 169 | pstr_gain_set_params->band_count, |
264 | 169 | pstr_gain_set_params); |
265 | | |
266 | 505 | for (l = 0; l < pstr_gain_set_params->band_count; l++) { |
267 | 339 | err_code = impd_drc_stft_drc_gain_calc_init(pstr_gain_enc, i, j, l); |
268 | 339 | if (err_code) { |
269 | 3 | return err_code; |
270 | 3 | } |
271 | 336 | pstr_gain_enc->str_drc_stft_gain_handle[i][j][l].ch_idx = ch_idx; |
272 | 336 | pstr_gain_enc->str_drc_stft_gain_handle[i][j][l].is_valid = 1; |
273 | 336 | } |
274 | 702 | } else if (pstr_gain_set_params->band_count == 1) { |
275 | 436 | impd_drc_util_td_read_gain_config(&pstr_gain_enc->str_drc_compand[i][j], |
276 | 436 | pstr_gain_set_params); |
277 | | |
278 | 436 | pstr_gain_enc->str_drc_compand[i][j].initial_volume = 0.0f; |
279 | | |
280 | 436 | err_code = impd_drc_td_drc_gain_calc_init(pstr_gain_enc, i, j); |
281 | 436 | if (err_code) { |
282 | 9 | return err_code; |
283 | 9 | } |
284 | 427 | pstr_gain_enc->str_drc_compand[i][j].ch_idx = ch_idx; |
285 | 427 | pstr_gain_enc->str_drc_compand[i][j].is_valid = 1; |
286 | 427 | } |
287 | | |
288 | 1.61k | for (l = 0; l < pstr_gain_set_params->band_count; l++) { |
289 | 760 | pstr_gain_enc->str_drc_gain_seq_buf[k].str_drc_group.n_gain_values = 1; |
290 | 760 | pstr_gain_enc->str_drc_gain_seq_buf[k].str_gain_set_params = |
291 | 760 | pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[j]; |
292 | 760 | k++; |
293 | 760 | } |
294 | 859 | } |
295 | 411 | } |
296 | | |
297 | 1.08k | impd_drc_generate_delta_time_code_table(num_gain_values_max, |
298 | 1.08k | pstr_gain_enc->str_delta_time_code_table); |
299 | | |
300 | 78.2k | for (i = num_gain_values_max - 1; i >= 0; i--) { |
301 | 77.1k | pstr_gain_enc->delta_time_quant_table[i] = pstr_gain_enc->delta_tmin * (i + 1); |
302 | 77.1k | } |
303 | | |
304 | 1.08k | return err_code; |
305 | 1.10k | } |
306 | | |
307 | | IA_ERRORCODE impd_drc_encode_uni_drc_gain(ia_drc_gain_enc_struct *pstr_gain_enc, |
308 | 51.3k | FLOAT32 *ptr_gain_buffer, VOID *pstr_scratch) { |
309 | 51.3k | LOOPIDX idx; |
310 | 51.3k | IA_ERRORCODE err_code = IA_NO_ERROR; |
311 | 137k | for (idx = 0; idx < pstr_gain_enc->n_sequences; idx++) { |
312 | 86.6k | err_code = impd_drc_quantize_and_encode_drc_gain( |
313 | 86.6k | pstr_gain_enc, &ptr_gain_buffer[idx * MAX_DRC_FRAME_SIZE], |
314 | 86.6k | &(pstr_gain_enc->drc_gain_per_sample_with_prev_frame[idx][0]), |
315 | 86.6k | pstr_gain_enc->str_delta_time_code_table, &(pstr_gain_enc->str_drc_gain_seq_buf[idx]), |
316 | 86.6k | pstr_scratch); |
317 | | |
318 | 86.6k | if (err_code) { |
319 | 0 | return err_code; |
320 | 0 | } |
321 | 86.6k | } |
322 | 51.3k | return err_code; |
323 | 51.3k | } |
324 | | |
325 | 4.53k | WORD32 impd_drc_get_delta_t_min(const WORD32 sample_rate) { |
326 | 4.53k | WORD32 lower_bound; |
327 | 4.53k | WORD32 result = 1; |
328 | 4.53k | WORD32 sample_rate_local = sample_rate; |
329 | | |
330 | 4.53k | if (sample_rate_local < 1000) { |
331 | 0 | sample_rate_local = 1000; |
332 | 0 | } |
333 | 4.53k | lower_bound = (WORD32)((0.0005f * sample_rate_local) + 0.5f); |
334 | | |
335 | 26.0k | while (result <= lower_bound) { |
336 | 21.5k | result = result << 1; |
337 | 21.5k | } |
338 | 4.53k | return result; |
339 | 4.53k | } |