Coverage Report

Created: 2026-10-31 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libxaac/encoder/ixheaace_fd_qc_adjthr.c
Line
Count
Source
1
/******************************************************************************
2
 *                                                                            *
3
 * Copyright (C) 2023 The Android Open Source Project
4
 *
5
 * Licensed under the Apache License, Version 2.0 (the "License");
6
 * you may not use this file except in compliance with the License.
7
 * You may obtain a copy of the License at:
8
 *
9
 * http://www.apache.org/licenses/LICENSE-2.0
10
 *
11
 * Unless required by applicable law or agreed to in writing, software
12
 * distributed under the License is distributed on an "AS IS" BASIS,
13
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
 * See the License for the specific language governing permissions and
15
 * limitations under the License.
16
 *
17
 *****************************************************************************
18
 * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
19
 */
20
21
#include <string.h>
22
#include <math.h>
23
#include <stdlib.h>
24
#include <limits.h>
25
#include <float.h>
26
#include "iusace_type_def.h"
27
#include "ixheaac_error_standards.h"
28
#include "ixheaace_error_codes.h"
29
#include "ixheaace_psy_const.h"
30
#include "ixheaace_tns.h"
31
#include "ixheaace_tns_params.h"
32
#include "ixheaace_rom.h"
33
#include "iusace_block_switch_const.h"
34
#include "iusace_cnst.h"
35
#include "iusace_rom.h"
36
#include "ixheaace_mps_common_define.h"
37
#include "iusace_bitbuffer.h"
38
#include "impd_drc_common_enc.h"
39
#include "impd_drc_uni_drc.h"
40
#include "impd_drc_api.h"
41
#include "impd_drc_uni_drc_eq.h"
42
#include "impd_drc_uni_drc_filter_bank.h"
43
#include "impd_drc_gain_enc.h"
44
#include "impd_drc_struct_def.h"
45
46
#include "ixheaace_memory_standards.h"
47
#include "iusace_tns_usac.h"
48
#include "iusace_psy_mod.h"
49
#include "iusace_config.h"
50
#include "ixheaace_adjust_threshold_data.h"
51
#include "iusace_fd_qc_util.h"
52
#include "iusace_fd_qc_adjthr.h"
53
#include "ixheaace_aac_constants.h"
54
#include "ixheaace_sbr_def.h"
55
#include "ixheaace_constants.h"
56
#include "ixheaac_basic_ops32.h"
57
#include "ixheaac_basic_ops16.h"
58
59
561k
FLOAT32 iusace_bits_to_pe(const FLOAT32 bits) { return (bits * 1.18f); }
60
61
VOID iusace_adj_thr_init(ia_adj_thr_elem_struct *pstr_adj_thr_ele, const FLOAT32 mean_pe,
62
2.92k
                         WORD32 ch_bitrate) {
63
2.92k
  ia_min_snr_adapt_param_struct *pstr_min_snr_params =
64
2.92k
      &pstr_adj_thr_ele->str_min_snr_adapt_params;
65
66
2.92k
  pstr_adj_thr_ele->pe_min = (FLOAT32)0.8f * mean_pe;
67
2.92k
  pstr_adj_thr_ele->pe_max = (FLOAT32)1.2f * mean_pe;
68
2.92k
  pstr_adj_thr_ele->pe_offset = 0.0f;
69
70
2.92k
  if (ch_bitrate < 32000) {
71
63
    pstr_adj_thr_ele->pe_offset =
72
63
        MAX((FLOAT32)50.0f, (FLOAT32)(100.0f) - (FLOAT32)(100.0f / 32000) * (FLOAT32)ch_bitrate);
73
63
  }
74
75
2.92k
  if (ch_bitrate > 20000) {
76
2.90k
    pstr_adj_thr_ele->str_ah_param.modify_min_snr = TRUE;
77
2.90k
    pstr_adj_thr_ele->str_ah_param.start_sfb_long = 15;
78
2.90k
    pstr_adj_thr_ele->str_ah_param.start_sfb_short = 3;
79
2.90k
  } else {
80
28
    pstr_adj_thr_ele->str_ah_param.modify_min_snr = FALSE;
81
28
    pstr_adj_thr_ele->str_ah_param.start_sfb_long = 0;
82
28
    pstr_adj_thr_ele->str_ah_param.start_sfb_short = 0;
83
28
  }
84
85
2.92k
  pstr_min_snr_params->max_red = (FLOAT32)0.25f;
86
87
2.92k
  pstr_min_snr_params->start_ratio = (FLOAT32)10.0f;
88
89
2.92k
  pstr_min_snr_params->max_ratio = (FLOAT32)1000.0f;
90
91
2.92k
  pstr_min_snr_params->red_ratio_fac =
92
2.92k
      (1.0f - pstr_min_snr_params->max_red) /
93
2.92k
      (10.0f * (FLOAT32)log10(pstr_min_snr_params->start_ratio / pstr_min_snr_params->max_ratio));
94
95
2.92k
  pstr_min_snr_params->red_offs = 1.0f - pstr_min_snr_params->red_ratio_fac * 10.0f *
96
2.92k
                                             (FLOAT32)log10(pstr_min_snr_params->start_ratio);
97
98
2.92k
  pstr_adj_thr_ele->pe_last = (FLOAT32)0.0f;
99
2.92k
  pstr_adj_thr_ele->dyn_bits_last = 0;
100
2.92k
  pstr_adj_thr_ele->pe_correction_fac = (FLOAT32)1.0f;
101
2.92k
}
102
103
static VOID iusace_calc_sfb_pe_data(ia_qc_pe_data_struct *pstr_qc_pe_data,
104
                                    ia_psy_mod_out_data_struct *pstr_psy_out, WORD32 num_channels,
105
475k
                                    WORD32 chn) {
106
475k
  WORD32 ch, idx = 0;
107
475k
  WORD32 scf_band_grp;
108
475k
  FLOAT32 num_lines;
109
475k
  FLOAT32 ld_thr, ld_ratio;
110
475k
  WORD32 i = 0, scf;
111
475k
  WORD32 sfb_count;
112
475k
  WORD32 scf_band_per_grp;
113
475k
  WORD32 max_sfb_per_grp;
114
475k
  FLOAT32 *ptr_sfb_energy;
115
475k
  FLOAT32 *ptr_sfb_thr;
116
475k
  ia_qc_pe_chan_data_struct *str_qc_pe_chan_data;
117
118
475k
  pstr_qc_pe_data->pe = pstr_qc_pe_data->offset;
119
475k
  pstr_qc_pe_data->const_part = 0.0f;
120
475k
  pstr_qc_pe_data->num_active_lines = 0.0f;
121
122
1.31M
  for (ch = chn; ch < chn + num_channels; ch++) {
123
841k
    sfb_count = pstr_psy_out[ch].sfb_count;
124
841k
    scf_band_per_grp = pstr_psy_out[ch].sfb_per_group;
125
841k
    max_sfb_per_grp = pstr_psy_out[ch].max_sfb_per_grp;
126
841k
    ptr_sfb_energy = pstr_psy_out[ch].ptr_sfb_energy;
127
841k
    ptr_sfb_thr = pstr_psy_out[ch].ptr_sfb_thr;
128
841k
    str_qc_pe_chan_data = &pstr_qc_pe_data->pe_ch_data[idx];
129
841k
    str_qc_pe_chan_data->pe = 0;
130
841k
    str_qc_pe_chan_data->num_active_lines = 0;
131
841k
    str_qc_pe_chan_data->const_part = 0;
132
133
2.58M
    for (scf_band_grp = 0; scf_band_grp < sfb_count; scf_band_grp += scf_band_per_grp) {
134
1.74M
      i = scf_band_grp;
135
36.2M
      for (scf = max_sfb_per_grp - 1; scf >= 0; scf--, i++) {
136
34.5M
        if (ptr_sfb_energy[i] > ptr_sfb_thr[i]) {
137
22.0M
          ld_thr = (FLOAT32)log(ptr_sfb_thr[i]) * LOG2_1;
138
22.0M
          ld_ratio = str_qc_pe_chan_data->sfb_ld_energy[i] - ld_thr;
139
22.0M
          num_lines = str_qc_pe_chan_data->sfb_lines[i];
140
22.0M
          if (ld_ratio >= PE_C1) {
141
16.3M
            str_qc_pe_chan_data->sfb_pe[i] = num_lines * ld_ratio;
142
16.3M
            str_qc_pe_chan_data->sfb_const_part[i] =
143
16.3M
                num_lines * str_qc_pe_chan_data->sfb_ld_energy[i];
144
16.3M
          } else {
145
5.65M
            str_qc_pe_chan_data->sfb_pe[i] = num_lines * (PE_C2 + PE_C3 * ld_ratio);
146
5.65M
            str_qc_pe_chan_data->sfb_const_part[i] =
147
5.65M
                num_lines * (PE_C2 + PE_C3 * str_qc_pe_chan_data->sfb_ld_energy[i]);
148
5.65M
            num_lines = num_lines * PE_C3;
149
5.65M
          }
150
22.0M
          str_qc_pe_chan_data->num_sfb_active_lines[i] = num_lines;
151
22.0M
        } else {
152
12.4M
          str_qc_pe_chan_data->sfb_pe[i] = 0.0f;
153
12.4M
          str_qc_pe_chan_data->sfb_const_part[i] = 0.0f;
154
12.4M
          str_qc_pe_chan_data->num_sfb_active_lines[i] = 0.0;
155
12.4M
        }
156
157
34.5M
        str_qc_pe_chan_data->pe += str_qc_pe_chan_data->sfb_pe[i];
158
34.5M
        str_qc_pe_chan_data->const_part += str_qc_pe_chan_data->sfb_const_part[i];
159
34.5M
        str_qc_pe_chan_data->num_active_lines += str_qc_pe_chan_data->num_sfb_active_lines[i];
160
34.5M
      }
161
1.74M
    }
162
841k
    pstr_qc_pe_data->pe += str_qc_pe_chan_data->pe;
163
841k
    pstr_qc_pe_data->const_part += str_qc_pe_chan_data->const_part;
164
841k
    pstr_qc_pe_data->num_active_lines += str_qc_pe_chan_data->num_active_lines;
165
841k
    pstr_psy_out[ch].pe = pstr_qc_pe_data->pe;
166
841k
    idx++;
167
841k
  }
168
475k
  return;
169
475k
}
170
171
215k
static VOID iusace_adj_pe_minmax(const FLOAT32 curr_pe, FLOAT32 *pe_min, FLOAT32 *pe_max) {
172
215k
  FLOAT32 min_hi_fac = 0.3f, max_hi_fac = 1.0f, min_low_fac = 0.14f, max_low_fac = 0.07f;
173
215k
  FLOAT32 diff;
174
215k
  FLOAT32 min_diff = curr_pe * (FLOAT32)0.1666666667f;
175
176
215k
  if (curr_pe > *pe_max) {
177
16.1k
    diff = (curr_pe - *pe_max);
178
16.1k
    *pe_min += diff * min_hi_fac;
179
16.1k
    *pe_max += diff * max_hi_fac;
180
199k
  } else {
181
199k
    if (curr_pe < *pe_min) {
182
136k
      diff = (*pe_min - curr_pe);
183
136k
      *pe_min -= diff * min_low_fac;
184
136k
      *pe_max -= diff * max_low_fac;
185
136k
    } else {
186
63.2k
      *pe_min += (curr_pe - *pe_min) * min_hi_fac;
187
63.2k
      *pe_max -= (*pe_max - curr_pe) * max_low_fac;
188
63.2k
    }
189
199k
  }
190
191
215k
  if ((*pe_max - *pe_min) < min_diff) {
192
15.9k
    FLOAT32 low_part, high_part;
193
15.9k
    low_part = MAX((FLOAT32)0.0f, curr_pe - *pe_min);
194
15.9k
    high_part = MAX((FLOAT32)0.0f, *pe_max - curr_pe);
195
15.9k
    *pe_max = curr_pe + high_part / (low_part + high_part) * min_diff;
196
15.9k
    *pe_min = curr_pe - low_part / (low_part + high_part) * min_diff;
197
15.9k
    *pe_min = MAX((FLOAT32)0.0f, *pe_min);
198
15.9k
  }
199
200
215k
  return;
201
215k
}
202
203
static FLOAT32 iusace_bitres_calc_bitfac(const WORD32 bitres_bits, const WORD32 max_bitres_bits,
204
                                         const FLOAT32 pe, const WORD32 win_seq,
205
                                         const WORD32 avg_bits, const FLOAT32 max_bit_fac,
206
215k
                                         ia_adj_thr_elem_struct *pstr_adj_thr_elem) {
207
215k
  FLOAT32 pex;
208
215k
  FLOAT32 fill_lvl = 0.0f;
209
215k
  FLOAT32 bit_save, bit_spend, bitres_factor;
210
211
215k
  if (max_bitres_bits) {
212
176k
    fill_lvl = (FLOAT32)bitres_bits / max_bitres_bits;
213
176k
  }
214
215
215k
  if (win_seq != EIGHT_SHORT_SEQUENCE) {
216
142k
    fill_lvl = MAX(fill_lvl, CLIP_SAVE_LO_LONG);
217
142k
    fill_lvl = MIN(fill_lvl, CLIP_SAVE_HI_LONG);
218
142k
    bit_save = MAX_BITS_SAVE_LONG - (BITS_SAVE_RATIO_LONG * (fill_lvl - CLIP_SAVE_LO_LONG));
219
142k
    bit_spend = MIN_BITS_SPEND_LONG + (BITS_SPEND_RATIO_LONG * (fill_lvl - CLIP_SPEND_LO_LONG));
220
142k
  } else {
221
73.4k
    fill_lvl = MAX(fill_lvl, CLIP_SPEND_LO_SHORT);
222
73.4k
    fill_lvl = MIN(fill_lvl, CLIP_SPEND_HI_SHORT);
223
73.4k
    bit_save = MAX_BITS_SAVE_SHORT - (BITS_SAVE_RATIO_SHORT * (fill_lvl - CLIP_SAVE_LO_SHORT));
224
73.4k
    bit_spend =
225
73.4k
        MIN_BITS_SPEND_SHORT + (BITS_SPEND_RATIO_SHORT * (fill_lvl - CLIP_SPEND_LO_SHORT));
226
73.4k
  }
227
228
215k
  pex = MAX(pe, pstr_adj_thr_elem->pe_min);
229
215k
  pex = MIN(pex, pstr_adj_thr_elem->pe_max);
230
231
215k
  bitres_factor =
232
215k
      (FLOAT32)1.0f - bit_save +
233
215k
      ((bit_spend + bit_save) / (pstr_adj_thr_elem->pe_max - pstr_adj_thr_elem->pe_min)) *
234
215k
          (pex - pstr_adj_thr_elem->pe_min);
235
215k
  bitres_factor = MIN(bitres_factor,
236
215k
                      (FLOAT32)1.0f - (FLOAT32)0.3f + (FLOAT32)bitres_bits / (FLOAT32)avg_bits);
237
238
215k
  bitres_factor = MIN(bitres_factor, max_bit_fac);
239
215k
  iusace_adj_pe_minmax(pe, &pstr_adj_thr_elem->pe_min, &pstr_adj_thr_elem->pe_max);
240
241
215k
  return bitres_factor;
242
215k
}
243
244
static VOID iusace_calc_pe_correction(FLOAT32 *correction_fac, const FLOAT32 pe_act,
245
215k
                                      const FLOAT32 pe_last, const WORD32 bits_prev) {
246
215k
  if ((bits_prev > 0) && (pe_act < (FLOAT32)1.5f * pe_last) &&
247
203k
      (pe_act > (FLOAT32)0.7f * pe_last) &&
248
133k
      ((FLOAT32)1.2f * iusace_bits_to_pe((FLOAT32)bits_prev) > pe_last) &&
249
106k
      ((FLOAT32)0.65f * iusace_bits_to_pe((FLOAT32)bits_prev) < pe_last)) {
250
96.1k
    FLOAT32 new_fac = pe_last / iusace_bits_to_pe((FLOAT32)bits_prev);
251
252
96.1k
    if (new_fac < (FLOAT32)1.0f) {
253
44.8k
      new_fac = MIN((FLOAT32)1.1f * new_fac, (FLOAT32)1.0f);
254
44.8k
      new_fac = MAX(new_fac, (FLOAT32)0.85f);
255
51.2k
    } else {
256
51.2k
      new_fac = MAX((FLOAT32)0.9f * new_fac, (FLOAT32)1.0f);
257
51.2k
      new_fac = MIN(new_fac, (FLOAT32)1.15f);
258
51.2k
    }
259
96.1k
    if (((new_fac > (FLOAT32)1.0f) && (*correction_fac < (FLOAT32)1.0f)) ||
260
94.5k
        ((new_fac < (FLOAT32)1.0f) && (*correction_fac > (FLOAT32)1.0f))) {
261
3.32k
      *correction_fac = (FLOAT32)1.0f;
262
3.32k
    }
263
264
96.1k
    if ((*correction_fac < (FLOAT32)1.0f && new_fac < *correction_fac) ||
265
78.2k
        (*correction_fac > (FLOAT32)1.0f && new_fac > *correction_fac))
266
22.9k
      *correction_fac = (FLOAT32)0.85f * (*correction_fac) + (FLOAT32)0.15f * new_fac;
267
73.1k
    else
268
73.1k
      *correction_fac = (FLOAT32)0.7f * (*correction_fac) + (FLOAT32)0.3f * new_fac;
269
270
96.1k
    *correction_fac = MIN(*correction_fac, (FLOAT32)1.15f);
271
96.1k
    *correction_fac = MAX(*correction_fac, (FLOAT32)0.85f);
272
119k
  } else {
273
119k
    *correction_fac = (FLOAT32)1.0f;
274
119k
  }
275
276
215k
  return;
277
215k
}
278
279
static VOID iusace_calc_thr_exp(FLOAT32 **thr_exp, ia_psy_mod_out_data_struct *pstr_psy_out,
280
117k
                                WORD32 num_chans, WORD32 chn) {
281
117k
  WORD32 sfb, ch, scf_band_grp, idx = 0;
282
117k
  ia_psy_mod_out_data_struct *pstr_psy_chan_out;
283
117k
  FLOAT32 *scf_band_thr;
284
117k
  FLOAT32 *ptr_thr_exp;
285
322k
  for (ch = chn; ch < chn + num_chans; ch++) {
286
205k
    pstr_psy_chan_out = &pstr_psy_out[ch];
287
205k
    ptr_thr_exp = thr_exp[idx];
288
651k
    for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count;
289
446k
         scf_band_grp += pstr_psy_chan_out->sfb_per_group) {
290
446k
      FLOAT32 *thr_exp1 = &ptr_thr_exp[scf_band_grp];
291
446k
      scf_band_thr = &pstr_psy_chan_out->ptr_sfb_thr[scf_band_grp];
292
8.97M
      for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) {
293
8.53M
        thr_exp1[sfb] = (FLOAT32)pow(*scf_band_thr++, RED_EXP_VAL);
294
8.53M
      }
295
446k
    }
