Coverage Report

Created: 2026-08-31 07:12

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