Coverage Report

Created: 2025-12-08 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libxaac/encoder/ixheaace_adjust_threshold.c
Line
Count
Source
1
/******************************************************************************
2
 *                                                                            *
3
 * Copyright (C) 2023 The Android Open Source Project
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at:
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 *****************************************************************************
18
 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19
 */
20
21
#include <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
56
VOID iaace_adj_thr_init(ia_adj_thr_state_struct *pstr_adj_thr_state, const FLOAT32 mean_pe,
57
5.82k
                        WORD32 ch_bitrate, WORD32 aot) {
58
5.82k
  ia_adj_thr_elem_struct *pstr_adj_thr_ele = &pstr_adj_thr_state->str_adj_thr_ele;
59
5.82k
  ia_min_snr_adapt_param_struct *pstr_min_snr_params =
60
5.82k
      &pstr_adj_thr_ele->str_min_snr_adapt_params;
61
62
5.82k
  pstr_adj_thr_state->str_bitres_params_long.clip_save_low = CLIP_SAVE_LO_LONG;
63
5.82k
  pstr_adj_thr_state->str_bitres_params_long.clip_save_high = CLIP_SAVE_HI_LONG;
64
5.82k
  pstr_adj_thr_state->str_bitres_params_long.min_bit_save = MIN_BITS_SAVE_LONG;
65
5.82k
  pstr_adj_thr_state->str_bitres_params_long.max_bit_save = MAX_BITS_SAVE_LONG;
66
5.82k
  pstr_adj_thr_state->str_bitres_params_long.clip_spend_low = CLIP_SPEND_LO_LONG;
67
5.82k
  pstr_adj_thr_state->str_bitres_params_long.clip_spend_high = CLIP_SPEND_HI_LONG;
68
5.82k
  pstr_adj_thr_state->str_bitres_params_long.min_bits_spend = MIN_BITS_SPEND_LONG;
69
5.82k
  pstr_adj_thr_state->str_bitres_params_long.max_bits_spend = MAX_BITS_SPEND_LONG;
70
71
5.82k
  pstr_adj_thr_state->str_bitres_params_short.clip_save_low = CLIP_SAVE_LO_SHORT;
72
5.82k
  pstr_adj_thr_state->str_bitres_params_short.clip_save_high = CLIP_SAVE_HI_SHORT;
73
5.82k
  pstr_adj_thr_state->str_bitres_params_short.min_bit_save = MIN_BITS_SAVE_SHORT;
74
5.82k
  pstr_adj_thr_state->str_bitres_params_short.max_bit_save = MAX_BITS_SAVE_SHORT;
75
5.82k
  pstr_adj_thr_state->str_bitres_params_short.clip_spend_low = CLIP_SPEND_LO_SHORT;
76
5.82k
  pstr_adj_thr_state->str_bitres_params_short.clip_spend_high = CLIP_SPEND_HI_SHORT;
77
5.82k
  pstr_adj_thr_state->str_bitres_params_short.min_bits_spend = MIN_BITS_SPEND_SHORT;
78
5.82k
  pstr_adj_thr_state->str_bitres_params_short.max_bits_spend = MAX_BITS_SPEND_SHORT;
79
80
5.82k
  pstr_adj_thr_ele->pe_min = (FLOAT32)0.8f * mean_pe;
81
5.82k
  pstr_adj_thr_ele->pe_max = (FLOAT32)1.2f * mean_pe;
82
5.82k
  pstr_adj_thr_ele->pe_offset = 0.0f;
83
5.82k
  switch (aot) {
84
1.25k
    case AOT_AAC_LC:
85
3.37k
    case AOT_SBR:
86
3.68k
    case AOT_PS:
87
3.68k
      if (ch_bitrate < 32000) {
88
2.66k
        pstr_adj_thr_ele->pe_offset = MAX(
89
2.66k
            (FLOAT32)50.0f, (FLOAT32)(100.0f) - (FLOAT32)(100.0f / 32000) * (FLOAT32)ch_bitrate);
90
2.66k
      }
91
3.68k
      break;
92
93
573
    case AOT_AAC_LD:
94
2.13k
    case AOT_AAC_ELD:
95
96
2.13k
      if (ch_bitrate <= 32000) {
97
1.28k
        pstr_adj_thr_ele->pe_offset = MAX(
98
1.28k
            (FLOAT32)50.0f, (FLOAT32)(100.0f) - (FLOAT32)(100.0f / 32000) * (FLOAT32)ch_bitrate);
99
1.28k
      }
100
2.13k
      break;
101
5.82k
  }
102
103
5.82k
  if (ch_bitrate > 20000) {
104
2.92k
    pstr_adj_thr_ele->str_ah_param.modify_min_snr = TRUE;
105
2.92k
    pstr_adj_thr_ele->str_ah_param.start_sfb_long = 15;
106
2.92k
    pstr_adj_thr_ele->str_ah_param.start_sfb_short = 3;
107
2.92k
  } else {
108
2.89k
    pstr_adj_thr_ele->str_ah_param.modify_min_snr = FALSE;
109
2.89k
    pstr_adj_thr_ele->str_ah_param.start_sfb_long = 0;
110
2.89k
    pstr_adj_thr_ele->str_ah_param.start_sfb_short = 0;
111
2.89k
  }
112
113
5.82k
  pstr_min_snr_params->max_red = (FLOAT32)0.25f;
114
115
5.82k
  pstr_min_snr_params->start_ratio = (FLOAT32)1.e1f;
116
117
5.82k
  pstr_min_snr_params->max_ratio = (FLOAT32)1.e3f;
118
119
5.82k
  pstr_min_snr_params->red_ratio_fac =
120
5.82k
      (1.0f - pstr_min_snr_params->max_red) /
121
5.82k
      (10.0f * (FLOAT32)log10(pstr_min_snr_params->start_ratio / pstr_min_snr_params->max_ratio));
122
123
5.82k
  pstr_min_snr_params->red_offs = 1.0f - pstr_min_snr_params->red_ratio_fac * 10.0f *
124
5.82k
                                             (FLOAT32)log10(pstr_min_snr_params->start_ratio);
125
126
5.82k
  pstr_adj_thr_ele->pe_last = (FLOAT32)0.0f;
127
5.82k
  pstr_adj_thr_ele->dyn_bits_last = 0;
128
5.82k
  pstr_adj_thr_ele->pe_correction_fac = (FLOAT32)1.0f;
129
5.82k
}
130
779k
FLOAT32 iaace_bits_to_pe(const FLOAT32 bits) { return (bits * 1.18f); }
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
754k
                                   WORD32 chn) {
134
754k
  WORD32 ch;
135
754k
  WORD32 scf_band_grp;
136
754k
  FLOAT32 num_lines;
137
754k
  FLOAT32 ld_thr, ld_ratio;
138
754k
  WORD32 i = 0, scf;
139
754k
  WORD32 sfb_count;
140
754k
  WORD32 scf_band_per_grp;
141
754k
  WORD32 max_sfb_per_grp;
142
754k
  FLOAT32 *ptr_sfb_energy;
143
754k
  FLOAT32 *ptr_sfb_thr;
144
754k
  ia_qc_pe_chan_data_struct *pstr_qc_pe_chan_data;
145
146
754k
  pstr_qc_pe_data->pe = pstr_qc_pe_data->offset;
147
754k
  pstr_qc_pe_data->const_part = 0.0f;
148
754k
  pstr_qc_pe_data->num_active_lines = 0.0f;
149
150
1.83M
  for (ch = chn; ch < chn + num_channels; ch++) {
151
1.08M
    sfb_count = pstr_psy_out[ch]->sfb_count;
152
1.08M
    scf_band_per_grp = pstr_psy_out[ch]->sfb_per_group;
153
1.08M
    max_sfb_per_grp = pstr_psy_out[ch]->max_sfb_per_grp;
154
1.08M
    ptr_sfb_energy = pstr_psy_out[ch]->ptr_sfb_energy;
155
1.08M
    ptr_sfb_thr = pstr_psy_out[ch]->ptr_sfb_thr;
156
1.08M
    pstr_qc_pe_chan_data = &pstr_qc_pe_data->pe_ch_data[ch];
157
1.08M
    pstr_qc_pe_chan_data->pe = 0;
158
1.08M
    pstr_qc_pe_chan_data->num_active_lines = 0;
159
1.08M
    pstr_qc_pe_chan_data->const_part = 0;
160
161
2.80M
    for (scf_band_grp = 0; scf_band_grp < sfb_count; scf_band_grp += scf_band_per_grp) {
162
1.71M
      i = scf_band_grp;
163
33.7M
      for (scf = max_sfb_per_grp - 1; scf >= 0; scf--, i++) {
164
32.0M
        if (ptr_sfb_energy[i] > ptr_sfb_thr[i]) {
165
19.7M
          ld_thr = (FLOAT32)log(ptr_sfb_thr[i]) * LOG2_1;
166
19.7M
          ld_ratio = pstr_qc_pe_chan_data->sfb_ld_energy[i] - ld_thr;
167
19.7M
          num_lines = pstr_qc_pe_chan_data->sfb_lines[i];
168
19.7M
          if (ld_ratio >= PE_C1) {
169
11.2M
            pstr_qc_pe_chan_data->sfb_pe[i] = num_lines * ld_ratio;
170
11.2M
            pstr_qc_pe_chan_data->sfb_const_part[i] =
171
11.2M
                num_lines * pstr_qc_pe_chan_data->sfb_ld_energy[i];
172
11.2M
          } else {
173
8.49M
            pstr_qc_pe_chan_data->sfb_pe[i] = num_lines * (PE_C2 + PE_C3 * ld_ratio);
174
8.49M
            pstr_qc_pe_chan_data->sfb_const_part[i] =
175
8.49M
                num_lines * (PE_C2 + PE_C3 * pstr_qc_pe_chan_data->sfb_ld_energy[i]);
176
8.49M
            num_lines = num_lines * PE_C3;
177
8.49M
          }
178
19.7M
          pstr_qc_pe_chan_data->num_sfb_active_lines[i] = num_lines;
179
19.7M
        } else {
180
12.3M
          pstr_qc_pe_chan_data->sfb_pe[i] = 0.0f;
181
12.3M
          pstr_qc_pe_chan_data->sfb_const_part[i] = 0.0f;
182
12.3M
          pstr_qc_pe_chan_data->num_sfb_active_lines[i] = 0.0;
183
12.3M
        }
184
185
32.0M
        pstr_qc_pe_chan_data->pe += pstr_qc_pe_chan_data->sfb_pe[i];
186
32.0M
        pstr_qc_pe_chan_data->const_part += pstr_qc_pe_chan_data->sfb_const_part[i];
187
32.0M
        pstr_qc_pe_chan_data->num_active_lines += pstr_qc_pe_chan_data->num_sfb_active_lines[i];
188
32.0M
      }
189
1.71M
    }
190
1.08M
    pstr_qc_pe_data->pe += pstr_qc_pe_chan_data->pe;
191
1.08M
    pstr_qc_pe_data->const_part += pstr_qc_pe_chan_data->const_part;
192
1.08M
    pstr_qc_pe_data->num_active_lines += pstr_qc_pe_chan_data->num_active_lines;
193
1.08M
    pstr_psy_out[ch]->pe = pstr_qc_pe_data->pe;
194
1.08M
  }
195
754k
}
196
292k
static FLOAT32 iaace_calc_bit_save(ia_bitres_param_struct *pstr_bitres_params, FLOAT32 fill_lvl) {
197
292k
  FLOAT32 bit_save;
198
292k
  const FLOAT32 clip_low = pstr_bitres_params->clip_save_low;
199
292k
  const FLOAT32 clip_high = pstr_bitres_params->clip_save_high;
200
292k
  const FLOAT32 min_bit_save = pstr_bitres_params->min_bit_save;
201
292k
  const FLOAT32 max_bit_save = pstr_bitres_params->max_bit_save;
202
203
292k
  fill_lvl = MAX(fill_lvl, clip_low);
204
292k
  fill_lvl = MIN(fill_lvl, clip_high);
205
292k
  bit_save = max_bit_save -
206
292k
             ((max_bit_save - min_bit_save) / (clip_high - clip_low)) * (fill_lvl - clip_low);
207
208
292k
  return bit_save;
209
292k
}
210
211
static FLOAT32 iaace_calc_bit_spend(ia_bitres_param_struct *pstr_bitres_params,
212
292k
                                    FLOAT32 fill_lvl) {
213
292k
  FLOAT32 bit_spend;
214
292k
  const FLOAT32 clip_low = pstr_bitres_params->clip_spend_low;
215
292k
  const FLOAT32 clip_high = pstr_bitres_params->clip_spend_high;
216
292k
  const FLOAT32 min_bits_spend = pstr_bitres_params->min_bits_spend;
217
292k
  const FLOAT32 max_bits_spend = pstr_bitres_params->max_bits_spend;
218
219
292k
  fill_lvl = MAX(fill_lvl, clip_low);
220
292k
  fill_lvl = MIN(fill_lvl, clip_high);
221
292k
  bit_spend = min_bits_spend + ((max_bits_spend - min_bits_spend) / (clip_high - clip_low)) *
222
292k
                                   (fill_lvl - clip_low);
223
224
292k
  return bit_spend;
225
292k
}
226
227
static VOID iaace_adjust_pe_minmax(const FLOAT32 curr_pe, FLOAT32 *ptr_pe_min,
228
292k
                                   FLOAT32 *ptr_pe_max) {
229
292k
  FLOAT32 min_hi_fac = 0.3f, max_hi_fac = 1.0f, min_low_fac = 0.14f, max_low_fac = 0.07f;
230
292k
  FLOAT32 diff;
231
292k
  FLOAT32 min_diff = curr_pe * (FLOAT32)0.1666666667f;
232
233
292k
  if (curr_pe > *ptr_pe_max) {
234
20.2k
    diff = (curr_pe - *ptr_pe_max);
235
20.2k
    *ptr_pe_min += diff * min_hi_fac;
236
20.2k
    *ptr_pe_max += diff * max_hi_fac;
237
272k
  } else {
238
272k
    if (curr_pe < *ptr_pe_min) {
239
193k
      diff = (*ptr_pe_min - curr_pe);
240
193k
      *ptr_pe_min -= diff * min_low_fac;
241
193k
      *ptr_pe_max -= diff * max_low_fac;
242
193k
    } else {
243
78.3k
      *ptr_pe_min += (curr_pe - *ptr_pe_min) * min_hi_fac;
244
78.3k
      *ptr_pe_max -= (*ptr_pe_max - curr_pe) * max_low_fac;
245
78.3k
    }
246
272k
  }
247
248
292k
  if ((*ptr_pe_max - *ptr_pe_min) < min_diff) {
249
12.2k
    FLOAT32 low_part, high_part;
250
12.2k
    low_part = MAX((FLOAT32)0.0f, curr_pe - *ptr_pe_min);
251
12.2k
    high_part = MAX((FLOAT32)0.0f, *ptr_pe_max - curr_pe);
252
12.2k
    *ptr_pe_max = curr_pe + high_part / (low_part + high_part) * min_diff;
253
12.2k
    *ptr_pe_min = curr_pe - low_part / (low_part + high_part) * min_diff;
254
12.2k
    *ptr_pe_min = MAX((FLOAT32)0.0f, *ptr_pe_min);
255
12.2k
  }
256
292k
}
257
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
292k
                                        ia_adj_thr_elem_struct *pstr_adj_the_elem) {
263
292k
  ia_bitres_param_struct *pstr_bitres_params;
264
292k
  FLOAT32 pex;
265
292k
  FLOAT32 fill_lvl = 0.0f;
266
292k
  FLOAT32 bit_save, bit_spend, bitres_factor;
267
268
292k
  if (max_bitres_bits) {
269
230k
    fill_lvl = (FLOAT32)bitres_bits / max_bitres_bits;
270
230k
  }
271
272
292k
  if (win_seq != SHORT_WINDOW) {
273
240k
    pstr_bitres_params = &(pstr_adj_thr_state->str_bitres_params_long);
274
240k
  } else {
275
51.9k
    pstr_bitres_params = &(pstr_adj_thr_state->str_bitres_params_short);
276
51.9k
  }
277
278
292k
  pex = MAX(pe, pstr_adj_the_elem->pe_min);
279
292k
  pex = MIN(pex, pstr_adj_the_elem->pe_max);
280
281
292k
  bit_save = iaace_calc_bit_save(pstr_bitres_params, fill_lvl);
282
292k
  bit_spend = iaace_calc_bit_spend(pstr_bitres_params, fill_lvl);
283
284
292k
  bitres_factor =
285
292k
      (FLOAT32)1.0f - bit_save +
286
292k
      ((bit_spend + bit_save) / (pstr_adj_the_elem->pe_max - pstr_adj_the_elem->pe_min)) *
287
292k
          (pex - pstr_adj_the_elem->pe_min);
288
292k
  if (avg_bits)
289
292k
  {
290
292k
    bitres_factor = MIN(bitres_factor,
291
292k
      (FLOAT32)1.0f - (FLOAT32)0.3f + (FLOAT32)bitres_bits / (FLOAT32)avg_bits);
292
292k
  }
293
294
292k
  bitres_factor = MIN(bitres_factor, max_bit_fac);
295
296
292k
  iaace_adjust_pe_minmax(pe, &pstr_adj_the_elem->pe_min, &pstr_adj_the_elem->pe_max);
297
298
292k
  return bitres_factor;
299
292k
}
300
301
static VOID iaace_calc_pe_correction(FLOAT32 *ptr_correction_fac, const FLOAT32 pe_act,
302
292k
                                     const FLOAT32 pe_last, const WORD32 bits_prev) {
303
292k
  if ((bits_prev > 0) && (pe_act < (FLOAT32)1.5f * pe_last) &&
304
249k
      (pe_act > (FLOAT32)0.7f * pe_last) &&
305
185k
      ((FLOAT32)1.2f * iaace_bits_to_pe((FLOAT32)bits_prev) > pe_last) &&
306
156k
      ((FLOAT32)0.65f * iaace_bits_to_pe((FLOAT32)bits_prev) < pe_last)) {
307
145k
    FLOAT32 new_fac = pe_last / iaace_bits_to_pe((FLOAT32)bits_prev);
308
309
145k
    if (new_fac < (FLOAT32)1.0f) {
310
98.2k
      new_fac = MIN((FLOAT32)1.1f * new_fac, (FLOAT32)1.0f);
311
98.2k
      new_fac = MAX(new_fac, (FLOAT32)0.85f);
312
98.2k
    } else {
313
47.5k
      new_fac = MAX((FLOAT32)0.9f * new_fac, (FLOAT32)1.0f);
314
47.5k
      new_fac = MIN(new_fac, (FLOAT32)1.15f);
315
47.5k
    }
316
145k
    if (((new_fac > (FLOAT32)1.0f) && (*ptr_correction_fac < (FLOAT32)1.0f)) ||
317
144k
        ((new_fac < (FLOAT32)1.0f) && (*ptr_correction_fac > (FLOAT32)1.0f))) {
318
3.28k
      *ptr_correction_fac = (FLOAT32)1.0f;
319
3.28k
    }
320
321
145k
    if ((*ptr_correction_fac < (FLOAT32)1.0f && new_fac < *ptr_correction_fac) ||
322
111k
        (*ptr_correction_fac > (FLOAT32)1.0f && new_fac > *ptr_correction_fac)) {
323
38.7k
      *ptr_correction_fac = (FLOAT32)0.85f * (*ptr_correction_fac) + (FLOAT32)0.15f * new_fac;
324
107k
    } else {
325
107k
      *ptr_correction_fac = (FLOAT32)0.7f * (*ptr_correction_fac) + (FLOAT32)0.3f * new_fac;
326
107k
    }
327
328
145k
    *ptr_correction_fac = MIN(*ptr_correction_fac, (FLOAT32)1.15f);
329
145k
    *ptr_correction_fac = MAX(*ptr_correction_fac, (FLOAT32)0.85f);
330
146k
  } else {
331
146k
    *ptr_correction_fac = (FLOAT32)1.0f;
332
146k
  }
333
292k
}
334
335
static VOID iaace_calc_thr_exp(
336
    FLOAT32 thr_exp[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],
337
185k
    ixheaace_psy_out_channel **pstr_psy_out, WORD32 num_chans, WORD32 chn) {
338
185k
  WORD32 sfb, ch, scf_band_grp;
339
185k
  ixheaace_psy_out_channel *pstr_psy_chan_out;
340
185k
  FLOAT32 *ptr_scf_band_thr;
341
185k
  FLOAT32 *ptr_thr_exp;
342
455k
  for (ch = chn; ch < chn + num_chans; ch++) {
343
269k
    pstr_psy_chan_out = pstr_psy_out[ch];
344
269k
    ptr_thr_exp = thr_exp[ch];
345
711k
    for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count;
346
441k
         scf_band_grp += pstr_psy_chan_out->sfb_per_group) {
347
441k
      FLOAT32 *ptr_thr_exp1 = &ptr_thr_exp[scf_band_grp];
348
441k
      ptr_scf_band_thr = &pstr_psy_chan_out->ptr_sfb_thr[scf_band_grp];
349
8.66M
      for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) {
350
8.22M
        ptr_thr_exp1[sfb] = (FLOAT32)pow(*ptr_scf_band_thr++, RED_EXP_VAL);
351
8.22M
      }
352
441k
    }