296
205k
    idx++;
297
205k
  }
298
299
117k
  return;
300
117k
}
301
302
static VOID iusace_adapt_min_snr(ia_psy_mod_out_data_struct *pstr_psy_out,
303
                                 ia_min_snr_adapt_param_struct *pstr_min_snr_params,
304
117k
                                 WORD32 num_chans, WORD32 chn) {
305
117k
  WORD32 num_sfb = 0, ch, scf_band_cnt, sfb_off, sfb;
306
117k
  FLOAT32 avg_energy = 0.0f, db_ratio, min_snr_red;
307
117k
  WORD32 i;
308
322k
  for (ch = chn; ch < chn + num_chans; ch++) {
309
205k
    ia_psy_mod_out_data_struct *pstr_psy_chan_out = &pstr_psy_out[ch];
310
311
205k
    num_sfb = 0;
312
205k
    avg_energy = 0;
313
205k
    scf_band_cnt = pstr_psy_chan_out->max_sfb_per_grp;
314
315
651k
    for (sfb_off = 0; sfb_off < pstr_psy_chan_out->sfb_count;
316
446k
         sfb_off += pstr_psy_chan_out->sfb_per_group) {
317
446k
      FLOAT32 *sfb_energy = &pstr_psy_chan_out->ptr_sfb_energy[sfb_off];
318
8.97M
      for (sfb = scf_band_cnt - 1; sfb >= 0; sfb--) {
319
8.53M
        avg_energy += sfb_energy[sfb];
320
8.53M
      }
321
446k
      num_sfb += scf_band_cnt;
322
446k
    }
323
324
205k
    if (num_sfb > 0) {
325
205k
      avg_energy /= num_sfb;
326
205k
    }
327
328
651k
    for (sfb_off = 0; sfb_off < pstr_psy_chan_out->sfb_count;
329
446k
         sfb_off += pstr_psy_chan_out->sfb_per_group) {
330
446k
      i = sfb_off;
331
8.97M
      for (sfb = scf_band_cnt - 1; sfb >= 0; sfb--, i++) {
332
8.53M
        if (pstr_min_snr_params->start_ratio * pstr_psy_chan_out->ptr_sfb_energy[i] <
333
8.53M
            avg_energy) {
334
5.93M
          db_ratio =
335
5.93M
              (FLOAT32)(10.0 * log10((MIN_FLT_VAL + avg_energy) /
336
5.93M
                                     (MIN_FLT_VAL + pstr_psy_chan_out->ptr_sfb_energy[i])));
337
5.93M
          min_snr_red =
338
5.93M
              pstr_min_snr_params->red_offs + pstr_min_snr_params->red_ratio_fac * db_ratio;
339
5.93M
          min_snr_red = MAX(min_snr_red, pstr_min_snr_params->max_red);
340
5.93M
          pstr_psy_chan_out->sfb_min_snr[i] =
341
5.93M
              (FLOAT32)pow(pstr_psy_out[ch].sfb_min_snr[i], min_snr_red);
342
5.93M
          pstr_psy_chan_out->sfb_min_snr[i] = MIN(MIN_SNR_LIMIT, pstr_psy_out[ch].sfb_min_snr[i]);
343
5.93M
        }
344
8.53M
      }
345
446k
    }
346
205k
  }
347
348
117k
  return;
349
117k
}
350
351
static VOID iusace_init_avoid_hole_flag(WORD32 **ah_flag,
352
                                        ia_psy_mod_out_data_struct *pstr_psy_out,
353
                                        ia_ah_param_struct *pstr_ah_param, WORD32 num_chans,
354
117k
                                        WORD32 chn) {
355
117k
  WORD32 ch, idx;
356
117k
  FLOAT32 sfb_energy;
357
117k
  FLOAT32 scale_spread_energy;
358
117k
  WORD32 scf_band_grp, sfb, scf_band;
359
117k
  FLOAT32 *ptr_scf_band_spread_energy, *ptr_scf_band_energy, *ptr_scf_band_min_snr;
360
322k
  for (ch = chn; ch < chn + num_chans; ch++) {
361
205k
    ia_psy_mod_out_data_struct *pstr_psy_chan_out = &pstr_psy_out[ch];
362
363
205k
    if (pstr_psy_chan_out->window_sequence != EIGHT_SHORT_SEQUENCE) {
364
123k
      scale_spread_energy = 0.5f;
365
123k
    } else {
366
82.3k
      scale_spread_energy = 0.63f;
367
82.3k
    }
368
369
651k
    for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count;
370
446k
         scf_band_grp += pstr_psy_chan_out->sfb_per_group) {
371
446k
      ptr_scf_band_spread_energy = &pstr_psy_chan_out->ptr_sfb_spread_energy[scf_band_grp];
372
446k
      sfb = pstr_psy_chan_out->max_sfb_per_grp;
373
8.97M
      for (scf_band = sfb - 1; scf_band >= 0; scf_band--) {
374
8.53M
        *ptr_scf_band_spread_energy = *ptr_scf_band_spread_energy * scale_spread_energy;
375
8.53M
        ptr_scf_band_spread_energy++;
376
8.53M
      }
377
446k
    }
378
205k
  }
379
380
117k
  if (pstr_ah_param->modify_min_snr) {
381
321k
    for (ch = chn; ch < chn + num_chans; ch++) {
382
204k
      ia_psy_mod_out_data_struct *pstr_psy_chan_out = &pstr_psy_out[ch];
383
204k
      ptr_scf_band_energy = pstr_psy_chan_out->ptr_sfb_energy;
384
385
204k
      ptr_scf_band_min_snr = pstr_psy_chan_out->sfb_min_snr;
386
387
648k
      for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count;
388
443k
           scf_band_grp += pstr_psy_chan_out->sfb_per_group) {
389
8.93M
        for (scf_band = 0; scf_band < pstr_psy_chan_out->max_sfb_per_grp; scf_band++) {
390
8.48M
          FLOAT32 sfb_en_m1, sfb_en_p1, avg_energy;
391
8.48M
          if (scf_band > 0) {
392
8.04M
            sfb_en_m1 = ptr_scf_band_energy[scf_band_grp + scf_band - 1];
393
8.04M
          } else {
394
443k
            sfb_en_m1 = ptr_scf_band_energy[scf_band_grp];
395
443k
          }
396
8.48M
          if (scf_band < pstr_psy_chan_out->max_sfb_per_grp - 1)
397
8.04M
            sfb_en_p1 = ptr_scf_band_energy[scf_band_grp + scf_band + 1];
398
443k
          else
399
443k
            sfb_en_p1 = ptr_scf_band_energy[scf_band_grp + scf_band];
400
401
8.48M
          avg_energy = (sfb_en_m1 + sfb_en_p1) / (FLOAT32)2.0f;
402
8.48M
          sfb_energy = ptr_scf_band_energy[scf_band_grp + scf_band];
403
404
8.48M
          if (sfb_energy > avg_energy) {
405
2.71M
            FLOAT32 temp_min_snr = MAX((FLOAT32)0.8f * avg_energy / sfb_energy, (FLOAT32)0.316f);
406
2.71M
            if (pstr_psy_chan_out->window_sequence != EIGHT_SHORT_SEQUENCE)
407
1.67M
              temp_min_snr = MAX(temp_min_snr, (FLOAT32)0.316f);
408
1.03M
            else
409
1.03M
              temp_min_snr = MAX(temp_min_snr, (FLOAT32)0.5f);
410
2.71M
            ptr_scf_band_min_snr[scf_band_grp + scf_band] =
411
2.71M
                MIN(ptr_scf_band_min_snr[scf_band_grp + scf_band], temp_min_snr);
412
2.71M
          }
413
414
8.48M
          if (((FLOAT32)2.0f * sfb_energy < avg_energy) && (sfb_energy > (FLOAT32)0.0f)) {
415
1.53M
            FLOAT32 temp_min_snr = avg_energy / ((FLOAT32)2.0f * sfb_energy) *
416
1.53M
                                   ptr_scf_band_min_snr[scf_band_grp + scf_band];
417
1.53M
            temp_min_snr = MIN((FLOAT32)0.8f, temp_min_snr);
418
1.53M
            ptr_scf_band_min_snr[scf_band_grp + scf_band] =
419
1.53M
                MIN(temp_min_snr, ptr_scf_band_min_snr[scf_band_grp + scf_band] * (FLOAT32)3.16f);
420
1.53M
          }
421
8.48M
        }
422
443k
      }
423
204k
    }
424
116k
  }
