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