xref: /aosp_15_r20/external/libxaac/encoder/drc_src/impd_drc_enc.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
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 
impd_drc_util_stft_read_gain_config(ia_drc_stft_gain_calc_struct * pstr_stft_drc_gain_handle,WORD32 band_count,ia_drc_gain_set_params_struct * str_gain_set_params)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     ia_drc_gain_set_params_struct *str_gain_set_params) {
40   LOOPIDX i, j;
41   WORD32 num_points;
42 
43   for (i = 0; i < band_count; i++) {
44     num_points = str_gain_set_params->gain_params[i].nb_points;
45     pstr_stft_drc_gain_handle[i].nb_points = num_points;
46     for (j = 0; j < num_points; j++) {
47       pstr_stft_drc_gain_handle[i].str_segment[2 * (j + 1)].x =
48           str_gain_set_params->gain_params[i].gain_points[j].x;
49       pstr_stft_drc_gain_handle[i].str_segment[2 * (j + 1)].y =
50           str_gain_set_params->gain_params[i].gain_points[j].y;
51     }
52 
53     pstr_stft_drc_gain_handle[i].width_db = str_gain_set_params->gain_params[i].width;
54     pstr_stft_drc_gain_handle[i].attack_ms = str_gain_set_params->gain_params[i].attack;
55     pstr_stft_drc_gain_handle[i].release_ms = str_gain_set_params->gain_params[i].decay;
56   }
57 }
58 
impd_drc_util_td_read_gain_config(ia_drc_compand_struct * pstr_drc_compand,ia_drc_gain_set_params_struct * str_gain_set_params)59 static VOID impd_drc_util_td_read_gain_config(
60     ia_drc_compand_struct *pstr_drc_compand, ia_drc_gain_set_params_struct *str_gain_set_params) {
61   LOOPIDX idx;
62   WORD32 num_points;
63 
64   num_points = str_gain_set_params->gain_params[0].nb_points;
65   pstr_drc_compand->nb_points = num_points;
66   for (idx = 0; idx < num_points; idx++) {
67     pstr_drc_compand->str_segment[2 * (idx + 1)].x =
68         str_gain_set_params->gain_params[0].gain_points[idx].x;
69     pstr_drc_compand->str_segment[2 * (idx + 1)].y =
70         str_gain_set_params->gain_params[0].gain_points[idx].y;
71   }
72 
73   pstr_drc_compand->width_db = str_gain_set_params->gain_params[0].width;
74   pstr_drc_compand->str_channel_param.attack = str_gain_set_params->gain_params[0].attack;
75   pstr_drc_compand->str_channel_param.decay = str_gain_set_params->gain_params[0].decay;
76 
77   pstr_drc_compand->str_channel_param.attack /= 1000.0;
78   pstr_drc_compand->str_channel_param.decay /= 1000.0;
79 }
80 
impd_drc_gain_enc_init(ia_drc_gain_enc_struct * pstr_gain_enc,ia_drc_uni_drc_config_struct * pstr_uni_drc_config,ia_drc_loudness_info_set_struct * pstr_loudness_info_set,const WORD32 frame_size,const WORD32 sample_rate,const WORD32 delay_mode,const WORD32 domain)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                                     const WORD32 delay_mode, const WORD32 domain) {
86   IA_ERRORCODE err_code = IA_NO_ERROR;
87   LOOPIDX i, j, k, l, m, ch;
88   WORD32 num_gain_values_max;
89   WORD32 params_found;
90   UWORD8 found_ch_idx;
91   UWORD32 ch_idx;
92 
93   ia_drc_uni_drc_config_ext_struct *pstr_uni_drc_config_ext =
94       &pstr_uni_drc_config->str_uni_drc_config_ext;
95   ia_drc_coefficients_uni_drc_struct *pstr_drc_coefficients_uni_drc =
96       &pstr_uni_drc_config->str_drc_coefficients_uni_drc[0];
97   ia_drc_coefficients_uni_drc_struct *pstr_drc_coefficients_uni_drc_v1 =
98       &pstr_uni_drc_config_ext->str_drc_coefficients_uni_drc_v1[0];
99 
100   if (pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count <= 0) {
101     WORD32 all_band_gain_count = 0;
102     WORD32 gain_set_count = pstr_drc_coefficients_uni_drc->gain_set_count;
103     for (i = 0; i < gain_set_count; i++) {
104       all_band_gain_count += pstr_drc_coefficients_uni_drc->str_gain_set_params[i].band_count;
105     }
106     pstr_gain_enc->n_sequences = all_band_gain_count;
107   }
108   else {
109     for (i = 0; i < pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count; i++) {
110       WORD32 all_band_gain_count = 0;
111       for (j = 0; j < pstr_drc_coefficients_uni_drc_v1[i].gain_set_count; j++) {
112         all_band_gain_count += pstr_drc_coefficients_uni_drc_v1[i].str_gain_set_params[j].band_count;
113       }
114       pstr_drc_coefficients_uni_drc_v1[i].gain_sequence_count = all_band_gain_count;
115       pstr_gain_enc->n_sequences += all_band_gain_count;
116     }
117   }
118 
119   if (pstr_gain_enc->n_sequences > IMPD_DRCMAX_NSEQ) {
120     return IA_EXHEAACE_CONFIG_FATAL_DRC_PARAM_OUT_OF_RANGE;
121   }
122 
123   if ((pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count > 0) &&
124       (pstr_drc_coefficients_uni_drc_v1->drc_frame_size_present)) {
125     pstr_gain_enc->drc_frame_size = pstr_drc_coefficients_uni_drc_v1->drc_frame_size;
126   } else if ((pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) &&
127              (pstr_drc_coefficients_uni_drc->drc_frame_size_present)) {
128     pstr_gain_enc->drc_frame_size = pstr_drc_coefficients_uni_drc->drc_frame_size;
129   } else {
130     pstr_gain_enc->drc_frame_size = frame_size;
131   }
132 
133   if (pstr_gain_enc->drc_frame_size > IMPD_DRCMAX_FRAMESIZE) {
134     return IA_EXHEAACE_CONFIG_FATAL_DRC_PARAM_OUT_OF_RANGE;
135   }
136   if (pstr_gain_enc->drc_frame_size < 1) {
137     return IA_EXHEAACE_CONFIG_FATAL_DRC_INVALID_CONFIG;
138   }
139 
140   if (!pstr_uni_drc_config->sample_rate_present) {
141     pstr_gain_enc->sample_rate = sample_rate;
142   } else {
143     pstr_gain_enc->sample_rate = pstr_uni_drc_config->sample_rate;
144   }
145 
146   pstr_gain_enc->domain = domain;
147   pstr_gain_enc->delay_mode = delay_mode;
148   pstr_gain_enc->delta_tmin_default = impd_drc_get_delta_t_min(pstr_gain_enc->sample_rate);
149 
150   if ((pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count > 0) &&
151       (pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[0].time_delta_min_present == 1)) {
152     pstr_gain_enc->delta_tmin =
153         pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[0].delta_tmin;
154   } else if ((pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) &&
155              (pstr_drc_coefficients_uni_drc->str_gain_set_params[0].time_delta_min_present ==
156               1)) {
157     pstr_gain_enc->delta_tmin = pstr_drc_coefficients_uni_drc->str_gain_set_params[0].delta_tmin;
158   } else {
159     pstr_gain_enc->delta_tmin = impd_drc_get_delta_t_min(pstr_gain_enc->sample_rate);
160   }
161 
162   num_gain_values_max = pstr_gain_enc->drc_frame_size / pstr_gain_enc->delta_tmin;
163   pstr_gain_enc->base_ch_count = pstr_uni_drc_config->str_channel_layout.base_ch_count;
164 
165   memcpy(&pstr_gain_enc->str_uni_drc_config, pstr_uni_drc_config,
166          sizeof(ia_drc_uni_drc_config_struct));
167   memcpy(&pstr_gain_enc->str_loudness_info_set, pstr_loudness_info_set,
168          sizeof(ia_drc_loudness_info_set_struct));
169 
170   k = 0;
171   if (pstr_uni_drc_config->drc_coefficients_uni_drc_count > 0) {
172     for (j = 0; j < pstr_drc_coefficients_uni_drc->gain_set_count; j++) {
173       ch_idx = 0;
174       found_ch_idx = 0;
175       ia_drc_gain_set_params_struct *pstr_gain_set_params =
176           &pstr_drc_coefficients_uni_drc->str_gain_set_params[j];
177 
178       for (m = 0; m < pstr_uni_drc_config->drc_instructions_uni_drc_count; m++) {
179         if (pstr_uni_drc_config->str_drc_instructions_uni_drc[m].drc_location ==
180             pstr_drc_coefficients_uni_drc->drc_location) {
181           for (ch = 0; ch < MAX_CHANNEL_COUNT; ch++) {
182             if (pstr_uni_drc_config->str_drc_instructions_uni_drc[m].gain_set_index[ch] == j) {
183               ch_idx = ch;
184               found_ch_idx = 1;
185               break;
186             }
187           }
188         }
189         if (found_ch_idx) {
190           break;
191         }
192       }
193       if (ch_idx >= (UWORD32)pstr_gain_enc->base_ch_count) {
194         return IA_EXHEAACE_INIT_FATAL_DRC_INVALID_CHANNEL_INDEX;
195       }
196       if (pstr_gain_set_params->band_count > 1) {
197         impd_drc_util_stft_read_gain_config(pstr_gain_enc->str_drc_stft_gain_handle[0][j],
198                                             pstr_gain_set_params->band_count,
199                                             pstr_gain_set_params);
200 
201         for (l = 0; l < pstr_gain_set_params->band_count; l++) {
202           err_code = impd_drc_stft_drc_gain_calc_init(pstr_gain_enc, 0, j, l);
203           if (err_code) {
204             return err_code;
205           }
206           pstr_gain_enc->str_drc_stft_gain_handle[0][j][l].ch_idx = ch_idx;
207           pstr_gain_enc->str_drc_stft_gain_handle[0][j][l].is_valid = 1;
208         }
209       } else if (pstr_gain_set_params->band_count == 1) {
210         impd_drc_util_td_read_gain_config(&pstr_gain_enc->str_drc_compand[0][j],
211                                           pstr_gain_set_params);
212 
213         pstr_gain_enc->str_drc_compand[0][j].initial_volume = 0.0f;
214 
215         err_code = impd_drc_td_drc_gain_calc_init(pstr_gain_enc, 0, j);
216         if (err_code) {
217           return err_code;
218         }
219         pstr_gain_enc->str_drc_compand[0][j].ch_idx = ch_idx;
220         pstr_gain_enc->str_drc_compand[0][j].is_valid = 1;
221       }
222 
223       for (l = 0; l < pstr_gain_set_params->band_count; l++) {
224         pstr_gain_enc->str_drc_gain_seq_buf[k].str_drc_group.n_gain_values = 1;
225         pstr_gain_enc->str_drc_gain_seq_buf[k].str_gain_set_params =
226             pstr_drc_coefficients_uni_drc->str_gain_set_params[j];
227         k++;
228       }
229     }
230   }
231   if (pstr_uni_drc_config_ext->drc_coefficients_uni_drc_v1_count > 0) {
232     for (i = 0; i < pstr_gain_enc->n_sequences; i++) {
233       params_found = 0;
234 
235       for (j = 0; j < pstr_drc_coefficients_uni_drc_v1->gain_set_count; j++) {
236         for (l = 0; l < pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[j].band_count;
237              l++) {
238           if (i == pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[j]
239                        .gain_params[l]
240                        .gain_sequence_index) {
241             pstr_gain_enc->str_drc_gain_seq_buf[i].str_drc_group.n_gain_values = 1;
242             pstr_gain_enc->str_drc_gain_seq_buf[i].str_gain_set_params =
243                 pstr_drc_coefficients_uni_drc_v1->str_gain_set_params[j];
244             params_found = 1;
245           }
246           if (params_found == 1) {
247             break;
248           }
249         }
250         if (params_found == 1) {
251           break;
252         }
253       }
254     }
255   }
256 
257   impd_drc_generate_delta_time_code_table(num_gain_values_max,
258                                           pstr_gain_enc->str_delta_time_code_table);
259 
260   for (i = num_gain_values_max - 1; i >= 0; i--) {
261     pstr_gain_enc->delta_time_quant_table[i] = pstr_gain_enc->delta_tmin * (i + 1);
262   }
263 
264   return err_code;
265 }
266 
impd_drc_encode_uni_drc_gain(ia_drc_gain_enc_struct * pstr_gain_enc,FLOAT32 * ptr_gain_buffer,VOID * pstr_scratch)267 IA_ERRORCODE impd_drc_encode_uni_drc_gain(ia_drc_gain_enc_struct *pstr_gain_enc,
268                                           FLOAT32 *ptr_gain_buffer, VOID *pstr_scratch) {
269   LOOPIDX idx;
270   IA_ERRORCODE err_code = IA_NO_ERROR;
271   for (idx = 0; idx < pstr_gain_enc->n_sequences; idx++) {
272     err_code = impd_drc_quantize_and_encode_drc_gain(
273         pstr_gain_enc, &ptr_gain_buffer[idx * MAX_DRC_FRAME_SIZE],
274         &(pstr_gain_enc->drc_gain_per_sample_with_prev_frame[idx][0]),
275         pstr_gain_enc->str_delta_time_code_table, &(pstr_gain_enc->str_drc_gain_seq_buf[idx]),
276         pstr_scratch);
277 
278     if (err_code) {
279       return err_code;
280     }
281   }
282   return err_code;
283 }
284 
impd_drc_get_delta_t_min(const WORD32 sample_rate)285 WORD32 impd_drc_get_delta_t_min(const WORD32 sample_rate) {
286   WORD32 lower_bound;
287   WORD32 result = 1;
288   WORD32 sample_rate_local = sample_rate;
289 
290   if (sample_rate_local < 1000) {
291     sample_rate_local = 1000;
292   }
293   lower_bound = (WORD32)((0.0005f * sample_rate_local) + 0.5f);
294 
295   while (result <= lower_bound) {
296     result = result << 1;
297   }
298   return result;
299 }
300