353
269k
  }
354
185k
}
355
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
185k
                                WORD32 num_chans, WORD32 chn) {
359
185k
  WORD32 num_scf_band = 0, ch, scf_band_cnt, scf_band_offs, sfb;
360
185k
  FLOAT32 avg_energy = 0.0f, db_ratio, min_snr_red;
361
185k
  WORD32 i;
362
363
455k
  for (ch = chn; ch < chn + num_chans; ch++) {
364
269k
    ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch];
365
269k
    num_scf_band = 0;
366
269k
    avg_energy = 0;
367
269k
    scf_band_cnt = pstr_psy_chan_out->max_sfb_per_grp;
368
369
711k
    for (scf_band_offs = 0; scf_band_offs < pstr_psy_chan_out->sfb_count;
370
441k
         scf_band_offs += pstr_psy_chan_out->sfb_per_group) {
371
441k
      FLOAT32 *ptr_sfb_energy = &pstr_psy_chan_out->ptr_sfb_energy[scf_band_offs];
372
8.66M
      for (sfb = scf_band_cnt - 1; sfb >= 0; sfb--) {
373
8.22M
        avg_energy += ptr_sfb_energy[sfb];
374
8.22M
      }
375
441k
      num_scf_band += scf_band_cnt;
376
441k
    }
377
378
269k
    if (num_scf_band > 0) {
379
269k
      avg_energy /= num_scf_band;
380
269k
    }
381
382
711k
    for (scf_band_offs = 0; scf_band_offs < pstr_psy_chan_out->sfb_count;
383
441k
         scf_band_offs += pstr_psy_chan_out->sfb_per_group) {
384
441k
      i = scf_band_offs;
385
8.66M
      for (sfb = scf_band_cnt - 1; sfb >= 0; sfb--, i++) {
386
8.22M
        if (pstr_min_snr_params->start_ratio * pstr_psy_chan_out->ptr_sfb_energy[i] <
387
8.22M
            avg_energy) {
388
5.41M
          db_ratio =
389
5.41M
              (FLOAT32)(10.0f * log10((MIN_FLT_VAL + avg_energy) /
390
5.41M
                                      (MIN_FLT_VAL + pstr_psy_chan_out->ptr_sfb_energy[i])));
391
5.41M
          min_snr_red =
392
5.41M
              pstr_min_snr_params->red_offs + pstr_min_snr_params->red_ratio_fac * db_ratio;
393
5.41M
          min_snr_red = MAX(min_snr_red, pstr_min_snr_params->max_red);
394
5.41M
          pstr_psy_chan_out->sfb_min_snr[i] =
395
5.41M
              (FLOAT32)pow(pstr_psy_out[ch]->sfb_min_snr[i], min_snr_red);
396
5.41M
          pstr_psy_chan_out->sfb_min_snr[i] =
397
5.41M
              MIN(MIN_SNR_LIMIT, pstr_psy_out[ch]->sfb_min_snr[i]);
398
5.41M
        }
399
8.22M
      }
400
441k
    }
401
269k
  }