425
426
117k
  if (num_chans == 2) {
427
88.4k
    ia_psy_mod_out_data_struct *psy_out_mid = &pstr_psy_out[chn];
428
88.4k
    ia_psy_mod_out_data_struct *psy_out_side = &pstr_psy_out[chn + 1];
429
430
4.19M
    for (sfb = 0; sfb < psy_out_mid->sfb_count; sfb++) {
431
4.10M
      if (pstr_psy_out[chn].ms_used[sfb]) {
432
3.09M
        FLOAT32 sfb_en_mid = psy_out_mid->ptr_sfb_energy[sfb];
433
3.09M
        FLOAT32 sfb_en_side = psy_out_side->ptr_sfb_energy[sfb];
434
3.09M
        FLOAT32 max_sfb_en = MAX(sfb_en_mid, sfb_en_side);
435
3.09M
        FLOAT32 max_thr = 0.25f * psy_out_mid->sfb_min_snr[sfb] * max_sfb_en;
436
437
3.09M
        psy_out_mid->sfb_min_snr[sfb] = (FLOAT32)MAX(
438
3.09M
            psy_out_mid->sfb_min_snr[sfb],
439
3.09M
            MIN(MAX_FLT_VAL, ((double)max_thr / (MIN_FLT_VAL + (double)sfb_en_mid))));
440
441
3.09M
        if (psy_out_mid->ptr_sfb_energy[sfb] <= 1.0f) {
442
419k
          psy_out_mid->ptr_sfb_energy[sfb] = MIN(psy_out_mid->ptr_sfb_energy[sfb], 0.8f);
443
419k
        }
444
445
3.09M
        psy_out_side->sfb_min_snr[sfb] = (FLOAT32)MAX(
446
3.09M
            psy_out_side->sfb_min_snr[sfb],
447
3.09M
            MIN(MAX_FLT_VAL, ((double)max_thr / (MIN_FLT_VAL + (double)sfb_en_side))));
448
449
3.09M
        if (psy_out_side->sfb_min_snr[sfb] <= 1.0f) {
450
1.59M
          psy_out_side->sfb_min_snr[sfb] = MIN(psy_out_side->sfb_min_snr[sfb], 0.8f);
451
1.59M
        }
452
453
3.09M
        if (sfb_en_mid > psy_out_mid->ptr_sfb_spread_energy[sfb]) {
454
2.57M
          psy_out_side->ptr_sfb_spread_energy[sfb] = 0.9f * sfb_en_side;
455
2.57M
        }
456
457
3.09M
        if (sfb_en_side > psy_out_side->ptr_sfb_spread_energy[sfb]) {
458
1.83M
          psy_out_mid->ptr_sfb_spread_energy[sfb] = 0.9f * sfb_en_mid;
459
1.83M
        }
460
3.09M
      }
461
4.10M
    }
462
88.4k
  }
463
117k
  idx = 0;
464
322k
  for (ch = chn; ch < chn + num_chans; ch++) {
465
205k
    ia_psy_mod_out_data_struct *pstr_psy_chan_out = &pstr_psy_out[ch];
466
651k
    for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count;
467
446k
         scf_band_grp += pstr_psy_chan_out->sfb_per_group) {
468
8.97M
      for (scf_band = 0; scf_band < pstr_psy_chan_out->max_sfb_per_grp; scf_band++) {
469
8.53M
        if (pstr_psy_chan_out->ptr_sfb_spread_energy[scf_band_grp + scf_band] >
470
8.53M
                pstr_psy_chan_out->ptr_sfb_energy[scf_band_grp + scf_band] ||
471
7.33M
            pstr_psy_chan_out->sfb_min_snr[scf_band_grp + scf_band] > (float)1.0) {
472
2.68M
          ah_flag[idx][scf_band_grp + scf_band] = NO_AH;
473
5.84M
        } else {
474
5.84M
          ah_flag[idx][scf_band_grp + scf_band] = AH_INACTIVE;
475
5.84M
        }
476
8.53M
      }
477
478
446k
      for (scf_band = pstr_psy_chan_out->max_sfb_per_grp;
479
1.41M
           scf_band < pstr_psy_chan_out->sfb_per_group; scf_band++) {
480
968k
        ah_flag[idx][scf_band_grp + scf_band] = NO_AH;
481
968k
      }
482
446k
    }
483
205k
    idx++;
484
205k
  }
485
486
117k
  return;
487
117k
}
488
489
static VOID iusace_reduce_thr(ia_psy_mod_out_data_struct *pstr_psy_out, WORD32 **ah_flag,
490
                              FLOAT32 **thr_exp, const FLOAT32 red_value, WORD32 num_channels,
491
257k
                              WORD32 chn) {
492
257k
  WORD32 ch, sfb_group, sfb, idx = 0;
493
257k
  FLOAT32 sfb_energy, sfb_threshold, sfb_thr_reduced;
494
257k
  FLOAT32 *sfb_energy_fix, *sfb_threshold_fix, *sfb_min_snr_fix, *thr_exp_fix;
495
713k
  for (ch = chn; ch < chn + num_channels; ch++) {
496
455k
    ia_psy_mod_out_data_struct *pstr_psy_chan_out = &pstr_psy_out[ch];
497
455k
    sfb_energy_fix = pstr_psy_chan_out->ptr_sfb_energy;
498
455k
    sfb_threshold_fix = pstr_psy_chan_out->ptr_sfb_thr;
499
455k
    sfb_min_snr_fix = pstr_psy_chan_out->sfb_min_snr;
500
455k
    thr_exp_fix = &thr_exp[idx][0];
501
1.43M
    for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count;
502
979k
         sfb_group += pstr_psy_chan_out->sfb_per_group) {
503
19.5M
      for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) {
504
18.5M
        sfb_energy = sfb_energy_fix[sfb_group + sfb];
505
18.5M
        sfb_threshold = sfb_threshold_fix[sfb_group + sfb];
506
18.5M
        if (sfb_energy > sfb_threshold) {
507
13.2M
          sfb_thr_reduced =
508
13.2M
              (FLOAT32)pow((thr_exp_fix[sfb_group + sfb] + red_value), INV_RED_EXP_VAL);
509
510
13.2M
          if ((sfb_thr_reduced > sfb_min_snr_fix[sfb_group + sfb] * sfb_energy) &&
511
3.84M
              (ah_flag[idx][sfb_group + sfb] != NO_AH)) {
512
3.60M
            sfb_thr_reduced = MAX(sfb_min_snr_fix[sfb_group + sfb] * sfb_energy, sfb_threshold);
513
3.60M
            ah_flag[idx][sfb_group + sfb] = AH_ACTIVE;
514
3.60M
          }
515
13.2M
          sfb_threshold_fix[sfb_group + sfb] = sfb_thr_reduced;
516
13.2M
        }
517
18.5M
      }
518
979k
    }
519
455k
    idx++;
520
455k
  }
521
522
257k
  return;
523
257k
}
524
525
static VOID iusace_calc_pe_no_active_holes(FLOAT32 *pe, FLOAT32 *const_part,
526
                                           FLOAT32 *nactive_lines,
527
                                           ia_qc_pe_data_struct *pstr_qs_pe_data,
528
                                           WORD32 **ah_flag,
529
                                           ia_psy_mod_out_data_struct *pstr_psy_out,
530
142k
                                           WORD32 num_channels, WORD32 chn) {
531
142k
  WORD32 ch, sfb_group, sfb, idx = 0;
532
142k
  *pe = 0.0f;
533
142k
  *const_part = 0.0f;
534
142k
  *nactive_lines = 0;
535
398k
  for (ch = chn; ch < chn + num_channels; ch++) {
536
255k
    ia_psy_mod_out_data_struct *pstr_psy_chan_out = &pstr_psy_out[ch];
537
255k
    ia_qc_pe_chan_data_struct *pe_channel_data = &pstr_qs_pe_data->pe_ch_data[idx];
538
539
794k
    for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count;
540
539k
         sfb_group += pstr_psy_chan_out->sfb_per_group) {
541
10.6M
      for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) {
542
10.1M
        if (ah_flag[idx][sfb_group + sfb] < AH_ACTIVE) {
543
8.15M
          *pe += pe_channel_data->sfb_pe[sfb_group + sfb];
544
8.15M
          *const_part += pe_channel_data->sfb_const_part[sfb_group + sfb];
545
8.15M
          *nactive_lines += pe_channel_data->num_sfb_active_lines[sfb_group + sfb];
546
8.15M
        }
547
10.1M
      }
548
539k
    }
549
255k
    idx++;
550
255k
  }
551
552
142k
  return;
553
142k
}
554
555
static IA_ERRORCODE iusace_correct_thr(ia_psy_mod_out_data_struct *pstr_psy_out, WORD32 **ah_flag,
556
                                       ia_qc_pe_data_struct *pstr_qs_pe_data, FLOAT32 **thr_exp,
557
                                       const FLOAT32 red_value, const FLOAT32 delta_pe,
558
103k
                                       WORD32 num_channels, WORD32 chn, UWORD8 *ptr_scratch) {
559
103k
  WORD32 i, ch, sfb_group, sfb, idx = 0;
560
103k
  FLOAT32 delta_sfb_pe;
561
103k
  FLOAT32 thr_factor;
562
103k
  FLOAT32 norm_factor[2] = {0};
563
103k
  FLOAT32 *sfb_pe_factors[2];
564
309k
  for (i = 0; i < 2; i++) {
565
206k
    sfb_pe_factors[i] = (FLOAT32 *)ptr_scratch;
566
206k
    ptr_scratch += (MAX_NUM_GROUPED_SFB) * sizeof(sfb_pe_factors[0][0]);
567
206k
  }
568
103k
  FLOAT32 sfb_en, sfb_thr, sfb_thr_reduced;
569
103k
  FLOAT32 *p_thr_exp;
570
103k
  FLOAT32 *p_sfb_energy, *p_sfb_thr, *p_sfb_min_snr;
571
103k
  ia_psy_mod_out_data_struct *pstr_psy_chan_out = NULL;
572
103k
  ia_qc_pe_chan_data_struct *pe_channel_data = NULL;
573
574
281k
  for (ch = chn; ch < chn + num_channels; ch++) {
575
178k
    if (idx >= IXHEAACE_MAX_CH_IN_BS_ELE) {
576
0
      return IA_EXHEAACE_EXE_FATAL_USAC_INVALID_NUM_CHANNEL;
577
0
    }
578
178k
    pstr_psy_chan_out = &pstr_psy_out[ch];
579
178k
    pe_channel_data = &pstr_qs_pe_data->pe_ch_data[idx];
580
178k
    norm_factor[idx] = MIN_FLT_VAL;
581
178k
    p_thr_exp = thr_exp[idx];
582
583
577k
    for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count;
584
399k
         sfb_group += pstr_psy_chan_out->sfb_per_group) {
585
8.06M
      for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) {
586
7.67M
        if ((ah_flag[idx][sfb_group + sfb] < AH_ACTIVE) || (delta_pe > 0)) {
587
6.83M
          sfb_pe_factors[idx][sfb_group + sfb] =
588
6.83M
              pe_channel_data->num_sfb_active_lines[sfb_group + sfb] /
589
6.83M
              (p_thr_exp[sfb_group + sfb] + red_value);
590
6.83M
          norm_factor[idx] += sfb_pe_factors[idx][sfb_group + sfb];
591
6.83M
        } else {
592
834k
          sfb_pe_factors[idx][sfb_group + sfb] = 0.0f;
593
834k
        }
594
7.67M
      }
595
399k
    }
596
178k
    idx++;
597
178k
  }
598
103k
  if (num_channels > 1) {
599
74.9k
    norm_factor[0] = norm_factor[0] + norm_factor[1];
600
74.9k
  }
601
103k
  norm_factor[0] = 1.0f / norm_factor[0];
602
103k
  idx = 0;
603
281k
  for (ch = chn; ch < chn + num_channels; ch++) {
604
178k
    if (idx >= IXHEAACE_MAX_CH_IN_BS_ELE) {
605
0
      return IA_EXHEAACE_EXE_FATAL_USAC_INVALID_NUM_CHANNEL;
606
0
    }
607
178k
    pstr_psy_chan_out = &pstr_psy_out[ch];
608
178k
    pe_channel_data = &pstr_qs_pe_data->pe_ch_data[idx];
609
178k
    p_sfb_energy = pstr_psy_chan_out->ptr_sfb_energy;
610
178k
    p_sfb_thr = pstr_psy_chan_out->ptr_sfb_thr;
611
178k
    p_sfb_min_snr = pstr_psy_chan_out->sfb_min_snr;
612
613
577k
    for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count;
614
399k
         sfb_group += pstr_psy_chan_out->sfb_per_group) {
615
399k
      i = sfb_group;
616
8.06M
      for (sfb = pstr_psy_chan_out->max_sfb_per_grp - 1; sfb >= 0; sfb--, i++) {
617
7.67M
        delta_sfb_pe = sfb_pe_factors[idx][i] * norm_factor[0] * delta_pe;
618
7.67M
        if (pe_channel_data->num_sfb_active_lines[i] > (FLOAT32)0.5f) {
619
5.02M
          sfb_en = p_sfb_energy[i];
620
5.02M
          sfb_thr = p_sfb_thr[i];
621
5.02M
          thr_factor = MIN(-delta_sfb_pe / pe_channel_data->num_sfb_active_lines[i], 20.f);
622
5.02M
          thr_factor = (FLOAT32)pow(2.0f, thr_factor);
623
5.02M
          sfb_thr_reduced = sfb_thr * thr_factor;
624
625
5.02M
          if ((sfb_thr_reduced > p_sfb_min_snr[i] * sfb_en) && (ah_flag[idx][i] == AH_INACTIVE)) {
626
24.1k
            sfb_thr_reduced = MAX(p_sfb_min_snr[i] * sfb_en, sfb_thr);
627
24.1k
            ah_flag[idx][i] = AH_ACTIVE;
628
24.1k
          }
629
5.02M
          p_sfb_thr[i] = sfb_thr_reduced;
630
5.02M
        }
631
7.67M
      }
632
399k
    }
