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