402
185k
}
403
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
185k
    WORD32 chn, WORD32 aot) {
408
185k
  WORD32 ch;
409
185k
  FLOAT32 sfb_energy;
410
185k
  FLOAT32 scale_spread_energy = 0.0f;
411
185k
  WORD32 scf_band_grp, scf_band_cnt, scf_band;
412
185k
  FLOAT32 *ptr_scf_band_spread_energy, *ptr_scf_band_energy, *ptr_scf_band_min_snr;
413
455k
  for (ch = chn; ch < chn + num_chans; ch++) {
414
269k
    ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch];
415
416
269k
    if (pstr_psy_chan_out->window_sequence != SHORT_WINDOW) {
417
209k
      switch (aot) {
418
43.0k
        case AOT_AAC_LC:
419
101k
        case AOT_SBR:
420
105k
        case AOT_PS:
421
105k
          scale_spread_energy = 0.5f;
422
105k
          break;
423
424
14.1k
        case AOT_AAC_LD:
425
104k
        case AOT_AAC_ELD:
426
104k
          scale_spread_energy = 0.56f;
427
104k
          break;
428
209k
      }
429
209k
    } else {
430
59.8k
      scale_spread_energy = 0.63f;
431
59.8k
    }
432
433
711k
    for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count;
434
441k
         scf_band_grp += pstr_psy_chan_out->sfb_per_group) {
435
441k
      ptr_scf_band_spread_energy = &pstr_psy_chan_out->ptr_sfb_spread_energy[scf_band_grp];
436
441k
      scf_band_cnt = pstr_psy_chan_out->max_sfb_per_grp;
437
8.66M
      for (scf_band = scf_band_cnt - 1; scf_band >= 0; scf_band--) {
438
8.22M
        *ptr_scf_band_spread_energy = *ptr_scf_band_spread_energy * scale_spread_energy;
439
8.22M
        ptr_scf_band_spread_energy++;
440
8.22M
      }
441
441k
    }