633
178k
    idx++;
634
178k
  }
635
636
103k
  return IA_NO_ERROR;
637
103k
}
638
639
static VOID iusace_reduce_min_snr(ia_psy_mod_out_data_struct *pstr_psy_out,
640
                                  ia_qc_pe_data_struct *pstr_qs_pe_data, WORD32 **ah_flag,
641
13.9k
                                  const FLOAT32 desired_pe, WORD32 num_channels, WORD32 chn) {
642
13.9k
  WORD32 sfb, sfb_sub_win, ch, idx;
643
13.9k
  FLOAT32 delta_pe;
644
645
13.9k
  sfb_sub_win = pstr_psy_out[chn].max_sfb_per_grp;
646
647
364k
  while (pstr_qs_pe_data->pe > desired_pe && sfb_sub_win > 0) {
648
350k
    sfb_sub_win--;
649
780k
    for (sfb = sfb_sub_win; sfb < pstr_psy_out[chn].sfb_count;
650
432k
         sfb += pstr_psy_out[chn].sfb_per_group) {
651
432k
      idx = 0;
652
1.28M
      for (ch = chn; ch < chn + num_channels; ch++) {
653
850k
        if (ah_flag[idx][sfb] != NO_AH && pstr_psy_out[ch].sfb_min_snr[sfb] < MIN_SNR_LIMIT) {
654
411k
          pstr_psy_out[ch].sfb_min_snr[sfb] = MIN_SNR_LIMIT;
655
411k
          pstr_psy_out[ch].ptr_sfb_thr[sfb] =
656
411k
              pstr_psy_out[ch].ptr_sfb_energy[sfb] * pstr_psy_out[ch].sfb_min_snr[sfb];
657
411k
          delta_pe = pstr_qs_pe_data->pe_ch_data[idx].sfb_lines[sfb] * 1.5f -
658
411k
                     pstr_qs_pe_data->pe_ch_data[idx].sfb_pe[sfb];
659
411k
          pstr_qs_pe_data->pe += delta_pe;
660
411k
          pstr_qs_pe_data->pe_ch_data[idx].pe += delta_pe;
661
411k
        }
662
850k
        idx++;
663
850k
      }
664
432k
      if (pstr_qs_pe_data->pe <= desired_pe) break;
665
432k
    }
666
350k
  }
667
668
13.9k
  return;
669
13.9k
}
670
671
static VOID iusace_allow_more_holes(ia_psy_mod_out_data_struct *pstr_psy_out,
672
                                    ia_qc_pe_data_struct *pstr_qs_pe_data, WORD32 **ah_flag,
673
                                    const ia_ah_param_struct *str_ah_param,
674
                                    const FLOAT32 desired_pe, WORD32 num_channels, WORD32 chn,
675
13.9k
                                    UWORD8 *ptr_scratch) {
676
13.9k
  WORD32 sfb, ch, idx;
677
13.9k
  FLOAT32 act_pe = pstr_qs_pe_data->pe;
678
679
13.9k
  if (num_channels == 2 &&
680
13.4k
      pstr_psy_out[chn].window_sequence == pstr_psy_out[chn + 1].window_sequence) {
681
13.4k
    ia_psy_mod_out_data_struct *psy_out_left = &pstr_psy_out[chn];
682
13.4k
    ia_psy_mod_out_data_struct *psy_out_right = &pstr_psy_out[chn + 1];
683
684
478k
    for (sfb = 0; sfb < psy_out_left->sfb_count; sfb++) {
685
466k
      if (pstr_psy_out[chn].ms_used[sfb]) {
686
227k
        if (ah_flag[1][sfb] != NO_AH &&
687
165k
            0.4f * psy_out_left->sfb_min_snr[sfb] * psy_out_left->ptr_sfb_energy[sfb] >
688
165k
                psy_out_right->ptr_sfb_energy[sfb]) {
689
9.79k
          ah_flag[1][sfb] = NO_AH;
690
691
9.79k
          psy_out_right->ptr_sfb_thr[sfb] = 2.0f * psy_out_right->ptr_sfb_energy[sfb];
692
693
9.79k
          act_pe -= pstr_qs_pe_data->pe_ch_data[1].sfb_pe[sfb];
694
217k
        } else {
695
217k
          if (ah_flag[0][sfb] != NO_AH &&
696
182k
              0.4f * psy_out_right->sfb_min_snr[sfb] * psy_out_right->ptr_sfb_energy[sfb] >
697
182k
                  psy_out_left->ptr_sfb_energy[sfb]) {
698
5.65k
            ah_flag[0][sfb] = NO_AH;
699
700
5.65k
            psy_out_left->ptr_sfb_thr[sfb] = 2.0f * psy_out_left->ptr_sfb_energy[sfb];
701
702
5.65k
            act_pe -= pstr_qs_pe_data->pe_ch_data[0].sfb_pe[sfb];
703
5.65k
          }
704
217k
        }
705
227k
        if (act_pe < desired_pe) break;
706
227k
      }
707
466k
    }
708
13.4k
  }
709
13.9k
  if (act_pe > desired_pe) {
710
11.2k
    WORD32 *start_sfb = (WORD32 *)ptr_scratch;
711
11.2k
    memset(start_sfb, 0, MAX_TIME_CHANNELS * sizeof(start_sfb[0]));
712
11.2k
    FLOAT32 average_energy, min_energy;
713
11.2k
    WORD32 ah_cnt;
714
11.2k
    WORD32 en_idx;
715
11.2k
    FLOAT32 energy[4];
716
11.2k
    WORD32 min_sfb, max_sfb;
717
11.2k
    WORD32 done;
718
33.6k
    for (ch = chn; ch < chn + num_channels; ch++) {
719
22.3k
      if (pstr_psy_out[ch].window_sequence != EIGHT_SHORT_SEQUENCE)
720
17.3k
        start_sfb[ch] = str_ah_param->start_sfb_long;
721
5.03k
      else
722
5.03k
        start_sfb[ch] = str_ah_param->start_sfb_short;
723
22.3k
    }
724
725
11.2k
    average_energy = 0.0f;
726
11.2k
    min_energy = MAX_FLT_VAL;
727
11.2k
    ah_cnt = 0;
728
11.2k
    idx = 0;
729
33.6k
    for (ch = chn; ch < chn + num_channels; ch++) {
730
22.3k
      ia_psy_mod_out_data_struct *pstr_psy_chan_out = &pstr_psy_out[ch];
731
638k
      for (sfb = start_sfb[ch]; sfb < pstr_psy_chan_out->sfb_count; sfb++) {
732
615k
        if ((ah_flag[idx][sfb] != NO_AH) &&
733
362k
            (pstr_psy_chan_out->ptr_sfb_energy[sfb] > pstr_psy_chan_out->ptr_sfb_thr[sfb])) {
734
355k
          min_energy = MIN(min_energy, pstr_psy_chan_out->ptr_sfb_energy[sfb]);
735
355k
          average_energy += pstr_psy_chan_out->ptr_sfb_energy[sfb];
736
355k
          ah_cnt++;
737
355k
        }
738
615k
      }
739
22.3k
      idx++;
740
22.3k
    }
741
742
11.2k
    average_energy = MIN(MAX_FLT_VAL, average_energy / (ah_cnt + MIN_FLT_VAL));
743
744
56.2k
    for (en_idx = 0; en_idx < 4; en_idx++) {
745
45.0k
      energy[en_idx] = min_energy * (FLOAT32)pow(average_energy / (min_energy + MIN_FLT_VAL),
746
45.0k
                                                 (2 * en_idx + 1) / 7.0f);
747
45.0k
    }
748
11.2k
    max_sfb = pstr_psy_out[chn].sfb_count - 1;
749
11.2k
    min_sfb = start_sfb[chn];
750
751
11.2k
    if (num_channels == 2) {
752
11.1k
      max_sfb = MAX(max_sfb, pstr_psy_out[chn + 1].sfb_count - 1);
753
754
11.1k
      min_sfb = MIN(min_sfb, start_sfb[chn + 1]);
755
11.1k
    }
756
757
11.2k
    sfb = max_sfb;
758
11.2k
    en_idx = 0;
759
11.2k
    done = 0;
760
623k
    while (!done) {
761
612k
      idx = 0;
762
1.81M
      for (ch = chn; ch < chn + num_channels; ch++) {
763
1.21M
        ia_psy_mod_out_data_struct *pstr_psy_chan_out = &pstr_psy_out[ch];
764
1.21M
        if (sfb >= start_sfb[ch] && sfb < pstr_psy_chan_out->sfb_count) {
765
1.21M
          if (ah_flag[idx][sfb] != NO_AH &&
766
646k
              pstr_psy_chan_out->ptr_sfb_energy[sfb] < energy[en_idx]) {
767
115k
            ah_flag[idx][sfb] = NO_AH;
768
115k
            pstr_psy_chan_out->ptr_sfb_thr[sfb] = 2.0f * pstr_psy_chan_out->ptr_sfb_energy[sfb];
769
115k
            act_pe -= pstr_qs_pe_data->pe_ch_data[idx].sfb_pe[sfb];
770
115k
          }
771
772
1.21M
          if (act_pe < desired_pe) {
773
9.66k
            done = 1;
774
9.66k
            break;
775
9.66k
          }
776
1.21M
        }
777
1.20M
        idx++;
778
1.20M
      }
779
612k
      sfb--;
780
612k
      if (sfb < min_sfb) {
781
18.5k
        sfb = max_sfb;
782
18.5k
        en_idx++;
783
18.5k
        if (en_idx >= 4) {
784
1.64k
          done = 1;
785
1.64k
        }
786
18.5k
      }
787
612k
    }
788
11.2k
  }
789
790
13.9k
  return;
791
13.9k
}
792
793
static IA_ERRORCODE iusace_adapt_thr_to_pe(ia_psy_mod_out_data_struct *pstr_psy_out,
794
                                           ia_qc_pe_data_struct *pstr_qs_pe_data,
795
                                           const FLOAT32 desired_pe,
796
                                           ia_ah_param_struct *str_ah_param,
797
                                           ia_min_snr_adapt_param_struct *msa_param,
798
117k
                                           WORD32 num_channels, WORD32 chn, UWORD8 *ptr_scratch) {
799
117k
  IA_ERRORCODE err_code;
800
117k
  FLOAT32 no_red_pe, red_pe, red_pe_no_ah;
801
117k
  FLOAT32 const_part, const_part_no_ah;
802
117k
  FLOAT32 nactive_lines, nactive_lines_no_ah;
803
117k
  FLOAT32 desired_pe_no_ah;
804
117k
  FLOAT32 redval = 0.0f;
805
117k
  WORD32 *ah_flag[2];
806
117k
  WORD32 iteration;
807
351k
  for (WORD32 i = 0; i < 2; i++) {
808
234k
    ah_flag[i] = (WORD32 *)ptr_scratch;
809
234k
    ptr_scratch += (MAX_NUM_GROUPED_SFB) * sizeof(ah_flag[0][0]);
810
234k
  }
811
117k
  FLOAT32 *thr_exp[2];
812
351k
  for (WORD32 i = 0; i < 2; i++) {
813
234k
    thr_exp[i] = (FLOAT32 *)ptr_scratch;
814
234k
    ptr_scratch += (MAX_NUM_GROUPED_SFB) * sizeof(thr_exp[0][0]);
815
234k
  }
816
817
117k
  iusace_calc_thr_exp(thr_exp, pstr_psy_out, num_channels, chn);
818
117k
  iusace_adapt_min_snr(pstr_psy_out, msa_param, num_channels, chn);
819
117k
  iusace_init_avoid_hole_flag(ah_flag, pstr_psy_out, str_ah_param, num_channels, chn);
820
821
117k
  no_red_pe = pstr_qs_pe_data->pe;
822
117k
  const_part = pstr_qs_pe_data->const_part;
823
117k
  nactive_lines = pstr_qs_pe_data->num_active_lines;
824
117k
  if (nactive_lines > FLT_EPSILON) {
825
117k
    FLOAT32 avg_thr_exp = (FLOAT32)pow(2.0f, (const_part - no_red_pe) /
826
117k
                  (INV_RED_EXP_VAL * nactive_lines));
827
117k
    redval = (FLOAT32)pow(2.0f, (const_part - desired_pe) / (INV_RED_EXP_VAL * nactive_lines)) -
828
117k
             avg_thr_exp;
829
117k
    redval = MAX(0.0f, redval);
830
117k
    iusace_reduce_thr(pstr_psy_out, ah_flag, thr_exp, redval, num_channels, chn);
831
117k
  }
832
833
117k
  iusace_calc_sfb_pe_data(pstr_qs_pe_data, pstr_psy_out, num_channels, chn);
834
117k
  red_pe = pstr_qs_pe_data->pe;
835
836
117k
  iteration = 0;
837
142k
  do {
838
142k
    iusace_calc_pe_no_active_holes(&red_pe_no_ah, &const_part_no_ah, &nactive_lines_no_ah,
839
142k
                                   pstr_qs_pe_data, ah_flag, pstr_psy_out, num_channels, chn);
840
841
142k
    desired_pe_no_ah = MAX(desired_pe - (red_pe - red_pe_no_ah), 0);
842
142k
    if (nactive_lines_no_ah > FLT_EPSILON) {
843
140k
      FLOAT32 avg_thr_exp = (FLOAT32)pow(
844
140k
          2.0f, (const_part_no_ah - red_pe_no_ah) / (INV_RED_EXP_VAL * nactive_lines_no_ah));
845
140k
      redval += (FLOAT32)pow(2.0f, (const_part_no_ah - desired_pe_no_ah) /
846
140k
                                       (INV_RED_EXP_VAL * nactive_lines_no_ah)) -
847
140k
                avg_thr_exp;
848
140k
      redval = MAX(0.0f, redval);
849
140k
      iusace_reduce_thr(pstr_psy_out, ah_flag, thr_exp, redval, num_channels, chn);
850
140k
    }
851
852
142k
    iusace_calc_sfb_pe_data(pstr_qs_pe_data, pstr_psy_out, num_channels, chn);
853
142k
    red_pe = pstr_qs_pe_data->pe;
854
142k
    iteration++;
855
142k
  } while ((fabs(red_pe - desired_pe) > (0.05f) * desired_pe) && (iteration < 2));
856
117k
  if (red_pe < 1.15f * desired_pe) {
857
103k
    err_code = iusace_correct_thr(pstr_psy_out, ah_flag, pstr_qs_pe_data, thr_exp, redval,
858
103k
                                  desired_pe - red_pe, num_channels, chn, ptr_scratch);
859
103k
    if (err_code != IA_NO_ERROR) {
860
0
      return err_code;
861
0
    }
862
103k
  } else {
863
13.9k
    iusace_reduce_min_snr(pstr_psy_out, pstr_qs_pe_data, ah_flag, 1.05f * desired_pe,
864
13.9k
                          num_channels, chn);
865
13.9k
    iusace_allow_more_holes(pstr_psy_out, pstr_qs_pe_data, ah_flag, str_ah_param,
866
13.9k
                            1.05f * desired_pe, num_channels, chn, ptr_scratch);
867
13.9k
  }
868
869
117k
  return IA_NO_ERROR;
870
117k
}
871
872
IA_ERRORCODE iusace_adj_thr(ia_adj_thr_elem_struct *pstr_adj_thr_elem,
873
                            ia_psy_mod_out_data_struct *pstr_psy_out, FLOAT32 *ch_bit_dist,
874
                            ia_qc_out_data_struct *pstr_qc_out, const WORD32 avg_bits,
875
                            const WORD32 bitres_bits, const WORD32 max_bitres_bits,
876
                            const WORD32 side_info_bits, FLOAT32 *max_bit_fac,
877
215k
                            WORD32 num_channels, WORD32 chn, iusace_scratch_mem *pstr_scratch) {
878
215k
  IA_ERRORCODE err_code;
879
215k
  FLOAT32 no_red_pe, granted_pe, granted_pe_corr;
880
215k
  WORD32 curr_win_sequence;
881
215k
  ia_qc_pe_data_struct *pstr_qc_pe_data = (ia_qc_pe_data_struct *)pstr_scratch->ptr_fd_scratch;
882
215k
  pUWORD8 ptr_scratch = pstr_scratch->ptr_fd_scratch + sizeof(ia_qc_pe_data_struct);
883
215k
  FLOAT32 bit_factor;
884
215k
  WORD32 ch;
885
886
215k
  pstr_qc_pe_data->pe_ch_data[0].sfb_lines = pstr_scratch->ptr_sfb_num_relevant_lines[0];
887
215k
  pstr_qc_pe_data->pe_ch_data[0].sfb_ld_energy = pstr_scratch->ptr_sfb_ld_energy[0];
888
215k
  if (num_channels == 2) {
889
165k
    pstr_qc_pe_data->pe_ch_data[1].sfb_lines = pstr_scratch->ptr_sfb_num_relevant_lines[1];
890
165k
    pstr_qc_pe_data->pe_ch_data[1].sfb_ld_energy = pstr_scratch->ptr_sfb_ld_energy[1];
891
165k
  }
892
215k
  pstr_qc_pe_data->offset = pstr_adj_thr_elem->pe_offset;
893
894
215k
  iusace_calc_sfb_pe_data(pstr_qc_pe_data, pstr_psy_out, num_channels, chn);
895
215k
  no_red_pe = pstr_qc_pe_data->pe;
896
897
215k
  curr_win_sequence = ONLY_LONG_SEQUENCE;
898
215k
  if (num_channels == 2) {
899
165k
    if ((pstr_psy_out[chn].window_sequence == EIGHT_SHORT_SEQUENCE) ||
900
105k
        (pstr_psy_out[chn + 1].window_sequence == EIGHT_SHORT_SEQUENCE)) {
901
59.9k
      curr_win_sequence = EIGHT_SHORT_SEQUENCE;
902
59.9k
    }
903
165k
  } else {
904
50.0k
    curr_win_sequence = pstr_psy_out[chn].window_sequence;
905
50.0k
  }
906
907
215k
  bit_factor =
908
215k
      iusace_bitres_calc_bitfac(bitres_bits, max_bitres_bits, no_red_pe + 5.0f * side_info_bits,
909
215k
                                curr_win_sequence, avg_bits, *max_bit_fac, pstr_adj_thr_elem);
910
215k
  granted_pe = bit_factor * iusace_bits_to_pe((FLOAT32)avg_bits);
911
215k
  iusace_calc_pe_correction(&(pstr_adj_thr_elem->pe_correction_fac), MIN(granted_pe, no_red_pe),
912
215k
                            pstr_adj_thr_elem->pe_last, pstr_adj_thr_elem->dyn_bits_last);
913
215k
  granted_pe_corr = granted_pe * pstr_adj_thr_elem->pe_correction_fac;
914
915
215k
  if (granted_pe_corr < no_red_pe) {
916
117k
    err_code = iusace_adapt_thr_to_pe(
917
117k
        pstr_psy_out, pstr_qc_pe_data, granted_pe_corr, &pstr_adj_thr_elem->str_ah_param,
918
117k
        &pstr_adj_thr_elem->str_min_snr_adapt_params, num_channels, chn, ptr_scratch);
919
117k
    if (err_code != IA_NO_ERROR) {
920
0
      return err_code;
921
0
    }
922
117k
  }
923
924
596k
  for (ch = 0; ch < num_channels; ch++) {
925
381k
    FLOAT32 tmp_var, temp1;
926
381k
    if (pstr_qc_pe_data->pe) {
927
348k
      tmp_var = 1.0f - num_channels * 0.2f;
928
348k
      temp1 = pstr_qc_pe_data->pe_ch_data[ch].pe / pstr_qc_pe_data->pe;
929
348k
      temp1 = temp1 * tmp_var;
930
348k
      ch_bit_dist[ch] = temp1 + 0.2f;
931
348k
      if (ch_bit_dist[ch] < 0.2f) ch_bit_dist[ch] = 0.2f;
932
348k
    } else {
933
32.4k
      ch_bit_dist[ch] = 0.2f;
934
32.4k
    }
935
381k
  }
936
937
215k
  pstr_qc_out->pe = no_red_pe;
938
215k
  pstr_adj_thr_elem->pe_last = granted_pe;
939
940
215k
  return IA_NO_ERROR;
941
215k
}
942
943
VOID iusace_calc_form_fac_per_chan(ia_psy_mod_out_data_struct *pstr_psy_out_chan,
944
381k
                                   iusace_scratch_mem *pstr_scratch, WORD32 i_ch) {
945
381k
  WORD32 i, j, sfb_offs;
946
381k
  WORD32 sfb, sfb_width;
947
381k
  FLOAT32 *ptr_sfb_form_factor = pstr_scratch->ptr_sfb_form_fac[i_ch];
948
381k
  FLOAT32 *ptr_sfb_num_relevant_lines = pstr_scratch->ptr_sfb_num_relevant_lines[i_ch];
949
381k
  FLOAT32 *ptr_sfb_ld_energy = pstr_scratch->ptr_sfb_ld_energy[i_ch];
950
381k
  FLOAT64 spec_coef = 0;
951
952
381k
  memset(ptr_sfb_num_relevant_lines, 0, sizeof(FLOAT32) * pstr_psy_out_chan->sfb_count);
953
954
1.14M
  for (sfb_offs = 0; sfb_offs < pstr_psy_out_chan->sfb_count;
955
761k
       sfb_offs += pstr_psy_out_chan->sfb_per_group) {
956
761k
    i = sfb_offs;
957
16.5M
    for (sfb = 0; sfb < pstr_psy_out_chan->max_sfb_per_grp; sfb++, i++) {
958
15.8M
      ptr_sfb_form_factor[i] = MIN_FLT_VAL;
959
15.8M
      if (pstr_psy_out_chan->ptr_sfb_energy[i] > pstr_psy_out_chan->ptr_sfb_thr[i]) {
960
8.88M
        FLOAT32 avg_form_factor;
961
962
165M
        for (j = pstr_psy_out_chan->sfb_offsets[i]; j < pstr_psy_out_chan->sfb_offsets[i + 1];
963
156M
             j++) {
964
156M
          spec_coef = fabs(pstr_psy_out_chan->ptr_spec_coeffs[j]);
965
156M
          if (spec_coef < EPS && spec_coef != 0) spec_coef = EPS;
966
156M
          ptr_sfb_form_factor[i] += (FLOAT32)sqrt(spec_coef);
967
156M
        }
968
969
8.88M
        sfb_width = pstr_psy_out_chan->sfb_offsets[i + 1] - pstr_psy_out_chan->sfb_offsets[i];
970
8.88M
        avg_form_factor =
971
8.88M
            (FLOAT32)pow(pstr_psy_out_chan->ptr_sfb_energy[i] / (FLOAT32)sfb_width, 0.25);
972
8.88M
        ptr_sfb_num_relevant_lines[i] = ptr_sfb_form_factor[i] / avg_form_factor;
973
8.88M
        ptr_sfb_ld_energy[i] = (FLOAT32)(log(pstr_psy_out_chan->ptr_sfb_energy[i]) * LOG2_1);
974
8.88M
      }
975
15.8M
    }
976
761k
  }
977
978
381k
  return;
979
381k
}
980
981
VOID iusace_quantize_lines(const WORD32 gain, const WORD32 num_lines, FLOAT32 *ptr_exp_spectrum,
982
3.80M
                           WORD16 *ptr_quant_spectrum, FLOAT32 *ptr_mdct_spec) {
983
3.80M
  FLOAT32 quantizer;
984
3.80M
  FLOAT32 k = 0.4054f;
985
3.80M
  WORD32 line;
986
987
3.80M
  quantizer = ixheaace_fd_quant_table[gain + 128];
988
44.4M
  for (line = 0; line < num_lines; line++) {
989
40.6M
    FLOAT32 tmp = ptr_mdct_spec[line];
990
40.6M
    if (tmp < 0.0f) {
991
7.59M
      ptr_exp_spectrum[line] = (FLOAT32)sqrt(-tmp);
992
7.59M
      ptr_exp_spectrum[line] *= (FLOAT32)sqrt(ptr_exp_spectrum[line]);
993
7.59M
      ptr_quant_spectrum[line] = -ixheaac_sat16((WORD32)(k + quantizer * ptr_exp_spectrum[line]));
994
33.0M
    } else {
995
33.0M
      ptr_exp_spectrum[line] = (FLOAT32)sqrt(tmp);
996
33.0M
      ptr_exp_spectrum[line] *= (FLOAT32)sqrt(ptr_exp_spectrum[line]);
997
33.0M
      ptr_quant_spectrum[line] = ixheaac_sat16((WORD32)(k + quantizer * ptr_exp_spectrum[line]));
998
33.0M
    }
999
40.6M
  }
1000
3.80M
  return;
1001
3.80M
}
1002
1003
VOID iusace_calculate_exp_spec(const WORD32 num_lines, FLOAT32 *ptr_exp_spectrum,
1004
8.45M
                               FLOAT32 *ptr_mdct_spec) {
1005
8.45M
  WORD32 line;
1006
1007
158M
  for (line = 0; line < num_lines; line++) {
1008
149M
    ptr_exp_spectrum[line] = (FLOAT32)sqrt(fabs(ptr_mdct_spec[line]));
1009
149M
    ptr_exp_spectrum[line] *= (FLOAT32)sqrt(ptr_exp_spectrum[line]);
1010
149M
  }
1011
8.45M
  return;
1012
8.45M
}
1013
1014
181M
static WORD32 iusace_scf_delta_bit_count(WORD32 delta) {
1015
181M
  if (delta > 60) {
1016
306
    return (iusace_huffman_code_table[120][0]);
1017
306
  }
1018
181M
  if (delta < -60) {
1019
240
    return (iusace_huffman_code_table[0][0]);
1020
240
  }
1021
181M
  return (iusace_huffman_code_table[delta + 60][0]);
1022
181M
}
1023
1024
36.0M
static WORD32 iusace_count_single_scf_bits(WORD32 scf, WORD32 left_scf, WORD32 right_scf) {
1025
36.0M
  WORD32 scf_bits;
1026
1027
36.0M
  scf_bits =
1028
36.0M
      iusace_scf_delta_bit_count(left_scf - scf) + iusace_scf_delta_bit_count(scf - right_scf);
1029
1030
36.0M
  return scf_bits;
1031
36.0M
}
1032
1033
static FLOAT32 iusace_calc_single_spec_pe(WORD32 scf, FLOAT32 sfb_const_pe_part,
1034
36.0M
                                          FLOAT32 num_lines) {
1035
36.0M
  FLOAT32 spec_pe;
1036
36.0M
  FLOAT32 ld_ratio;
1037
1038
36.0M
  ld_ratio = sfb_const_pe_part - (FLOAT32)0.375f * (FLOAT32)scf;
1039
1040
36.0M
  if (ld_ratio >= PE_C1) {
1041
27.6M
    spec_pe = (FLOAT32)0.7f * num_lines * ld_ratio;
1042
27.6M
  } else {
1043
8.41M
    spec_pe = (FLOAT32)0.7f * num_lines * (PE_C2 + PE_C3 * ld_ratio);
1044
8.41M
  }
1045
1046
36.0M
  return spec_pe;
1047
36.0M
}
1048
1049
static WORD32 iusace_count_scf_bits_diff(WORD16 *ptr_sfb_prev, WORD16 *ptr_sfb_new,
1050
8.33M
                                         WORD32 sfb_count, WORD32 start_sfb, WORD32 stop_sfb) {
1051
8.33M
  WORD32 scf_bits_diff = 0;
1052
8.33M
  WORD32 sfb = 0, sfb_last;
1053
8.33M
  WORD32 sfb_prev, sfb_next;
1054
1055
8.33M
  sfb_last = start_sfb;
1056
1057
8.33M
  while ((sfb_last < stop_sfb) && (ptr_sfb_prev[sfb_last] == SHRT_MIN)) {
1058
0
    sfb_last++;
1059
0
  }
1060
1061
8.33M
  sfb_prev = start_sfb - 1;
1062
1063
16.1M
  while ((sfb_prev >= 0) && (ptr_sfb_prev[sfb_prev] == SHRT_MIN)) {
1064
7.83M
    sfb_prev--;
1065
7.83M
  }
1066
1067
8.33M
  if (sfb_prev >= 0) {
1068
5.57M
    scf_bits_diff += iusace_scf_delta_bit_count(ptr_sfb_new[sfb_prev] - ptr_sfb_new[sfb_last]) -
1069
5.57M
                     iusace_scf_delta_bit_count(ptr_sfb_prev[sfb_prev] - ptr_sfb_prev[sfb_last]);
1070
5.57M
  }
1071
1072
83.3M
  for (sfb = sfb_last + 1; sfb < stop_sfb; sfb++) {
1073
75.0M
    if (ptr_sfb_prev[sfb] != SHRT_MIN) {
1074
42.6M
      scf_bits_diff += iusace_scf_delta_bit_count(ptr_sfb_new[sfb_last] - ptr_sfb_new[sfb]) -
1075
42.6M
                       iusace_scf_delta_bit_count(ptr_sfb_prev[sfb_last] - ptr_sfb_prev[sfb]);
1076
1077
42.6M
      sfb_last = sfb;
1078
42.6M
    }
1079
75.0M
  }
1080
1081
8.33M
  sfb_next = stop_sfb;
1082
1083
8.33M
  while ((sfb_next < sfb_count) && (ptr_sfb_prev[sfb_next] == SHRT_MIN)) {
1084
0
    sfb_next++;
1085
0
  }
1086
1087
8.33M
  if (sfb_next < sfb_count) {
1088
6.19M
    scf_bits_diff += iusace_scf_delta_bit_count(ptr_sfb_new[sfb_last] - ptr_sfb_new[sfb_next]) -
1089
6.19M
                     iusace_scf_delta_bit_count(ptr_sfb_prev[sfb_last] - ptr_sfb_prev[sfb_next]);
1090
6.19M
  }
1091
1092
8.33M
  return scf_bits_diff;
1093
8.33M
}
1094
1095
static FLOAT32 iusace_calc_spec_pe_diff(ia_psy_mod_out_data_struct *pstr_psy_out,
1096
                                        WORD16 *scf_prev, WORD16 *scf_new,
1097
                                        FLOAT32 *ptr_sfb_const_pe_part, FLOAT32 *ptr_sfb_form_fac,
1098
                                        FLOAT32 *ptr_sfb_num_rel_lines, WORD32 start_sfb,
1099
8.33M
                                        WORD32 stop_sfb) {
1100
8.33M
  FLOAT32 spec_pe_diff = 0.0f;
1101
8.33M
  WORD32 sfb;
1102
1103
91.6M
  for (sfb = start_sfb; sfb < stop_sfb; sfb++) {
1104
83.3M
    if (scf_prev[sfb] != SHRT_MIN) {
1105
50.9M
      FLOAT32 ld_ratio_prev, ld_ratio_new, pe_prev, pe_new;
1106
1107
50.9M
      if (ptr_sfb_const_pe_part[sfb] == MIN_FLT_VAL) {
1108
2.43M
        ptr_sfb_const_pe_part[sfb] = (FLOAT32)log(pstr_psy_out->ptr_sfb_energy[sfb] *
1109
2.43M
                                                  (FLOAT32)6.75f / ptr_sfb_form_fac[sfb]) *
1110
2.43M
                                     LOG2_1;
1111
2.43M
      }
1112
1113
50.9M
      ld_ratio_prev = ptr_sfb_const_pe_part[sfb] - 0.375f * scf_prev[sfb];
1114
50.9M
      ld_ratio_new = ptr_sfb_const_pe_part[sfb] - 0.375f * scf_new[sfb];
1115
1116
50.9M
      if (ld_ratio_prev >= PE_C1) {
1117
35.4M
        pe_prev = ld_ratio_prev;
1118
35.4M
      } else {
1119
15.5M
        pe_prev = PE_C2 + PE_C3 * ld_ratio_prev;
1120
15.5M
      }
1121
1122
50.9M
      if (ld_ratio_new >= PE_C1) {
1123
45.2M
        pe_new = ld_ratio_new;
1124
45.2M
      } else {
1125
5.75M
        pe_new = PE_C2 + PE_C3 * ld_ratio_new;
1126
5.75M
      }
1127
1128
50.9M
      spec_pe_diff += (FLOAT32)0.7f * ptr_sfb_num_rel_lines[sfb] * (pe_new - pe_prev);
1129
50.9M
    }
1130
83.3M
  }
1131
1132
8.33M
  return spec_pe_diff;
1133
8.33M
}
1134
1135
FLOAT32 iusace_calc_sfb_dist(const FLOAT32 *ptr_spec, const FLOAT32 *ptr_exp_spec,
1136
51.3M
                             WORD16 *ptr_quant_spec, WORD32 sfb_width, WORD32 gain) {
1137
51.3M
  WORD32 i;
1138
51.3M
  FLOAT32 dist = 0;
1139
51.3M
  FLOAT32 k = 0.4054f;
1140
51.3M
  FLOAT32 quantizer = ixheaace_fd_quant_table[gain + 128];
1141
51.3M
  FLOAT32 inv_quantizer = ixheaace_fd_inv_quant_table[gain + 128];
1142
1143
799M
  for (i = 0; i < sfb_width; i++) {
1144
748M
    FLOAT32 iq_val;
1145
748M
    FLOAT32 diff;
1146
1147
748M
    ptr_quant_spec[i] = ixheaac_sat16((WORD32)(k + quantizer * ptr_exp_spec[i]));
1148
1149
748M
    if (ptr_quant_spec[i] < 64) {
1150
726M
      iq_val = ixheaace_pow_4_3_table[ptr_quant_spec[i]] * inv_quantizer;
1151
726M
    } else {
1152
21.8M
      iq_val = (FLOAT32)((pow((FLOAT32)abs(ptr_quant_spec[i]), 4.0f / 3.0f)) * inv_quantizer);
1153
21.8M
    }
1154
1155
748M
    diff = (FLOAT32)fabs(ptr_spec[i]) - iq_val;
1156
1157
748M
    dist += diff * diff;
1158
748M
  }
1159
1160
51.3M
  return dist;
1161
51.3M
}
1162
1163
static WORD16 iusace_improve_scf(FLOAT32 *ptr_spec, FLOAT32 *ptr_exp_spec, WORD16 *ptr_quant_spec,
1164
                                 WORD16 *ptr_quant_spec_temp, WORD32 sfb_width, FLOAT32 threshold,
1165
                                 WORD16 scf, WORD16 min_scf, FLOAT32 *dist,
1166
8.45M
                                 WORD16 *ptr_min_calc_scf) {
1167
8.45M
  FLOAT32 sfb_dist;
1168
8.45M
  WORD16 best_scf = scf;
1169
8.45M
  WORD32 j;
1170
1171
8.45M
  sfb_dist = iusace_calc_sfb_dist(ptr_spec, ptr_exp_spec, ptr_quant_spec, sfb_width, scf);
1172
1173
8.45M
  *ptr_min_calc_scf = scf;
1174
1175
8.45M
  if (sfb_dist > (1.25 * threshold)) {
1176
1.61M
    WORD16 estimated_scf = scf;
1177
1.61M
    FLOAT32 best_sfb_dist = sfb_dist;
1178
1.61M
    WORD32 count;
1179
1180
1.61M
    count = 0;
1181
1182
4.89M
    while ((sfb_dist > (1.25 * threshold)) && (count++ < SCF_COUNT_LIMIT_THREE)) {
1183
3.28M
      scf++;
1184
1185
3.28M
      sfb_dist =
1186
3.28M
          iusace_calc_sfb_dist(ptr_spec, ptr_exp_spec, ptr_quant_spec_temp, sfb_width, scf);
1187
1188
3.28M
      if (sfb_dist < best_sfb_dist) {
1189
1.15M
        best_scf = scf;
1190
1.15M
        best_sfb_dist = sfb_dist;
1191
1192
1.15M
        memcpy(ptr_quant_spec, ptr_quant_spec_temp, sfb_width * sizeof(WORD16));
1193
1.15M
      }
1194
3.28M
    }
1195
1196
1.61M
    count = 0;
1197
1.61M
    scf = estimated_scf;
1198
1.61M
    sfb_dist = best_sfb_dist;
1199
1200
2.28M
    while ((sfb_dist > (1.25 * threshold)) && (count++ < SCF_COUNT_LIMIT_ONE) &&
1201
681k
      (scf > min_scf)) {
1202
675k
      scf--;
1203
1204
675k
      sfb_dist =
1205
675k
          iusace_calc_sfb_dist(ptr_spec, ptr_exp_spec, ptr_quant_spec_temp, sfb_width, scf);
1206
1207
675k
      if (sfb_dist < best_sfb_dist) {
1208
604k
        best_scf = scf;
1209
604k
        best_sfb_dist = sfb_dist;
1210
1211
604k
        memcpy(ptr_quant_spec, ptr_quant_spec_temp, sfb_width * sizeof(WORD16));
1212
604k
      }
1213
675k
      *ptr_min_calc_scf = scf;
1214
675k
    }
1215
1.61M
    *dist = best_sfb_dist;
1216
6.84M
  } else {
1217
6.84M
    FLOAT32 best_sfb_dist = sfb_dist;
1218
6.84M
    FLOAT32 allowed_sfb_dist = MIN(sfb_dist * 1.25f, threshold);
1219
6.84M
    WORD32 count;
1220
1221
27.3M
    for (count = 0; count < SCF_COUNT_LIMIT_THREE; count++) {
1222
20.5M
      scf++;
1223
1224
20.5M
      sfb_dist =
1225
20.5M
          iusace_calc_sfb_dist(ptr_spec, ptr_exp_spec, ptr_quant_spec_temp, sfb_width, scf);
1226
1227
20.5M
      if (sfb_dist < allowed_sfb_dist) {
1228
3.63M
        *ptr_min_calc_scf = best_scf + 1;
1229
1230
3.63M
        best_scf = scf;
1231
3.63M
        best_sfb_dist = sfb_dist;
1232
3.63M
        memcpy(ptr_quant_spec, ptr_quant_spec_temp, sfb_width * sizeof(WORD16));
1233
3.63M
      }
1234
20.5M
    }
1235
6.84M
    *dist = best_sfb_dist;
1236
6.84M
  }
1237
1238
158M
  for (j = 0; j < sfb_width; j++) {
1239
149M
    if (ptr_spec[j] < 0) {
1240
71.4M
      ptr_quant_spec[j] = -ptr_quant_spec[j];
1241
71.4M
    }
1242
149M
  }
1243
1244
8.45M
  return best_scf;
1245
8.45M
}
1246
1247
static VOID iusace_assimilate_single_scf(ia_psy_mod_out_data_struct *pstr_psy_out,
1248
                                         FLOAT32 *ptr_exp_spec, WORD16 *ptr_quant_spec,
1249
                                         WORD16 *ptr_quant_spec_temp, WORD16 *scf,
1250
                                         WORD16 *ptr_min_scf, FLOAT32 *ptr_sfb_dist,
1251
                                         FLOAT32 *ptr_sfb_const_pe_part,
1252
                                         FLOAT32 *ptr_sfb_form_fac, FLOAT32 *ptr_sfb_num_lines,
1253
381k
                                         WORD16 *ptr_min_calc_scf, FLOAT32 *ptr_mdct_spec_float) {
1254
381k
  WORD32 sfb_prev, sfb_act, sfb_next;
1255
381k
  WORD16 scf_act = 0, *scf_prev, *scf_next, min_scf, max_scf;
1256
381k
  WORD32 sfb_width, sfb_offs;
1257
381k
  FLOAT32 energy;
1258
381k
  FLOAT32 sfb_pe_prev, sfb_pe_new;
1259
381k
  FLOAT32 sfb_dist_new;
1260
381k
  WORD32 j;
1261
381k
  WORD32 success = 0;
1262
381k
  FLOAT32 delta_pe = 0.0f, delta_pe_new, delta_pe_temp;
1263
381k
  WORD16 prev_scf_last[MAX_NUM_GROUPED_SFB], prev_scf_next[MAX_NUM_GROUPED_SFB];
1264
381k
  FLOAT32 delta_pe_last[MAX_NUM_GROUPED_SFB];
1265
381k
  WORD32 update_min_scf;
1266
1267
18.1M
  for (j = 0; j < pstr_psy_out->sfb_count; j++) {
1268
17.7M
    prev_scf_last[j] = SHRT_MAX;
1269
17.7M
    prev_scf_next[j] = SHRT_MAX;
1270
17.7M
    delta_pe_last[j] = MAX_FLT_VAL;
1271
17.7M
  }
1272
1273
381k
  sfb_prev = -1;
1274
381k
  sfb_act = -1;
1275
381k
  sfb_next = -1;
1276
381k
  scf_prev = 0;
1277
381k
  scf_next = 0;
1278
381k
  min_scf = SHRT_MAX;
1279
381k
  max_scf = SHRT_MAX;
1280
1281
38.5M
  do {
1282
38.5M
    sfb_next++;
1283
1284
60.6M
    while ((sfb_next < pstr_psy_out->sfb_count) && (scf[sfb_next] == SHRT_MIN)) {
1285
22.1M
      sfb_next++;
1286
22.1M
    }
1287
1288
38.5M
    if ((sfb_prev >= 0) && (sfb_act >= 0) && (sfb_next < pstr_psy_out->sfb_count)) {
1289
32.4M
      scf_act = scf[sfb_act];
1290
1291
32.4M
      scf_prev = scf + sfb_prev;
1292
32.4M
      scf_next = scf + sfb_next;
1293
1294
32.4M
      min_scf = MIN(*scf_prev, *scf_next);
1295
1296
32.4M
      max_scf = MAX(*scf_prev, *scf_next);
1297
32.4M
    } else {
1298
6.09M
      if ((sfb_prev == -1) && (sfb_act >= 0) && (sfb_next < pstr_psy_out->sfb_count)) {
1299
2.83M
        scf_act = scf[sfb_act];
1300
1301
2.83M
        scf_prev = &scf_act;
1302
1303
2.83M
        scf_next = scf + sfb_next;
1304
1305
2.83M
        min_scf = *scf_next;
1306
1307
2.83M
        max_scf = *scf_next;
1308
3.25M
      } else {
1309
3.25M
        if ((sfb_prev >= 0) && (sfb_act >= 0) && (sfb_next == pstr_psy_out->sfb_count)) {
1310
316k
          scf_act = scf[sfb_act];
1311
1312
316k
          scf_prev = scf + sfb_prev;
1313
1314
316k
          scf_next = &scf_act;
1315
1316
316k
          min_scf = *scf_prev;
1317
1318
316k
          max_scf = *scf_prev;
1319
316k
        }
1320
3.25M
      }
1321
6.09M
    }
1322
1323
38.5M
    if (sfb_act >= 0) {
1324
35.6M
      min_scf = MAX(min_scf, ptr_min_scf[sfb_act]);
1325
35.6M
    }
1326
1327
38.5M
    if ((sfb_act >= 0) && (sfb_prev >= 0 || sfb_next < pstr_psy_out->sfb_count) &&
1328
35.6M
        (scf_act > min_scf) && (scf_act <= min_scf + MAX_SCF_DELTA) &&
1329
16.9M
        (scf_act >= max_scf - MAX_SCF_DELTA) &&
1330
16.9M
        (*scf_prev != prev_scf_last[sfb_act] || *scf_next != prev_scf_next[sfb_act] ||
1331
9.64M
         delta_pe < delta_pe_last[sfb_act])) {
1332
9.64M
      success = 0;
1333
1334
9.64M
      sfb_width = pstr_psy_out->sfb_offsets[sfb_act + 1] - pstr_psy_out->sfb_offsets[sfb_act];
1335
1336
9.64M
      sfb_offs = pstr_psy_out->sfb_offsets[sfb_act];
1337
1338
9.64M
      energy = pstr_psy_out->ptr_sfb_energy[sfb_act];
1339
1340
9.64M
      if (ptr_sfb_const_pe_part[sfb_act] == MIN_FLT_VAL) {
1341
5.23M
        ptr_sfb_const_pe_part[sfb_act] =
1342
5.23M
            (FLOAT32)log(energy * (FLOAT32)6.75f / ptr_sfb_form_fac[sfb_act]) * LOG2_1;
1343
5.23M
      }
1344
1345
9.64M
      sfb_pe_prev = iusace_calc_single_spec_pe(scf_act, ptr_sfb_const_pe_part[sfb_act],
1346
9.64M
                                               ptr_sfb_num_lines[sfb_act]) +
1347
9.64M
                    iusace_count_single_scf_bits(scf_act, *scf_prev, *scf_next);
1348
1349
9.64M
      delta_pe_new = delta_pe;
1350
9.64M
      update_min_scf = 1;
1351
1352
33.6M
      do {
1353
33.6M
        scf_act--;
1354
1355
33.6M
        if (scf_act < ptr_min_calc_scf[sfb_act] && scf_act >= max_scf - MAX_SCF_DELTA) {
1356
26.4M
          sfb_pe_new = iusace_calc_single_spec_pe(scf_act, ptr_sfb_const_pe_part[sfb_act],
1357
26.4M
                                                  ptr_sfb_num_lines[sfb_act]) +
1358
26.4M
                       (FLOAT32)iusace_count_single_scf_bits(scf_act, *scf_prev, *scf_next);
1359
1360
26.4M
          delta_pe_temp = delta_pe + sfb_pe_new - sfb_pe_prev;
1361
1362
26.4M
          if (delta_pe_temp < (FLOAT32)10.0f) {
1363
9.84M
            sfb_dist_new =
1364
9.84M
                iusace_calc_sfb_dist(ptr_mdct_spec_float + sfb_offs, ptr_exp_spec + sfb_offs,
1365
9.84M
                                     ptr_quant_spec_temp + sfb_offs, sfb_width, scf_act);
1366
1367
9.84M
            if (sfb_dist_new < ptr_sfb_dist[sfb_act]) {
1368
4.63M
              scf[sfb_act] = scf_act;
1369
4.63M
              ptr_sfb_dist[sfb_act] = sfb_dist_new;
1370
1371
41.2M
              for (j = sfb_offs; j < sfb_offs + sfb_width; j++) {
1372
36.5M
                ptr_quant_spec[j] = ptr_quant_spec_temp[j];
1373
1374
36.5M
                if (ptr_mdct_spec_float[j] < 0.0f) {
1375
16.6M
                  ptr_quant_spec[j] = -ptr_quant_spec[j];
1376
16.6M
                }
1377
36.5M
              }
1378
4.63M
              delta_pe_new = delta_pe_temp;
1379
4.63M
              success = 1;
1380
4.63M
            }
1381
1382
9.84M
            if (update_min_scf) {
1383
9.35M
              ptr_min_calc_scf[sfb_act] = scf_act;
1384
9.35M
            }
1385
16.5M
          } else {
1386
16.5M
            update_min_scf = 0;
1387
16.5M
          }
1388
26.4M
        }
1389
33.6M
      } while (scf_act > min_scf);
1390
1391
9.64M
      delta_pe = delta_pe_new;
1392
1393
9.64M
      prev_scf_last[sfb_act] = *scf_prev;
1394
9.64M
      prev_scf_next[sfb_act] = *scf_next;
1395
9.64M
      delta_pe_last[sfb_act] = delta_pe;
1396
9.64M
    }
1397
1398
38.5M
    if (success) {
1399
2.55M
      sfb_prev = -1;
1400
2.55M
      sfb_act = -1;
1401
2.55M
      sfb_next = -1;
1402
2.55M
      scf_prev = 0;
1403
2.55M
      scf_next = 0;
1404
2.55M
      min_scf = SHRT_MAX;
1405
2.55M
      max_scf = SHRT_MAX;
1406
2.55M
      success = 0;
1407
35.9M
    } else {
1408
35.9M
      sfb_prev = sfb_act;
1409
35.9M
      sfb_act = sfb_next;
1410
35.9M
    }
1411
38.5M
  } while (sfb_next < pstr_psy_out->sfb_count);
1412
381k
  return;
1413
381k
}
1414
1415
static VOID iusace_assimilate_multiple_scf(ia_psy_mod_out_data_struct *pstr_psy_out,
1416
                                           FLOAT32 *ptr_exp_spec, WORD16 *ptr_quant_spec,
1417
                                           WORD16 *ptr_quant_spec_temp, WORD16 *ptr_scf,
1418
                                           WORD16 *ptr_min_scf, FLOAT32 *ptr_sfb_dist,
1419
                                           FLOAT32 *ptr_sfb_const_pe_part,
1420
                                           FLOAT32 *ptr_sfb_form_fac, FLOAT32 *ptr_sfb_num_lines,
1421
381k
                                           FLOAT32 *ptr_mdct_spec_float, pUWORD8 pstr_scratch) {
1422
381k
  WORD32 sfb, start_sfb, stop_sfb;
1423
381k
  WORD16 scf_temp[MAX_NUM_GROUPED_SFB], min_scf, max_scf, scf_act;
1424
381k
  WORD32 possible_region_found;
1425
381k
  WORD32 sfb_width, sfb_offs, j;
1426
381k
  FLOAT32 prev_dist_sum, new_dist_sum;
1427
381k
  WORD32 delta_scf_bits;
1428
381k
  FLOAT32 delta_spec_pe;
1429
381k
  FLOAT32 delta_pe = 0.0f, delta_pe_new;
1430
381k
  WORD32 sfb_count = pstr_psy_out->sfb_count;
1431
381k
  FLOAT32 *sfb_dist_new = (FLOAT32 *)pstr_scratch;
1432
381k
  min_scf = SHRT_MAX;
1433
381k
  max_scf = SHRT_MIN;
1434
1435
18.1M
  for (sfb = 0; sfb < sfb_count; sfb++) {
1436
17.7M
    if (ptr_scf[sfb] != SHRT_MIN) {
1437
8.45M
      min_scf = MIN(min_scf, ptr_scf[sfb]);
1438
1439
8.45M
      max_scf = MAX(max_scf, ptr_scf[sfb]);
1440
8.45M
    }
1441
17.7M
  }
1442
1443
381k
  if (max_scf != SHRT_MIN && max_scf <= min_scf + MAX_SCF_DELTA) {
1444
288k
    scf_act = max_scf;
1445
1446
5.18M
    do {
1447
5.18M
      scf_act--;
1448
1449
5.18M
      memcpy(scf_temp, ptr_scf, MAX_NUM_GROUPED_SFB * sizeof(WORD16));
1450
1451
5.18M
      stop_sfb = 0;
1452
1453
14.6M
      do {
1454
14.6M
        sfb = stop_sfb;
1455
1456
164M
        while (sfb < sfb_count && (ptr_scf[sfb] == SHRT_MIN || ptr_scf[sfb] <= scf_act)) {
1457
149M
          sfb++;
1458
149M
        }
1459
1460
14.6M
        start_sfb = sfb;
1461
1462
14.6M
        sfb++;
1463
1464
101M
        while (sfb < sfb_count && (ptr_scf[sfb] == SHRT_MIN || ptr_scf[sfb] > scf_act)) {
1465
86.4M
          sfb++;
1466
86.4M
        }
1467
1468
14.6M
        stop_sfb = sfb;
1469
1470
14.6M
        possible_region_found = 0;
1471
1472
14.6M
        if (start_sfb < sfb_count) {
1473
9.47M
          possible_region_found = 1;
1474
1475
93.2M
          for (sfb = start_sfb; sfb < stop_sfb; sfb++) {
1476
84.9M
            if (ptr_scf[sfb] != SHRT_MIN) {
1477
52.4M
              if (scf_act < ptr_min_scf[sfb]) {
1478
1.14M
                possible_region_found = 0;
1479
1.14M
                break;
1480
1.14M
              }
1481
52.4M
            }
1482
84.9M
          }
1483
9.47M
        }
1484
1485
14.6M
        if (possible_region_found) {
1486
91.6M
          for (sfb = start_sfb; sfb < stop_sfb; sfb++) {
1487
83.3M
            if (scf_temp[sfb] != SHRT_MIN) {
1488
50.9M
              scf_temp[sfb] = scf_act;
1489
50.9M
            }
1490
83.3M
          }
1491
1492
8.33M
          delta_scf_bits =
1493
8.33M
              iusace_count_scf_bits_diff(ptr_scf, scf_temp, sfb_count, start_sfb, stop_sfb);
1494
1495
8.33M
          delta_spec_pe =
1496
8.33M
              iusace_calc_spec_pe_diff(pstr_psy_out, ptr_scf, scf_temp, ptr_sfb_const_pe_part,
1497
8.33M
                                       ptr_sfb_form_fac, ptr_sfb_num_lines, start_sfb, stop_sfb);
1498
1499
8.33M
          delta_pe_new = delta_pe + (FLOAT32)delta_scf_bits + delta_spec_pe;
1500
1501
8.33M
          if (delta_pe_new < (FLOAT32)10.0f) {
1502
3.64M
            prev_dist_sum = new_dist_sum = 0.0f;
1503
1504
21.4M
            for (sfb = start_sfb; sfb < stop_sfb; sfb++) {
1505
18.9M
              if (scf_temp[sfb] != SHRT_MIN) {
1506
8.51M
                prev_dist_sum += ptr_sfb_dist[sfb];
1507
1508
8.51M
                sfb_width = pstr_psy_out->sfb_offsets[sfb + 1] - pstr_psy_out->sfb_offsets[sfb];
1509
1510
8.51M
                sfb_offs = pstr_psy_out->sfb_offsets[sfb];
1511
1512
8.51M
                sfb_dist_new[sfb] =
1513
8.51M
                    iusace_calc_sfb_dist(ptr_mdct_spec_float + sfb_offs, ptr_exp_spec + sfb_offs,
1514
8.51M
                                         ptr_quant_spec_temp + sfb_offs, sfb_width, scf_act);
1515
1516
8.51M
                if (sfb_dist_new[sfb] > pstr_psy_out->ptr_sfb_thr[sfb]) {
1517
1.11M
                  new_dist_sum = (FLOAT32)2.0f * prev_dist_sum;
1518
1.11M
                  break;
1519
1.11M
                }
1520
1521
7.40M
                new_dist_sum += sfb_dist_new[sfb];
1522
7.40M
              }
1523
18.9M
            }
1524
1525
3.64M
            if (new_dist_sum < prev_dist_sum) {
1526
612k
              delta_pe = delta_pe_new;
1527
1528
4.03M
              for (sfb = start_sfb; sfb < stop_sfb; sfb++) {
1529
3.42M
                if (ptr_scf[sfb] != SHRT_MIN) {
1530
1.60M
                  sfb_width = pstr_psy_out->sfb_offsets[sfb + 1] - pstr_psy_out->sfb_offsets[sfb];
1531
1532
1.60M
                  sfb_offs = pstr_psy_out->sfb_offsets[sfb];
1533
1.60M
                  ptr_scf[sfb] = scf_act;
1534
1.60M
                  ptr_sfb_dist[sfb] = sfb_dist_new[sfb];
1535
1536
19.3M
                  for (j = sfb_offs; j < sfb_offs + sfb_width; j++) {
1537
17.7M
                    ptr_quant_spec[j] = ptr_quant_spec_temp[j];
1538
1539
17.7M
                    if (ptr_mdct_spec_float[j] < 0.0f) {
1540
7.68M
                      ptr_quant_spec[j] = -ptr_quant_spec[j];
1541
7.68M
                    }
1542
17.7M
                  }
1543
1.60M
                }
1544
3.42M
              }
1545
612k
            }
1546
3.64M
          }
1547
8.33M
        }
1548
1549
14.6M
      } while (stop_sfb <= sfb_count);
1550
1551
5.18M
    } while (scf_act > min_scf);
1552
288k
  }
1553
381k
  return;
1554
381k
}
1555
1556
VOID iusace_estimate_scfs_chan(ia_psy_mod_out_data_struct *pstr_psy_out,
1557
                               ia_qc_out_chan_struct *str_qc_out_chan, WORD32 num_channels,
1558
215k
                               WORD32 chn, iusace_scratch_mem *pstr_scratch) {
1559
215k
  WORD16 *ptr_scalefactor;
1560
215k
  WORD32 *global_gain;
1561
215k
  FLOAT32 *p_sfb_form_factor;
1562
215k
  FLOAT32 *p_sfb_num_relevant_lines;
1563
215k
  WORD16 *ptr_quant_spec;
1564
215k
  WORD32 i, ch, j, idx = 0;
1565
215k
  FLOAT32 thresh, energy, energy_part, thr_part;
1566
215k
  FLOAT32 scf_float;
1567
215k
  WORD16 scf_int = 0, min_scf = 0, max_scf = 0;
1568
215k
  FLOAT64 max_spec = 0.0f;
1569
215k
  WORD16 min_sf_max_quant[MAX_NUM_GROUPED_SFB] = {0};
1570
215k
  pUWORD8 ptr_scratch = pstr_scratch->ptr_fd_scratch;
1571
215k
  FLOAT32 *ptr_sfb_dist = (FLOAT32 *)ptr_scratch;
1572
215k
  ptr_scratch += MAX_NUM_GROUPED_SFB * sizeof(ptr_sfb_dist[0]);
1573
215k
  WORD16 min_calc_scf[MAX_NUM_GROUPED_SFB] = {0};
1574
1575
215k
  WORD16 *ptr_quant_spec_temp = pstr_scratch->p_adjthr_quant_spec_temp;
1576
215k
  FLOAT32 *ptr_exp_spec = pstr_scratch->p_adjthr_ptr_exp_spec;
1577
215k
  FLOAT32 *ptr_mdct_spec_float = pstr_scratch->p_adjthr_mdct_spec_float;
1578
215k
  FLOAT32 *sfb_const_pe_part = (FLOAT32 *)ptr_scratch;
1579
1580
215k
  FLOAT32 **ptr_sfb_form_factor = &pstr_scratch->ptr_sfb_form_fac[0];
1581
215k
  FLOAT32 **ptr_sfb_num_relevant_lines = &pstr_scratch->ptr_sfb_num_relevant_lines[0];
1582
1583
215k
  ptr_scratch += MAX_NUM_GROUPED_SFB * sizeof(sfb_const_pe_part[0]);
1584
1585
215k
  memset(ptr_quant_spec_temp, 0, FRAME_LEN_LONG * sizeof(WORD16));
1586
215k
  memset(ptr_mdct_spec_float, 0, FRAME_LEN_LONG * sizeof(FLOAT32));
1587
215k
  memset(ptr_exp_spec, 0, FRAME_LEN_LONG * sizeof(FLOAT32));
1588
215k
  memset(ptr_sfb_dist, 0, MAX_NUM_GROUPED_SFB * sizeof(FLOAT32));
1589
596k
  for (ch = chn; ch < chn + num_channels; ch++) {
1590
381k
    ia_psy_mod_out_data_struct *ptr_psy_out = &pstr_psy_out[ch];
1591
381k
    str_qc_out_chan[idx].global_gain = 0;
1592
1593
381k
    memset(str_qc_out_chan[idx].scalefactor, 0,
1594
381k
           sizeof(str_qc_out_chan[idx].scalefactor[0]) * pstr_psy_out[ch].sfb_count);
1595
381k
    memset(str_qc_out_chan[idx].quant_spec, 0,
1596
381k
           sizeof(str_qc_out_chan[idx].quant_spec[0]) * FRAME_LEN_LONG);
1597
1598
381k
    ptr_scalefactor = str_qc_out_chan[idx].scalefactor;
1599
381k
    global_gain = &str_qc_out_chan[idx].global_gain;
1600
381k
    p_sfb_form_factor = &ptr_sfb_form_factor[idx][0];
1601
381k
    p_sfb_num_relevant_lines = &ptr_sfb_num_relevant_lines[idx][0];
1602
381k
    ptr_quant_spec = str_qc_out_chan[idx].quant_spec;
1603
18.1M
    for (i = 0; i < ptr_psy_out->sfb_count; i++) {
1604
17.7M
      thresh = ptr_psy_out->ptr_sfb_thr[i];
1605
17.7M
      energy = ptr_psy_out->ptr_sfb_energy[i];
1606
17.7M
      max_spec = 0.0;
1607
1608
378M
      for (j = ptr_psy_out->sfb_offsets[i]; j < ptr_psy_out->sfb_offsets[i + 1]; j++) {
1609
360M
        max_spec = MAX(max_spec, fabs(ptr_psy_out->ptr_spec_coeffs[j]));
1610
360M
      }
1611
1612
17.7M
      ptr_scalefactor[i] = MIN_SHRT_VAL;
1613
17.7M
      min_sf_max_quant[i] = MIN_SHRT_VAL;
1614
1615
17.7M
      if ((max_spec > 0.0) && (energy > thresh) && (p_sfb_form_factor[i] != MIN_FLT_VAL)) {
1616
8.45M
        energy_part = (FLOAT32)log10(p_sfb_form_factor[i] + FLT_EPSILON);
1617
1618
8.45M
        thr_part = (FLOAT32)log10(6.75 * thresh + MIN_FLT_VAL);
1619
8.45M
        scf_float = 8.8585f * (thr_part - energy_part);
1620
8.45M
        scf_int = (WORD16)floor(scf_float);
1621
8.45M
        min_sf_max_quant[i] = (WORD16)ceil(C1_SF + C2_SF * log(max_spec));
1622
8.45M
        scf_int = MAX(scf_int, min_sf_max_quant[i]);
1623
8.45M
        scf_int = MAX(scf_int, MIN_GAIN_INDEX);
1624
8.45M
        scf_int = MIN(scf_int, (MAX_GAIN_INDEX - SCF_COUNT_LIMIT_THREE));
1625
158M
        for (j = 0; j < ptr_psy_out->sfb_offsets[i + 1] - ptr_psy_out->sfb_offsets[i]; j++) {
1626
149M
          ptr_exp_spec[ptr_psy_out->sfb_offsets[i] + j] =
1627
149M
              (FLOAT32)(ptr_psy_out->ptr_spec_coeffs[ptr_psy_out->sfb_offsets[i] + j]);
1628
149M
          ptr_mdct_spec_float[ptr_psy_out->sfb_offsets[i] + j] =
1629
149M
              (FLOAT32)(ptr_psy_out->ptr_spec_coeffs[ptr_psy_out->sfb_offsets[i] + j]);
1630
149M
        }
1631
1632
8.45M
        iusace_calculate_exp_spec(ptr_psy_out->sfb_offsets[i + 1] - ptr_psy_out->sfb_offsets[i],
1633
8.45M
                                  ptr_exp_spec + ptr_psy_out->sfb_offsets[i],
1634
8.45M
                                  ptr_mdct_spec_float + ptr_psy_out->sfb_offsets[i]);
1635
1636
8.45M
        scf_int = iusace_improve_scf(
1637
8.45M
            ptr_mdct_spec_float + ptr_psy_out->sfb_offsets[i],
1638
8.45M
            ptr_exp_spec + ptr_psy_out->sfb_offsets[i],
1639
8.45M
            ptr_quant_spec + ptr_psy_out->sfb_offsets[i],
1640
8.45M
            ptr_quant_spec_temp + ptr_psy_out->sfb_offsets[i],
1641
8.45M
            ptr_psy_out->sfb_offsets[i + 1] - ptr_psy_out->sfb_offsets[i], thresh, scf_int,
1642
8.45M
            min_sf_max_quant[i], &ptr_sfb_dist[i], &min_calc_scf[i]);
1643
1644
8.45M
        ptr_scalefactor[i] = scf_int;
1645
8.45M
      }
1646
17.7M
    }
1647
1648
18.1M
    for (i = 0; i < ptr_psy_out->sfb_count; i++) {
1649
17.7M
      sfb_const_pe_part[i] = MIN_FLT_VAL;
1650
17.7M
    }
1651
1652
381k
    iusace_assimilate_single_scf(ptr_psy_out, ptr_exp_spec, ptr_quant_spec, ptr_quant_spec_temp,
1653
381k
                                 ptr_scalefactor, min_sf_max_quant, ptr_sfb_dist,
1654
381k
                                 sfb_const_pe_part, p_sfb_form_factor, p_sfb_num_relevant_lines,
1655
381k
                                 min_calc_scf, ptr_mdct_spec_float);
1656
1657
381k
    iusace_assimilate_multiple_scf(ptr_psy_out, ptr_exp_spec, ptr_quant_spec, ptr_quant_spec_temp,
1658
381k
                                   ptr_scalefactor, min_sf_max_quant, ptr_sfb_dist,
1659
381k
                                   sfb_const_pe_part, p_sfb_form_factor, p_sfb_num_relevant_lines,
1660
381k
                                   ptr_mdct_spec_float, ptr_scratch);
1661
1662
381k
    max_scf = MIN_SHRT_VAL;
1663
381k
    min_scf = MAX_SHRT_VAL;
1664
18.1M
    for (i = 0; i < ptr_psy_out->sfb_count; i++) {
1665
17.7M
      if (max_scf < ptr_scalefactor[i]) {
1666
772k
        max_scf = ptr_scalefactor[i];
1667
772k
      }
1668
17.7M
      if ((ptr_scalefactor[i] != MIN_SHRT_VAL) && (min_scf > ptr_scalefactor[i])) {
1669
1.37M
        min_scf = ptr_scalefactor[i];
1670
1.37M
      }
1671
17.7M
    }
1672
1673
18.1M
    for (i = 0; i < pstr_psy_out[ch].sfb_count; i++) {
1674
17.7M
      if ((ptr_scalefactor[i] != MIN_SHRT_VAL) &&
1675
8.45M
          (min_scf + MAX_SCF_DELTA) < ptr_scalefactor[i]) {
1676
2.93k
        ptr_scalefactor[i] = min_scf + MAX_SCF_DELTA;
1677
1678
2.93k
        iusace_calc_sfb_dist(ptr_mdct_spec_float + ptr_psy_out->sfb_offsets[i],
1679
2.93k
                             ptr_exp_spec + ptr_psy_out->sfb_offsets[i],
1680
2.93k
                             ptr_quant_spec + ptr_psy_out->sfb_offsets[i],
1681
2.93k
                             ptr_psy_out->sfb_offsets[i + 1] - ptr_psy_out->sfb_offsets[i],
1682
2.93k
                             ptr_scalefactor[i]);
1683
2.93k
      }
1684
17.7M
    }
1685
1686
381k
    max_scf = MIN((min_scf + MAX_SCF_DELTA), max_scf);
1687
1688
381k
    if (max_scf > MIN_SHRT_VAL) {
1689
290k
      *global_gain = max_scf;
1690
13.9M
      for (i = 0; i < ptr_psy_out->sfb_count; i++) {
1691
13.6M
        if (ptr_scalefactor[i] == MIN_SHRT_VAL) {
1692
5.17M
          ptr_scalefactor[i] = 0;
1693
5.17M
          memset(
1694
5.17M
              &ptr_psy_out->ptr_spec_coeffs[ptr_psy_out->sfb_offsets[i]], 0,
1695
5.17M
              (ptr_psy_out->sfb_offsets[i + 1] - ptr_psy_out->sfb_offsets[i]) * sizeof(FLOAT64));
1696
8.45M
        } else {
1697
8.45M
          ptr_scalefactor[i] = max_scf - ptr_scalefactor[i];
1698
8.45M
        }
1699
13.6M
      }
1700
290k
    } else {
1701
91.0k
      *global_gain = 0;
1702
4.22M
      for (i = 0; i < ptr_psy_out->sfb_count; i++) {
1703
4.13M
        ptr_scalefactor[i] = 0;
1704
4.13M
        memset(&ptr_psy_out->ptr_spec_coeffs[ptr_psy_out->sfb_offsets[i]], 0,
1705
4.13M
               (ptr_psy_out->sfb_offsets[i + 1] - ptr_psy_out->sfb_offsets[i]) * sizeof(FLOAT64));
1706
4.13M
      }
1707
91.0k
    }
1708
381k
    idx++;
1709
381k
  }
1710
1711
215k
  return;
1712
215k
}