xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_adjust_threshold.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 <float.h>
22 #include <math.h>
23 #include <stdlib.h>
24 
25 #include <string.h>
26 
27 #include "ixheaac_type_def.h"
28 #include "ixheaac_constants.h"
29 #include "impd_drc_common_enc.h"
30 #include "impd_drc_uni_drc.h"
31 #include "impd_drc_tables.h"
32 #include "impd_drc_api.h"
33 #include "ixheaace_api.h"
34 #include "ixheaace_aac_constants.h"
35 #include "ixheaace_psy_const.h"
36 #include "ixheaace_tns.h"
37 #include "ixheaace_tns_params.h"
38 #include "ixheaace_rom.h"
39 
40 #include "ixheaac_basic_ops32.h"
41 #include "ixheaac_basic_ops16.h"
42 #include "ixheaac_basic_ops40.h"
43 #include "ixheaac_basic_ops.h"
44 
45 #include "ixheaace_common_rom.h"
46 #include "ixheaace_bitbuffer.h"
47 #include "ixheaace_adjust_threshold_data.h"
48 #include "ixheaace_dynamic_bits.h"
49 #include "ixheaace_qc_data.h"
50 #include "ixheaace_block_switch.h"
51 #include "ixheaace_psy_data.h"
52 #include "ixheaace_interface.h"
53 #include "ixheaace_adjust_threshold.h"
54 #include "ixheaace_common_utils.h"
55 
iaace_adj_thr_init(ia_adj_thr_state_struct * pstr_adj_thr_state,const FLOAT32 mean_pe,WORD32 ch_bitrate,WORD32 aot)56 VOID iaace_adj_thr_init(ia_adj_thr_state_struct *pstr_adj_thr_state, const FLOAT32 mean_pe,
57                         WORD32 ch_bitrate, WORD32 aot) {
58   ia_adj_thr_elem_struct *pstr_adj_thr_ele = &pstr_adj_thr_state->str_adj_thr_ele;
59   ia_min_snr_adapt_param_struct *pstr_min_snr_params =
60       &pstr_adj_thr_ele->str_min_snr_adapt_params;
61 
62   pstr_adj_thr_state->str_bitres_params_long.clip_save_low = CLIP_SAVE_LO_LONG;
63   pstr_adj_thr_state->str_bitres_params_long.clip_save_high = CLIP_SAVE_HI_LONG;
64   pstr_adj_thr_state->str_bitres_params_long.min_bit_save = MIN_BITS_SAVE_LONG;
65   pstr_adj_thr_state->str_bitres_params_long.max_bit_save = MAX_BITS_SAVE_LONG;
66   pstr_adj_thr_state->str_bitres_params_long.clip_spend_low = CLIP_SPEND_LO_LONG;
67   pstr_adj_thr_state->str_bitres_params_long.clip_spend_high = CLIP_SPEND_HI_LONG;
68   pstr_adj_thr_state->str_bitres_params_long.min_bits_spend = MIN_BITS_SPEND_LONG;
69   pstr_adj_thr_state->str_bitres_params_long.max_bits_spend = MAX_BITS_SPEND_LONG;
70 
71   pstr_adj_thr_state->str_bitres_params_short.clip_save_low = CLIP_SAVE_LO_SHORT;
72   pstr_adj_thr_state->str_bitres_params_short.clip_save_high = CLIP_SAVE_HI_SHORT;
73   pstr_adj_thr_state->str_bitres_params_short.min_bit_save = MIN_BITS_SAVE_SHORT;
74   pstr_adj_thr_state->str_bitres_params_short.max_bit_save = MAX_BITS_SAVE_SHORT;
75   pstr_adj_thr_state->str_bitres_params_short.clip_spend_low = CLIP_SPEND_LO_SHORT;
76   pstr_adj_thr_state->str_bitres_params_short.clip_spend_high = CLIP_SPEND_HI_SHORT;
77   pstr_adj_thr_state->str_bitres_params_short.min_bits_spend = MIN_BITS_SPEND_SHORT;
78   pstr_adj_thr_state->str_bitres_params_short.max_bits_spend = MAX_BITS_SPEND_SHORT;
79 
80   pstr_adj_thr_ele->pe_min = (FLOAT32)0.8f * mean_pe;
81   pstr_adj_thr_ele->pe_max = (FLOAT32)1.2f * mean_pe;
82   pstr_adj_thr_ele->pe_offset = 0.0f;
83   switch (aot) {
84     case AOT_AAC_LC:
85     case AOT_SBR:
86     case AOT_PS:
87       if (ch_bitrate < 32000) {
88         pstr_adj_thr_ele->pe_offset = MAX(
89             (FLOAT32)50.0f, (FLOAT32)(100.0f) - (FLOAT32)(100.0f / 32000) * (FLOAT32)ch_bitrate);
90       }
91       break;
92 
93     case AOT_AAC_LD:
94     case AOT_AAC_ELD:
95 
96       if (ch_bitrate <= 32000) {
97         pstr_adj_thr_ele->pe_offset = MAX(
98             (FLOAT32)50.0f, (FLOAT32)(100.0f) - (FLOAT32)(100.0f / 32000) * (FLOAT32)ch_bitrate);
99       }
100       break;
101   }
102 
103   if (ch_bitrate > 20000) {
104     pstr_adj_thr_ele->str_ah_param.modify_min_snr = TRUE;
105     pstr_adj_thr_ele->str_ah_param.start_sfb_long = 15;
106     pstr_adj_thr_ele->str_ah_param.start_sfb_short = 3;
107   } else {
108     pstr_adj_thr_ele->str_ah_param.modify_min_snr = FALSE;
109     pstr_adj_thr_ele->str_ah_param.start_sfb_long = 0;
110     pstr_adj_thr_ele->str_ah_param.start_sfb_short = 0;
111   }
112 
113   pstr_min_snr_params->max_red = (FLOAT32)0.25f;
114 
115   pstr_min_snr_params->start_ratio = (FLOAT32)1.e1f;
116 
117   pstr_min_snr_params->max_ratio = (FLOAT32)1.e3f;
118 
119   pstr_min_snr_params->red_ratio_fac =
120       (1.0f - pstr_min_snr_params->max_red) /
121       (10.0f * (FLOAT32)log10(pstr_min_snr_params->start_ratio / pstr_min_snr_params->max_ratio));
122 
123   pstr_min_snr_params->red_offs = 1.0f - pstr_min_snr_params->red_ratio_fac * 10.0f *
124                                              (FLOAT32)log10(pstr_min_snr_params->start_ratio);
125 
126   pstr_adj_thr_ele->pe_last = (FLOAT32)0.0f;
127   pstr_adj_thr_ele->dyn_bits_last = 0;
128   pstr_adj_thr_ele->pe_correction_fac = (FLOAT32)1.0f;
129 }
iaace_bits_to_pe(const FLOAT32 bits)130 FLOAT32 iaace_bits_to_pe(const FLOAT32 bits) { return (bits * 1.18f); }
iaace_calc_sfb_pe_data(ia_qc_pe_data_struct * pstr_qc_pe_data,ixheaace_psy_out_channel ** pstr_psy_out,WORD32 num_channels,WORD32 chn)131 static VOID iaace_calc_sfb_pe_data(ia_qc_pe_data_struct *pstr_qc_pe_data,
132                                    ixheaace_psy_out_channel **pstr_psy_out, WORD32 num_channels,
133                                    WORD32 chn) {
134   WORD32 ch;
135   WORD32 scf_band_grp;
136   FLOAT32 num_lines;
137   FLOAT32 ld_thr, ld_ratio;
138   WORD32 i = 0, scf;
139   WORD32 sfb_count;
140   WORD32 scf_band_per_grp;
141   WORD32 max_sfb_per_grp;
142   FLOAT32 *ptr_sfb_energy;
143   FLOAT32 *ptr_sfb_thr;
144   ia_qc_pe_chan_data_struct *pstr_qc_pe_chan_data;
145 
146   pstr_qc_pe_data->pe = pstr_qc_pe_data->offset;
147   pstr_qc_pe_data->const_part = 0.0f;
148   pstr_qc_pe_data->num_active_lines = 0.0f;
149 
150   for (ch = chn; ch < chn + num_channels; ch++) {
151     sfb_count = pstr_psy_out[ch]->sfb_count;
152     scf_band_per_grp = pstr_psy_out[ch]->sfb_per_group;
153     max_sfb_per_grp = pstr_psy_out[ch]->max_sfb_per_grp;
154     ptr_sfb_energy = pstr_psy_out[ch]->ptr_sfb_energy;
155     ptr_sfb_thr = pstr_psy_out[ch]->ptr_sfb_thr;
156     pstr_qc_pe_chan_data = &pstr_qc_pe_data->pe_ch_data[ch];
157     pstr_qc_pe_chan_data->pe = 0;
158     pstr_qc_pe_chan_data->num_active_lines = 0;
159     pstr_qc_pe_chan_data->const_part = 0;
160 
161     for (scf_band_grp = 0; scf_band_grp < sfb_count; scf_band_grp += scf_band_per_grp) {
162       i = scf_band_grp;
163       for (scf = max_sfb_per_grp - 1; scf >= 0; scf--, i++) {
164         if (ptr_sfb_energy[i] > ptr_sfb_thr[i]) {
165           ld_thr = (FLOAT32)log(ptr_sfb_thr[i]) * LOG2_1;
166           ld_ratio = pstr_qc_pe_chan_data->sfb_ld_energy[i] - ld_thr;
167           num_lines = pstr_qc_pe_chan_data->sfb_lines[i];
168           if (ld_ratio >= PE_C1) {
169             pstr_qc_pe_chan_data->sfb_pe[i] = num_lines * ld_ratio;
170             pstr_qc_pe_chan_data->sfb_const_part[i] =
171                 num_lines * pstr_qc_pe_chan_data->sfb_ld_energy[i];
172           } else {
173             pstr_qc_pe_chan_data->sfb_pe[i] = num_lines * (PE_C2 + PE_C3 * ld_ratio);
174             pstr_qc_pe_chan_data->sfb_const_part[i] =
175                 num_lines * (PE_C2 + PE_C3 * pstr_qc_pe_chan_data->sfb_ld_energy[i]);
176             num_lines = num_lines * PE_C3;
177           }
178           pstr_qc_pe_chan_data->num_sfb_active_lines[i] = num_lines;
179         } else {
180           pstr_qc_pe_chan_data->sfb_pe[i] = 0.0f;
181           pstr_qc_pe_chan_data->sfb_const_part[i] = 0.0f;
182           pstr_qc_pe_chan_data->num_sfb_active_lines[i] = 0.0;
183         }
184 
185         pstr_qc_pe_chan_data->pe += pstr_qc_pe_chan_data->sfb_pe[i];
186         pstr_qc_pe_chan_data->const_part += pstr_qc_pe_chan_data->sfb_const_part[i];
187         pstr_qc_pe_chan_data->num_active_lines += pstr_qc_pe_chan_data->num_sfb_active_lines[i];
188       }
189     }
190     pstr_qc_pe_data->pe += pstr_qc_pe_chan_data->pe;
191     pstr_qc_pe_data->const_part += pstr_qc_pe_chan_data->const_part;
192     pstr_qc_pe_data->num_active_lines += pstr_qc_pe_chan_data->num_active_lines;
193     pstr_psy_out[ch]->pe = pstr_qc_pe_data->pe;
194   }
195 }
iaace_calc_bit_save(ia_bitres_param_struct * pstr_bitres_params,FLOAT32 fill_lvl)196 static FLOAT32 iaace_calc_bit_save(ia_bitres_param_struct *pstr_bitres_params, FLOAT32 fill_lvl) {
197   FLOAT32 bit_save;
198   const FLOAT32 clip_low = pstr_bitres_params->clip_save_low;
199   const FLOAT32 clip_high = pstr_bitres_params->clip_save_high;
200   const FLOAT32 min_bit_save = pstr_bitres_params->min_bit_save;
201   const FLOAT32 max_bit_save = pstr_bitres_params->max_bit_save;
202 
203   fill_lvl = MAX(fill_lvl, clip_low);
204   fill_lvl = MIN(fill_lvl, clip_high);
205   bit_save = max_bit_save -
206              ((max_bit_save - min_bit_save) / (clip_high - clip_low)) * (fill_lvl - clip_low);
207 
208   return bit_save;
209 }
210 
iaace_calc_bit_spend(ia_bitres_param_struct * pstr_bitres_params,FLOAT32 fill_lvl)211 static FLOAT32 iaace_calc_bit_spend(ia_bitres_param_struct *pstr_bitres_params,
212                                     FLOAT32 fill_lvl) {
213   FLOAT32 bit_spend;
214   const FLOAT32 clip_low = pstr_bitres_params->clip_spend_low;
215   const FLOAT32 clip_high = pstr_bitres_params->clip_spend_high;
216   const FLOAT32 min_bits_spend = pstr_bitres_params->min_bits_spend;
217   const FLOAT32 max_bits_spend = pstr_bitres_params->max_bits_spend;
218 
219   fill_lvl = MAX(fill_lvl, clip_low);
220   fill_lvl = MIN(fill_lvl, clip_high);
221   bit_spend = min_bits_spend + ((max_bits_spend - min_bits_spend) / (clip_high - clip_low)) *
222                                    (fill_lvl - clip_low);
223 
224   return bit_spend;
225 }
226 
iaace_adjust_pe_minmax(const FLOAT32 curr_pe,FLOAT32 * ptr_pe_min,FLOAT32 * ptr_pe_max)227 static VOID iaace_adjust_pe_minmax(const FLOAT32 curr_pe, FLOAT32 *ptr_pe_min,
228                                    FLOAT32 *ptr_pe_max) {
229   FLOAT32 min_hi_fac = 0.3f, max_hi_fac = 1.0f, min_low_fac = 0.14f, max_low_fac = 0.07f;
230   FLOAT32 diff;
231   FLOAT32 min_diff = curr_pe * (FLOAT32)0.1666666667f;
232 
233   if (curr_pe > *ptr_pe_max) {
234     diff = (curr_pe - *ptr_pe_max);
235     *ptr_pe_min += diff * min_hi_fac;
236     *ptr_pe_max += diff * max_hi_fac;
237   } else {
238     if (curr_pe < *ptr_pe_min) {
239       diff = (*ptr_pe_min - curr_pe);
240       *ptr_pe_min -= diff * min_low_fac;
241       *ptr_pe_max -= diff * max_low_fac;
242     } else {
243       *ptr_pe_min += (curr_pe - *ptr_pe_min) * min_hi_fac;
244       *ptr_pe_max -= (*ptr_pe_max - curr_pe) * max_low_fac;
245     }
246   }
247 
248   if ((*ptr_pe_max - *ptr_pe_min) < min_diff) {
249     FLOAT32 low_part, high_part;
250     low_part = MAX((FLOAT32)0.0f, curr_pe - *ptr_pe_min);
251     high_part = MAX((FLOAT32)0.0f, *ptr_pe_max - curr_pe);
252     *ptr_pe_max = curr_pe + high_part / (low_part + high_part) * min_diff;
253     *ptr_pe_min = curr_pe - low_part / (low_part + high_part) * min_diff;
254     *ptr_pe_min = MAX((FLOAT32)0.0f, *ptr_pe_min);
255   }
256 }
257 
iaace_bitres_calc_bitfac(const WORD32 bitres_bits,const WORD32 max_bitres_bits,const FLOAT32 pe,const WORD32 win_seq,const WORD32 avg_bits,const FLOAT32 max_bit_fac,ia_adj_thr_state_struct * pstr_adj_thr_state,ia_adj_thr_elem_struct * pstr_adj_the_elem)258 static FLOAT32 iaace_bitres_calc_bitfac(const WORD32 bitres_bits, const WORD32 max_bitres_bits,
259                                         const FLOAT32 pe, const WORD32 win_seq,
260                                         const WORD32 avg_bits, const FLOAT32 max_bit_fac,
261                                         ia_adj_thr_state_struct *pstr_adj_thr_state,
262                                         ia_adj_thr_elem_struct *pstr_adj_the_elem) {
263   ia_bitres_param_struct *pstr_bitres_params;
264   FLOAT32 pex;
265   FLOAT32 fill_lvl = 0.0f;
266   FLOAT32 bit_save, bit_spend, bitres_factor;
267 
268   if (max_bitres_bits) {
269     fill_lvl = (FLOAT32)bitres_bits / max_bitres_bits;
270   }
271 
272   if (win_seq != SHORT_WINDOW) {
273     pstr_bitres_params = &(pstr_adj_thr_state->str_bitres_params_long);
274   } else {
275     pstr_bitres_params = &(pstr_adj_thr_state->str_bitres_params_short);
276   }
277 
278   pex = MAX(pe, pstr_adj_the_elem->pe_min);
279   pex = MIN(pex, pstr_adj_the_elem->pe_max);
280 
281   bit_save = iaace_calc_bit_save(pstr_bitres_params, fill_lvl);
282   bit_spend = iaace_calc_bit_spend(pstr_bitres_params, fill_lvl);
283 
284   bitres_factor =
285       (FLOAT32)1.0f - bit_save +
286       ((bit_spend + bit_save) / (pstr_adj_the_elem->pe_max - pstr_adj_the_elem->pe_min)) *
287           (pex - pstr_adj_the_elem->pe_min);
288   if (avg_bits)
289   {
290     bitres_factor = MIN(bitres_factor,
291       (FLOAT32)1.0f - (FLOAT32)0.3f + (FLOAT32)bitres_bits / (FLOAT32)avg_bits);
292   }
293 
294   bitres_factor = MIN(bitres_factor, max_bit_fac);
295 
296   iaace_adjust_pe_minmax(pe, &pstr_adj_the_elem->pe_min, &pstr_adj_the_elem->pe_max);
297 
298   return bitres_factor;
299 }
300 
iaace_calc_pe_correction(FLOAT32 * ptr_correction_fac,const FLOAT32 pe_act,const FLOAT32 pe_last,const WORD32 bits_prev)301 static VOID iaace_calc_pe_correction(FLOAT32 *ptr_correction_fac, const FLOAT32 pe_act,
302                                      const FLOAT32 pe_last, const WORD32 bits_prev) {
303   if ((bits_prev > 0) && (pe_act < (FLOAT32)1.5f * pe_last) &&
304       (pe_act > (FLOAT32)0.7f * pe_last) &&
305       ((FLOAT32)1.2f * iaace_bits_to_pe((FLOAT32)bits_prev) > pe_last) &&
306       ((FLOAT32)0.65f * iaace_bits_to_pe((FLOAT32)bits_prev) < pe_last)) {
307     FLOAT32 new_fac = pe_last / iaace_bits_to_pe((FLOAT32)bits_prev);
308 
309     if (new_fac < (FLOAT32)1.0f) {
310       new_fac = MIN((FLOAT32)1.1f * new_fac, (FLOAT32)1.0f);
311       new_fac = MAX(new_fac, (FLOAT32)0.85f);
312     } else {
313       new_fac = MAX((FLOAT32)0.9f * new_fac, (FLOAT32)1.0f);
314       new_fac = MIN(new_fac, (FLOAT32)1.15f);
315     }
316     if (((new_fac > (FLOAT32)1.0f) && (*ptr_correction_fac < (FLOAT32)1.0f)) ||
317         ((new_fac < (FLOAT32)1.0f) && (*ptr_correction_fac > (FLOAT32)1.0f))) {
318       *ptr_correction_fac = (FLOAT32)1.0f;
319     }
320 
321     if ((*ptr_correction_fac < (FLOAT32)1.0f && new_fac < *ptr_correction_fac) ||
322         (*ptr_correction_fac > (FLOAT32)1.0f && new_fac > *ptr_correction_fac)) {
323       *ptr_correction_fac = (FLOAT32)0.85f * (*ptr_correction_fac) + (FLOAT32)0.15f * new_fac;
324     } else {
325       *ptr_correction_fac = (FLOAT32)0.7f * (*ptr_correction_fac) + (FLOAT32)0.3f * new_fac;
326     }
327 
328     *ptr_correction_fac = MIN(*ptr_correction_fac, (FLOAT32)1.15f);
329     *ptr_correction_fac = MAX(*ptr_correction_fac, (FLOAT32)0.85f);
330   } else {
331     *ptr_correction_fac = (FLOAT32)1.0f;
332   }
333 }
334 
iaace_calc_thr_exp(FLOAT32 thr_exp[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],ixheaace_psy_out_channel ** pstr_psy_out,WORD32 num_chans,WORD32 chn)335 static VOID iaace_calc_thr_exp(
336     FLOAT32 thr_exp[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],
337     ixheaace_psy_out_channel **pstr_psy_out, WORD32 num_chans, WORD32 chn) {
338   WORD32 sfb, ch, scf_band_grp;
339   ixheaace_psy_out_channel *pstr_psy_chan_out;
340   FLOAT32 *ptr_scf_band_thr;
341   FLOAT32 *ptr_thr_exp;
342   for (ch = chn; ch < chn + num_chans; ch++) {
343     pstr_psy_chan_out = pstr_psy_out[ch];
344     ptr_thr_exp = thr_exp[ch];
345     for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count;
346          scf_band_grp += pstr_psy_chan_out->sfb_per_group) {
347       FLOAT32 *ptr_thr_exp1 = &ptr_thr_exp[scf_band_grp];
348       ptr_scf_band_thr = &pstr_psy_chan_out->ptr_sfb_thr[scf_band_grp];
349       for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) {
350         ptr_thr_exp1[sfb] = (FLOAT32)pow(*ptr_scf_band_thr++, RED_EXP_VAL);
351       }
352     }
353   }
354 }
355 
iaace_adapt_min_snr(ixheaace_psy_out_channel ** pstr_psy_out,ia_min_snr_adapt_param_struct * pstr_min_snr_params,WORD32 num_chans,WORD32 chn)356 static VOID iaace_adapt_min_snr(ixheaace_psy_out_channel **pstr_psy_out,
357                                 ia_min_snr_adapt_param_struct *pstr_min_snr_params,
358                                 WORD32 num_chans, WORD32 chn) {
359   WORD32 num_scf_band = 0, ch, scf_band_cnt, scf_band_offs, sfb;
360   FLOAT32 avg_energy = 0.0f, db_ratio, min_snr_red;
361   WORD32 i;
362 
363   for (ch = chn; ch < chn + num_chans; ch++) {
364     ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch];
365     num_scf_band = 0;
366     avg_energy = 0;
367     scf_band_cnt = pstr_psy_chan_out->max_sfb_per_grp;
368 
369     for (scf_band_offs = 0; scf_band_offs < pstr_psy_chan_out->sfb_count;
370          scf_band_offs += pstr_psy_chan_out->sfb_per_group) {
371       FLOAT32 *ptr_sfb_energy = &pstr_psy_chan_out->ptr_sfb_energy[scf_band_offs];
372       for (sfb = scf_band_cnt - 1; sfb >= 0; sfb--) {
373         avg_energy += ptr_sfb_energy[sfb];
374       }
375       num_scf_band += scf_band_cnt;
376     }
377 
378     if (num_scf_band > 0) {
379       avg_energy /= num_scf_band;
380     }
381 
382     for (scf_band_offs = 0; scf_band_offs < pstr_psy_chan_out->sfb_count;
383          scf_band_offs += pstr_psy_chan_out->sfb_per_group) {
384       i = scf_band_offs;
385       for (sfb = scf_band_cnt - 1; sfb >= 0; sfb--, i++) {
386         if (pstr_min_snr_params->start_ratio * pstr_psy_chan_out->ptr_sfb_energy[i] <
387             avg_energy) {
388           db_ratio =
389               (FLOAT32)(10.0f * log10((MIN_FLT_VAL + avg_energy) /
390                                       (MIN_FLT_VAL + pstr_psy_chan_out->ptr_sfb_energy[i])));
391           min_snr_red =
392               pstr_min_snr_params->red_offs + pstr_min_snr_params->red_ratio_fac * db_ratio;
393           min_snr_red = MAX(min_snr_red, pstr_min_snr_params->max_red);
394           pstr_psy_chan_out->sfb_min_snr[i] =
395               (FLOAT32)pow(pstr_psy_out[ch]->sfb_min_snr[i], min_snr_red);
396           pstr_psy_chan_out->sfb_min_snr[i] =
397               MIN(MIN_SNR_LIMIT, pstr_psy_out[ch]->sfb_min_snr[i]);
398         }
399       }
400     }
401   }
402 }
403 
iaace_init_avoid_hole_flag(WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],ixheaace_psy_out_channel ** pstr_psy_out,ia_ah_param_struct * pstr_ah_param,WORD32 num_chans,WORD32 chn,WORD32 aot)404 static VOID iaace_init_avoid_hole_flag(
405     WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],
406     ixheaace_psy_out_channel **pstr_psy_out, ia_ah_param_struct *pstr_ah_param, WORD32 num_chans,
407     WORD32 chn, WORD32 aot) {
408   WORD32 ch;
409   FLOAT32 sfb_energy;
410   FLOAT32 scale_spread_energy = 0.0f;
411   WORD32 scf_band_grp, scf_band_cnt, scf_band;
412   FLOAT32 *ptr_scf_band_spread_energy, *ptr_scf_band_energy, *ptr_scf_band_min_snr;
413   for (ch = chn; ch < chn + num_chans; ch++) {
414     ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch];
415 
416     if (pstr_psy_chan_out->window_sequence != SHORT_WINDOW) {
417       switch (aot) {
418         case AOT_AAC_LC:
419         case AOT_SBR:
420         case AOT_PS:
421           scale_spread_energy = 0.5f;
422           break;
423 
424         case AOT_AAC_LD:
425         case AOT_AAC_ELD:
426           scale_spread_energy = 0.56f;
427           break;
428       }
429     } else {
430       scale_spread_energy = 0.63f;
431     }
432 
433     for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count;
434          scf_band_grp += pstr_psy_chan_out->sfb_per_group) {
435       ptr_scf_band_spread_energy = &pstr_psy_chan_out->ptr_sfb_spread_energy[scf_band_grp];
436       scf_band_cnt = pstr_psy_chan_out->max_sfb_per_grp;
437       for (scf_band = scf_band_cnt - 1; scf_band >= 0; scf_band--) {
438         *ptr_scf_band_spread_energy = *ptr_scf_band_spread_energy * scale_spread_energy;
439         ptr_scf_band_spread_energy++;
440       }
441     }
442   }
443 
444   if (pstr_ah_param->modify_min_snr) {
445     for (ch = chn; ch < chn + num_chans; ch++) {
446       ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch];
447       ptr_scf_band_energy = pstr_psy_chan_out->ptr_sfb_energy;
448 
449       ptr_scf_band_min_snr = pstr_psy_chan_out->sfb_min_snr;
450 
451       for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count;
452            scf_band_grp += pstr_psy_chan_out->sfb_per_group) {
453         for (scf_band = 0; scf_band < pstr_psy_chan_out->max_sfb_per_grp; scf_band++) {
454           FLOAT32 sfb_en_m1, sfb_en_p1, avg_energy;
455           if (scf_band > 0) {
456             sfb_en_m1 = ptr_scf_band_energy[scf_band_grp + scf_band - 1];
457           } else {
458             sfb_en_m1 = ptr_scf_band_energy[scf_band_grp];
459           }
460           if (scf_band < pstr_psy_chan_out->max_sfb_per_grp - 1) {
461             sfb_en_p1 = ptr_scf_band_energy[scf_band_grp + scf_band + 1];
462           } else {
463             sfb_en_p1 = ptr_scf_band_energy[scf_band_grp + scf_band];
464           }
465 
466           avg_energy = (sfb_en_m1 + sfb_en_p1) / (FLOAT32)2.0f;
467           sfb_energy = ptr_scf_band_energy[scf_band_grp + scf_band];
468           FLOAT32 temp_min_snr = 0.0f;
469           if (sfb_energy > avg_energy) {
470             switch (aot) {
471               case AOT_AAC_LC:
472               case AOT_SBR:
473               case AOT_PS:
474                 temp_min_snr = MAX((FLOAT32)0.8f * avg_energy / sfb_energy, (FLOAT32)0.316f);
475                 break;
476 
477               case AOT_AAC_LD:
478               case AOT_AAC_ELD:
479                 temp_min_snr = MAX((FLOAT32)0.8f * avg_energy / sfb_energy, (FLOAT32)0.408f);
480                 break;
481             }
482             if (pstr_psy_chan_out->window_sequence != SHORT_WINDOW) {
483               switch (aot) {
484                 case AOT_AAC_LC:
485                 case AOT_PS:
486                   temp_min_snr = MAX(temp_min_snr, (FLOAT32)0.316f);
487                   break;
488 
489                 case AOT_AAC_LD:
490                   temp_min_snr = MAX(temp_min_snr, (FLOAT32)0.408f);
491                   break;
492               }
493             } else {
494               temp_min_snr = MAX(temp_min_snr, (FLOAT32)0.5f);
495             }
496             ptr_scf_band_min_snr[scf_band_grp + scf_band] =
497                 MIN(ptr_scf_band_min_snr[scf_band_grp + scf_band], temp_min_snr);
498           }
499 
500           if (((FLOAT32)2.0f * sfb_energy < avg_energy) && (sfb_energy > (FLOAT32)0.0f)) {
501             temp_min_snr = avg_energy / ((FLOAT32)2.0f * sfb_energy) *
502                            ptr_scf_band_min_snr[scf_band_grp + scf_band];
503             temp_min_snr = MIN((FLOAT32)0.8f, temp_min_snr);
504             ptr_scf_band_min_snr[scf_band_grp + scf_band] =
505                 MIN(temp_min_snr, ptr_scf_band_min_snr[scf_band_grp + scf_band] * (FLOAT32)3.16f);
506           }
507         }
508       }
509     }
510   }
511 
512   if (num_chans == 2) {
513     ixheaace_psy_out_channel *pstr_psy_out_mid = pstr_psy_out[chn];
514     ixheaace_psy_out_channel *pstr_psy_out_side = pstr_psy_out[chn + 1];
515     WORD32 sfb;
516 
517     for (sfb = 0; sfb < pstr_psy_out_mid->sfb_count; sfb++) {
518       if (pstr_psy_out[chn]->ms_used[sfb]) {
519         FLOAT32 sfb_en_mid = pstr_psy_out_mid->ptr_sfb_energy[sfb];
520         FLOAT32 sfb_en_side = pstr_psy_out_side->ptr_sfb_energy[sfb];
521         FLOAT32 max_sfb_en = MAX(sfb_en_mid, sfb_en_side);
522         FLOAT32 max_thr = 0.25f * pstr_psy_out_mid->sfb_min_snr[sfb] * max_sfb_en;
523 
524         pstr_psy_out_mid->sfb_min_snr[sfb] = (FLOAT32)MAX(
525             pstr_psy_out_mid->sfb_min_snr[sfb],
526             MIN(MAX_FLT_VAL, ((FLOAT32)max_thr / (MIN_FLT_VAL + (FLOAT32)sfb_en_mid))));
527 
528         if (pstr_psy_out_mid->ptr_sfb_energy[sfb] <= 1.0f) {
529           pstr_psy_out_mid->ptr_sfb_energy[sfb] =
530               MIN(pstr_psy_out_mid->ptr_sfb_energy[sfb], 0.8f);
531         }
532 
533         pstr_psy_out_side->sfb_min_snr[sfb] = (FLOAT32)MAX(
534             pstr_psy_out_side->sfb_min_snr[sfb],
535             MIN(MAX_FLT_VAL, ((FLOAT32)max_thr / (MIN_FLT_VAL + (FLOAT32)sfb_en_side))));
536 
537         if (pstr_psy_out_side->sfb_min_snr[sfb] <= 1.0f) {
538           pstr_psy_out_side->sfb_min_snr[sfb] = MIN(pstr_psy_out_side->sfb_min_snr[sfb], 0.8f);
539         }
540       }
541     }
542   }
543 
544   for (ch = chn; ch < chn + num_chans; ch++) {
545     ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch];
546     for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count;
547          scf_band_grp += pstr_psy_chan_out->sfb_per_group) {
548       for (scf_band = 0; scf_band < pstr_psy_chan_out->max_sfb_per_grp; scf_band++) {
549         if (pstr_psy_chan_out->ptr_sfb_spread_energy[scf_band_grp + scf_band] >
550                 pstr_psy_chan_out->ptr_sfb_energy[scf_band_grp + scf_band] ||
551             pstr_psy_chan_out->sfb_min_snr[scf_band_grp + scf_band] > 1.0f) {
552           ah_flag[ch][scf_band_grp + scf_band] = NO_AH;
553         } else {
554           ah_flag[ch][scf_band_grp + scf_band] = AH_INACTIVE;
555         }
556       }
557 
558       for (scf_band = pstr_psy_chan_out->max_sfb_per_grp;
559            scf_band < pstr_psy_chan_out->sfb_per_group; scf_band++) {
560         ah_flag[ch][scf_band_grp + scf_band] = NO_AH;
561       }
562     }
563   }
564 }
565 
iaace_reduce_thr(ixheaace_psy_out_channel ** pstr_psy_out,WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],FLOAT32 thr_exp[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],const FLOAT32 red_value,WORD32 num_channels,WORD32 chn)566 static VOID iaace_reduce_thr(
567     ixheaace_psy_out_channel **pstr_psy_out,
568     WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],
569     FLOAT32 thr_exp[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],
570     const FLOAT32 red_value, WORD32 num_channels, WORD32 chn) {
571   WORD32 ch, sfb_group, sfb;
572   FLOAT32 sfb_energy, sfb_threshold, sfb_thr_reduced;
573   FLOAT32 *ptr_sfb_energy_fix, *ptr_sfb_threshold_fix, *ptr_sfb_min_snr_fix, *ptr_thr_exp_fix;
574 
575   for (ch = chn; ch < chn + num_channels; ch++) {
576     ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch];
577     ptr_sfb_energy_fix = pstr_psy_chan_out->ptr_sfb_energy;
578     ptr_sfb_threshold_fix = pstr_psy_chan_out->ptr_sfb_thr;
579     ptr_sfb_min_snr_fix = pstr_psy_chan_out->sfb_min_snr;
580     ptr_thr_exp_fix = &thr_exp[ch][0];
581     for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count;
582          sfb_group += pstr_psy_chan_out->sfb_per_group) {
583       for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) {
584         sfb_energy = ptr_sfb_energy_fix[sfb_group + sfb];
585         sfb_threshold = ptr_sfb_threshold_fix[sfb_group + sfb];
586         if (sfb_energy > sfb_threshold) {
587           sfb_thr_reduced =
588               (FLOAT32)pow((ptr_thr_exp_fix[sfb_group + sfb] + red_value), INV_RED_EXP_VAL);
589 
590           if ((sfb_thr_reduced > ptr_sfb_min_snr_fix[sfb_group + sfb] * sfb_energy) &&
591               (ah_flag[ch][sfb_group + sfb] != NO_AH)) {
592             sfb_thr_reduced =
593                 MAX(ptr_sfb_min_snr_fix[sfb_group + sfb] * sfb_energy, sfb_threshold);
594             ah_flag[ch][sfb_group + sfb] = AH_ACTIVE;
595           }
596           ptr_sfb_threshold_fix[sfb_group + sfb] = sfb_thr_reduced;
597         }
598       }
599     }
600   }
601 }
602 
iaace_calc_pe_no_active_holes(FLOAT32 * ptr_pe,FLOAT32 * ptr_const_part,FLOAT32 * ptr_num_active_lines,ia_qc_pe_data_struct * pstr_qs_pe_data,WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],ixheaace_psy_out_channel ** pstr_psy_out,WORD32 num_channels,WORD32 chn)603 static VOID iaace_calc_pe_no_active_holes(
604     FLOAT32 *ptr_pe, FLOAT32 *ptr_const_part, FLOAT32 *ptr_num_active_lines,
605     ia_qc_pe_data_struct *pstr_qs_pe_data,
606     WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],
607     ixheaace_psy_out_channel **pstr_psy_out, WORD32 num_channels, WORD32 chn) {
608   WORD32 ch, sfb_group, sfb;
609   *ptr_pe = 0.0f;
610   *ptr_const_part = 0.0f;
611   *ptr_num_active_lines = 0;
612 
613   for (ch = chn; ch < chn + num_channels; ch++) {
614     ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch];
615     ia_qc_pe_chan_data_struct *ptr_pe_chan_data = &pstr_qs_pe_data->pe_ch_data[ch];
616 
617     for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count;
618          sfb_group += pstr_psy_chan_out->sfb_per_group) {
619       for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) {
620         if (ah_flag[ch][sfb_group + sfb] < AH_ACTIVE) {
621           *ptr_pe += ptr_pe_chan_data->sfb_pe[sfb_group + sfb];
622           *ptr_const_part += ptr_pe_chan_data->sfb_const_part[sfb_group + sfb];
623           *ptr_num_active_lines += ptr_pe_chan_data->num_sfb_active_lines[sfb_group + sfb];
624         }
625       }
626     }
627   }
628 }
629 
iaace_correct_thr(ixheaace_psy_out_channel ** pstr_psy_out,WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],ia_qc_pe_data_struct * pstr_qs_pe_data,FLOAT32 thr_exp[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],const FLOAT32 red_value,const FLOAT32 delta_pe,WORD32 num_channels,WORD32 chn)630 static VOID iaace_correct_thr(
631     ixheaace_psy_out_channel **pstr_psy_out,
632     WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],
633     ia_qc_pe_data_struct *pstr_qs_pe_data,
634     FLOAT32 thr_exp[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],
635     const FLOAT32 red_value, const FLOAT32 delta_pe, WORD32 num_channels, WORD32 chn) {
636   WORD32 i, ch, sfb_group, sfb;
637   FLOAT32 delta_sfb_pe;
638   FLOAT32 thr_factor;
639   FLOAT32 sfb_pe_factors[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],
640       norm_factor[IXHEAACE_MAX_CH_IN_BS_ELE] = {MIN_FLT_VAL};
641   FLOAT32 sfb_en, sfb_thr, sfb_thr_reduced;
642   FLOAT32 *ptr_thr_exp;
643   FLOAT32 *ptr_sfb_energy, *ptr_sfb_thr, *ptr_sfb_min_snr;
644   ixheaace_psy_out_channel *pstr_psy_chan_out = NULL;
645   ia_qc_pe_chan_data_struct *pstr_pe_chan_data = NULL;
646 
647   for (ch = chn; ch < chn + num_channels; ch++) {
648     pstr_psy_chan_out = pstr_psy_out[ch];
649     pstr_pe_chan_data = &pstr_qs_pe_data->pe_ch_data[ch];
650     norm_factor[ch] = MIN_FLT_VAL;
651     ptr_thr_exp = thr_exp[ch];
652 
653     for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count;
654          sfb_group += pstr_psy_chan_out->sfb_per_group) {
655       for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) {
656         if ((ah_flag[ch][sfb_group + sfb] < AH_ACTIVE) || (delta_pe > 0)) {
657           sfb_pe_factors[ch][sfb_group + sfb] =
658               pstr_pe_chan_data->num_sfb_active_lines[sfb_group + sfb] /
659               (ptr_thr_exp[sfb_group + sfb] + red_value);
660           norm_factor[ch] += sfb_pe_factors[ch][sfb_group + sfb];
661         } else {
662           sfb_pe_factors[ch][sfb_group + sfb] = 0.0f;
663         }
664       }
665     }
666   }
667   if (num_channels > 1) {
668     norm_factor[chn] = norm_factor[chn] + norm_factor[chn + 1];
669   }
670   norm_factor[chn] = 1.0f / norm_factor[chn];
671 
672   for (ch = chn; ch < chn + num_channels; ch++) {
673     pstr_psy_chan_out = pstr_psy_out[ch];
674     pstr_pe_chan_data = &pstr_qs_pe_data->pe_ch_data[ch];
675     ptr_sfb_energy = pstr_psy_chan_out->ptr_sfb_energy;
676     ptr_sfb_thr = pstr_psy_chan_out->ptr_sfb_thr;
677     ptr_sfb_min_snr = pstr_psy_chan_out->sfb_min_snr;
678 
679     for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count;
680          sfb_group += pstr_psy_chan_out->sfb_per_group) {
681       i = sfb_group;
682       for (sfb = pstr_psy_chan_out->max_sfb_per_grp - 1; sfb >= 0; sfb--, i++) {
683         delta_sfb_pe = sfb_pe_factors[ch][i] * norm_factor[chn] * delta_pe;
684         if (pstr_pe_chan_data->num_sfb_active_lines[i] > (FLOAT32)0.5f) {
685           sfb_en = ptr_sfb_energy[i];
686           sfb_thr = ptr_sfb_thr[i];
687           thr_factor = MIN(-delta_sfb_pe / pstr_pe_chan_data->num_sfb_active_lines[i], 20.f);
688           thr_factor = (FLOAT32)pow(2.0f, thr_factor);
689           sfb_thr_reduced = sfb_thr * thr_factor;
690 
691           if ((sfb_thr_reduced > ptr_sfb_min_snr[i] * sfb_en) &&
692               (ah_flag[ch][i] == AH_INACTIVE)) {
693             sfb_thr_reduced = MAX(ptr_sfb_min_snr[i] * sfb_en, sfb_thr);
694             ah_flag[ch][i] = AH_ACTIVE;
695           }
696           ptr_sfb_thr[i] = sfb_thr_reduced;
697         }
698       }
699     }
700   }
701 }
702 
iaace_reduce_min_snr(ixheaace_psy_out_channel ** pstr_psy_out,ia_qc_pe_data_struct * pstr_qs_pe_data,WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],const FLOAT32 desired_pe,WORD32 num_channels,WORD32 chn)703 static VOID iaace_reduce_min_snr(
704     ixheaace_psy_out_channel **pstr_psy_out, ia_qc_pe_data_struct *pstr_qs_pe_data,
705     WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],
706     const FLOAT32 desired_pe, WORD32 num_channels, WORD32 chn) {
707   WORD32 sfb, sfb_sub_win, ch;
708   FLOAT32 delta_pe;
709 
710   sfb_sub_win = pstr_psy_out[chn]->max_sfb_per_grp;
711 
712   while (pstr_qs_pe_data->pe > desired_pe && sfb_sub_win > 0) {
713     sfb_sub_win--;
714     for (sfb = sfb_sub_win; sfb < pstr_psy_out[chn]->sfb_count;
715          sfb += pstr_psy_out[chn]->sfb_per_group) {
716       for (ch = chn; ch < chn + num_channels; ch++) {
717         if (ah_flag[ch][sfb] != NO_AH && pstr_psy_out[ch]->sfb_min_snr[sfb] < MIN_SNR_LIMIT) {
718           pstr_psy_out[ch]->sfb_min_snr[sfb] = MIN_SNR_LIMIT;
719           pstr_psy_out[ch]->ptr_sfb_thr[sfb] =
720               pstr_psy_out[ch]->ptr_sfb_energy[sfb] * pstr_psy_out[ch]->sfb_min_snr[sfb];
721           delta_pe = pstr_qs_pe_data->pe_ch_data[ch].sfb_lines[sfb] * 1.5f -
722                      pstr_qs_pe_data->pe_ch_data[ch].sfb_pe[sfb];
723           pstr_qs_pe_data->pe += delta_pe;
724           pstr_qs_pe_data->pe_ch_data[ch].pe += delta_pe;
725         }
726       }
727       if (pstr_qs_pe_data->pe <= desired_pe) {
728         break;
729       }
730     }
731   }
732 }
733 
iaace_allow_more_holes(ixheaace_psy_out_channel ** pstr_psy_out,ia_qc_pe_data_struct * pstr_qs_pe_data,WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],const ia_ah_param_struct * pstr_str_ah_param,const FLOAT32 desired_pe,WORD32 num_channels,WORD32 chn)734 static VOID iaace_allow_more_holes(
735     ixheaace_psy_out_channel **pstr_psy_out, ia_qc_pe_data_struct *pstr_qs_pe_data,
736     WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],
737     const ia_ah_param_struct *pstr_str_ah_param, const FLOAT32 desired_pe, WORD32 num_channels,
738     WORD32 chn) {
739   WORD32 sfb, ch;
740   FLOAT32 act_pe = pstr_qs_pe_data->pe;
741 
742   if (num_channels == 2 &&
743       pstr_psy_out[chn]->window_sequence == pstr_psy_out[chn + 1]->window_sequence) {
744     ixheaace_psy_out_channel *pstr_psy_out_left = pstr_psy_out[chn];
745     ixheaace_psy_out_channel *pstr_psy_out_right = pstr_psy_out[chn + 1];
746 
747     for (sfb = 0; sfb < pstr_psy_out_left->sfb_count; sfb++) {
748       if (pstr_psy_out[chn]->ms_used[sfb]) {
749         if (ah_flag[chn + 1][sfb] != NO_AH &&
750             0.4f * pstr_psy_out_left->sfb_min_snr[sfb] * pstr_psy_out_left->ptr_sfb_energy[sfb] >
751                 pstr_psy_out_right->ptr_sfb_energy[sfb]) {
752           ah_flag[chn + 1][sfb] = NO_AH;
753 
754           pstr_psy_out_right->ptr_sfb_thr[sfb] = 2.0f * pstr_psy_out_right->ptr_sfb_energy[sfb];
755 
756           act_pe -= pstr_qs_pe_data->pe_ch_data[chn + 1].sfb_pe[sfb];
757         } else {
758           if (ah_flag[chn][sfb] != NO_AH && 0.4f * pstr_psy_out_right->sfb_min_snr[sfb] *
759                                                     pstr_psy_out_right->ptr_sfb_energy[sfb] >
760                                                 pstr_psy_out_left->ptr_sfb_energy[sfb]) {
761             ah_flag[chn][sfb] = NO_AH;
762 
763             pstr_psy_out_left->ptr_sfb_thr[sfb] = 2.0f * pstr_psy_out_left->ptr_sfb_energy[sfb];
764 
765             act_pe -= pstr_qs_pe_data->pe_ch_data[chn].sfb_pe[sfb];
766           }
767         }
768         if (act_pe < desired_pe) {
769           break;
770         }
771       }
772     }
773   }
774   if (act_pe > desired_pe) {
775     WORD32 start_sfb[IXHEAACE_MAX_CH_IN_BS_ELE] = {0};
776     FLOAT32 average_energy, min_energy;
777     WORD32 ah_cnt;
778     WORD32 en_idx;
779     FLOAT32 energy[4];
780     WORD32 min_sfb, max_sfb;
781     WORD32 done;
782 
783     for (ch = chn; ch < chn + num_channels; ch++) {
784       if (pstr_psy_out[ch]->window_sequence != SHORT_WINDOW) {
785         start_sfb[ch] = pstr_str_ah_param->start_sfb_long;
786       } else {
787         start_sfb[ch] = pstr_str_ah_param->start_sfb_short;
788       }
789     }
790 
791     average_energy = 0.0f;
792     min_energy = MAX_FLT_VAL;
793     ah_cnt = 0;
794     for (ch = chn; ch < chn + num_channels; ch++) {
795       ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch];
796       for (sfb = start_sfb[ch]; sfb < pstr_psy_chan_out->sfb_count; sfb++) {
797         if ((ah_flag[ch][sfb] != NO_AH) &&
798             (pstr_psy_chan_out->ptr_sfb_energy[sfb] > pstr_psy_chan_out->ptr_sfb_thr[sfb])) {
799           min_energy = MIN(min_energy, pstr_psy_chan_out->ptr_sfb_energy[sfb]);
800           average_energy += pstr_psy_chan_out->ptr_sfb_energy[sfb];
801           ah_cnt++;
802         }
803       }
804     }
805 
806     average_energy = MIN(MAX_FLT_VAL, average_energy / (ah_cnt + MIN_FLT_VAL));
807 
808     for (en_idx = 0; en_idx < 4; en_idx++) {
809       energy[en_idx] = min_energy * (FLOAT32)pow(average_energy / (min_energy + MIN_FLT_VAL),
810                                                  (2 * en_idx + 1) / 7.0f);
811     }
812     max_sfb = pstr_psy_out[chn]->sfb_count - 1;
813     min_sfb = start_sfb[chn];
814 
815     if (num_channels == 2) {
816       max_sfb = MAX(max_sfb, pstr_psy_out[chn + 1]->sfb_count - 1);
817 
818       min_sfb = MIN(min_sfb, start_sfb[chn + 1]);
819     }
820 
821     sfb = max_sfb;
822     en_idx = 0;
823     done = 0;
824     while (!done) {
825       for (ch = chn; ch < chn + num_channels; ch++) {
826         ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch];
827         if (sfb >= start_sfb[ch] && sfb < pstr_psy_chan_out->sfb_count) {
828           if (ah_flag[ch][sfb] != NO_AH &&
829               pstr_psy_chan_out->ptr_sfb_energy[sfb] < energy[en_idx]) {
830             ah_flag[ch][sfb] = NO_AH;
831             pstr_psy_chan_out->ptr_sfb_thr[sfb] = 2.0f * pstr_psy_chan_out->ptr_sfb_energy[sfb];
832             act_pe -= pstr_qs_pe_data->pe_ch_data[ch].sfb_pe[sfb];
833           }
834 
835           if (act_pe < desired_pe) {
836             done = 1;
837             break;
838           }
839         }
840       }
841       sfb--;
842       if (sfb < min_sfb) {
843         sfb = max_sfb;
844         en_idx++;
845         if (en_idx >= 4) {
846           done = 1;
847         }
848       }
849     }
850   }
851 }
852 
iaace_adapt_thr_to_pe(ixheaace_psy_out_channel ** pstr_psy_out,ia_qc_pe_data_struct * pstr_qs_pe_data,const FLOAT32 desired_pe,ia_ah_param_struct * pstr_ah_param,ia_min_snr_adapt_param_struct * pstr_msa_param,WORD32 num_channels,WORD32 chn,WORD32 aot)853 static VOID iaace_adapt_thr_to_pe(
854     ixheaace_psy_out_channel **pstr_psy_out,
855     ia_qc_pe_data_struct *pstr_qs_pe_data, const FLOAT32 desired_pe,
856     ia_ah_param_struct *pstr_ah_param, ia_min_snr_adapt_param_struct *pstr_msa_param,
857     WORD32 num_channels, WORD32 chn, WORD32 aot) {
858   FLOAT32 no_red_pe, red_pe, red_pe_no_ah;
859   FLOAT32 const_part, const_part_no_ah;
860   FLOAT32 num_active_lines, num_active_lines_no_ah;
861   FLOAT32 desired_pe_no_ah;
862   FLOAT32 redval = 0.0f;
863   WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND];
864   FLOAT32 thr_exp[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND];
865   WORD32 iteration;
866 
867   iaace_calc_thr_exp(thr_exp, pstr_psy_out, num_channels, chn);
868   iaace_adapt_min_snr(pstr_psy_out, pstr_msa_param, num_channels, chn);
869   iaace_init_avoid_hole_flag(ah_flag, pstr_psy_out, pstr_ah_param, num_channels, chn, aot);
870 
871   no_red_pe = pstr_qs_pe_data->pe;
872   const_part = pstr_qs_pe_data->const_part;
873   num_active_lines = pstr_qs_pe_data->num_active_lines;
874   if (num_active_lines > FLT_EPSILON) {
875     FLOAT32 avg_thr_exp =
876         (FLOAT32)pow(2.0f, (const_part - no_red_pe) / (INV_RED_EXP_VAL * num_active_lines));
877     redval = (FLOAT32)pow(2.0f, (const_part - desired_pe) / (INV_RED_EXP_VAL * num_active_lines))
878              - avg_thr_exp;
879     redval = MAX(0.0f, redval);
880     iaace_reduce_thr(pstr_psy_out, ah_flag, thr_exp, redval, num_channels, chn);
881   }
882 
883   iaace_calc_sfb_pe_data(pstr_qs_pe_data, pstr_psy_out, num_channels, chn);
884   red_pe = pstr_qs_pe_data->pe;
885 
886   iteration = 0;
887   do {
888     iaace_calc_pe_no_active_holes(&red_pe_no_ah, &const_part_no_ah, &num_active_lines_no_ah,
889                                   pstr_qs_pe_data, ah_flag, pstr_psy_out, num_channels, chn);
890 
891     desired_pe_no_ah = MAX(desired_pe - (red_pe - red_pe_no_ah), 0);
892 
893     if (num_active_lines_no_ah > FLT_EPSILON) {
894       FLOAT32 avg_thr_exp = (FLOAT32)pow(
895           2.0f, (const_part_no_ah - red_pe_no_ah) / (INV_RED_EXP_VAL * num_active_lines_no_ah));
896       redval += (FLOAT32)pow(2.0f, (const_part_no_ah - desired_pe_no_ah) /
897                                        (INV_RED_EXP_VAL * num_active_lines_no_ah)) -
898                 avg_thr_exp;
899       redval = MAX(0.0f, redval);
900       iaace_reduce_thr(pstr_psy_out, ah_flag, thr_exp, redval, num_channels, chn);
901     }
902 
903     iaace_calc_sfb_pe_data(pstr_qs_pe_data, pstr_psy_out, num_channels, chn);
904 
905     red_pe = pstr_qs_pe_data->pe;
906     iteration++;
907   } while ((fabs(red_pe - desired_pe) > (0.05f) * desired_pe) && (iteration < 2));
908 
909   if (red_pe < 1.15f * desired_pe) {
910     iaace_correct_thr(pstr_psy_out, ah_flag, pstr_qs_pe_data, thr_exp, redval,
911                       desired_pe - red_pe, num_channels, chn);
912   } else {
913     iaace_reduce_min_snr(pstr_psy_out, pstr_qs_pe_data, ah_flag, 1.05f * desired_pe, num_channels,
914                          chn);
915     iaace_allow_more_holes(pstr_psy_out, pstr_qs_pe_data, ah_flag, pstr_ah_param,
916                            1.05f * desired_pe, num_channels, chn);
917   }
918 }
919 
iaace_adjust_threshold(ia_adj_thr_state_struct * pstr_adj_thr_state,ia_adj_thr_elem_struct * pstr_adj_thr_elem,ixheaace_psy_out_channel ** pstr_psy_out,FLOAT32 * ptr_ch_bit_dist,ixheaace_qc_out_element * pstr_qc_out_el,const WORD32 avg_bits,const WORD32 bitres_bits,const WORD32 max_bitres_bits,const WORD32 side_info_bits,FLOAT32 * max_bit_fac,FLOAT32 * ptr_sfb_n_relevant_lines,FLOAT32 * ptr_sfb_ld_energy,WORD32 num_channels,WORD32 chn,WORD32 aot,WORD8 * ptr_scratch)920 VOID iaace_adjust_threshold(ia_adj_thr_state_struct *pstr_adj_thr_state,
921                             ia_adj_thr_elem_struct *pstr_adj_thr_elem,
922                             ixheaace_psy_out_channel **pstr_psy_out,
923                             FLOAT32 *ptr_ch_bit_dist, ixheaace_qc_out_element *pstr_qc_out_el,
924                             const WORD32 avg_bits, const WORD32 bitres_bits,
925                             const WORD32 max_bitres_bits, const WORD32 side_info_bits,
926                             FLOAT32 *max_bit_fac, FLOAT32 *ptr_sfb_n_relevant_lines,
927                             FLOAT32 *ptr_sfb_ld_energy, WORD32 num_channels, WORD32 chn,
928                             WORD32 aot, WORD8 *ptr_scratch) {
929   FLOAT32 no_red_pe, granted_pe, granted_pe_corr;
930   WORD32 curr_win_sequence;
931   ia_qc_pe_data_struct *pstr_qc_pe_data = (ia_qc_pe_data_struct *)ptr_scratch;
932   FLOAT32 bit_factor;
933   WORD32 ch;
934 
935   for (ch = chn; ch < chn + num_channels; ch++) {
936     pstr_qc_pe_data->pe_ch_data[ch].sfb_lines =
937         ptr_sfb_n_relevant_lines + MAXIMUM_GROUPED_SCALE_FACTOR_BAND * ch;
938     pstr_qc_pe_data->pe_ch_data[ch].sfb_ld_energy =
939         ptr_sfb_ld_energy + MAXIMUM_GROUPED_SCALE_FACTOR_BAND * ch;
940   }
941   pstr_qc_pe_data->offset = pstr_adj_thr_elem->pe_offset;
942 
943   iaace_calc_sfb_pe_data(pstr_qc_pe_data, pstr_psy_out, num_channels, chn);
944 
945   no_red_pe = pstr_qc_pe_data->pe;
946 
947   curr_win_sequence = LONG_WINDOW;
948   if (num_channels == 2) {
949     if ((pstr_psy_out[chn]->window_sequence == SHORT_WINDOW) ||
950         (pstr_psy_out[chn + 1]->window_sequence == SHORT_WINDOW)) {
951       curr_win_sequence = SHORT_WINDOW;
952     }
953   } else {
954     curr_win_sequence = pstr_psy_out[chn]->window_sequence;
955   }
956 
957   bit_factor = iaace_bitres_calc_bitfac(
958       bitres_bits, max_bitres_bits, no_red_pe + 5.0f * side_info_bits, curr_win_sequence,
959       avg_bits, *max_bit_fac, pstr_adj_thr_state, pstr_adj_thr_elem);
960 
961   granted_pe = bit_factor * iaace_bits_to_pe((FLOAT32)avg_bits);
962 
963   iaace_calc_pe_correction(&(pstr_adj_thr_elem->pe_correction_fac), MIN(granted_pe, no_red_pe),
964                            pstr_adj_thr_elem->pe_last, pstr_adj_thr_elem->dyn_bits_last);
965 
966   granted_pe_corr = granted_pe * pstr_adj_thr_elem->pe_correction_fac;
967 
968   if (granted_pe_corr < no_red_pe) {
969     iaace_adapt_thr_to_pe(pstr_psy_out, pstr_qc_pe_data, granted_pe_corr,
970                           &pstr_adj_thr_elem->str_ah_param,
971                           &pstr_adj_thr_elem->str_min_snr_adapt_params, num_channels, chn, aot);
972   }
973 
974   for (ch = chn; ch < chn + num_channels; ch++) {
975     FLOAT32 tmp_var, temp1;
976     if (pstr_qc_pe_data->pe) {
977       tmp_var = 1.0f - num_channels * 0.2f;
978       temp1 = pstr_qc_pe_data->pe_ch_data[ch].pe / pstr_qc_pe_data->pe;
979       temp1 = temp1 * tmp_var;
980       ptr_ch_bit_dist[ch] = temp1 + 0.2f;
981       if (ptr_ch_bit_dist[ch] < 0.2f) {
982         ptr_ch_bit_dist[ch] = 0.2f;
983       }
984     } else {
985       ptr_ch_bit_dist[ch] = 0.2f;
986     }
987   }
988 
989   pstr_qc_out_el->pe = no_red_pe;
990   pstr_adj_thr_elem->pe_last = granted_pe;
991 }
992