442
269k
  }
443
444
185k
  if (pstr_ah_param->modify_min_snr) {
445
181k
    for (ch = chn; ch < chn + num_chans; ch++) {
446
103k
      ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch];
447
103k
      ptr_scf_band_energy = pstr_psy_chan_out->ptr_sfb_energy;
448
449
103k
      ptr_scf_band_min_snr = pstr_psy_chan_out->sfb_min_snr;
450
451
246k
      for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count;
452
142k
           scf_band_grp += pstr_psy_chan_out->sfb_per_group) {
453
3.44M
        for (scf_band = 0; scf_band < pstr_psy_chan_out->max_sfb_per_grp; scf_band++) {
454
3.30M
          FLOAT32 sfb_en_m1, sfb_en_p1, avg_energy;
455
3.30M
          if (scf_band > 0) {
456
3.15M
            sfb_en_m1 = ptr_scf_band_energy[scf_band_grp + scf_band - 1];
457
3.15M
          } else {
458
142k
            sfb_en_m1 = ptr_scf_band_energy[scf_band_grp];
459
142k
          }
460
3.30M
          if (scf_band < pstr_psy_chan_out->max_sfb_per_grp - 1) {
461
3.15M
            sfb_en_p1 = ptr_scf_band_energy[scf_band_grp + scf_band + 1];
462
3.15M
          } else {
463
142k
            sfb_en_p1 = ptr_scf_band_energy[scf_band_grp + scf_band];
464
142k
          }
465
466
3.30M
          avg_energy = (sfb_en_m1 + sfb_en_p1) / (FLOAT32)2.0f;
467
3.30M
          sfb_energy = ptr_scf_band_energy[scf_band_grp + scf_band];
468
3.30M
          FLOAT32 temp_min_snr = 0.0f;
469
3.30M
          if (sfb_energy > avg_energy) {
470
1.15M
            switch (aot) {
471
165k
              case AOT_AAC_LC:
472
461k
              case AOT_SBR:
473
699k
              case AOT_PS:
474
699k
                temp_min_snr = MAX((FLOAT32)0.8f * avg_energy / sfb_energy, (FLOAT32)0.316f);
475
699k
                break;
476
477
25.6k
              case AOT_AAC_LD:
478
460k
              case AOT_AAC_ELD:
479
460k
                temp_min_snr = MAX((FLOAT32)0.8f * avg_energy / sfb_energy, (FLOAT32)0.408f);
480
460k
                break;
481
1.15M
            }
482
1.15M
            if (pstr_psy_chan_out->window_sequence != SHORT_WINDOW) {
483
892k
              switch (aot) {
484
147k
                case AOT_AAC_LC:
485
196k
                case AOT_PS:
486
196k
                  temp_min_snr = MAX(temp_min_snr, (FLOAT32)0.316f);
487
196k
                  break;
488
489
25.6k
                case AOT_AAC_LD:
490
25.6k
                  temp_min_snr = MAX(temp_min_snr, (FLOAT32)0.408f);
491
25.6k
                  break;
492
892k
              }
493
892k
            } else {
494
267k
              temp_min_snr = MAX(temp_min_snr, (FLOAT32)0.5f);
495
267k
            }
496
1.15M
            ptr_scf_band_min_snr[scf_band_grp + scf_band] =
497
1.15M
                MIN(ptr_scf_band_min_snr[scf_band_grp + scf_band], temp_min_snr);
498
1.15M
          }
499
500
3.30M
          if (((FLOAT32)2.0f * sfb_energy < avg_energy) && (sfb_energy > (FLOAT32)0.0f)) {
501
698k
            temp_min_snr = avg_energy / ((FLOAT32)2.0f * sfb_energy) *
502
698k
                           ptr_scf_band_min_snr[scf_band_grp + scf_band];
503
698k
            temp_min_snr = MIN((FLOAT32)0.8f, temp_min_snr);
504
698k
            ptr_scf_band_min_snr[scf_band_grp + scf_band] =
505
698k
                MIN(temp_min_snr, ptr_scf_band_min_snr[scf_band_grp + scf_band] * (FLOAT32)3.16f);
506
698k
          }
507
3.30M
        }
508
142k
      }
