xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_fd_quant.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 <math.h>
23 #include "iusace_type_def.h"
24 #include "ixheaac_error_standards.h"
25 #include "ixheaace_error_codes.h"
26 #include "ixheaace_mps_common_define.h"
27 #include "iusace_cnst.h"
28 #include "iusace_block_switch_const.h"
29 #include "iusace_bitbuffer.h"
30 #include "impd_drc_common_enc.h"
31 #include "impd_drc_uni_drc.h"
32 #include "impd_drc_api.h"
33 #include "impd_drc_uni_drc_eq.h"
34 #include "impd_drc_uni_drc_filter_bank.h"
35 #include "impd_drc_gain_enc.h"
36 #include "impd_drc_struct_def.h"
37 
38 #include "ixheaace_memory_standards.h"
39 #include "iusace_tns_usac.h"
40 #include "iusace_psy_mod.h"
41 #include "iusace_config.h"
42 #include "iusace_ms.h"
43 #include "ixheaace_adjust_threshold_data.h"
44 #include "iusace_fd_qc_util.h"
45 #include "iusace_arith_enc.h"
46 #include "iusace_fd_quant.h"
47 #include "iusace_signal_classifier.h"
48 #include "iusace_block_switch_struct_def.h"
49 #include "ixheaace_sbr_header.h"
50 #include "ixheaace_config.h"
51 #include "ixheaace_asc_write.h"
52 #include "iusace_main.h"
53 #include "iusace_write_bitstream.h"
54 #include "ixheaace_nf.h"
55 #include "iusace_fd_qc_adjthr.h"
56 #include "iusace_block_switch_const.h"
57 #include "iusace_rom.h"
58 #include "ixheaace_cplx_pred.h"
59 #include "ixheaace_aac_constants.h"
60 
61 static WORD32 iusace_window_shape[5] = {WIN_SEL_1, WIN_SEL_0, WIN_SEL_0, WIN_SEL_1, WIN_SEL_0};
62 
iusace_count_ms_bits(WORD32 sfb_count,WORD32 sfb_per_grp,WORD32 max_sfb_per_grp)63 static WORD32 iusace_count_ms_bits(WORD32 sfb_count, WORD32 sfb_per_grp, WORD32 max_sfb_per_grp) {
64   WORD32 ms_bits = 0, sfb_offs, sfb;
65   for (sfb_offs = 0; sfb_offs < sfb_count; sfb_offs += sfb_per_grp) {
66     for (sfb = 0; sfb < max_sfb_per_grp; sfb++) {
67       ms_bits++;
68     }
69   }
70   return (ms_bits);
71 }
72 
iusace_count_static_bits(ia_usac_data_struct * ptr_usac_data,ia_usac_encoder_config_struct * ptr_usac_config,ia_sfb_params_struct * pstr_sfb_params,ia_psy_mod_out_data_struct * pstr_psy_out,WORD32 channels,WORD32 chn,WORD32 usac_independency_flag,WORD32 ele_id)73 static WORD32 iusace_count_static_bits(ia_usac_data_struct *ptr_usac_data,
74                                        ia_usac_encoder_config_struct *ptr_usac_config,
75                                        ia_sfb_params_struct *pstr_sfb_params,
76                                        ia_psy_mod_out_data_struct *pstr_psy_out, WORD32 channels,
77                                        WORD32 chn, WORD32 usac_independency_flag, WORD32 ele_id) {
78   WORD32 ms_mask = ptr_usac_data->str_ms_info[chn].ms_mask;
79   WORD32 noise_filling = ptr_usac_data->noise_filling[ele_id];
80   WORD32 stat_bits = 0, i;
81   WORD32 tns_active = 0, tns_present_both = 0;
82   WORD32 max_sfb = pstr_psy_out[chn].max_sfb_per_grp;
83   (VOID) ptr_usac_config;
84 
85   if (channels == 1) {
86     stat_bits += 1;  // core mode
87     stat_bits += 1;  // tns active
88 
89     switch (pstr_psy_out[chn].window_sequence) {
90       case ONLY_LONG_SEQUENCE:
91       case LONG_START_SEQUENCE:
92       case LONG_STOP_SEQUENCE:
93         stat_bits += SI_ICS_INFO_BITS_LONG;
94         break;
95       case EIGHT_SHORT_SEQUENCE:
96         stat_bits += SI_ICS_INFO_BITS_SHORT;
97         break;
98     }
99   } else {
100     stat_bits += 2;  // core mode
101     stat_bits += 2;  // tns and common window
102 
103     switch (pstr_psy_out[chn].window_sequence) {
104       case ONLY_LONG_SEQUENCE:
105       case LONG_START_SEQUENCE:
106       case LONG_STOP_SEQUENCE:
107         stat_bits += SI_ICS_INFO_BITS_LONG;
108         break;
109       case EIGHT_SHORT_SEQUENCE:
110         stat_bits += SI_ICS_INFO_BITS_SHORT;
111         break;
112     }
113 
114     stat_bits += 1;  // common_max_sfb
115     stat_bits += SI_CPE_MS_MASK_BITS;
116 
117     if (ms_mask != 3) {
118       if (ms_mask == 1) {
119         stat_bits += iusace_count_ms_bits(pstr_psy_out[chn].sfb_count,
120                                           pstr_psy_out[chn].sfb_per_group, max_sfb);
121       }
122     } else {
123       stat_bits += iusace_write_cplx_pred_data(
124           NULL, pstr_sfb_params->num_window_groups[chn], max_sfb,
125           ptr_usac_data->complex_coef[chn], ptr_usac_data->pred_coef_re[chn],
126           ptr_usac_data->pred_coef_im[chn], iusace_huffman_code_table, usac_independency_flag,
127           ptr_usac_data->pred_dir_idx[chn], ptr_usac_data->cplx_pred_used[chn],
128           ptr_usac_data->cplx_pred_all[chn], ptr_usac_data->temp_pred_coef_re_prev[chn],
129           ptr_usac_data->temp_pred_coef_im_prev[chn], &ptr_usac_data->delta_code_time[chn]);
130     }
131 
132     if (ptr_usac_data->pstr_tns_info[chn] != NULL &&
133         ptr_usac_data->pstr_tns_info[chn + 1] != NULL) {
134       tns_active = ptr_usac_data->pstr_tns_info[chn]->tns_data_present ||
135                    ptr_usac_data->pstr_tns_info[chn + 1]->tns_data_present;
136       tns_present_both = ptr_usac_data->pstr_tns_info[chn]->tns_data_present &&
137                          ptr_usac_data->pstr_tns_info[chn + 1]->tns_data_present;
138     }
139     if (tns_active) {
140       stat_bits += 1;  // common_tns
141 
142       stat_bits += 1;  // tns_present_both
143 
144       if (!tns_present_both) {
145         stat_bits += 1;  // tns_data_present1
146       }
147     }
148   }
149 
150   for (i = chn; i < chn + channels; i++) {
151     stat_bits += 8;  // global_gain
152 
153     if (noise_filling) {
154       stat_bits += 8;
155     }
156   }
157 
158   for (i = chn; i < chn + channels; i++) {
159     if (ptr_usac_data->pstr_tns_info[i] != NULL &&
160         ptr_usac_data->pstr_tns_info[i]->tns_data_present == 1) {
161       stat_bits += iusace_write_tns_data(NULL, ptr_usac_data->pstr_tns_info[i],
162                                          pstr_psy_out[i].window_sequence, 0);
163     }
164 
165     if (!usac_independency_flag) {
166       stat_bits += 1;  // arith_reset_flag
167     }
168 
169     stat_bits += 1;  // fac_data_present
170     stat_bits += ptr_usac_data->str_scratch.ptr_num_fac_bits[i];
171   }
172 
173   stat_bits += (ptr_usac_data->num_sbr_bits + ptr_usac_data->num_drc_bits);
174 
175   return stat_bits;
176 }
177 
iusace_sort_for_grouping(WORD32 * sfb_offset,const WORD32 * sfb_width_table,FLOAT64 * ptr_scratch,FLOAT64 * ptr_spec,WORD32 num_window_groups,const WORD32 * window_group_length,WORD32 nr_of_sfb,WORD32 ccfl)178 static VOID iusace_sort_for_grouping(WORD32 *sfb_offset, const WORD32 *sfb_width_table,
179                                      FLOAT64 *ptr_scratch, FLOAT64 *ptr_spec,
180                                      WORD32 num_window_groups, const WORD32 *window_group_length,
181                                      WORD32 nr_of_sfb, WORD32 ccfl) {
182   WORD32 i, j, ii;
183   WORD32 index = 0;
184   WORD32 group_offset = 0;
185   WORD32 k = 0;
186   WORD32 frame_len_short = (ccfl * FRAME_LEN_SHORT_128) / FRAME_LEN_LONG;
187 
188   sfb_offset[k] = 0;
189   for (k = 1; k < nr_of_sfb + 1; k++) {
190     sfb_offset[k] = sfb_offset[k - 1] + sfb_width_table[k - 1];
191   }
192 
193   index = 0;
194   group_offset = 0;
195   for (i = 0; i < num_window_groups; i++) {
196     for (k = 0; k < nr_of_sfb; k++) {
197       for (j = 0; j < window_group_length[i]; j++) {
198         for (ii = 0; ii < sfb_width_table[k]; ii++) {
199           ptr_scratch[index++] =
200               ptr_spec[ii + sfb_offset[k] + frame_len_short * j + group_offset];
201         }
202       }
203     }
204     group_offset += frame_len_short * window_group_length[i];
205   }
206 
207   memcpy(ptr_spec, ptr_scratch, ccfl * sizeof(ptr_spec[0]));
208 
209   index = 0;
210   sfb_offset[index++] = 0;
211   for (i = 0; i < num_window_groups; i++) {
212     for (k = 0; k < nr_of_sfb; k++) {
213       sfb_offset[index] = sfb_offset[index - 1] + sfb_width_table[k] * window_group_length[i];
214       index++;
215     }
216   }
217 
218   return;
219 }
220 
iusace_degroup_int(const WORD32 * ptr_grouped_sfb_offsets,WORD32 sfb_per_group,WORD32 * ptr_scratch,WORD32 * ptr_spec,WORD32 num_window_groups,const WORD32 * window_group_length,WORD32 ccfl)221 static VOID iusace_degroup_int(const WORD32 *ptr_grouped_sfb_offsets, WORD32 sfb_per_group,
222                                WORD32 *ptr_scratch, WORD32 *ptr_spec, WORD32 num_window_groups,
223                                const WORD32 *window_group_length, WORD32 ccfl)
224 
225 {
226   WORD32 i, j, k, n;
227   WORD32 index, group_offset;
228   WORD32 loop1, loop2;
229   WORD32 frame_len_short = (ccfl * FRAME_LEN_SHORT_128) / FRAME_LEN_LONG;
230   index = 0;
231   group_offset = 0;
232 
233   memset(ptr_scratch, 0, ccfl * sizeof(WORD32));
234 
235   for (i = 0; i < num_window_groups; i++) {
236     for (j = 0; j < sfb_per_group; j++) {
237       WORD32 idx = i * sfb_per_group + j;
238       loop1 = ((ptr_grouped_sfb_offsets[idx + 1] - ptr_grouped_sfb_offsets[idx]) /
239                window_group_length[i]);
240 
241       for (k = 0; k < window_group_length[i]; k++) {
242         loop2 = ((ptr_grouped_sfb_offsets[idx] - group_offset) / window_group_length[i]) +
243                 frame_len_short * k + group_offset;
244 
245         for (n = 0; n < loop1; n++) {
246           ptr_scratch[n + loop2] = ptr_spec[index++];
247         }
248       }
249     }
250     group_offset += frame_len_short * window_group_length[i];
251   }
252 
253   memcpy(ptr_spec, ptr_scratch, ccfl * sizeof(WORD32));
254 
255   return;
256 }
257 
iusace_stereo_proc(ia_sfb_params_struct * pstr_sfb_prms,WORD32 usac_independancy_flag,ia_usac_data_struct * ptr_usac_data,ia_usac_encoder_config_struct * ptr_usac_config,WORD32 chn)258 IA_ERRORCODE iusace_stereo_proc(ia_sfb_params_struct *pstr_sfb_prms,
259                                 WORD32 usac_independancy_flag, ia_usac_data_struct *ptr_usac_data,
260                                 ia_usac_encoder_config_struct *ptr_usac_config, WORD32 chn) {
261   IA_ERRORCODE err_code;
262   WORD32 i = 0;
263   WORD32 j = 0;
264   iusace_scratch_mem *pstr_scratch = &ptr_usac_data->str_scratch;
265   ia_psy_mod_data_struct *pstr_psy_data = ptr_usac_data->str_psy_mod.str_psy_data;
266   ia_psy_mod_out_data_struct *pstr_psy_out = ptr_usac_data->str_psy_mod.str_psy_out_data;
267   WORD32 *ptr_num_sfb = pstr_sfb_prms->num_sfb;
268   WORD32 *ptr_num_window_groups = pstr_sfb_prms->num_window_groups;
269   WORD32 ccfl = ptr_usac_config->ccfl;
270   ia_ms_info_struct *pstr_ms_info = &ptr_usac_data->str_ms_info[chn];
271 
272   FLOAT64 tmp = 0.0f;
273   FLOAT32 nrg_mid = 0.0f, nrg_side = 0.0f, nrg_left = 0.0f, nrg_right = 0.0f;
274   FLOAT64 *ptr_scratch_spec = pstr_scratch->p_quant_spectrum_spec_scratch;
275   FLOAT32 ratio_mid = 0.0f, ratio_side = 0.0f;
276   FLOAT32 eps = 1.0e-6f;
277   /* Save a copy of left and right channel MDCT spectra before they are modified */
278   memcpy(ptr_usac_data->left_chan_save[chn], ptr_usac_data->spectral_line_vector[chn],
279          ccfl * sizeof(FLOAT64));
280   memcpy(ptr_usac_data->right_chan_save[chn], ptr_usac_data->spectral_line_vector[chn + 1],
281          ccfl * sizeof(FLOAT64));
282 
283   if (ptr_usac_config->cmplx_pred_flag == 1) {
284     /* Refinement - decision on whether to use complex prediction or MS */
285     for (i = 0; i < ccfl; i++) {
286       tmp = ptr_usac_data->spectral_line_vector[chn][i];
287       ptr_scratch_spec[i] = 0.5f * (ptr_usac_data->spectral_line_vector[chn][i] +
288                                     ptr_usac_data->spectral_line_vector[chn + 1][i]);
289       ptr_scratch_spec[ccfl + i] = 0.5f * (tmp - ptr_usac_data->spectral_line_vector[chn + 1][i]);
290     }
291 
292     for (i = 0; i < ccfl; i++) {
293       nrg_mid += (FLOAT32)(ptr_scratch_spec[i] * ptr_scratch_spec[i]);
294       nrg_side += (FLOAT32)(ptr_scratch_spec[ccfl + i] * ptr_scratch_spec[ccfl + i]);
295       nrg_left += (FLOAT32)(ptr_usac_data->spectral_line_vector[chn][i] *
296                             ptr_usac_data->spectral_line_vector[chn][i]);
297       nrg_right += (FLOAT32)(ptr_usac_data->spectral_line_vector[chn + 1][i] *
298                              ptr_usac_data->spectral_line_vector[chn + 1][i]);
299     }
300 
301     ratio_mid = nrg_mid / (MAX(nrg_left, nrg_right) + eps);
302     ratio_side = nrg_side / (MAX(nrg_left, nrg_right) + eps);
303 
304     if (ratio_mid >= 0.8f || ratio_side >= 0.8f || nrg_mid == 0.f || nrg_side == 0.f) {
305       pstr_ms_info->ms_mask = 0;
306     } else {
307       pstr_ms_info->ms_mask = 3;
308     }
309   }
310 
311   if (pstr_ms_info->ms_mask != 3) {
312     WORD32 idx = 0;
313     WORD32 sfb;
314 
315     for (sfb = 0; sfb < ptr_num_sfb[chn]; sfb++) {
316       ptr_usac_data->pred_coef_re_prev[chn][sfb] = 0;
317       ptr_usac_data->pred_coef_im_prev[chn][sfb] = 0;
318       ptr_usac_data->temp_pred_coef_re_prev[chn][sfb] = 0;
319       ptr_usac_data->temp_pred_coef_im_prev[chn][sfb] = 0;
320     }
321 
322     memset(ptr_usac_data->str_ms_info[chn].ms_used, 0,
323            MAX_SFB_LONG * MAX_SHORT_WINDOWS * sizeof(WORD32));
324 
325     iusace_ms_apply(pstr_psy_data, ptr_usac_data->spectral_line_vector[chn],
326                     ptr_usac_data->spectral_line_vector[chn + 1],
327                     &ptr_usac_data->str_ms_info[chn].ms_mask,
328                     ptr_usac_data->str_ms_info[chn].ms_used,
329                     ptr_num_window_groups[chn] * ptr_num_sfb[chn], ptr_num_sfb[chn],
330                     pstr_psy_out[chn].max_sfb_per_grp, pstr_sfb_prms->grouped_sfb_offset[chn],
331                     chn, ptr_usac_config->cmplx_pred_flag == 1 ? ptr_scratch_spec : NULL);
332 
333     for (i = 0; i < ptr_num_window_groups[chn]; i++) {
334       for (j = 0; j < ptr_num_sfb[chn]; j++) {
335         pstr_psy_out[chn].ms_used[idx++] = ptr_usac_data->str_ms_info[chn].ms_used[i][j];
336       }
337     }
338   } else {
339     /* Reset buffer to zero */
340     for (WORD32 group = 0; group < MAX_SHORT_WINDOWS; group++) {
341       memset(ptr_usac_data->cplx_pred_used[chn][group], 0, MAX_SFB_LONG * sizeof(WORD32));
342     }
343 
344     ptr_usac_data->cplx_pred_all[chn] = 1; /* Disable bandwise switching to L/R */
345     for (i = 0; i < ptr_num_window_groups[chn]; i++) {
346       for (j = 0; j < ptr_num_sfb[chn]; j += 2) {
347         ptr_usac_data->cplx_pred_used[chn][i][j] = 1;
348         if ((j + 1) < ptr_num_sfb[chn]) {
349           ptr_usac_data->cplx_pred_used[chn][i][j + 1] = ptr_usac_data->cplx_pred_used[chn][i][j];
350         }
351       }
352     }
353 
354     err_code = iusace_cplx_pred_proc(
355         ptr_usac_data, ptr_usac_config, usac_independancy_flag, pstr_sfb_prms, chn, pstr_psy_data,
356         pstr_sfb_prms->grouped_sfb_offset[chn], pstr_scratch->p_cmpx_mdct_temp_buf,
357         ptr_scratch_spec, nrg_mid, nrg_side);
358     if (err_code != IA_NO_ERROR) {
359       return err_code;
360     }
361   }
362   return IA_NO_ERROR;
363 }
364 
iusace_grouping(ia_sfb_params_struct * pstr_sfb_prms,WORD32 num_chans,ia_usac_data_struct * ptr_usac_data,ia_usac_encoder_config_struct * ptr_usac_config,WORD32 chn,WORD32 ele_id)365 IA_ERRORCODE iusace_grouping(ia_sfb_params_struct *pstr_sfb_prms, WORD32 num_chans,
366                              ia_usac_data_struct *ptr_usac_data,
367                              ia_usac_encoder_config_struct *ptr_usac_config, WORD32 chn,
368                              WORD32 ele_id) {
369   WORD32 i = 0, grp, sfb, wnd;
370   WORD32 j = 0;
371   WORD32 k;
372   WORD32 ch;
373   ia_psy_mod_struct *pstr_psy_config = &ptr_usac_data->str_psy_mod;
374   ia_psy_mod_data_struct *pstr_psy_data = ptr_usac_data->str_psy_mod.str_psy_data;
375   WORD32 *ptr_window_sequence = pstr_sfb_prms->window_sequence;
376   WORD32 *ptr_num_sfb = pstr_sfb_prms->num_sfb;
377   WORD32 *ptr_num_window_groups = pstr_sfb_prms->num_window_groups;
378   ia_psy_mod_out_data_struct *pstr_psy_out = ptr_usac_data->str_psy_mod.str_psy_out_data;
379 
380   for (ch = chn; ch < chn + num_chans; ch++) {
381     if (ptr_window_sequence[ch] == EIGHT_SHORT_SEQUENCE) {
382       iusace_sort_for_grouping(
383           pstr_sfb_prms->grouped_sfb_offset[ch], pstr_sfb_prms->sfb_width_table[ch],
384           ptr_usac_data->str_scratch.p_sort_grouping_scratch,
385           ptr_usac_data->spectral_line_vector[ch], ptr_num_window_groups[ch],
386           pstr_sfb_prms->window_group_length[ch], ptr_num_sfb[ch], ptr_usac_config->ccfl);
387     } else if ((ptr_window_sequence[ch] == ONLY_LONG_SEQUENCE) ||
388                (ptr_window_sequence[ch] == LONG_START_SEQUENCE) ||
389                (ptr_window_sequence[ch] == LONG_STOP_SEQUENCE) ||
390                (ptr_window_sequence[ch] == STOP_START_SEQUENCE)) {
391       pstr_sfb_prms->grouped_sfb_offset[ch][0] = 0;
392       k = 0;
393       for (i = 0; i < ptr_num_sfb[ch]; i++) {
394         pstr_sfb_prms->grouped_sfb_offset[ch][i] = k;
395         k += pstr_sfb_prms->sfb_width_table[ch][i];
396       }
397       pstr_sfb_prms->grouped_sfb_offset[ch][i] = k;
398     } else {
399       return IA_EXHEAACE_EXE_FATAL_USAC_INVALID_WINDOW_TYPE;
400     }
401   }
402 
403   for (ch = chn; ch < chn + num_chans; ch++) {
404     if (pstr_psy_data[ch].window_sequence == 2) {
405       i = 0;
406       for (grp = 0; grp < ptr_num_window_groups[ch]; grp++) {
407         for (sfb = 0; sfb < ptr_num_sfb[ch]; sfb++) {
408           pstr_psy_out[ch].sfb_min_snr[i++] =
409               pstr_psy_config->str_psy_short_config[ele_id].sfb_min_snr[sfb];
410         }
411       }
412       wnd = 0;
413       i = 0;
414       for (grp = 0; grp < ptr_num_window_groups[ch]; grp++) {
415         for (sfb = 0; sfb < ptr_num_sfb[ch]; sfb++) {
416           FLOAT32 threshold = pstr_psy_data[ch].sfb_thr_short[wnd][sfb];
417           FLOAT32 energy = pstr_psy_data[ch].sfb_energy_short[wnd][sfb];
418           FLOAT32 energy_ms = pstr_psy_data[ch].ptr_sfb_energy_short_ms[wnd][sfb];
419           FLOAT32 spread_energy = pstr_psy_data[ch].sfb_spreaded_energy_short[wnd][sfb];
420           for (j = 1; j < pstr_sfb_prms->window_group_length[ch][grp]; j++) {
421             threshold = threshold + pstr_psy_data[ch].sfb_thr_short[wnd + j][sfb];
422             energy = energy + pstr_psy_data[ch].sfb_energy_short[wnd + j][sfb];
423             spread_energy =
424                 spread_energy + pstr_psy_data[ch].sfb_spreaded_energy_short[wnd + j][sfb];
425             energy_ms = energy_ms + pstr_psy_data[ch].ptr_sfb_energy_short_ms[wnd + j][sfb];
426           }
427           pstr_psy_data[ch].ptr_sfb_thr_long[i] = threshold;
428           pstr_psy_data[ch].ptr_sfb_energy_long[i] = energy;
429           pstr_psy_data[ch].ptr_sfb_energy_long_ms[i] = energy_ms;
430           pstr_psy_data[ch].ptr_sfb_spreaded_energy_long[i++] = spread_energy;
431         }
432         wnd += pstr_sfb_prms->window_group_length[ch][grp];
433       }
434     } else {
435       for (sfb = 0; sfb < ptr_num_sfb[ch]; sfb++) {
436         pstr_psy_out[ch].sfb_min_snr[sfb] =
437             pstr_psy_config->str_psy_long_config[ele_id].sfb_min_snr[sfb];
438       }
439     }
440   }
441   return IA_NO_ERROR;
442 }
443 
iusace_quantize_spec(ia_sfb_params_struct * pstr_sfb_prms,WORD32 usac_independancy_flag,WORD32 num_chans,ia_usac_data_struct * ptr_usac_data,ia_usac_encoder_config_struct * ptr_usac_config,WORD32 chn,WORD32 ele_id,WORD32 * is_quant_spec_zero,WORD32 * is_gain_limited)444 IA_ERRORCODE iusace_quantize_spec(ia_sfb_params_struct *pstr_sfb_prms,
445                                   WORD32 usac_independancy_flag, WORD32 num_chans,
446                                   ia_usac_data_struct *ptr_usac_data,
447                                   ia_usac_encoder_config_struct *ptr_usac_config, WORD32 chn,
448                                   WORD32 ele_id, WORD32 *is_quant_spec_zero,
449                                   WORD32 *is_gain_limited) {
450   IA_ERRORCODE err_code;
451   WORD32 i = 0, sfb;
452   WORD32 j = 0;
453   WORD32 k;
454   WORD32 max_bits;
455   WORD32 ch;
456   iusace_scratch_mem *pstr_scratch = &ptr_usac_data->str_scratch;
457   WORD32 num_scfs[2];
458   FLOAT32 **sfb_form_fac = &pstr_scratch->ptr_sfb_form_fac[0];
459   WORD32 max_ch_dyn_bits[2] = {0};
460   FLOAT32 ch_bit_dist[2];
461   WORD32 constraints_fulfilled;
462   WORD32 iterations = 0;
463   WORD32 max_val;
464   WORD32 kk, idx = 0;
465 
466   FLOAT32 *ptr_exp_spec = pstr_scratch->p_exp_spec;
467   FLOAT32 *ptr_mdct_spec_float = pstr_scratch->p_mdct_spec_float;
468   ia_psy_mod_data_struct *pstr_psy_data = ptr_usac_data->str_psy_mod.str_psy_data;
469   ia_qc_out_data_struct *pstr_qc_out = &ptr_usac_data->str_qc_main.str_qc_out;
470   ia_psy_mod_out_data_struct *pstr_psy_out = ptr_usac_data->str_psy_mod.str_psy_out_data;
471   ia_qc_data_struct *pstr_qc_data = &ptr_usac_data->str_qc_main.str_qc_data[ele_id];
472   ia_adj_thr_elem_struct *pstr_adj_thr_elem = &pstr_qc_data->str_adj_thr_ele;
473   WORD32 *ptr_window_sequence = pstr_sfb_prms->window_sequence;
474   WORD32 *ptr_max_sfb = pstr_sfb_prms->max_sfb;
475   WORD32 *ptr_num_sfb = pstr_sfb_prms->num_sfb;
476   WORD32 *ptr_num_window_groups = pstr_sfb_prms->num_window_groups;
477   WORD32 bitres_bits, bitres_diff;
478   WORD32 gain;
479 
480   memset(num_scfs, 0, 2 * sizeof(num_scfs[0]));
481 
482   for (ch = chn; ch < chn + num_chans; ch++) {
483     num_scfs[idx] = ptr_num_sfb[ch] * ptr_num_window_groups[ch];
484 
485     pstr_psy_out[ch].sfb_count = num_scfs[idx];
486     pstr_psy_out[ch].sfb_per_group = num_scfs[idx] / ptr_num_window_groups[ch];
487     pstr_psy_out[ch].window_sequence = pstr_psy_data[ch].window_sequence;
488     pstr_psy_out[ch].window_shape = iusace_window_shape[pstr_psy_data[ch].window_sequence];
489     pstr_psy_out[ch].ptr_spec_coeffs = ptr_usac_data->spectral_line_vector[ch];
490     pstr_psy_out[ch].ptr_sfb_energy = pstr_psy_data[ch].ptr_sfb_energy_long;
491     pstr_psy_out[ch].ptr_sfb_thr = pstr_psy_data[ch].ptr_sfb_thr_long;
492     pstr_psy_out[ch].ptr_sfb_spread_energy = pstr_psy_data[ch].ptr_sfb_spreaded_energy_long;
493 
494     for (j = 0; j < num_scfs[idx]; j++) {
495       pstr_psy_out[ch].sfb_offsets[j] = pstr_sfb_prms->grouped_sfb_offset[ch][j];
496     }
497     pstr_psy_out[ch].sfb_offsets[num_scfs[idx]] =
498         pstr_sfb_prms->grouped_sfb_offset[ch][num_scfs[idx]];
499 
500     for (j = 0; j < MAX_NUM_GROUPED_SFB; j++) {
501       sfb_form_fac[idx][j] = MIN_FLT_VAL;
502     }
503 
504     iusace_calc_form_fac_per_chan(&pstr_psy_out[ch], pstr_scratch, idx);
505     idx++;
506   }
507 
508   pstr_qc_out->static_bits =
509       iusace_count_static_bits(ptr_usac_data, ptr_usac_config, pstr_sfb_prms, pstr_psy_out,
510                                num_chans, chn, usac_independancy_flag, ele_id);
511 
512   iusace_adj_bitrate(pstr_qc_data, pstr_qc_data->ch_bitrate, ptr_usac_config->core_sample_rate,
513                      ptr_usac_config->ccfl);
514   err_code =
515       iusace_adj_thr(pstr_adj_thr_elem, pstr_psy_out, ch_bit_dist, pstr_qc_out,
516                      pstr_qc_data->avg_bits - pstr_qc_out->static_bits, pstr_qc_data->bit_res_lvl,
517                      pstr_qc_data->max_bitres_bits, pstr_qc_out->static_bits,
518                      &pstr_qc_data->max_bit_fac, num_chans, chn, pstr_scratch);
519   if (err_code != IA_NO_ERROR) {
520     return err_code;
521   }
522 
523   iusace_estimate_scfs_chan(pstr_psy_out, pstr_qc_out->str_qc_out_chan, num_chans, chn,
524                             pstr_scratch);
525   idx = 0;
526   for (ch = 0; ch < num_chans; ch++) {
527     max_ch_dyn_bits[ch] = (WORD32)floor(
528         ch_bit_dist[ch] * (FLOAT32)(pstr_qc_data->avg_bits + pstr_qc_data->bit_res_lvl - 7 -
529                                     pstr_qc_out->static_bits));
530     idx++;
531   }
532 
533   pstr_qc_out->dyn_bits = 0;
534   idx = 0;
535   for (ch = chn; ch < chn + num_chans; ch++) {
536     iterations = 0;
537     gain = 0;
538     for (kk = 0; kk < ptr_usac_config->ccfl; kk++) {
539       ptr_exp_spec[kk] = (FLOAT32)pstr_psy_out[ch].ptr_spec_coeffs[kk];
540       ptr_mdct_spec_float[kk] = (FLOAT32)pstr_psy_out[ch].ptr_spec_coeffs[kk];
541     }
542     do {
543       constraints_fulfilled = 1;
544       WORD32 quant_spec_is_zero = 1;
545       if (iterations > 0) {
546         for (WORD32 sfb_offs = 0; sfb_offs < pstr_psy_out[ch].sfb_count;
547              sfb_offs += pstr_psy_out[ch].sfb_per_group) {
548           for (sfb = 0; sfb < pstr_psy_out[ch].max_sfb_per_grp; sfb++) {
549             WORD32 scalefactor = pstr_qc_out->str_qc_out_chan[idx].scalefactor[sfb + sfb_offs];
550             gain = MAX(gain, pstr_qc_out->str_qc_out_chan[idx].global_gain - scalefactor);
551             iusace_quantize_lines(
552                 pstr_qc_out->str_qc_out_chan[idx].global_gain - scalefactor,
553                 pstr_psy_out[ch].sfb_offsets[sfb_offs + sfb + 1] -
554                     pstr_psy_out[ch].sfb_offsets[sfb_offs + sfb],
555                 ptr_exp_spec + pstr_psy_out[ch].sfb_offsets[sfb_offs + sfb],
556                 pstr_qc_out->str_qc_out_chan[idx].quant_spec +
557                     pstr_psy_out[ch].sfb_offsets[sfb_offs + sfb],
558                 ptr_mdct_spec_float + pstr_psy_out[ch].sfb_offsets[sfb_offs + sfb]);
559           }
560         }
561       }
562       max_val =
563           iusace_calc_max_val_in_sfb(pstr_psy_out[ch].sfb_count, pstr_psy_out[ch].max_sfb_per_grp,
564                                      pstr_psy_out[ch].sfb_per_group, pstr_psy_out[ch].sfb_offsets,
565                                      pstr_qc_out->str_qc_out_chan[idx].quant_spec);
566       if (max_val > MAX_QUANT) {
567         constraints_fulfilled = 0;
568       }
569 
570       for (k = 0; k < num_scfs[idx]; k++) {
571         for (i = pstr_sfb_prms->grouped_sfb_offset[ch][k];
572              i < pstr_sfb_prms->grouped_sfb_offset[ch][k + 1]; i++) {
573           ptr_usac_data->str_quant_info[idx].quant_degroup[i] =
574               (WORD32)pstr_qc_out->str_qc_out_chan[idx].quant_spec[i];
575           if (ptr_usac_data->str_quant_info[idx].quant_degroup[i] != 0) {
576             quant_spec_is_zero = 0;
577           }
578         }
579       }
580 
581       if (ptr_window_sequence[ch] == EIGHT_SHORT_SEQUENCE) {
582         iusace_degroup_int(pstr_sfb_prms->grouped_sfb_offset[ch], ptr_num_sfb[ch],
583                            ptr_usac_data->str_scratch.p_degroup_scratch,
584                            ptr_usac_data->str_quant_info[idx].quant_degroup,
585                            ptr_num_window_groups[ch], pstr_sfb_prms->window_group_length[ch],
586                            ptr_usac_config->ccfl);
587       }
588 
589       ptr_usac_data->str_quant_info[idx].max_spec_coeffs = 0;
590       for (k = 0; k < ptr_max_sfb[ch]; k++) {
591         ptr_usac_data->str_quant_info[idx].max_spec_coeffs +=
592             pstr_sfb_prms->sfb_width_table[ch][k];
593       }
594 
595       for (i = 0; i < num_scfs[idx]; i++) {
596         ptr_usac_data->str_quant_info[idx].scale_factor[i] =
597             pstr_qc_out->str_qc_out_chan[idx].global_gain -
598             pstr_qc_out->str_qc_out_chan[idx].scalefactor[i] + SF_OFFSET;
599       }
600 
601       max_bits = iusace_count_fd_bits(pstr_sfb_prms, ptr_usac_data, usac_independancy_flag,
602                                       ptr_usac_config, ch, idx);
603 
604       if (max_bits > max_ch_dyn_bits[idx]) {
605         constraints_fulfilled = 0;
606       }
607       if (quant_spec_is_zero == 1) {
608         constraints_fulfilled = 1;
609         /*Bit consuption is exceding bit reservoir, there is no scope left for bit consumption
610           reduction, as spectrum is zero. Hence breaking the quantization loop. */
611         if (iterations > 0) {
612           *is_quant_spec_zero = 1;
613           max_bits = max_ch_dyn_bits[idx];
614         }
615       }
616       if ((gain == MAX_GAIN_INDEX) && (constraints_fulfilled == 0)) {
617         /* Bit consuption is exceding bit reservoir, there is no scope left for bit consumption
618            reduction, as gain has reached the maximum value. Hence breaking the quantization
619            loop. */
620         constraints_fulfilled = 1;
621         *is_gain_limited = 1;
622         max_bits = max_ch_dyn_bits[idx];
623       }
624       if (!constraints_fulfilled) {
625         pstr_qc_out->str_qc_out_chan[idx].global_gain++;
626       }
627       iterations++;
628     } while (!constraints_fulfilled);
629 
630     pstr_qc_out->dyn_bits += max_bits;
631 
632     if (ptr_usac_data->noise_filling[ele_id]) {
633       WORD32 max_nf_sfb = ptr_max_sfb[ch];
634 
635       if (ptr_window_sequence[ch] != EIGHT_SHORT_SEQUENCE) {
636         iusace_noise_filling(
637             &ptr_usac_data->noise_level[idx], &ptr_usac_data->noise_offset[idx],
638             ptr_usac_data->spectral_line_vector[ch], &ptr_usac_data->str_quant_info[idx],
639             pstr_sfb_prms->grouped_sfb_offset[ch], max_nf_sfb, ptr_usac_config->ccfl,
640             ptr_num_window_groups[ch], pstr_sfb_prms->window_group_length[ch], 160,
641             ptr_usac_data->str_scratch.p_noise_filling_highest_tone);
642       } else {
643         iusace_noise_filling(
644             &ptr_usac_data->noise_level[idx], &ptr_usac_data->noise_offset[idx],
645             ptr_usac_data->spectral_line_vector[ch], &ptr_usac_data->str_quant_info[idx],
646             pstr_sfb_prms->grouped_sfb_offset[ch], max_nf_sfb, ptr_usac_config->ccfl >> 3,
647             ptr_num_window_groups[ch], pstr_sfb_prms->window_group_length[ch], 20,
648             (FLOAT64 *)ptr_usac_data->str_scratch.p_noise_filling_highest_tone);
649       }
650 
651       if (ptr_usac_data->noise_level[idx] == 0 && ptr_usac_data->noise_offset[idx] != 0 &&
652           pstr_sfb_prms->common_win[ch]) {
653         ptr_usac_data->complex_coef[ch] = 0;
654       }
655     }
656     idx++;
657   }
658 
659   pstr_adj_thr_elem->dyn_bits_last = pstr_qc_out->dyn_bits;
660 
661   bitres_bits = pstr_qc_data->max_bitres_bits - pstr_qc_data->bit_res_lvl;
662   bitres_diff = pstr_qc_data->avg_bits - (pstr_qc_out->static_bits + pstr_qc_out->dyn_bits);
663   pstr_qc_out->fill_bits = MAX(0, (bitres_diff - bitres_bits));
664 
665   if (pstr_qc_data->avg_bits > 0) {
666     pstr_qc_data->bit_res_lvl +=
667         pstr_qc_data->avg_bits -
668         (pstr_qc_out->static_bits + pstr_qc_out->dyn_bits + pstr_qc_out->fill_bits);
669   } else {
670     pstr_qc_data->bit_res_lvl = pstr_qc_data->max_bits;
671   }
672 
673   if (pstr_qc_data->bit_res_lvl < 0 ||
674       pstr_qc_data->bit_res_lvl > pstr_qc_data->max_bitres_bits) {
675     return IA_EXHEAACE_EXE_FATAL_USAC_INVALID_BIT_RSVR_LVL;
676   }
677 
678   return IA_NO_ERROR;
679 }
680