/src/libxaac/encoder/ixheaace_adjust_threshold.c
Line | Count | Source (jump to first uncovered line) |
1 | | /****************************************************************************** |
2 | | * * |
3 | | * Copyright (C) 2023 The Android Open Source Project |
4 | | * |
5 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
6 | | * you may not use this file except in compliance with the License. |
7 | | * You may obtain a copy of the License at: |
8 | | * |
9 | | * http://www.apache.org/licenses/LICENSE-2.0 |
10 | | * |
11 | | * Unless required by applicable law or agreed to in writing, software |
12 | | * distributed under the License is distributed on an "AS IS" BASIS, |
13 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | | * See the License for the specific language governing permissions and |
15 | | * limitations under the License. |
16 | | * |
17 | | ***************************************************************************** |
18 | | * Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore |
19 | | */ |
20 | | |
21 | | #include <float.h> |
22 | | #include <math.h> |
23 | | #include <stdlib.h> |
24 | | |
25 | | #include <string.h> |
26 | | |
27 | | #include "ixheaac_type_def.h" |
28 | | #include "ixheaac_constants.h" |
29 | | #include "impd_drc_common_enc.h" |
30 | | #include "impd_drc_uni_drc.h" |
31 | | #include "impd_drc_tables.h" |
32 | | #include "impd_drc_api.h" |
33 | | #include "ixheaace_api.h" |
34 | | #include "ixheaace_aac_constants.h" |
35 | | #include "ixheaace_psy_const.h" |
36 | | #include "ixheaace_tns.h" |
37 | | #include "ixheaace_tns_params.h" |
38 | | #include "ixheaace_rom.h" |
39 | | |
40 | | #include "ixheaac_basic_ops32.h" |
41 | | #include "ixheaac_basic_ops16.h" |
42 | | #include "ixheaac_basic_ops40.h" |
43 | | #include "ixheaac_basic_ops.h" |
44 | | |
45 | | #include "ixheaace_common_rom.h" |
46 | | #include "ixheaace_bitbuffer.h" |
47 | | #include "ixheaace_adjust_threshold_data.h" |
48 | | #include "ixheaace_dynamic_bits.h" |
49 | | #include "ixheaace_qc_data.h" |
50 | | #include "ixheaace_block_switch.h" |
51 | | #include "ixheaace_psy_data.h" |
52 | | #include "ixheaace_interface.h" |
53 | | #include "ixheaace_adjust_threshold.h" |
54 | | #include "ixheaace_common_utils.h" |
55 | | |
56 | | VOID iaace_adj_thr_init(ia_adj_thr_state_struct *pstr_adj_thr_state, const FLOAT32 mean_pe, |
57 | 6.85k | WORD32 ch_bitrate, WORD32 aot) { |
58 | 6.85k | ia_adj_thr_elem_struct *pstr_adj_thr_ele = &pstr_adj_thr_state->str_adj_thr_ele; |
59 | 6.85k | ia_min_snr_adapt_param_struct *pstr_min_snr_params = |
60 | 6.85k | &pstr_adj_thr_ele->str_min_snr_adapt_params; |
61 | | |
62 | 6.85k | pstr_adj_thr_state->str_bitres_params_long.clip_save_low = CLIP_SAVE_LO_LONG; |
63 | 6.85k | pstr_adj_thr_state->str_bitres_params_long.clip_save_high = CLIP_SAVE_HI_LONG; |
64 | 6.85k | pstr_adj_thr_state->str_bitres_params_long.min_bit_save = MIN_BITS_SAVE_LONG; |
65 | 6.85k | pstr_adj_thr_state->str_bitres_params_long.max_bit_save = MAX_BITS_SAVE_LONG; |
66 | 6.85k | pstr_adj_thr_state->str_bitres_params_long.clip_spend_low = CLIP_SPEND_LO_LONG; |
67 | 6.85k | pstr_adj_thr_state->str_bitres_params_long.clip_spend_high = CLIP_SPEND_HI_LONG; |
68 | 6.85k | pstr_adj_thr_state->str_bitres_params_long.min_bits_spend = MIN_BITS_SPEND_LONG; |
69 | 6.85k | pstr_adj_thr_state->str_bitres_params_long.max_bits_spend = MAX_BITS_SPEND_LONG; |
70 | | |
71 | 6.85k | pstr_adj_thr_state->str_bitres_params_short.clip_save_low = CLIP_SAVE_LO_SHORT; |
72 | 6.85k | pstr_adj_thr_state->str_bitres_params_short.clip_save_high = CLIP_SAVE_HI_SHORT; |
73 | 6.85k | pstr_adj_thr_state->str_bitres_params_short.min_bit_save = MIN_BITS_SAVE_SHORT; |
74 | 6.85k | pstr_adj_thr_state->str_bitres_params_short.max_bit_save = MAX_BITS_SAVE_SHORT; |
75 | 6.85k | pstr_adj_thr_state->str_bitres_params_short.clip_spend_low = CLIP_SPEND_LO_SHORT; |
76 | 6.85k | pstr_adj_thr_state->str_bitres_params_short.clip_spend_high = CLIP_SPEND_HI_SHORT; |
77 | 6.85k | pstr_adj_thr_state->str_bitres_params_short.min_bits_spend = MIN_BITS_SPEND_SHORT; |
78 | 6.85k | pstr_adj_thr_state->str_bitres_params_short.max_bits_spend = MAX_BITS_SPEND_SHORT; |
79 | | |
80 | 6.85k | pstr_adj_thr_ele->pe_min = (FLOAT32)0.8f * mean_pe; |
81 | 6.85k | pstr_adj_thr_ele->pe_max = (FLOAT32)1.2f * mean_pe; |
82 | 6.85k | pstr_adj_thr_ele->pe_offset = 0.0f; |
83 | 6.85k | switch (aot) { |
84 | 1.60k | case AOT_AAC_LC: |
85 | 4.04k | case AOT_SBR: |
86 | 4.36k | case AOT_PS: |
87 | 4.36k | if (ch_bitrate < 32000) { |
88 | 2.99k | pstr_adj_thr_ele->pe_offset = MAX( |
89 | 2.99k | (FLOAT32)50.0f, (FLOAT32)(100.0f) - (FLOAT32)(100.0f / 32000) * (FLOAT32)ch_bitrate); |
90 | 2.99k | } |
91 | 4.36k | break; |
92 | | |
93 | 704 | case AOT_AAC_LD: |
94 | 2.48k | case AOT_AAC_ELD: |
95 | | |
96 | 2.48k | if (ch_bitrate <= 32000) { |
97 | 1.45k | pstr_adj_thr_ele->pe_offset = MAX( |
98 | 1.45k | (FLOAT32)50.0f, (FLOAT32)(100.0f) - (FLOAT32)(100.0f / 32000) * (FLOAT32)ch_bitrate); |
99 | 1.45k | } |
100 | 2.48k | break; |
101 | 6.85k | } |
102 | | |
103 | 6.85k | if (ch_bitrate > 20000) { |
104 | 3.44k | pstr_adj_thr_ele->str_ah_param.modify_min_snr = TRUE; |
105 | 3.44k | pstr_adj_thr_ele->str_ah_param.start_sfb_long = 15; |
106 | 3.44k | pstr_adj_thr_ele->str_ah_param.start_sfb_short = 3; |
107 | 3.44k | } else { |
108 | 3.41k | pstr_adj_thr_ele->str_ah_param.modify_min_snr = FALSE; |
109 | 3.41k | pstr_adj_thr_ele->str_ah_param.start_sfb_long = 0; |
110 | 3.41k | pstr_adj_thr_ele->str_ah_param.start_sfb_short = 0; |
111 | 3.41k | } |
112 | | |
113 | 6.85k | pstr_min_snr_params->max_red = (FLOAT32)0.25f; |
114 | | |
115 | 6.85k | pstr_min_snr_params->start_ratio = (FLOAT32)1.e1f; |
116 | | |
117 | 6.85k | pstr_min_snr_params->max_ratio = (FLOAT32)1.e3f; |
118 | | |
119 | 6.85k | pstr_min_snr_params->red_ratio_fac = |
120 | 6.85k | (1.0f - pstr_min_snr_params->max_red) / |
121 | 6.85k | (10.0f * (FLOAT32)log10(pstr_min_snr_params->start_ratio / pstr_min_snr_params->max_ratio)); |
122 | | |
123 | 6.85k | pstr_min_snr_params->red_offs = 1.0f - pstr_min_snr_params->red_ratio_fac * 10.0f * |
124 | 6.85k | (FLOAT32)log10(pstr_min_snr_params->start_ratio); |
125 | | |
126 | 6.85k | pstr_adj_thr_ele->pe_last = (FLOAT32)0.0f; |
127 | 6.85k | pstr_adj_thr_ele->dyn_bits_last = 0; |
128 | 6.85k | pstr_adj_thr_ele->pe_correction_fac = (FLOAT32)1.0f; |
129 | 6.85k | } |
130 | 797k | FLOAT32 iaace_bits_to_pe(const FLOAT32 bits) { return (bits * 1.18f); } |
131 | | static VOID iaace_calc_sfb_pe_data(ia_qc_pe_data_struct *pstr_qc_pe_data, |
132 | | ixheaace_psy_out_channel **pstr_psy_out, WORD32 num_channels, |
133 | 764k | WORD32 chn) { |
134 | 764k | WORD32 ch; |
135 | 764k | WORD32 scf_band_grp; |
136 | 764k | FLOAT32 num_lines; |
137 | 764k | FLOAT32 ld_thr, ld_ratio; |
138 | 764k | WORD32 i = 0, scf; |
139 | 764k | WORD32 sfb_count; |
140 | 764k | WORD32 scf_band_per_grp; |
141 | 764k | WORD32 max_sfb_per_grp; |
142 | 764k | FLOAT32 *ptr_sfb_energy; |
143 | 764k | FLOAT32 *ptr_sfb_thr; |
144 | 764k | ia_qc_pe_chan_data_struct *pstr_qc_pe_chan_data; |
145 | | |
146 | 764k | pstr_qc_pe_data->pe = pstr_qc_pe_data->offset; |
147 | 764k | pstr_qc_pe_data->const_part = 0.0f; |
148 | 764k | pstr_qc_pe_data->num_active_lines = 0.0f; |
149 | | |
150 | 1.85M | for (ch = chn; ch < chn + num_channels; ch++) { |
151 | 1.09M | sfb_count = pstr_psy_out[ch]->sfb_count; |
152 | 1.09M | scf_band_per_grp = pstr_psy_out[ch]->sfb_per_group; |
153 | 1.09M | max_sfb_per_grp = pstr_psy_out[ch]->max_sfb_per_grp; |
154 | 1.09M | ptr_sfb_energy = pstr_psy_out[ch]->ptr_sfb_energy; |
155 | 1.09M | ptr_sfb_thr = pstr_psy_out[ch]->ptr_sfb_thr; |
156 | 1.09M | pstr_qc_pe_chan_data = &pstr_qc_pe_data->pe_ch_data[ch]; |
157 | 1.09M | pstr_qc_pe_chan_data->pe = 0; |
158 | 1.09M | pstr_qc_pe_chan_data->num_active_lines = 0; |
159 | 1.09M | pstr_qc_pe_chan_data->const_part = 0; |
160 | | |
161 | 2.74M | for (scf_band_grp = 0; scf_band_grp < sfb_count; scf_band_grp += scf_band_per_grp) { |
162 | 1.65M | i = scf_band_grp; |
163 | 33.9M | for (scf = max_sfb_per_grp - 1; scf >= 0; scf--, i++) { |
164 | 32.2M | if (ptr_sfb_energy[i] > ptr_sfb_thr[i]) { |
165 | 19.0M | ld_thr = (FLOAT32)log(ptr_sfb_thr[i]) * LOG2_1; |
166 | 19.0M | ld_ratio = pstr_qc_pe_chan_data->sfb_ld_energy[i] - ld_thr; |
167 | 19.0M | num_lines = pstr_qc_pe_chan_data->sfb_lines[i]; |
168 | 19.0M | if (ld_ratio >= PE_C1) { |
169 | 10.9M | pstr_qc_pe_chan_data->sfb_pe[i] = num_lines * ld_ratio; |
170 | 10.9M | pstr_qc_pe_chan_data->sfb_const_part[i] = |
171 | 10.9M | num_lines * pstr_qc_pe_chan_data->sfb_ld_energy[i]; |
172 | 10.9M | } else { |
173 | 8.08M | pstr_qc_pe_chan_data->sfb_pe[i] = num_lines * (PE_C2 + PE_C3 * ld_ratio); |
174 | 8.08M | pstr_qc_pe_chan_data->sfb_const_part[i] = |
175 | 8.08M | num_lines * (PE_C2 + PE_C3 * pstr_qc_pe_chan_data->sfb_ld_energy[i]); |
176 | 8.08M | num_lines = num_lines * PE_C3; |
177 | 8.08M | } |
178 | 19.0M | pstr_qc_pe_chan_data->num_sfb_active_lines[i] = num_lines; |
179 | 19.0M | } else { |
180 | 13.1M | pstr_qc_pe_chan_data->sfb_pe[i] = 0.0f; |
181 | 13.1M | pstr_qc_pe_chan_data->sfb_const_part[i] = 0.0f; |
182 | 13.1M | pstr_qc_pe_chan_data->num_sfb_active_lines[i] = 0.0; |
183 | 13.1M | } |
184 | | |
185 | 32.2M | pstr_qc_pe_chan_data->pe += pstr_qc_pe_chan_data->sfb_pe[i]; |
186 | 32.2M | pstr_qc_pe_chan_data->const_part += pstr_qc_pe_chan_data->sfb_const_part[i]; |
187 | 32.2M | pstr_qc_pe_chan_data->num_active_lines += pstr_qc_pe_chan_data->num_sfb_active_lines[i]; |
188 | 32.2M | } |
189 | 1.65M | } |
190 | 1.09M | pstr_qc_pe_data->pe += pstr_qc_pe_chan_data->pe; |
191 | 1.09M | pstr_qc_pe_data->const_part += pstr_qc_pe_chan_data->const_part; |
192 | 1.09M | pstr_qc_pe_data->num_active_lines += pstr_qc_pe_chan_data->num_active_lines; |
193 | 1.09M | pstr_psy_out[ch]->pe = pstr_qc_pe_data->pe; |
194 | 1.09M | } |
195 | 764k | } |
196 | 308k | static FLOAT32 iaace_calc_bit_save(ia_bitres_param_struct *pstr_bitres_params, FLOAT32 fill_lvl) { |
197 | 308k | FLOAT32 bit_save; |
198 | 308k | const FLOAT32 clip_low = pstr_bitres_params->clip_save_low; |
199 | 308k | const FLOAT32 clip_high = pstr_bitres_params->clip_save_high; |
200 | 308k | const FLOAT32 min_bit_save = pstr_bitres_params->min_bit_save; |
201 | 308k | const FLOAT32 max_bit_save = pstr_bitres_params->max_bit_save; |
202 | | |
203 | 308k | fill_lvl = MAX(fill_lvl, clip_low); |
204 | 308k | fill_lvl = MIN(fill_lvl, clip_high); |
205 | 308k | bit_save = max_bit_save - |
206 | 308k | ((max_bit_save - min_bit_save) / (clip_high - clip_low)) * (fill_lvl - clip_low); |
207 | | |
208 | 308k | return bit_save; |
209 | 308k | } |
210 | | |
211 | | static FLOAT32 iaace_calc_bit_spend(ia_bitres_param_struct *pstr_bitres_params, |
212 | 308k | FLOAT32 fill_lvl) { |
213 | 308k | FLOAT32 bit_spend; |
214 | 308k | const FLOAT32 clip_low = pstr_bitres_params->clip_spend_low; |
215 | 308k | const FLOAT32 clip_high = pstr_bitres_params->clip_spend_high; |
216 | 308k | const FLOAT32 min_bits_spend = pstr_bitres_params->min_bits_spend; |
217 | 308k | const FLOAT32 max_bits_spend = pstr_bitres_params->max_bits_spend; |
218 | | |
219 | 308k | fill_lvl = MAX(fill_lvl, clip_low); |
220 | 308k | fill_lvl = MIN(fill_lvl, clip_high); |
221 | 308k | bit_spend = min_bits_spend + ((max_bits_spend - min_bits_spend) / (clip_high - clip_low)) * |
222 | 308k | (fill_lvl - clip_low); |
223 | | |
224 | 308k | return bit_spend; |
225 | 308k | } |
226 | | |
227 | | static VOID iaace_adjust_pe_minmax(const FLOAT32 curr_pe, FLOAT32 *ptr_pe_min, |
228 | 308k | FLOAT32 *ptr_pe_max) { |
229 | 308k | FLOAT32 min_hi_fac = 0.3f, max_hi_fac = 1.0f, min_low_fac = 0.14f, max_low_fac = 0.07f; |
230 | 308k | FLOAT32 diff; |
231 | 308k | FLOAT32 min_diff = curr_pe * (FLOAT32)0.1666666667f; |
232 | | |
233 | 308k | if (curr_pe > *ptr_pe_max) { |
234 | 20.3k | diff = (curr_pe - *ptr_pe_max); |
235 | 20.3k | *ptr_pe_min += diff * min_hi_fac; |
236 | 20.3k | *ptr_pe_max += diff * max_hi_fac; |
237 | 288k | } else { |
238 | 288k | if (curr_pe < *ptr_pe_min) { |
239 | 206k | diff = (*ptr_pe_min - curr_pe); |
240 | 206k | *ptr_pe_min -= diff * min_low_fac; |
241 | 206k | *ptr_pe_max -= diff * max_low_fac; |
242 | 206k | } else { |
243 | 81.6k | *ptr_pe_min += (curr_pe - *ptr_pe_min) * min_hi_fac; |
244 | 81.6k | *ptr_pe_max -= (*ptr_pe_max - curr_pe) * max_low_fac; |
245 | 81.6k | } |
246 | 288k | } |
247 | | |
248 | 308k | if ((*ptr_pe_max - *ptr_pe_min) < min_diff) { |
249 | 13.8k | FLOAT32 low_part, high_part; |
250 | 13.8k | low_part = MAX((FLOAT32)0.0f, curr_pe - *ptr_pe_min); |
251 | 13.8k | high_part = MAX((FLOAT32)0.0f, *ptr_pe_max - curr_pe); |
252 | 13.8k | *ptr_pe_max = curr_pe + high_part / (low_part + high_part) * min_diff; |
253 | 13.8k | *ptr_pe_min = curr_pe - low_part / (low_part + high_part) * min_diff; |
254 | 13.8k | *ptr_pe_min = MAX((FLOAT32)0.0f, *ptr_pe_min); |
255 | 13.8k | } |
256 | 308k | } |
257 | | |
258 | | static FLOAT32 iaace_bitres_calc_bitfac(const WORD32 bitres_bits, const WORD32 max_bitres_bits, |
259 | | const FLOAT32 pe, const WORD32 win_seq, |
260 | | const WORD32 avg_bits, const FLOAT32 max_bit_fac, |
261 | | ia_adj_thr_state_struct *pstr_adj_thr_state, |
262 | 308k | ia_adj_thr_elem_struct *pstr_adj_the_elem) { |
263 | 308k | ia_bitres_param_struct *pstr_bitres_params; |
264 | 308k | FLOAT32 pex; |
265 | 308k | FLOAT32 fill_lvl = 0.0f; |
266 | 308k | FLOAT32 bit_save, bit_spend, bitres_factor; |
267 | | |
268 | 308k | if (max_bitres_bits) { |
269 | 237k | fill_lvl = (FLOAT32)bitres_bits / max_bitres_bits; |
270 | 237k | } |
271 | | |
272 | 308k | if (win_seq != SHORT_WINDOW) { |
273 | 262k | pstr_bitres_params = &(pstr_adj_thr_state->str_bitres_params_long); |
274 | 262k | } else { |
275 | 46.2k | pstr_bitres_params = &(pstr_adj_thr_state->str_bitres_params_short); |
276 | 46.2k | } |
277 | | |
278 | 308k | pex = MAX(pe, pstr_adj_the_elem->pe_min); |
279 | 308k | pex = MIN(pex, pstr_adj_the_elem->pe_max); |
280 | | |
281 | 308k | bit_save = iaace_calc_bit_save(pstr_bitres_params, fill_lvl); |
282 | 308k | bit_spend = iaace_calc_bit_spend(pstr_bitres_params, fill_lvl); |
283 | | |
284 | 308k | bitres_factor = |
285 | 308k | (FLOAT32)1.0f - bit_save + |
286 | 308k | ((bit_spend + bit_save) / (pstr_adj_the_elem->pe_max - pstr_adj_the_elem->pe_min)) * |
287 | 308k | (pex - pstr_adj_the_elem->pe_min); |
288 | 308k | if (avg_bits) |
289 | 308k | { |
290 | 308k | bitres_factor = MIN(bitres_factor, |
291 | 308k | (FLOAT32)1.0f - (FLOAT32)0.3f + (FLOAT32)bitres_bits / (FLOAT32)avg_bits); |
292 | 308k | } |
293 | | |
294 | 308k | bitres_factor = MIN(bitres_factor, max_bit_fac); |
295 | | |
296 | 308k | iaace_adjust_pe_minmax(pe, &pstr_adj_the_elem->pe_min, &pstr_adj_the_elem->pe_max); |
297 | | |
298 | 308k | return bitres_factor; |
299 | 308k | } |
300 | | |
301 | | static VOID iaace_calc_pe_correction(FLOAT32 *ptr_correction_fac, const FLOAT32 pe_act, |
302 | 308k | const FLOAT32 pe_last, const WORD32 bits_prev) { |
303 | 308k | if ((bits_prev > 0) && (pe_act < (FLOAT32)1.5f * pe_last) && |
304 | 308k | (pe_act > (FLOAT32)0.7f * pe_last) && |
305 | 308k | ((FLOAT32)1.2f * iaace_bits_to_pe((FLOAT32)bits_prev) > pe_last) && |
306 | 308k | ((FLOAT32)0.65f * iaace_bits_to_pe((FLOAT32)bits_prev) < pe_last)) { |
307 | 147k | FLOAT32 new_fac = pe_last / iaace_bits_to_pe((FLOAT32)bits_prev); |
308 | | |
309 | 147k | if (new_fac < (FLOAT32)1.0f) { |
310 | 97.4k | new_fac = MIN((FLOAT32)1.1f * new_fac, (FLOAT32)1.0f); |
311 | 97.4k | new_fac = MAX(new_fac, (FLOAT32)0.85f); |
312 | 97.4k | } else { |
313 | 50.0k | new_fac = MAX((FLOAT32)0.9f * new_fac, (FLOAT32)1.0f); |
314 | 50.0k | new_fac = MIN(new_fac, (FLOAT32)1.15f); |
315 | 50.0k | } |
316 | 147k | if (((new_fac > (FLOAT32)1.0f) && (*ptr_correction_fac < (FLOAT32)1.0f)) || |
317 | 147k | ((new_fac < (FLOAT32)1.0f) && (*ptr_correction_fac > (FLOAT32)1.0f))) { |
318 | 3.07k | *ptr_correction_fac = (FLOAT32)1.0f; |
319 | 3.07k | } |
320 | | |
321 | 147k | if ((*ptr_correction_fac < (FLOAT32)1.0f && new_fac < *ptr_correction_fac) || |
322 | 147k | (*ptr_correction_fac > (FLOAT32)1.0f && new_fac > *ptr_correction_fac)) { |
323 | 35.4k | *ptr_correction_fac = (FLOAT32)0.85f * (*ptr_correction_fac) + (FLOAT32)0.15f * new_fac; |
324 | 111k | } else { |
325 | 111k | *ptr_correction_fac = (FLOAT32)0.7f * (*ptr_correction_fac) + (FLOAT32)0.3f * new_fac; |
326 | 111k | } |
327 | | |
328 | 147k | *ptr_correction_fac = MIN(*ptr_correction_fac, (FLOAT32)1.15f); |
329 | 147k | *ptr_correction_fac = MAX(*ptr_correction_fac, (FLOAT32)0.85f); |
330 | 161k | } else { |
331 | 161k | *ptr_correction_fac = (FLOAT32)1.0f; |
332 | 161k | } |
333 | 308k | } |
334 | | |
335 | | static VOID iaace_calc_thr_exp( |
336 | | FLOAT32 thr_exp[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND], |
337 | 184k | ixheaace_psy_out_channel **pstr_psy_out, WORD32 num_chans, WORD32 chn) { |
338 | 184k | WORD32 sfb, ch, scf_band_grp; |
339 | 184k | ixheaace_psy_out_channel *pstr_psy_chan_out; |
340 | 184k | FLOAT32 *ptr_scf_band_thr; |
341 | 184k | FLOAT32 *ptr_thr_exp; |
342 | 450k | for (ch = chn; ch < chn + num_chans; ch++) { |
343 | 266k | pstr_psy_chan_out = pstr_psy_out[ch]; |
344 | 266k | ptr_thr_exp = thr_exp[ch]; |
345 | 679k | for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count; |
346 | 412k | scf_band_grp += pstr_psy_chan_out->sfb_per_group) { |
347 | 412k | FLOAT32 *ptr_thr_exp1 = &ptr_thr_exp[scf_band_grp]; |
348 | 412k | ptr_scf_band_thr = &pstr_psy_chan_out->ptr_sfb_thr[scf_band_grp]; |
349 | 8.40M | for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) { |
350 | 7.99M | ptr_thr_exp1[sfb] = (FLOAT32)pow(*ptr_scf_band_thr++, RED_EXP_VAL); |
351 | 7.99M | } |
352 | 412k | } |
353 | 266k | } |
354 | 184k | } |
355 | | |
356 | | static VOID iaace_adapt_min_snr(ixheaace_psy_out_channel **pstr_psy_out, |
357 | | ia_min_snr_adapt_param_struct *pstr_min_snr_params, |
358 | 184k | WORD32 num_chans, WORD32 chn) { |
359 | 184k | WORD32 num_scf_band = 0, ch, scf_band_cnt, scf_band_offs, sfb; |
360 | 184k | FLOAT32 avg_energy = 0.0f, db_ratio, min_snr_red; |
361 | 184k | WORD32 i; |
362 | | |
363 | 450k | for (ch = chn; ch < chn + num_chans; ch++) { |
364 | 266k | ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch]; |
365 | 266k | num_scf_band = 0; |
366 | 266k | avg_energy = 0; |
367 | 266k | scf_band_cnt = pstr_psy_chan_out->max_sfb_per_grp; |
368 | | |
369 | 679k | for (scf_band_offs = 0; scf_band_offs < pstr_psy_chan_out->sfb_count; |
370 | 412k | scf_band_offs += pstr_psy_chan_out->sfb_per_group) { |
371 | 412k | FLOAT32 *ptr_sfb_energy = &pstr_psy_chan_out->ptr_sfb_energy[scf_band_offs]; |
372 | 8.40M | for (sfb = scf_band_cnt - 1; sfb >= 0; sfb--) { |
373 | 7.99M | avg_energy += ptr_sfb_energy[sfb]; |
374 | 7.99M | } |
375 | 412k | num_scf_band += scf_band_cnt; |
376 | 412k | } |
377 | | |
378 | 266k | if (num_scf_band > 0) { |
379 | 266k | avg_energy /= num_scf_band; |
380 | 266k | } |
381 | | |
382 | 679k | for (scf_band_offs = 0; scf_band_offs < pstr_psy_chan_out->sfb_count; |
383 | 412k | scf_band_offs += pstr_psy_chan_out->sfb_per_group) { |
384 | 412k | i = scf_band_offs; |
385 | 8.40M | for (sfb = scf_band_cnt - 1; sfb >= 0; sfb--, i++) { |
386 | 7.99M | if (pstr_min_snr_params->start_ratio * pstr_psy_chan_out->ptr_sfb_energy[i] < |
387 | 7.99M | avg_energy) { |
388 | 5.16M | db_ratio = |
389 | 5.16M | (FLOAT32)(10.0f * log10((MIN_FLT_VAL + avg_energy) / |
390 | 5.16M | (MIN_FLT_VAL + pstr_psy_chan_out->ptr_sfb_energy[i]))); |
391 | 5.16M | min_snr_red = |
392 | 5.16M | pstr_min_snr_params->red_offs + pstr_min_snr_params->red_ratio_fac * db_ratio; |
393 | 5.16M | min_snr_red = MAX(min_snr_red, pstr_min_snr_params->max_red); |
394 | 5.16M | pstr_psy_chan_out->sfb_min_snr[i] = |
395 | 5.16M | (FLOAT32)pow(pstr_psy_out[ch]->sfb_min_snr[i], min_snr_red); |
396 | 5.16M | pstr_psy_chan_out->sfb_min_snr[i] = |
397 | 5.16M | MIN(MIN_SNR_LIMIT, pstr_psy_out[ch]->sfb_min_snr[i]); |
398 | 5.16M | } |
399 | 7.99M | } |
400 | 412k | } |
401 | 266k | } |
402 | 184k | } |
403 | | |
404 | | static VOID iaace_init_avoid_hole_flag( |
405 | | WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND], |
406 | | ixheaace_psy_out_channel **pstr_psy_out, ia_ah_param_struct *pstr_ah_param, WORD32 num_chans, |
407 | 184k | WORD32 chn, WORD32 aot) { |
408 | 184k | WORD32 ch; |
409 | 184k | FLOAT32 sfb_energy; |
410 | 184k | FLOAT32 scale_spread_energy = 0.0f; |
411 | 184k | WORD32 scf_band_grp, scf_band_cnt, scf_band; |
412 | 184k | FLOAT32 *ptr_scf_band_spread_energy, *ptr_scf_band_energy, *ptr_scf_band_min_snr; |
413 | 450k | for (ch = chn; ch < chn + num_chans; ch++) { |
414 | 266k | ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch]; |
415 | | |
416 | 266k | if (pstr_psy_chan_out->window_sequence != SHORT_WINDOW) { |
417 | 216k | switch (aot) { |
418 | 40.3k | case AOT_AAC_LC: |
419 | 100k | case AOT_SBR: |
420 | 103k | case AOT_PS: |
421 | 103k | scale_spread_energy = 0.5f; |
422 | 103k | break; |
423 | | |
424 | 13.3k | case AOT_AAC_LD: |
425 | 112k | case AOT_AAC_ELD: |
426 | 112k | scale_spread_energy = 0.56f; |
427 | 112k | break; |
428 | 216k | } |
429 | 216k | } else { |
430 | 50.6k | scale_spread_energy = 0.63f; |
431 | 50.6k | } |
432 | | |
433 | 679k | for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count; |
434 | 412k | scf_band_grp += pstr_psy_chan_out->sfb_per_group) { |
435 | 412k | ptr_scf_band_spread_energy = &pstr_psy_chan_out->ptr_sfb_spread_energy[scf_band_grp]; |
436 | 412k | scf_band_cnt = pstr_psy_chan_out->max_sfb_per_grp; |
437 | 8.40M | for (scf_band = scf_band_cnt - 1; scf_band >= 0; scf_band--) { |
438 | 7.99M | *ptr_scf_band_spread_energy = *ptr_scf_band_spread_energy * scale_spread_energy; |
439 | 7.99M | ptr_scf_band_spread_energy++; |
440 | 7.99M | } |
441 | 412k | } |
442 | 266k | } |
443 | | |
444 | 184k | if (pstr_ah_param->modify_min_snr) { |
445 | 177k | for (ch = chn; ch < chn + num_chans; ch++) { |
446 | 102k | ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch]; |
447 | 102k | ptr_scf_band_energy = pstr_psy_chan_out->ptr_sfb_energy; |
448 | | |
449 | 102k | ptr_scf_band_min_snr = pstr_psy_chan_out->sfb_min_snr; |
450 | | |
451 | 223k | for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count; |
452 | 120k | scf_band_grp += pstr_psy_chan_out->sfb_per_group) { |
453 | 3.06M | for (scf_band = 0; scf_band < pstr_psy_chan_out->max_sfb_per_grp; scf_band++) { |
454 | 2.94M | FLOAT32 sfb_en_m1, sfb_en_p1, avg_energy; |
455 | 2.94M | if (scf_band > 0) { |
456 | 2.82M | sfb_en_m1 = ptr_scf_band_energy[scf_band_grp + scf_band - 1]; |
457 | 2.82M | } else { |
458 | 120k | sfb_en_m1 = ptr_scf_band_energy[scf_band_grp]; |
459 | 120k | } |
460 | 2.94M | if (scf_band < pstr_psy_chan_out->max_sfb_per_grp - 1) { |
461 | 2.82M | sfb_en_p1 = ptr_scf_band_energy[scf_band_grp + scf_band + 1]; |
462 | 2.82M | } else { |
463 | 120k | sfb_en_p1 = ptr_scf_band_energy[scf_band_grp + scf_band]; |
464 | 120k | } |
465 | | |
466 | 2.94M | avg_energy = (sfb_en_m1 + sfb_en_p1) / (FLOAT32)2.0f; |
467 | 2.94M | sfb_energy = ptr_scf_band_energy[scf_band_grp + scf_band]; |
468 | 2.94M | FLOAT32 temp_min_snr = 0.0f; |
469 | 2.94M | if (sfb_energy > avg_energy) { |
470 | 977k | switch (aot) { |
471 | 127k | case AOT_AAC_LC: |
472 | 351k | case AOT_SBR: |
473 | 441k | case AOT_PS: |
474 | 441k | temp_min_snr = MAX((FLOAT32)0.8f * avg_energy / sfb_energy, (FLOAT32)0.316f); |
475 | 441k | break; |
476 | | |
477 | 28.2k | case AOT_AAC_LD: |
478 | 536k | case AOT_AAC_ELD: |
479 | 536k | temp_min_snr = MAX((FLOAT32)0.8f * avg_energy / sfb_energy, (FLOAT32)0.408f); |
480 | 536k | break; |
481 | 977k | } |
482 | 977k | if (pstr_psy_chan_out->window_sequence != SHORT_WINDOW) { |
483 | 865k | switch (aot) { |
484 | 115k | case AOT_AAC_LC: |
485 | 147k | case AOT_PS: |
486 | 147k | temp_min_snr = MAX(temp_min_snr, (FLOAT32)0.316f); |
487 | 147k | break; |
488 | | |
489 | 28.2k | case AOT_AAC_LD: |
490 | 28.2k | temp_min_snr = MAX(temp_min_snr, (FLOAT32)0.408f); |
491 | 28.2k | break; |
492 | 865k | } |
493 | 865k | } else { |
494 | 112k | temp_min_snr = MAX(temp_min_snr, (FLOAT32)0.5f); |
495 | 112k | } |
496 | 977k | ptr_scf_band_min_snr[scf_band_grp + scf_band] = |
497 | 977k | MIN(ptr_scf_band_min_snr[scf_band_grp + scf_band], temp_min_snr); |
498 | 977k | } |
499 | | |
500 | 2.94M | if (((FLOAT32)2.0f * sfb_energy < avg_energy) && (sfb_energy > (FLOAT32)0.0f)) { |
501 | 499k | temp_min_snr = avg_energy / ((FLOAT32)2.0f * sfb_energy) * |
502 | 499k | ptr_scf_band_min_snr[scf_band_grp + scf_band]; |
503 | 499k | temp_min_snr = MIN((FLOAT32)0.8f, temp_min_snr); |
504 | 499k | ptr_scf_band_min_snr[scf_band_grp + scf_band] = |
505 | 499k | MIN(temp_min_snr, ptr_scf_band_min_snr[scf_band_grp + scf_band] * (FLOAT32)3.16f); |
506 | 499k | } |
507 | 2.94M | } |
508 | 120k | } |
509 | 102k | } |
510 | 75.6k | } |
511 | | |
512 | 184k | if (num_chans == 2) { |
513 | 82.7k | ixheaace_psy_out_channel *pstr_psy_out_mid = pstr_psy_out[chn]; |
514 | 82.7k | ixheaace_psy_out_channel *pstr_psy_out_side = pstr_psy_out[chn + 1]; |
515 | 82.7k | WORD32 sfb; |
516 | | |
517 | 3.31M | for (sfb = 0; sfb < pstr_psy_out_mid->sfb_count; sfb++) { |
518 | 3.22M | if (pstr_psy_out[chn]->ms_used[sfb]) { |
519 | 2.73M | FLOAT32 sfb_en_mid = pstr_psy_out_mid->ptr_sfb_energy[sfb]; |
520 | 2.73M | FLOAT32 sfb_en_side = pstr_psy_out_side->ptr_sfb_energy[sfb]; |
521 | 2.73M | FLOAT32 max_sfb_en = MAX(sfb_en_mid, sfb_en_side); |
522 | 2.73M | FLOAT32 max_thr = 0.25f * pstr_psy_out_mid->sfb_min_snr[sfb] * max_sfb_en; |
523 | | |
524 | 2.73M | pstr_psy_out_mid->sfb_min_snr[sfb] = (FLOAT32)MAX( |
525 | 2.73M | pstr_psy_out_mid->sfb_min_snr[sfb], |
526 | 2.73M | MIN(MAX_FLT_VAL, ((FLOAT32)max_thr / (MIN_FLT_VAL + (FLOAT32)sfb_en_mid)))); |
527 | | |
528 | 2.73M | if (pstr_psy_out_mid->ptr_sfb_energy[sfb] <= 1.0f) { |
529 | 557k | pstr_psy_out_mid->ptr_sfb_energy[sfb] = |
530 | 557k | MIN(pstr_psy_out_mid->ptr_sfb_energy[sfb], 0.8f); |
531 | 557k | } |
532 | | |
533 | 2.73M | pstr_psy_out_side->sfb_min_snr[sfb] = (FLOAT32)MAX( |
534 | 2.73M | pstr_psy_out_side->sfb_min_snr[sfb], |
535 | 2.73M | MIN(MAX_FLT_VAL, ((FLOAT32)max_thr / (MIN_FLT_VAL + (FLOAT32)sfb_en_side)))); |
536 | | |
537 | 2.73M | if (pstr_psy_out_side->sfb_min_snr[sfb] <= 1.0f) { |
538 | 552k | pstr_psy_out_side->sfb_min_snr[sfb] = MIN(pstr_psy_out_side->sfb_min_snr[sfb], 0.8f); |
539 | 552k | } |
540 | 2.73M | } |
541 | 3.22M | } |
542 | 82.7k | } |
543 | | |
544 | 450k | for (ch = chn; ch < chn + num_chans; ch++) { |
545 | 266k | ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch]; |
546 | 679k | for (scf_band_grp = 0; scf_band_grp < pstr_psy_chan_out->sfb_count; |
547 | 412k | scf_band_grp += pstr_psy_chan_out->sfb_per_group) { |
548 | 8.40M | for (scf_band = 0; scf_band < pstr_psy_chan_out->max_sfb_per_grp; scf_band++) { |
549 | 7.99M | if (pstr_psy_chan_out->ptr_sfb_spread_energy[scf_band_grp + scf_band] > |
550 | 7.99M | pstr_psy_chan_out->ptr_sfb_energy[scf_band_grp + scf_band] || |
551 | 7.99M | pstr_psy_chan_out->sfb_min_snr[scf_band_grp + scf_band] > 1.0f) { |
552 | 3.08M | ah_flag[ch][scf_band_grp + scf_band] = NO_AH; |
553 | 4.90M | } else { |
554 | 4.90M | ah_flag[ch][scf_band_grp + scf_band] = AH_INACTIVE; |
555 | 4.90M | } |
556 | 7.99M | } |
557 | | |
558 | 412k | for (scf_band = pstr_psy_chan_out->max_sfb_per_grp; |
559 | 2.62M | scf_band < pstr_psy_chan_out->sfb_per_group; scf_band++) { |
560 | 2.21M | ah_flag[ch][scf_band_grp + scf_band] = NO_AH; |
561 | 2.21M | } |
562 | 412k | } |
563 | 266k | } |
564 | 184k | } |
565 | | |
566 | | static VOID iaace_reduce_thr( |
567 | | ixheaace_psy_out_channel **pstr_psy_out, |
568 | | WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND], |
569 | | FLOAT32 thr_exp[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND], |
570 | 454k | const FLOAT32 red_value, WORD32 num_channels, WORD32 chn) { |
571 | 454k | WORD32 ch, sfb_group, sfb; |
572 | 454k | FLOAT32 sfb_energy, sfb_threshold, sfb_thr_reduced; |
573 | 454k | FLOAT32 *ptr_sfb_energy_fix, *ptr_sfb_threshold_fix, *ptr_sfb_min_snr_fix, *ptr_thr_exp_fix; |
574 | | |
575 | 1.10M | for (ch = chn; ch < chn + num_channels; ch++) { |
576 | 646k | ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch]; |
577 | 646k | ptr_sfb_energy_fix = pstr_psy_chan_out->ptr_sfb_energy; |
578 | 646k | ptr_sfb_threshold_fix = pstr_psy_chan_out->ptr_sfb_thr; |
579 | 646k | ptr_sfb_min_snr_fix = pstr_psy_chan_out->sfb_min_snr; |
580 | 646k | ptr_thr_exp_fix = &thr_exp[ch][0]; |
581 | 1.63M | for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count; |
582 | 985k | sfb_group += pstr_psy_chan_out->sfb_per_group) { |
583 | 20.1M | for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) { |
584 | 19.1M | sfb_energy = ptr_sfb_energy_fix[sfb_group + sfb]; |
585 | 19.1M | sfb_threshold = ptr_sfb_threshold_fix[sfb_group + sfb]; |
586 | 19.1M | if (sfb_energy > sfb_threshold) { |
587 | 12.2M | sfb_thr_reduced = |
588 | 12.2M | (FLOAT32)pow((ptr_thr_exp_fix[sfb_group + sfb] + red_value), INV_RED_EXP_VAL); |
589 | | |
590 | 12.2M | if ((sfb_thr_reduced > ptr_sfb_min_snr_fix[sfb_group + sfb] * sfb_energy) && |
591 | 12.2M | (ah_flag[ch][sfb_group + sfb] != NO_AH)) { |
592 | 5.05M | sfb_thr_reduced = |
593 | 5.05M | MAX(ptr_sfb_min_snr_fix[sfb_group + sfb] * sfb_energy, sfb_threshold); |
594 | 5.05M | ah_flag[ch][sfb_group + sfb] = AH_ACTIVE; |
595 | 5.05M | } |
596 | 12.2M | ptr_sfb_threshold_fix[sfb_group + sfb] = sfb_thr_reduced; |
597 | 12.2M | } |
598 | 19.1M | } |
599 | 985k | } |
600 | 646k | } |
601 | 454k | } |
602 | | |
603 | | static VOID iaace_calc_pe_no_active_holes( |
604 | | FLOAT32 *ptr_pe, FLOAT32 *ptr_const_part, FLOAT32 *ptr_num_active_lines, |
605 | | ia_qc_pe_data_struct *pstr_qs_pe_data, |
606 | | WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND], |
607 | 271k | ixheaace_psy_out_channel **pstr_psy_out, WORD32 num_channels, WORD32 chn) { |
608 | 271k | WORD32 ch, sfb_group, sfb; |
609 | 271k | *ptr_pe = 0.0f; |
610 | 271k | *ptr_const_part = 0.0f; |
611 | 271k | *ptr_num_active_lines = 0; |
612 | | |
613 | 654k | for (ch = chn; ch < chn + num_channels; ch++) { |
614 | 382k | ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch]; |
615 | 382k | ia_qc_pe_chan_data_struct *ptr_pe_chan_data = &pstr_qs_pe_data->pe_ch_data[ch]; |
616 | | |
617 | 958k | for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count; |
618 | 576k | sfb_group += pstr_psy_chan_out->sfb_per_group) { |
619 | 11.8M | for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) { |
620 | 11.2M | if (ah_flag[ch][sfb_group + sfb] < AH_ACTIVE) { |
621 | 8.44M | *ptr_pe += ptr_pe_chan_data->sfb_pe[sfb_group + sfb]; |
622 | 8.44M | *ptr_const_part += ptr_pe_chan_data->sfb_const_part[sfb_group + sfb]; |
623 | 8.44M | *ptr_num_active_lines += ptr_pe_chan_data->num_sfb_active_lines[sfb_group + sfb]; |
624 | 8.44M | } |
625 | 11.2M | } |
626 | 576k | } |
627 | 382k | } |
628 | 271k | } |
629 | | |
630 | | static VOID iaace_correct_thr( |
631 | | ixheaace_psy_out_channel **pstr_psy_out, |
632 | | WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND], |
633 | | ia_qc_pe_data_struct *pstr_qs_pe_data, |
634 | | FLOAT32 thr_exp[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND], |
635 | 133k | const FLOAT32 red_value, const FLOAT32 delta_pe, WORD32 num_channels, WORD32 chn) { |
636 | 133k | WORD32 i, ch, sfb_group, sfb; |
637 | 133k | FLOAT32 delta_sfb_pe; |
638 | 133k | FLOAT32 thr_factor; |
639 | 133k | FLOAT32 sfb_pe_factors[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND], |
640 | 133k | norm_factor[IXHEAACE_MAX_CH_IN_BS_ELE] = {MIN_FLT_VAL}; |
641 | 133k | FLOAT32 sfb_en, sfb_thr, sfb_thr_reduced; |
642 | 133k | FLOAT32 *ptr_thr_exp; |
643 | 133k | FLOAT32 *ptr_sfb_energy, *ptr_sfb_thr, *ptr_sfb_min_snr; |
644 | 133k | ixheaace_psy_out_channel *pstr_psy_chan_out = NULL; |
645 | 133k | ia_qc_pe_chan_data_struct *pstr_pe_chan_data = NULL; |
646 | | |
647 | 336k | for (ch = chn; ch < chn + num_channels; ch++) { |
648 | 202k | pstr_psy_chan_out = pstr_psy_out[ch]; |
649 | 202k | pstr_pe_chan_data = &pstr_qs_pe_data->pe_ch_data[ch]; |
650 | 202k | norm_factor[ch] = MIN_FLT_VAL; |
651 | 202k | ptr_thr_exp = thr_exp[ch]; |
652 | | |
653 | 542k | for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count; |
654 | 339k | sfb_group += pstr_psy_chan_out->sfb_per_group) { |
655 | 6.56M | for (sfb = 0; sfb < pstr_psy_chan_out->max_sfb_per_grp; sfb++) { |
656 | 6.22M | if ((ah_flag[ch][sfb_group + sfb] < AH_ACTIVE) || (delta_pe > 0)) { |
657 | 5.36M | sfb_pe_factors[ch][sfb_group + sfb] = |
658 | 5.36M | pstr_pe_chan_data->num_sfb_active_lines[sfb_group + sfb] / |
659 | 5.36M | (ptr_thr_exp[sfb_group + sfb] + red_value); |
660 | 5.36M | norm_factor[ch] += sfb_pe_factors[ch][sfb_group + sfb]; |
661 | 5.36M | } else { |
662 | 851k | sfb_pe_factors[ch][sfb_group + sfb] = 0.0f; |
663 | 851k | } |
664 | 6.22M | } |
665 | 339k | } |
666 | 202k | } |
667 | 133k | if (num_channels > 1) { |
668 | 68.9k | norm_factor[chn] = norm_factor[chn] + norm_factor[chn + 1]; |
669 | 68.9k | } |
670 | 133k | norm_factor[chn] = 1.0f / norm_factor[chn]; |
671 | | |
672 | 336k | for (ch = chn; ch < chn + num_channels; ch++) { |
673 | 202k | pstr_psy_chan_out = pstr_psy_out[ch]; |
674 | 202k | pstr_pe_chan_data = &pstr_qs_pe_data->pe_ch_data[ch]; |
675 | 202k | ptr_sfb_energy = pstr_psy_chan_out->ptr_sfb_energy; |
676 | 202k | ptr_sfb_thr = pstr_psy_chan_out->ptr_sfb_thr; |
677 | 202k | ptr_sfb_min_snr = pstr_psy_chan_out->sfb_min_snr; |
678 | | |
679 | 542k | for (sfb_group = 0; sfb_group < pstr_psy_chan_out->sfb_count; |
680 | 339k | sfb_group += pstr_psy_chan_out->sfb_per_group) { |
681 | 339k | i = sfb_group; |
682 | 6.56M | for (sfb = pstr_psy_chan_out->max_sfb_per_grp - 1; sfb >= 0; sfb--, i++) { |
683 | 6.22M | delta_sfb_pe = sfb_pe_factors[ch][i] * norm_factor[chn] * delta_pe; |
684 | 6.22M | if (pstr_pe_chan_data->num_sfb_active_lines[i] > (FLOAT32)0.5f) { |
685 | 3.38M | sfb_en = ptr_sfb_energy[i]; |
686 | 3.38M | sfb_thr = ptr_sfb_thr[i]; |
687 | 3.38M | thr_factor = MIN(-delta_sfb_pe / pstr_pe_chan_data->num_sfb_active_lines[i], 20.f); |
688 | 3.38M | thr_factor = (FLOAT32)pow(2.0f, thr_factor); |
689 | 3.38M | sfb_thr_reduced = sfb_thr * thr_factor; |
690 | | |
691 | 3.38M | if ((sfb_thr_reduced > ptr_sfb_min_snr[i] * sfb_en) && |
692 | 3.38M | (ah_flag[ch][i] == AH_INACTIVE)) { |
693 | 37.4k | sfb_thr_reduced = MAX(ptr_sfb_min_snr[i] * sfb_en, sfb_thr); |
694 | 37.4k | ah_flag[ch][i] = AH_ACTIVE; |
695 | 37.4k | } |
696 | 3.38M | ptr_sfb_thr[i] = sfb_thr_reduced; |
697 | 3.38M | } |
698 | 6.22M | } |
699 | 339k | } |
700 | 202k | } |
701 | 133k | } |
702 | | |
703 | | static VOID iaace_reduce_min_snr( |
704 | | ixheaace_psy_out_channel **pstr_psy_out, ia_qc_pe_data_struct *pstr_qs_pe_data, |
705 | | WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND], |
706 | 50.2k | const FLOAT32 desired_pe, WORD32 num_channels, WORD32 chn) { |
707 | 50.2k | WORD32 sfb, sfb_sub_win, ch; |
708 | 50.2k | FLOAT32 delta_pe; |
709 | | |
710 | 50.2k | sfb_sub_win = pstr_psy_out[chn]->max_sfb_per_grp; |
711 | | |
712 | 1.41M | while (pstr_qs_pe_data->pe > desired_pe && sfb_sub_win > 0) { |
713 | 1.36M | sfb_sub_win--; |
714 | 2.78M | for (sfb = sfb_sub_win; sfb < pstr_psy_out[chn]->sfb_count; |
715 | 1.42M | sfb += pstr_psy_out[chn]->sfb_per_group) { |
716 | 3.18M | for (ch = chn; ch < chn + num_channels; ch++) { |
717 | 1.76M | if (ah_flag[ch][sfb] != NO_AH && pstr_psy_out[ch]->sfb_min_snr[sfb] < MIN_SNR_LIMIT) { |
718 | 457k | pstr_psy_out[ch]->sfb_min_snr[sfb] = MIN_SNR_LIMIT; |
719 | 457k | pstr_psy_out[ch]->ptr_sfb_thr[sfb] = |
720 | 457k | pstr_psy_out[ch]->ptr_sfb_energy[sfb] * pstr_psy_out[ch]->sfb_min_snr[sfb]; |
721 | 457k | delta_pe = pstr_qs_pe_data->pe_ch_data[ch].sfb_lines[sfb] * 1.5f - |
722 | 457k | pstr_qs_pe_data->pe_ch_data[ch].sfb_pe[sfb]; |
723 | 457k | pstr_qs_pe_data->pe += delta_pe; |
724 | 457k | pstr_qs_pe_data->pe_ch_data[ch].pe += delta_pe; |
725 | 457k | } |
726 | 1.76M | } |
727 | 1.42M | if (pstr_qs_pe_data->pe <= desired_pe) { |
728 | 3.50k | break; |
729 | 3.50k | } |
730 | 1.42M | } |
731 | 1.36M | } |
732 | 50.2k | } |
733 | | |
734 | | static VOID iaace_allow_more_holes( |
735 | | ixheaace_psy_out_channel **pstr_psy_out, ia_qc_pe_data_struct *pstr_qs_pe_data, |
736 | | WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND], |
737 | | const ia_ah_param_struct *pstr_str_ah_param, const FLOAT32 desired_pe, WORD32 num_channels, |
738 | 50.2k | WORD32 chn) { |
739 | 50.2k | WORD32 sfb, ch; |
740 | 50.2k | FLOAT32 act_pe = pstr_qs_pe_data->pe; |
741 | | |
742 | 50.2k | if (num_channels == 2 && |
743 | 50.2k | pstr_psy_out[chn]->window_sequence == pstr_psy_out[chn + 1]->window_sequence) { |
744 | 13.8k | ixheaace_psy_out_channel *pstr_psy_out_left = pstr_psy_out[chn]; |
745 | 13.8k | ixheaace_psy_out_channel *pstr_psy_out_right = pstr_psy_out[chn + 1]; |
746 | | |
747 | 505k | for (sfb = 0; sfb < pstr_psy_out_left->sfb_count; sfb++) { |
748 | 492k | if (pstr_psy_out[chn]->ms_used[sfb]) { |
749 | 355k | if (ah_flag[chn + 1][sfb] != NO_AH && |
750 | 355k | 0.4f * pstr_psy_out_left->sfb_min_snr[sfb] * pstr_psy_out_left->ptr_sfb_energy[sfb] > |
751 | 50.6k | pstr_psy_out_right->ptr_sfb_energy[sfb]) { |
752 | 4.68k | ah_flag[chn + 1][sfb] = NO_AH; |
753 | | |
754 | 4.68k | pstr_psy_out_right->ptr_sfb_thr[sfb] = 2.0f * pstr_psy_out_right->ptr_sfb_energy[sfb]; |
755 | | |
756 | 4.68k | act_pe -= pstr_qs_pe_data->pe_ch_data[chn + 1].sfb_pe[sfb]; |
757 | 350k | } else { |
758 | 350k | if (ah_flag[chn][sfb] != NO_AH && 0.4f * pstr_psy_out_right->sfb_min_snr[sfb] * |
759 | 243k | pstr_psy_out_right->ptr_sfb_energy[sfb] > |
760 | 243k | pstr_psy_out_left->ptr_sfb_energy[sfb]) { |
761 | 2.09k | ah_flag[chn][sfb] = NO_AH; |
762 | | |
763 | 2.09k | pstr_psy_out_left->ptr_sfb_thr[sfb] = 2.0f * pstr_psy_out_left->ptr_sfb_energy[sfb]; |
764 | | |
765 | 2.09k | act_pe -= pstr_qs_pe_data->pe_ch_data[chn].sfb_pe[sfb]; |
766 | 2.09k | } |
767 | 350k | } |
768 | 355k | if (act_pe < desired_pe) { |
769 | 1.17k | break; |
770 | 1.17k | } |
771 | 355k | } |
772 | 492k | } |
773 | 13.8k | } |
774 | 50.2k | if (act_pe > desired_pe) { |
775 | 46.5k | WORD32 start_sfb[IXHEAACE_MAX_CH_IN_BS_ELE] = {0}; |
776 | 46.5k | FLOAT32 average_energy, min_energy; |
777 | 46.5k | WORD32 ah_cnt; |
778 | 46.5k | WORD32 en_idx; |
779 | 46.5k | FLOAT32 energy[4]; |
780 | 46.5k | WORD32 min_sfb, max_sfb; |
781 | 46.5k | WORD32 done; |
782 | | |
783 | 105k | for (ch = chn; ch < chn + num_channels; ch++) { |
784 | 59.1k | if (pstr_psy_out[ch]->window_sequence != SHORT_WINDOW) { |
785 | 56.3k | start_sfb[ch] = pstr_str_ah_param->start_sfb_long; |
786 | 56.3k | } else { |
787 | 2.79k | start_sfb[ch] = pstr_str_ah_param->start_sfb_short; |
788 | 2.79k | } |
789 | 59.1k | } |
790 | | |
791 | 46.5k | average_energy = 0.0f; |
792 | 46.5k | min_energy = MAX_FLT_VAL; |
793 | 46.5k | ah_cnt = 0; |
794 | 105k | for (ch = chn; ch < chn + num_channels; ch++) { |
795 | 59.1k | ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch]; |
796 | 2.09M | for (sfb = start_sfb[ch]; sfb < pstr_psy_chan_out->sfb_count; sfb++) { |
797 | 2.03M | if ((ah_flag[ch][sfb] != NO_AH) && |
798 | 2.03M | (pstr_psy_chan_out->ptr_sfb_energy[sfb] > pstr_psy_chan_out->ptr_sfb_thr[sfb])) { |
799 | 1.02M | min_energy = MIN(min_energy, pstr_psy_chan_out->ptr_sfb_energy[sfb]); |
800 | 1.02M | average_energy += pstr_psy_chan_out->ptr_sfb_energy[sfb]; |
801 | 1.02M | ah_cnt++; |
802 | 1.02M | } |
803 | 2.03M | } |
804 | 59.1k | } |
805 | | |
806 | 46.5k | average_energy = MIN(MAX_FLT_VAL, average_energy / (ah_cnt + MIN_FLT_VAL)); |
807 | | |
808 | 232k | for (en_idx = 0; en_idx < 4; en_idx++) { |
809 | 186k | energy[en_idx] = min_energy * (FLOAT32)pow(average_energy / (min_energy + MIN_FLT_VAL), |
810 | 186k | (2 * en_idx + 1) / 7.0f); |
811 | 186k | } |
812 | 46.5k | max_sfb = pstr_psy_out[chn]->sfb_count - 1; |
813 | 46.5k | min_sfb = start_sfb[chn]; |
814 | | |
815 | 46.5k | if (num_channels == 2) { |
816 | 12.6k | max_sfb = MAX(max_sfb, pstr_psy_out[chn + 1]->sfb_count - 1); |
817 | | |
818 | 12.6k | min_sfb = MIN(min_sfb, start_sfb[chn + 1]); |
819 | 12.6k | } |
820 | | |
821 | 46.5k | sfb = max_sfb; |
822 | 46.5k | en_idx = 0; |
823 | 46.5k | done = 0; |
824 | 2.08M | while (!done) { |
825 | 4.57M | for (ch = chn; ch < chn + num_channels; ch++) { |
826 | 2.57M | ixheaace_psy_out_channel *pstr_psy_chan_out = pstr_psy_out[ch]; |
827 | 2.57M | if (sfb >= start_sfb[ch] && sfb < pstr_psy_chan_out->sfb_count) { |
828 | 2.57M | if (ah_flag[ch][sfb] != NO_AH && |
829 | 2.57M | pstr_psy_chan_out->ptr_sfb_energy[sfb] < energy[en_idx]) { |
830 | 328k | ah_flag[ch][sfb] = NO_AH; |
831 | 328k | pstr_psy_chan_out->ptr_sfb_thr[sfb] = 2.0f * pstr_psy_chan_out->ptr_sfb_energy[sfb]; |
832 | 328k | act_pe -= pstr_qs_pe_data->pe_ch_data[ch].sfb_pe[sfb]; |
833 | 328k | } |
834 | | |
835 | 2.57M | if (act_pe < desired_pe) { |
836 | 39.1k | done = 1; |
837 | 39.1k | break; |
838 | 39.1k | } |
839 | 2.57M | } |
840 | 2.57M | } |
841 | 2.04M | sfb--; |
842 | 2.04M | if (sfb < min_sfb) { |
843 | 55.6k | sfb = max_sfb; |
844 | 55.6k | en_idx++; |
845 | 55.6k | if (en_idx >= 4) { |
846 | 7.43k | done = 1; |
847 | 7.43k | } |
848 | 55.6k | } |
849 | 2.04M | } |
850 | 46.5k | } |
851 | 50.2k | } |
852 | | |
853 | | static VOID iaace_adapt_thr_to_pe( |
854 | | ixheaace_psy_out_channel **pstr_psy_out, |
855 | | ia_qc_pe_data_struct *pstr_qs_pe_data, const FLOAT32 desired_pe, |
856 | | ia_ah_param_struct *pstr_ah_param, ia_min_snr_adapt_param_struct *pstr_msa_param, |
857 | 184k | WORD32 num_channels, WORD32 chn, WORD32 aot) { |
858 | 184k | FLOAT32 no_red_pe, red_pe, red_pe_no_ah; |
859 | 184k | FLOAT32 const_part, const_part_no_ah; |
860 | 184k | FLOAT32 num_active_lines, num_active_lines_no_ah; |
861 | 184k | FLOAT32 desired_pe_no_ah; |
862 | 184k | FLOAT32 redval = 0.0f; |
863 | 184k | WORD32 ah_flag[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND]; |
864 | 184k | FLOAT32 thr_exp[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND]; |
865 | 184k | WORD32 iteration; |
866 | | |
867 | 184k | iaace_calc_thr_exp(thr_exp, pstr_psy_out, num_channels, chn); |
868 | 184k | iaace_adapt_min_snr(pstr_psy_out, pstr_msa_param, num_channels, chn); |
869 | 184k | iaace_init_avoid_hole_flag(ah_flag, pstr_psy_out, pstr_ah_param, num_channels, chn, aot); |
870 | | |
871 | 184k | no_red_pe = pstr_qs_pe_data->pe; |
872 | 184k | const_part = pstr_qs_pe_data->const_part; |
873 | 184k | num_active_lines = pstr_qs_pe_data->num_active_lines; |
874 | 184k | if (num_active_lines > FLT_EPSILON) { |
875 | 184k | FLOAT32 avg_thr_exp = |
876 | 184k | (FLOAT32)pow(2.0f, (const_part - no_red_pe) / (INV_RED_EXP_VAL * num_active_lines)); |
877 | 184k | redval = (FLOAT32)pow(2.0f, (const_part - desired_pe) / (INV_RED_EXP_VAL * num_active_lines)) |
878 | 184k | - avg_thr_exp; |
879 | 184k | redval = MAX(0.0f, redval); |
880 | 184k | iaace_reduce_thr(pstr_psy_out, ah_flag, thr_exp, redval, num_channels, chn); |
881 | 184k | } |
882 | | |
883 | 184k | iaace_calc_sfb_pe_data(pstr_qs_pe_data, pstr_psy_out, num_channels, chn); |
884 | 184k | red_pe = pstr_qs_pe_data->pe; |
885 | | |
886 | 184k | iteration = 0; |
887 | 271k | do { |
888 | 271k | iaace_calc_pe_no_active_holes(&red_pe_no_ah, &const_part_no_ah, &num_active_lines_no_ah, |
889 | 271k | pstr_qs_pe_data, ah_flag, pstr_psy_out, num_channels, chn); |
890 | | |
891 | 271k | desired_pe_no_ah = MAX(desired_pe - (red_pe - red_pe_no_ah), 0); |
892 | | |
893 | 271k | if (num_active_lines_no_ah > FLT_EPSILON) { |
894 | 269k | FLOAT32 avg_thr_exp = (FLOAT32)pow( |
895 | 269k | 2.0f, (const_part_no_ah - red_pe_no_ah) / (INV_RED_EXP_VAL * num_active_lines_no_ah)); |
896 | 269k | redval += (FLOAT32)pow(2.0f, (const_part_no_ah - desired_pe_no_ah) / |
897 | 269k | (INV_RED_EXP_VAL * num_active_lines_no_ah)) - |
898 | 269k | avg_thr_exp; |
899 | 269k | redval = MAX(0.0f, redval); |
900 | 269k | iaace_reduce_thr(pstr_psy_out, ah_flag, thr_exp, redval, num_channels, chn); |
901 | 269k | } |
902 | | |
903 | 271k | iaace_calc_sfb_pe_data(pstr_qs_pe_data, pstr_psy_out, num_channels, chn); |
904 | | |
905 | 271k | red_pe = pstr_qs_pe_data->pe; |
906 | 271k | iteration++; |
907 | 271k | } while ((fabs(red_pe - desired_pe) > (0.05f) * desired_pe) && (iteration < 2)); |
908 | | |
909 | 184k | if (red_pe < 1.15f * desired_pe) { |
910 | 133k | iaace_correct_thr(pstr_psy_out, ah_flag, pstr_qs_pe_data, thr_exp, redval, |
911 | 133k | desired_pe - red_pe, num_channels, chn); |
912 | 133k | } else { |
913 | 50.2k | iaace_reduce_min_snr(pstr_psy_out, pstr_qs_pe_data, ah_flag, 1.05f * desired_pe, num_channels, |
914 | 50.2k | chn); |
915 | 50.2k | iaace_allow_more_holes(pstr_psy_out, pstr_qs_pe_data, ah_flag, pstr_ah_param, |
916 | 50.2k | 1.05f * desired_pe, num_channels, chn); |
917 | 50.2k | } |
918 | 184k | } |
919 | | |
920 | | VOID iaace_adjust_threshold(ia_adj_thr_state_struct *pstr_adj_thr_state, |
921 | | ia_adj_thr_elem_struct *pstr_adj_thr_elem, |
922 | | ixheaace_psy_out_channel **pstr_psy_out, |
923 | | FLOAT32 *ptr_ch_bit_dist, ixheaace_qc_out_element *pstr_qc_out_el, |
924 | | const WORD32 avg_bits, const WORD32 bitres_bits, |
925 | | const WORD32 max_bitres_bits, const WORD32 side_info_bits, |
926 | | FLOAT32 *max_bit_fac, FLOAT32 *ptr_sfb_n_relevant_lines, |
927 | | FLOAT32 *ptr_sfb_ld_energy, WORD32 num_channels, WORD32 chn, |
928 | 308k | WORD32 aot, WORD8 *ptr_scratch) { |
929 | 308k | FLOAT32 no_red_pe, granted_pe, granted_pe_corr; |
930 | 308k | WORD32 curr_win_sequence; |
931 | 308k | ia_qc_pe_data_struct *pstr_qc_pe_data = (ia_qc_pe_data_struct *)ptr_scratch; |
932 | 308k | FLOAT32 bit_factor; |
933 | 308k | WORD32 ch; |
934 | | |
935 | 752k | for (ch = chn; ch < chn + num_channels; ch++) { |
936 | 443k | pstr_qc_pe_data->pe_ch_data[ch].sfb_lines = |
937 | 443k | ptr_sfb_n_relevant_lines + MAXIMUM_GROUPED_SCALE_FACTOR_BAND * ch; |
938 | 443k | pstr_qc_pe_data->pe_ch_data[ch].sfb_ld_energy = |
939 | 443k | ptr_sfb_ld_energy + MAXIMUM_GROUPED_SCALE_FACTOR_BAND * ch; |
940 | 443k | } |
941 | 308k | pstr_qc_pe_data->offset = pstr_adj_thr_elem->pe_offset; |
942 | | |
943 | 308k | iaace_calc_sfb_pe_data(pstr_qc_pe_data, pstr_psy_out, num_channels, chn); |
944 | | |
945 | 308k | no_red_pe = pstr_qc_pe_data->pe; |
946 | | |
947 | 308k | curr_win_sequence = LONG_WINDOW; |
948 | 308k | if (num_channels == 2) { |
949 | 134k | if ((pstr_psy_out[chn]->window_sequence == SHORT_WINDOW) || |
950 | 134k | (pstr_psy_out[chn + 1]->window_sequence == SHORT_WINDOW)) { |
951 | 31.3k | curr_win_sequence = SHORT_WINDOW; |
952 | 31.3k | } |
953 | 174k | } else { |
954 | 174k | curr_win_sequence = pstr_psy_out[chn]->window_sequence; |
955 | 174k | } |
956 | | |
957 | 308k | bit_factor = iaace_bitres_calc_bitfac( |
958 | 308k | bitres_bits, max_bitres_bits, no_red_pe + 5.0f * side_info_bits, curr_win_sequence, |
959 | 308k | avg_bits, *max_bit_fac, pstr_adj_thr_state, pstr_adj_thr_elem); |
960 | | |
961 | 308k | granted_pe = bit_factor * iaace_bits_to_pe((FLOAT32)avg_bits); |
962 | | |
963 | 308k | iaace_calc_pe_correction(&(pstr_adj_thr_elem->pe_correction_fac), MIN(granted_pe, no_red_pe), |
964 | 308k | pstr_adj_thr_elem->pe_last, pstr_adj_thr_elem->dyn_bits_last); |
965 | | |
966 | 308k | granted_pe_corr = granted_pe * pstr_adj_thr_elem->pe_correction_fac; |
967 | | |
968 | 308k | if (granted_pe_corr < no_red_pe) { |
969 | 184k | iaace_adapt_thr_to_pe(pstr_psy_out, pstr_qc_pe_data, granted_pe_corr, |
970 | 184k | &pstr_adj_thr_elem->str_ah_param, |
971 | 184k | &pstr_adj_thr_elem->str_min_snr_adapt_params, num_channels, chn, aot); |
972 | 184k | } |
973 | | |
974 | 752k | for (ch = chn; ch < chn + num_channels; ch++) { |
975 | 443k | FLOAT32 tmp_var, temp1; |
976 | 443k | if (pstr_qc_pe_data->pe) { |
977 | 417k | tmp_var = 1.0f - num_channels * 0.2f; |
978 | 417k | temp1 = pstr_qc_pe_data->pe_ch_data[ch].pe / pstr_qc_pe_data->pe; |
979 | 417k | temp1 = temp1 * tmp_var; |
980 | 417k | ptr_ch_bit_dist[ch] = temp1 + 0.2f; |
981 | 417k | if (ptr_ch_bit_dist[ch] < 0.2f) { |
982 | 0 | ptr_ch_bit_dist[ch] = 0.2f; |
983 | 0 | } |
984 | 417k | } else { |
985 | 26.0k | ptr_ch_bit_dist[ch] = 0.2f; |
986 | 26.0k | } |
987 | 443k | } |
988 | | |
989 | 308k | pstr_qc_out_el->pe = no_red_pe; |
990 | 308k | pstr_adj_thr_elem->pe_last = granted_pe; |
991 | 308k | } |