509
103k
    }
510
78.1k
  }
511
512
185k
  if (num_chans == 2) {
513
84.1k
    ixheaace_psy_out_channel *pstr_psy_out_mid = pstr_psy_out[chn];
514
84.1k
    ixheaace_psy_out_channel *pstr_psy_out_side = pstr_psy_out[chn + 1];
515
84.1k
    WORD32 sfb;
516
517
3.37M
    for (sfb = 0; sfb < pstr_psy_out_mid->sfb_count; sfb++) {
518
3.28M
      if (pstr_psy_out[chn]->ms_used[sfb]) {
519
2.74M
        FLOAT32 sfb_en_mid = pstr_psy_out_mid->ptr_sfb_energy[sfb];
520
2.74M
        FLOAT32 sfb_en_side = pstr_psy_out_side->ptr_sfb_energy[sfb];
521
2.74M
        FLOAT32 max_sfb_en = MAX(sfb_en_mid, sfb_en_side);
522
2.74M
        FLOAT32 max_thr = 0.25f * pstr_psy_out_mid->sfb_min_snr[sfb] * max_sfb_en;
523
524
2.74M
        pstr_psy_out_mid->sfb_min_snr[sfb] = (FLOAT32)MAX(
525
2.74M
            pstr_psy_out_mid->sfb_min_snr[sfb],
526
2.74M
            MIN(MAX_FLT_VAL, ((FLOAT32)max_thr / (MIN_FLT_VAL + (FLOAT32)sfb_en_mid))));
527
528
2.74M
        if (pstr_psy_out_mid->ptr_sfb_energy[sfb] <= 1.0f) {
529
551k
          pstr_psy_out_mid->ptr_sfb_energy[sfb] =
530
551k
              MIN(pstr_psy_out_mid->ptr_sfb_energy[sfb], 0.8f);
531
551k
        }
532
533
2.74M
        pstr_psy_out_side->sfb_min_snr[sfb] = (FLOAT32)MAX(
534
2.74M
            pstr_psy_out_side->sfb_min_snr[sfb],
535
2.74M
            MIN(MAX_FLT_VAL, ((FLOAT32)max_thr / (MIN_FLT_VAL + (FLOAT32)sfb_en_side))));
536
537
2.74M
        if (pstr_psy_out_side->sfb_min_snr[sfb] <= 1.0f) {
538
653k
          pstr_psy_out_side->sfb_min_snr[sfb] = MIN(pstr_psy_out_side->sfb_min_snr[sfb], 0.8f);
539
653k
        }
540
2.74M
      }
541
3.28M
    }
542
84.1k
  }
543
544
455k
  for (ch = chn; ch < chn + num_chans; ch++) {
545
269k
    ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch];
546
711k
    for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count;
547
441k
         scf_band_grp += pstr_psy_chan_out->sfb_per_group) {
548
8.66M
      for (scf_band = 0; scf_band < pstr_psy_chan_out->max_sfb_per_grp; scf_band++) {
549
8.22M
        if (pstr_psy_chan_out->ptr_sfb_spread_energy[scf_band_grp + scf_band] >
550
8.22M
                pstr_psy_chan_out->ptr_sfb_energy[scf_band_grp + scf_band] ||
551
5.24M
            pstr_psy_chan_out->sfb_min_snr[scf_band_grp + scf_band] > 1.0f) {
552
2.98M
          ah_flag[ch][scf_band_grp + scf_band] = NO_AH;
553
5.24M
        } else {
554
5.24M
          ah_flag[ch][scf_band_grp + scf_band] = AH_INACTIVE;
555
5.24M
        }
556
8.22M
      }
557
558
441k
      for (scf_band = pstr_psy_chan_out->max_sfb_per_grp;
559
2.79M
           scf_band < pstr_psy_chan_out->sfb_per_group; scf_band++) {
560
2.35M
        ah_flag[ch][scf_band_grp + scf_band] = NO_AH;
561
2.35M
      }
562
441k
    }
563
269k
  }
564
185k
}
565
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
460k
    const FLOAT32 red_value, WORD32 num_channels, WORD32 chn) {
571
460k
  WORD32 ch, sfb_group, sfb;
572
460k
  FLOAT32 sfb_energy, sfb_threshold, sfb_thr_reduced;
573
460k
  FLOAT32 *ptr_sfb_energy_fix, *ptr_sfb_threshold_fix, *ptr_sfb_min_snr_fix, *ptr_thr_exp_fix;
574
575
1.12M
  for (ch = chn; ch < chn + num_channels; ch++) {
576
659k
    ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch];
577
659k
    ptr_sfb_energy_fix = pstr_psy_chan_out->ptr_sfb_energy;
578
659k
    ptr_sfb_threshold_fix = pstr_psy_chan_out->ptr_sfb_thr;
579
659k
    ptr_sfb_min_snr_fix = pstr_psy_chan_out->sfb_min_snr;
580
659k
    ptr_thr_exp_fix = &thr_exp[ch][0];
581
1.71M
    for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count;
582
1.05M
         sfb_group += pstr_psy_chan_out->sfb_per_group) {
583
20.8M
      for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) {
584
19.8M
        sfb_energy = ptr_sfb_energy_fix[sfb_group + sfb];
585
19.8M
        sfb_threshold = ptr_sfb_threshold_fix[sfb_group + sfb];
586
19.8M
        if (sfb_energy > sfb_threshold) {
587
13.0M
          sfb_thr_reduced =
588
13.0M
              (FLOAT32)pow((ptr_thr_exp_fix[sfb_group + sfb] + red_value), INV_RED_EXP_VAL);
589
590
13.0M
          if ((sfb_thr_reduced > ptr_sfb_min_snr_fix[sfb_group + sfb] * sfb_energy) &&
591
5.82M
              (ah_flag[ch][sfb_group + sfb] != NO_AH)) {
592
5.41M
            sfb_thr_reduced =
593
5.41M
                MAX(ptr_sfb_min_snr_fix[sfb_group + sfb] * sfb_energy, sfb_threshold);
594
5.41M
            ah_flag[ch][sfb_group + sfb] = AH_ACTIVE;
595
5.41M
          }
596
13.0M
          ptr_sfb_threshold_fix[sfb_group + sfb] = sfb_thr_reduced;
597
13.0M
        }
598
19.8M
      }
599
1.05M
    }
600
659k
  }
601
460k
}
602
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
276k
    ixheaace_psy_out_channel **pstr_psy_out, WORD32 num_channels, WORD32 chn) {
608
276k
  WORD32 ch, sfb_group, sfb;
609
276k
  *ptr_pe = 0.0f;
610
276k
  *ptr_const_part = 0.0f;
611
276k
  *ptr_num_active_lines = 0;
612
613
669k
  for (ch = chn; ch < chn + num_channels; ch++) {
614
392k
    ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch];
615
392k
    ia_qc_pe_chan_data_struct *ptr_pe_chan_data = &pstr_qs_pe_data->pe_ch_data[ch];
616
617
1.00M
    for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count;
618
616k
         sfb_group += pstr_psy_chan_out->sfb_per_group) {
619
12.2M
      for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) {
620
11.6M
        if (ah_flag[ch][sfb_group + sfb] < AH_ACTIVE) {
621
8.66M
          *ptr_pe += ptr_pe_chan_data->sfb_pe[sfb_group + sfb];
622
8.66M
          *ptr_const_part += ptr_pe_chan_data->sfb_const_part[sfb_group + sfb];
623
8.66M
          *ptr_num_active_lines += ptr_pe_chan_data->num_sfb_active_lines[sfb_group + sfb];
624
8.66M
        }
625
11.6M
      }
