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