626
616k
    }
627
392k
  }
628
276k
}
629
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
133k
    const FLOAT32 red_value, const FLOAT32 delta_pe, WORD32 num_channels, WORD32 chn) {
636
133k
  WORD32 i, ch, sfb_group, sfb;
637
133k
  FLOAT32 delta_sfb_pe;
638
133k
  FLOAT32 thr_factor;
639
133k
  FLOAT32 sfb_pe_factors[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],
640
133k
      norm_factor[IXHEAACE_MAX_CH_IN_BS_ELE] = {MIN_FLT_VAL};
641
133k
  FLOAT32 sfb_en, sfb_thr, sfb_thr_reduced;
642
133k
  FLOAT32 *ptr_thr_exp;
643
133k
  FLOAT32 *ptr_sfb_energy, *ptr_sfb_thr, *ptr_sfb_min_snr;
644
133k
  ixheaace_psy_out_channel *pstr_psy_chan_out = NULL;
645
133k
  ia_qc_pe_chan_data_struct *pstr_pe_chan_data = NULL;
646
647
335k
  for (ch = chn; ch < chn + num_channels; ch++) {
648
201k
    pstr_psy_chan_out = pstr_psy_out[ch];
649
201k
    pstr_pe_chan_data = &pstr_qs_pe_data->pe_ch_data[ch];
650
201k
    norm_factor[ch] = MIN_FLT_VAL;
651
201k
    ptr_thr_exp = thr_exp[ch];
652
653
567k
    for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count;
654
365k
         sfb_group += pstr_psy_chan_out->sfb_per_group) {
655
6.74M
      for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) {
656
6.37M
        if ((ah_flag[ch][sfb_group + sfb] < AH_ACTIVE) || (delta_pe > 0)) {
657
5.44M
          sfb_pe_factors[ch][sfb_group + sfb] =
658
5.44M
              pstr_pe_chan_data->num_sfb_active_lines[sfb_group + sfb] /
659
5.44M
              (ptr_thr_exp[sfb_group + sfb] + red_value);
660
5.44M
          norm_factor[ch] += sfb_pe_factors[ch][sfb_group + sfb];
661
5.44M
        } else {
662
930k
          sfb_pe_factors[ch][sfb_group + sfb] = 0.0f;
663
930k
        }
664
6.37M
      }
665
365k
    }
666
201k
  }
667
133k
  if (num_channels > 1) {
668
68.1k
    norm_factor[chn] = norm_factor[chn] + norm_factor[chn + 1];
669
68.1k
  }
670
133k
  norm_factor[chn] = 1.0f / norm_factor[chn];
671
672
335k
  for (ch = chn; ch < chn + num_channels; ch++) {
673
201k
    pstr_psy_chan_out = pstr_psy_out[ch];
674
201k
    pstr_pe_chan_data = &pstr_qs_pe_data->pe_ch_data[ch];
675
201k
    ptr_sfb_energy = pstr_psy_chan_out->ptr_sfb_energy;
676
201k
    ptr_sfb_thr = pstr_psy_chan_out->ptr_sfb_thr;
677
201k
    ptr_sfb_min_snr = pstr_psy_chan_out->sfb_min_snr;
678
679
567k
    for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count;
680
365k
         sfb_group += pstr_psy_chan_out->sfb_per_group) {
681
365k
      i = sfb_group;
682
6.74M
      for (sfb = pstr_psy_chan_out->max_sfb_per_grp - 1; sfb >= 0; sfb--, i++) {
683
6.37M
        delta_sfb_pe = sfb_pe_factors[ch][i] * norm_factor[chn] * delta_pe;
684
6.37M
        if (pstr_pe_chan_data->num_sfb_active_lines[i] > (FLOAT32)0.5f) {
685
3.63M
          sfb_en = ptr_sfb_energy[i];
686
3.63M
          sfb_thr = ptr_sfb_thr[i];
687
3.63M
          thr_factor = MIN(-delta_sfb_pe / pstr_pe_chan_data->num_sfb_active_lines[i], 20.f);
688
3.63M
          thr_factor = (FLOAT32)pow(2.0f, thr_factor);
689
3.63M
          sfb_thr_reduced = sfb_thr * thr_factor;
690
691
3.63M
          if ((sfb_thr_reduced > ptr_sfb_min_snr[i] * sfb_en) &&
692
103k
              (ah_flag[ch][i] == AH_INACTIVE)) {
693
42.3k
            sfb_thr_reduced = MAX(ptr_sfb_min_snr[i] * sfb_en, sfb_thr);
694
42.3k
            ah_flag[ch][i] = AH_ACTIVE;
695
42.3k
          }
696
3.63M
          ptr_sfb_thr[i] = sfb_thr_reduced;
697
3.63M
        }
698
6.37M
      }
699
365k
    }
700
201k
  }
701
133k
}
702
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
51.6k
    const FLOAT32 desired_pe, WORD32 num_channels, WORD32 chn) {
707
51.6k
  WORD32 sfb, sfb_sub_win, ch;
708
51.6k
  FLOAT32 delta_pe;
709
710
51.6k
  sfb_sub_win = pstr_psy_out[chn]->max_sfb_per_grp;
711
712
1.45M
  while (pstr_qs_pe_data->pe > desired_pe && sfb_sub_win > 0) {
713
1.40M
    sfb_sub_win--;
714
2.86M
    for (sfb = sfb_sub_win; sfb < pstr_psy_out[chn]->sfb_count;
715
1.45M
         sfb += pstr_psy_out[chn]->sfb_per_group) {
716
3.30M
      for (ch = chn; ch < chn + num_channels; ch++) {
717
1.84M
        if (ah_flag[ch][sfb] != NO_AH && pstr_psy_out[ch]->sfb_min_snr[sfb] < MIN_SNR_LIMIT) {
718
479k
          pstr_psy_out[ch]->sfb_min_snr[sfb] = MIN_SNR_LIMIT;
719
479k
          pstr_psy_out[ch]->ptr_sfb_thr[sfb] =
720
479k
              pstr_psy_out[ch]->ptr_sfb_energy[sfb] * pstr_psy_out[ch]->sfb_min_snr[sfb];
721
479k
          delta_pe = pstr_qs_pe_data->pe_ch_data[ch].sfb_lines[sfb] * 1.5f -
722
479k
                     pstr_qs_pe_data->pe_ch_data[ch].sfb_pe[sfb];
723
479k
          pstr_qs_pe_data->pe += delta_pe;
724
479k
          pstr_qs_pe_data->pe_ch_data[ch].pe += delta_pe;
725
479k
        }
726
1.84M
      }
727
1.45M
      if (pstr_qs_pe_data->pe <= desired_pe) {
728
3.13k
        break;
729
3.13k
      }
730
1.45M
    }
731
1.40M
  }
732
51.6k
}
733
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
51.6k
    WORD32 chn) {
739
51.6k
  WORD32 sfb, ch;
740
51.6k
  FLOAT32 act_pe = pstr_qs_pe_data->pe;
741
742
51.6k
  if (num_channels == 2 &&
743
15.9k
      pstr_psy_out[chn]->window_sequence == pstr_psy_out[chn + 1]->window_sequence) {
744
15.9k
    ixheaace_psy_out_channel *pstr_psy_out_left = pstr_psy_out[chn];
745
15.9k
    ixheaace_psy_out_channel *pstr_psy_out_right = pstr_psy_out[chn + 1];
746
747
563k
    for (sfb = 0; sfb < pstr_psy_out_left->sfb_count; sfb++) {
748
548k
      if (pstr_psy_out[chn]->ms_used[sfb]) {
749
389k
        if (ah_flag[chn + 1][sfb] != NO_AH &&
750
58.7k
            0.4f * pstr_psy_out_left->sfb_min_snr[sfb] * pstr_psy_out_left->ptr_sfb_energy[sfb] >
751
58.7k
                pstr_psy_out_right->ptr_sfb_energy[sfb]) {
752
6.11k
          ah_flag[chn + 1][sfb] = NO_AH;
753
754
6.11k
          pstr_psy_out_right->ptr_sfb_thr[sfb] = 2.0f * pstr_psy_out_right->ptr_sfb_energy[sfb];
755
756
6.11k
          act_pe -= pstr_qs_pe_data->pe_ch_data[chn + 1].sfb_pe[sfb];
757
382k
        } else {
758
382k
          if (ah_flag[chn][sfb] != NO_AH && 0.4f * pstr_psy_out_right->sfb_min_snr[sfb] *
759
270k
                                                    pstr_psy_out_right->ptr_sfb_energy[sfb] >
760
270k
                                                pstr_psy_out_left->ptr_sfb_energy[sfb]) {
761
2.33k
            ah_flag[chn][sfb] = NO_AH;
762
763
2.33k
            pstr_psy_out_left->ptr_sfb_thr[sfb] = 2.0f * pstr_psy_out_left->ptr_sfb_energy[sfb];
764
765
2.33k
            act_pe -= pstr_qs_pe_data->pe_ch_data[chn].sfb_pe[sfb];
766
2.33k
          }
767
382k
        }
768
389k
        if (act_pe < desired_pe) {
769
1.25k
          break;
770
1.25k
        }
771
389k
      }
772
548k
    }
773
15.9k
  }
774
51.6k
  if (act_pe > desired_pe) {
775
48.2k
    WORD32 start_sfb[IXHEAACE_MAX_CH_IN_BS_ELE] = {0};
776
48.2k
    FLOAT32 average_energy, min_energy;
777
48.2k
    WORD32 ah_cnt;
778
48.2k
    WORD32 en_idx;
779
48.2k
    FLOAT32 energy[4];
780
48.2k
    WORD32 min_sfb, max_sfb;
781
48.2k
    WORD32 done;
782
783
111k
    for (ch = chn; ch < chn + num_channels; ch++) {
784
62.9k
      if (pstr_psy_out[ch]->window_sequence != SHORT_WINDOW) {
785
60.2k
        start_sfb[ch] = pstr_str_ah_param->start_sfb_long;
786
60.2k
      } else {
787
2.66k
        start_sfb[ch] = pstr_str_ah_param->start_sfb_short;
788
2.66k
      }
789
62.9k
    }
790
791
48.2k
    average_energy = 0.0f;
792
48.2k
    min_energy = MAX_FLT_VAL;
793
48.2k
    ah_cnt = 0;
794
111k
    for (ch = chn; ch < chn + num_channels; ch++) {
795
62.9k
      ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch];
796
2.18M
      for (sfb = start_sfb[ch]; sfb < pstr_psy_chan_out->sfb_count; sfb++) {
797
2.12M
        if ((ah_flag[ch][sfb] != NO_AH) &&
798
1.10M
            (pstr_psy_chan_out->ptr_sfb_energy[sfb] > pstr_psy_chan_out->ptr_sfb_thr[sfb])) {
799
1.06M
          min_energy = MIN(min_energy, pstr_psy_chan_out->ptr_sfb_energy[sfb]);
800
1.06M
          average_energy += pstr_psy_chan_out->ptr_sfb_energy[sfb];
801
1.06M
          ah_cnt++;
802
1.06M
        }
803
2.12M
      }
804
62.9k
    }
805
806
48.2k
    average_energy = MIN(MAX_FLT_VAL, average_energy / (ah_cnt + MIN_FLT_VAL));
807
808
241k
    for (en_idx = 0; en_idx < 4; en_idx++) {
809
192k
      energy[en_idx] = min_energy * (FLOAT32)pow(average_energy / (min_energy + MIN_FLT_VAL),
810
192k
                                                 (2 * en_idx + 1) / 7.0f);
811
192k
    }
812
48.2k
    max_sfb = pstr_psy_out[chn]->sfb_count - 1;
813
48.2k
    min_sfb = start_sfb[chn];
814
815
48.2k
    if (num_channels == 2) {
816
14.7k
      max_sfb = MAX(max_sfb, pstr_psy_out[chn + 1]->sfb_count - 1);
817
818
14.7k
      min_sfb = MIN(min_sfb, start_sfb[chn + 1]);
819
14.7k
    }
820
821
48.2k
    sfb = max_sfb;
822
48.2k
    en_idx = 0;
823
48.2k
    done = 0;
824
2.25M
    while (!done) {
825
4.95M
      for (ch = chn; ch < chn + num_channels; ch++) {
826
2.78M
        ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch];
827
2.78M
        if (sfb >= start_sfb[ch] && sfb < pstr_psy_chan_out->sfb_count) {
828
2.78M
          if (ah_flag[ch][sfb] != NO_AH &&
829
1.13M
              pstr_psy_chan_out->ptr_sfb_energy[sfb] < energy[en_idx]) {
830
358k
            ah_flag[ch][sfb] = NO_AH;
831
358k
            pstr_psy_chan_out->ptr_sfb_thr[sfb] = 2.0f * pstr_psy_chan_out->ptr_sfb_energy[sfb];
832
358k
            act_pe -= pstr_qs_pe_data->pe_ch_data[ch].sfb_pe[sfb];
833
358k
          }
834
835
2.78M
          if (act_pe < desired_pe) {
836
40.2k
            done = 1;
837
40.2k
            break;
838
40.2k
          }
839
2.78M
        }
840
2.78M
      }
841
2.20M
      sfb--;
842
2.20M
      if (sfb < min_sfb) {
843
58.7k
        sfb = max_sfb;
844
58.7k
        en_idx++;
845
58.7k
        if (en_idx >= 4) {
846
8.09k
          done = 1;
847
8.09k
        }
848
58.7k
      }
849
2.20M
    }
850
48.2k
  }
851
51.6k
}
852
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
185k
    WORD32 num_channels, WORD32 chn, WORD32 aot) {
858
185k
  FLOAT32 no_red_pe, red_pe, red_pe_no_ah;
859
185k
  FLOAT32 const_part, const_part_no_ah;
860
185k
  FLOAT32 num_active_lines, num_active_lines_no_ah;
861
185k
  FLOAT32 desired_pe_no_ah;
862
185k
  FLOAT32 redval = 0.0f;
863
185k
  WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND];
864
185k
  FLOAT32 thr_exp[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND];
865
185k
  WORD32 iteration;
866
867
185k
  iaace_calc_thr_exp(thr_exp, pstr_psy_out, num_channels, chn);
868
185k
  iaace_adapt_min_snr(pstr_psy_out, pstr_msa_param, num_channels, chn);
869
185k
  iaace_init_avoid_hole_flag(ah_flag, pstr_psy_out, pstr_ah_param, num_channels, chn, aot);
870
871
185k
  no_red_pe = pstr_qs_pe_data->pe;
872
185k
  const_part = pstr_qs_pe_data->const_part;
873
185k
  num_active_lines = pstr_qs_pe_data->num_active_lines;
874
185k
  if (num_active_lines > FLT_EPSILON) {
875
185k
    FLOAT32 avg_thr_exp =
876
185k
        (FLOAT32)pow(2.0f, (const_part - no_red_pe) / (INV_RED_EXP_VAL * num_active_lines));
877
185k
    redval = (FLOAT32)pow(2.0f, (const_part - desired_pe) / (INV_RED_EXP_VAL * num_active_lines))
878
185k
             - avg_thr_exp;
879
185k
    redval = MAX(0.0f, redval);
880
185k
    iaace_reduce_thr(pstr_psy_out, ah_flag, thr_exp, redval, num_channels, chn);
881
185k
  }
882
883
185k
  iaace_calc_sfb_pe_data(pstr_qs_pe_data, pstr_psy_out, num_channels, chn);
884
185k
  red_pe = pstr_qs_pe_data->pe;
885
886
185k
  iteration = 0;
887
276k
  do {
888
276k
    iaace_calc_pe_no_active_holes(&red_pe_no_ah, &const_part_no_ah, &num_active_lines_no_ah,
889
276k
                                  pstr_qs_pe_data, ah_flag, pstr_psy_out, num_channels, chn);
890
891
276k
    desired_pe_no_ah = MAX(desired_pe - (red_pe - red_pe_no_ah), 0);
892
893
276k
    if (num_active_lines_no_ah > FLT_EPSILON) {
894
275k
      FLOAT32 avg_thr_exp = (FLOAT32)pow(
895
275k
          2.0f, (const_part_no_ah - red_pe_no_ah) / (INV_RED_EXP_VAL * num_active_lines_no_ah));
896
275k
      redval += (FLOAT32)pow(2.0f, (const_part_no_ah - desired_pe_no_ah) /
897
275k
                                       (INV_RED_EXP_VAL * num_active_lines_no_ah)) -
898
275k
                avg_thr_exp;
899
275k
      redval = MAX(0.0f, redval);
900
275k
      iaace_reduce_thr(pstr_psy_out, ah_flag, thr_exp, redval, num_channels, chn);
901
275k
    }
902
903
276k
    iaace_calc_sfb_pe_data(pstr_qs_pe_data, pstr_psy_out, num_channels, chn);
904
905
276k
    red_pe = pstr_qs_pe_data->pe;
906
276k
    iteration++;
907
276k
  } while ((fabs(red_pe - desired_pe) > (0.05f) * desired_pe) && (iteration < 2));
908
909
185k
  if (red_pe < 1.15f * desired_pe) {
910
133k
    iaace_correct_thr(pstr_psy_out, ah_flag, pstr_qs_pe_data, thr_exp, redval,
911
133k
                      desired_pe - red_pe, num_channels, chn);
912
133k
  } else {
913
51.6k
    iaace_reduce_min_snr(pstr_psy_out, pstr_qs_pe_data, ah_flag, 1.05f * desired_pe, num_channels,
914
51.6k
                         chn);
915
51.6k
    iaace_allow_more_holes(pstr_psy_out, pstr_qs_pe_data, ah_flag, pstr_ah_param,
916
51.6k
                           1.05f * desired_pe, num_channels, chn);
917
51.6k
  }
918
185k
}
919
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
292k
                            WORD32 aot, WORD8 *ptr_scratch) {
929
292k
  FLOAT32 no_red_pe, granted_pe, granted_pe_corr;
930
292k
  WORD32 curr_win_sequence;
931
292k
  ia_qc_pe_data_struct *pstr_qc_pe_data = (ia_qc_pe_data_struct *)ptr_scratch;
932
292k
  FLOAT32 bit_factor;
933
292k
  WORD32 ch;
934
935
715k
  for (ch = chn; ch < chn + num_channels; ch++) {
936
423k
    pstr_qc_pe_data->pe_ch_data[ch].sfb_lines =
937
423k
        ptr_sfb_n_relevant_lines + MAXIMUM_GROUPED_SCALE_FACTOR_BAND * ch;
938
423k
    pstr_qc_pe_data->pe_ch_data[ch].sfb_ld_energy =
939
423k
        ptr_sfb_ld_energy + MAXIMUM_GROUPED_SCALE_FACTOR_BAND * ch;
940
423k
  }
941
292k
  pstr_qc_pe_data->offset = pstr_adj_thr_elem->pe_offset;
942
943
292k
  iaace_calc_sfb_pe_data(pstr_qc_pe_data, pstr_psy_out, num_channels, chn);
944
945
292k
  no_red_pe = pstr_qc_pe_data->pe;
946
947
292k
  curr_win_sequence = LONG_WINDOW;
948
292k
  if (num_channels == 2) {
949
130k
    if ((pstr_psy_out[chn]->window_sequence == SHORT_WINDOW) ||
950
99.0k
        (pstr_psy_out[chn + 1]->window_sequence == SHORT_WINDOW)) {
951
31.6k
      curr_win_sequence = SHORT_WINDOW;
952
31.6k
    }
953
161k
  } else {
954
161k
    curr_win_sequence = pstr_psy_out[chn]->window_sequence;
955
161k
  }
956
957
292k
  bit_factor = iaace_bitres_calc_bitfac(
958
292k
      bitres_bits, max_bitres_bits, no_red_pe + 5.0f * side_info_bits, curr_win_sequence,
959
292k
      avg_bits, *max_bit_fac, pstr_adj_thr_state, pstr_adj_thr_elem);
960
961
292k
  granted_pe = bit_factor * iaace_bits_to_pe((FLOAT32)avg_bits);
962
963
292k
  iaace_calc_pe_correction(&(pstr_adj_thr_elem->pe_correction_fac), MIN(granted_pe, no_red_pe),
964
292k
                           pstr_adj_thr_elem->pe_last, pstr_adj_thr_elem->dyn_bits_last);
965
966
292k
  granted_pe_corr = granted_pe * pstr_adj_thr_elem->pe_correction_fac;
967
968
292k
  if (granted_pe_corr < no_red_pe) {
969
185k
    iaace_adapt_thr_to_pe(pstr_psy_out, pstr_qc_pe_data, granted_pe_corr,
970
185k
                          &pstr_adj_thr_elem->str_ah_param,
971
185k
                          &pstr_adj_thr_elem->str_min_snr_adapt_params, num_channels, chn, aot);
972
185k
  }
973
974
715k
  for (ch = chn; ch < chn + num_channels; ch++) {
975
423k
    FLOAT32 tmp_var, temp1;
976
423k
    if (pstr_qc_pe_data->pe) {
977
397k
      tmp_var = 1.0f - num_channels * 0.2f;
978
397k
      temp1 = pstr_qc_pe_data->pe_ch_data[ch].pe / pstr_qc_pe_data->pe;
979
397k
      temp1 = temp1 * tmp_var;
980
397k
      ptr_ch_bit_dist[ch] = temp1 + 0.2f;
981
397k
      if (ptr_ch_bit_dist[ch] < 0.2f) {
982
0
        ptr_ch_bit_dist[ch] = 0.2f;
983
0
      }
984
397k
    } else {
985
25.4k
      ptr_ch_bit_dist[ch] = 0.2f;
986
25.4k
    }
987
423k
  }
988
989
292k
  pstr_qc_out_el->pe = no_red_pe;
990
292k
  pstr_adj_thr_elem->pe_last = granted_pe;
991
292k
}