xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_sf_estimation.c (revision 15dc779a375ca8b5125643b829a8aa4b70d7f451)
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 <math.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <limits.h>
25 
26 #include "ixheaac_type_def.h"
27 #include "ixheaac_constants.h"
28 #include "ixheaace_aac_constants.h"
29 #include "ixheaac_basic_ops32.h"
30 #include "ixheaac_basic_ops16.h"
31 #include "ixheaac_basic_ops40.h"
32 #include "ixheaac_basic_ops.h"
33 
34 #include "ixheaace_psy_const.h"
35 #include "ixheaace_block_switch.h"
36 #include "ixheaace_tns.h"
37 #include "ixheaace_tns_params.h"
38 #include "ixheaace_rom.h"
39 #include "ixheaace_common_rom.h"
40 #include "ixheaace_bitbuffer.h"
41 #include "ixheaace_psy_data.h"
42 #include "ixheaace_interface.h"
43 #include "ixheaace_adjust_threshold_data.h"
44 #include "ixheaace_dynamic_bits.h"
45 #include "ixheaace_qc_data.h"
46 
47 #include "ixheaace_sf_estimation.h"
48 #include "ixheaace_quant.h"
49 #include "ixheaace_bits_count.h"
50 #include "ixheaace_tns_params.h"
51 #include "ixheaace_common_utils.h"
52 
iaace_calc_form_fac_per_chan(FLOAT32 * ptr_sfb_form_factor,FLOAT32 * ptr_sfb_num_relevant_lines,ixheaace_psy_out_channel * pstr_psy_out_chan,FLOAT32 * ptr_sfb_ld_energy)53 VOID iaace_calc_form_fac_per_chan(FLOAT32 *ptr_sfb_form_factor,
54                                   FLOAT32 *ptr_sfb_num_relevant_lines,
55                                   ixheaace_psy_out_channel *pstr_psy_out_chan,
56                                   FLOAT32 *ptr_sfb_ld_energy) {
57   WORD32 i, j, sfb_offs;
58   WORD32 sfb, sfb_width;
59 
60   memset(ptr_sfb_num_relevant_lines, 0,
61          sizeof(*ptr_sfb_num_relevant_lines) * pstr_psy_out_chan->sfb_count);
62 
63   memset(ptr_sfb_ld_energy, 0, sizeof(*ptr_sfb_ld_energy) * pstr_psy_out_chan->sfb_count);
64 
65   for (sfb_offs = 0; sfb_offs < pstr_psy_out_chan->sfb_count;
66        sfb_offs += pstr_psy_out_chan->sfb_per_group) {
67     i = sfb_offs;
68     for (sfb = 0; sfb < pstr_psy_out_chan->max_sfb_per_grp; sfb++, i++) {
69       ptr_sfb_form_factor[i] = MIN_FLT_VAL;
70       if (pstr_psy_out_chan->ptr_sfb_energy[i] > pstr_psy_out_chan->ptr_sfb_thr[i]) {
71         FLOAT32 avg_form_factor;
72 
73         for (j = pstr_psy_out_chan->sfb_offsets[i]; j < pstr_psy_out_chan->sfb_offsets[i + 1];
74              j++) {
75           ptr_sfb_form_factor[i] += (FLOAT32)sqrt(fabs(pstr_psy_out_chan->ptr_spec_coeffs[j]));
76         }
77 
78         sfb_width = pstr_psy_out_chan->sfb_offsets[i + 1] - pstr_psy_out_chan->sfb_offsets[i];
79         avg_form_factor =
80             (FLOAT32)pow(pstr_psy_out_chan->ptr_sfb_energy[i] / (FLOAT32)sfb_width, 0.25f);
81         ptr_sfb_num_relevant_lines[i] = ptr_sfb_form_factor[i] / avg_form_factor;
82         ptr_sfb_ld_energy[i] = (FLOAT32)(log(pstr_psy_out_chan->ptr_sfb_energy[i]) * LOG2_1);
83       }
84     }
85   }
86 }
87 
iaace_calculate_exp_spec(const WORD32 num_lines,FLOAT32 * ptr_exp_spec,FLOAT32 * ptr_ptr_mdct_spec)88 static VOID iaace_calculate_exp_spec(const WORD32 num_lines, FLOAT32 *ptr_exp_spec,
89                                      FLOAT32 *ptr_ptr_mdct_spec) {
90   WORD32 line;
91 
92   for (line = 0; line < num_lines; line++) {
93     FLOAT32 tmp = ptr_ptr_mdct_spec[line];
94     ptr_exp_spec[line] = (FLOAT32)sqrt(fabs(tmp));
95     ptr_exp_spec[line] *= (FLOAT32)sqrt(ptr_exp_spec[line]);
96   }
97 }
98 
iaace_scf_delta_bit_count(WORD32 delta)99 static WORD32 iaace_scf_delta_bit_count(WORD32 delta) {
100   if (delta > 60) {
101     return (ixheaace_huffman_code_table[120][0]);
102   }
103   if (delta < -60) {
104     return (ixheaace_huffman_code_table[0][0]);
105   }
106   return (ixheaace_huffman_code_table[delta + 60][0]);
107 }
108 
iaace_count_single_scf_bits(WORD32 scf,WORD32 left_scf,WORD32 right_scf)109 static WORD32 iaace_count_single_scf_bits(WORD32 scf, WORD32 left_scf, WORD32 right_scf) {
110   WORD32 scf_bits;
111 
112   scf_bits =
113       iaace_scf_delta_bit_count(left_scf - scf) + iaace_scf_delta_bit_count(scf - right_scf);
114 
115   return scf_bits;
116 }
117 
iaace_calc_single_spec_pe(WORD32 scf,FLOAT32 sfb_const_pe_part,FLOAT32 num_lines)118 static FLOAT32 iaace_calc_single_spec_pe(WORD32 scf, FLOAT32 sfb_const_pe_part,
119                                          FLOAT32 num_lines) {
120   FLOAT32 spec_pe;
121   FLOAT32 ld_ratio;
122 
123   ld_ratio = sfb_const_pe_part - (FLOAT32)0.375f * (FLOAT32)scf;
124 
125   if (ld_ratio >= PE_C1) {
126     spec_pe = (FLOAT32)0.7f * num_lines * ld_ratio;
127   } else {
128     spec_pe = (FLOAT32)0.7f * num_lines * (PE_C2 + PE_C3 * ld_ratio);
129   }
130 
131   return spec_pe;
132 }
133 
iaace_count_scf_bits_diff(WORD16 * ptr_sfb_prev,WORD16 * ptr_sfb_new,WORD32 sfb_count,WORD32 start_sfb,WORD32 stop_sfb)134 static WORD32 iaace_count_scf_bits_diff(WORD16 *ptr_sfb_prev, WORD16 *ptr_sfb_new,
135                                         WORD32 sfb_count, WORD32 start_sfb, WORD32 stop_sfb) {
136   WORD32 scf_bits_diff = 0;
137   WORD32 sfb = 0, sfb_last;
138   WORD32 sfb_prev, sfb_next;
139 
140   sfb_last = start_sfb;
141 
142   while ((sfb_last < stop_sfb) && (ptr_sfb_prev[sfb_last] == SHRT_MIN)) {
143     sfb_last++;
144   }
145 
146   sfb_prev = start_sfb - 1;
147 
148   while ((sfb_prev >= 0) && (ptr_sfb_prev[sfb_prev] == SHRT_MIN)) {
149     sfb_prev--;
150   }
151 
152   if (sfb_prev >= 0) {
153     scf_bits_diff += iaace_scf_delta_bit_count(ptr_sfb_new[sfb_prev] - ptr_sfb_new[sfb_last]) -
154                      iaace_scf_delta_bit_count(ptr_sfb_prev[sfb_prev] - ptr_sfb_prev[sfb_last]);
155   }
156 
157   for (sfb = sfb_last + 1; sfb < stop_sfb; sfb++) {
158     if (ptr_sfb_prev[sfb] != SHRT_MIN) {
159       scf_bits_diff += iaace_scf_delta_bit_count(ptr_sfb_new[sfb_last] - ptr_sfb_new[sfb]) -
160                        iaace_scf_delta_bit_count(ptr_sfb_prev[sfb_last] - ptr_sfb_prev[sfb]);
161 
162       sfb_last = sfb;
163     }
164   }
165 
166   sfb_next = stop_sfb;
167 
168   while ((sfb_next < sfb_count) && (ptr_sfb_prev[sfb_next] == SHRT_MIN)) {
169     sfb_next++;
170   }
171 
172   if (sfb_next < sfb_count) {
173     scf_bits_diff += iaace_scf_delta_bit_count(ptr_sfb_new[sfb_last] - ptr_sfb_new[sfb_next]) -
174                      iaace_scf_delta_bit_count(ptr_sfb_prev[sfb_last] - ptr_sfb_prev[sfb_next]);
175   }
176 
177   return scf_bits_diff;
178 }
179 
iaace_calc_spec_pe_diff(ixheaace_psy_out_channel * pstr_psy_out,WORD16 * ptr_scf_prev,WORD16 * ptr_scf_new,FLOAT32 * ptr_sfb_const_pe_part,FLOAT32 * ptr_sfb_form_fac,FLOAT32 * ptr_sfb_num_rel_lines,WORD32 start_sfb,WORD32 stop_sfb)180 static FLOAT32 iaace_calc_spec_pe_diff(ixheaace_psy_out_channel *pstr_psy_out,
181                                        WORD16 *ptr_scf_prev, WORD16 *ptr_scf_new,
182                                        FLOAT32 *ptr_sfb_const_pe_part, FLOAT32 *ptr_sfb_form_fac,
183                                        FLOAT32 *ptr_sfb_num_rel_lines, WORD32 start_sfb,
184                                        WORD32 stop_sfb) {
185   FLOAT32 spec_pe_diff = 0.0f;
186   WORD32 sfb;
187 
188   for (sfb = start_sfb; sfb < stop_sfb; sfb++) {
189     if (ptr_scf_prev[sfb] != SHRT_MIN) {
190       FLOAT32 ld_ratio_prev, ld_ratio_new, pe_prev, pe_new;
191 
192       if (ptr_sfb_const_pe_part[sfb] == MIN_FLT_VAL) {
193         ptr_sfb_const_pe_part[sfb] = (FLOAT32)log(pstr_psy_out->ptr_sfb_energy[sfb] *
194                                                   (FLOAT32)6.75f / ptr_sfb_form_fac[sfb]) *
195                                      LOG2_1;
196       }
197 
198       ld_ratio_prev = ptr_sfb_const_pe_part[sfb] - 0.375f * ptr_scf_prev[sfb];
199       ld_ratio_new = ptr_sfb_const_pe_part[sfb] - 0.375f * ptr_scf_new[sfb];
200 
201       if (ld_ratio_prev >= PE_C1) {
202         pe_prev = ld_ratio_prev;
203       } else {
204         pe_prev = PE_C2 + PE_C3 * ld_ratio_prev;
205       }
206 
207       if (ld_ratio_new >= PE_C1) {
208         pe_new = ld_ratio_new;
209       } else {
210         pe_new = PE_C2 + PE_C3 * ld_ratio_new;
211       }
212 
213       spec_pe_diff += (FLOAT32)0.7f * ptr_sfb_num_rel_lines[sfb] * (pe_new - pe_prev);
214     }
215   }
216 
217   return spec_pe_diff;
218 }
219 
iaace_calc_sfb_dist(const FLOAT32 * ptr_spec,const FLOAT32 * ptr_exp_spec,WORD16 * ptr_quant_spec,WORD32 sfb_width,WORD32 gain)220 static FLOAT32 iaace_calc_sfb_dist(const FLOAT32 *ptr_spec, const FLOAT32 *ptr_exp_spec,
221                                    WORD16 *ptr_quant_spec, WORD32 sfb_width, WORD32 gain) {
222   WORD32 i = 0;
223   FLOAT32 dist = 0;
224   FLOAT32 k = -0.0946f + 0.5f;
225   FLOAT32 quantizer = ixheaace_fd_quant_table[gain + 128];
226   FLOAT32 inv_quantizer = ixheaace_fd_inv_quant_table[gain + 128];
227 
228   while (i < sfb_width) {
229     FLOAT32 iq_val;
230     FLOAT32 diff;
231 
232     ptr_quant_spec[i] = (WORD16)(k + quantizer * ptr_exp_spec[i]);
233 
234     if (ptr_quant_spec[i] < 64) {
235       iq_val = ixheaace_pow_4_3_table[ptr_quant_spec[i]] * inv_quantizer;
236     } else {
237       iq_val = (FLOAT32)((pow((FLOAT32)abs(ptr_quant_spec[i]), 4.0f / 3.0f)) * inv_quantizer);
238     }
239 
240     diff = (FLOAT32)fabs(ptr_spec[i]) - iq_val;
241 
242     dist += diff * diff;
243 
244     i++;
245   }
246 
247   return dist;
248 }
249 
iaace_improve_scf(FLOAT32 * ptr_spec,FLOAT32 * ptr_exp_spec,WORD16 * ptr_quant_spec,WORD16 * ptr_quant_spec_temp,WORD32 sfb_width,FLOAT32 threshold,WORD16 scf,WORD16 min_scf,FLOAT32 * dist,WORD16 * ptr_min_calc_scf)250 static WORD16 iaace_improve_scf(FLOAT32 *ptr_spec, FLOAT32 *ptr_exp_spec, WORD16 *ptr_quant_spec,
251                                 WORD16 *ptr_quant_spec_temp, WORD32 sfb_width, FLOAT32 threshold,
252                                 WORD16 scf, WORD16 min_scf, FLOAT32 *dist,
253                                 WORD16 *ptr_min_calc_scf) {
254   FLOAT32 sfb_dist;
255   WORD16 best_scf = scf;
256   WORD32 j;
257 
258   sfb_dist = iaace_calc_sfb_dist(ptr_spec, ptr_exp_spec, ptr_quant_spec, sfb_width, scf);
259 
260   *ptr_min_calc_scf = scf;
261 
262   if (sfb_dist > (1.25 * threshold)) {
263     FLOAT32 best_sfb_dist = sfb_dist;
264 
265     if (scf > min_scf) {
266       scf--;
267 
268       sfb_dist = iaace_calc_sfb_dist(ptr_spec, ptr_exp_spec, ptr_quant_spec_temp, sfb_width, scf);
269 
270       if (sfb_dist < best_sfb_dist) {
271         best_scf = scf;
272         best_sfb_dist = sfb_dist;
273 
274         for (j = 0; j < sfb_width; j++) {
275           ptr_quant_spec[j] = ptr_quant_spec_temp[j];
276         }
277       }
278 
279       *ptr_min_calc_scf = scf;
280     }
281     *dist = best_sfb_dist;
282   } else {
283     FLOAT32 best_sfb_dist = sfb_dist;
284     FLOAT32 allowed_sfb_dist = MIN(sfb_dist * 1.25f, threshold);
285     WORD32 count;
286 
287     for (count = SCF_COUNT_LIMIT_AAC; count >= 0; count--) {
288       scf++;
289 
290       sfb_dist = iaace_calc_sfb_dist(ptr_spec, ptr_exp_spec, ptr_quant_spec_temp, sfb_width, scf);
291 
292       if (sfb_dist < allowed_sfb_dist) {
293         *ptr_min_calc_scf = best_scf + 1;
294 
295         best_scf = scf;
296         best_sfb_dist = sfb_dist;
297 
298         for (j = 0; j < sfb_width; j++) {
299           ptr_quant_spec[j] = ptr_quant_spec_temp[j];
300         }
301       }
302     }
303     *dist = best_sfb_dist;
304   }
305 
306   for (j = 0; j < sfb_width; j++) {
307     if (ptr_spec[j] < 0) {
308       ptr_quant_spec[j] = -ptr_quant_spec[j];
309     }
310   }
311 
312   return best_scf;
313 }
314 
iaace_assimilate_single_scf(ixheaace_psy_out_channel * pstr_psy_out,FLOAT32 * ptr_exp_spec,WORD16 * ptr_quant_spec,WORD16 * ptr_quant_spec_temp,WORD16 * ptr_scf,WORD16 * ptr_min_scf,FLOAT32 * ptr_sfb_dist,FLOAT32 * ptr_sfb_const_pe_part,FLOAT32 * ptr_sfb_form_fac,FLOAT32 * ptr_sfb_num_lines,WORD16 * ptr_min_calc_scf,FLOAT32 * ptr_ptr_mdct_spec)315 static VOID iaace_assimilate_single_scf(ixheaace_psy_out_channel *pstr_psy_out,
316                                         FLOAT32 *ptr_exp_spec, WORD16 *ptr_quant_spec,
317                                         WORD16 *ptr_quant_spec_temp, WORD16 *ptr_scf,
318                                         WORD16 *ptr_min_scf, FLOAT32 *ptr_sfb_dist,
319                                         FLOAT32 *ptr_sfb_const_pe_part, FLOAT32 *ptr_sfb_form_fac,
320                                         FLOAT32 *ptr_sfb_num_lines, WORD16 *ptr_min_calc_scf,
321                                         FLOAT32 *ptr_ptr_mdct_spec) {
322   WORD32 sfb_prev, sfb_act, sfb_next;
323   WORD16 scf_act = 0, *scf_prev, *scf_next, min_scf, max_scf;
324   WORD32 sfb_width, sfb_offs;
325   FLOAT32 energy;
326   FLOAT32 sfb_pe_prev, sfb_pe_new;
327   FLOAT32 sfb_dist_new;
328   WORD32 j;
329   WORD32 success = 0;
330   FLOAT32 delta_pe = 0.0f, delta_pe_new, delta_pe_temp;
331   WORD16 prev_scf_last[MAXIMUM_GROUPED_SCALE_FACTOR_BAND],
332       prev_scf_next[MAXIMUM_GROUPED_SCALE_FACTOR_BAND];
333   FLOAT32 delta_pe_last[MAXIMUM_GROUPED_SCALE_FACTOR_BAND];
334   WORD32 update_min_scf;
335 
336   for (j = 0; j < pstr_psy_out->sfb_count; j++) {
337     prev_scf_last[j] = SHRT_MAX;
338     prev_scf_next[j] = SHRT_MAX;
339     delta_pe_last[j] = MAX_FLT_VAL;
340   }
341 
342   sfb_prev = -1;
343   sfb_act = -1;
344   sfb_next = -1;
345   scf_prev = 0;
346   scf_next = 0;
347   min_scf = SHRT_MAX;
348   max_scf = SHRT_MAX;
349 
350   do {
351     sfb_next++;
352 
353     while ((sfb_next < pstr_psy_out->sfb_count) && (ptr_scf[sfb_next] == SHRT_MIN)) {
354       sfb_next++;
355     }
356 
357     if ((sfb_prev >= 0) && (sfb_act >= 0) && (sfb_next < pstr_psy_out->sfb_count)) {
358       scf_act = ptr_scf[sfb_act];
359 
360       scf_prev = ptr_scf + sfb_prev;
361       scf_next = ptr_scf + sfb_next;
362 
363       min_scf = MIN(*scf_prev, *scf_next);
364 
365       max_scf = MAX(*scf_prev, *scf_next);
366     } else {
367       if ((sfb_prev == -1) && (sfb_act >= 0) && (sfb_next < pstr_psy_out->sfb_count)) {
368         scf_act = ptr_scf[sfb_act];
369 
370         scf_prev = &scf_act;
371 
372         scf_next = ptr_scf + sfb_next;
373 
374         min_scf = *scf_next;
375 
376         max_scf = *scf_next;
377       } else {
378         if ((sfb_prev >= 0) && (sfb_act >= 0) && (sfb_next == pstr_psy_out->sfb_count)) {
379           scf_act = ptr_scf[sfb_act];
380 
381           scf_prev = ptr_scf + sfb_prev;
382 
383           scf_next = &scf_act;
384 
385           min_scf = *scf_prev;
386 
387           max_scf = *scf_prev;
388         }
389       }
390     }
391 
392     if (sfb_act >= 0) {
393       min_scf = MAX(min_scf, ptr_min_scf[sfb_act]);
394     }
395 
396     if ((sfb_act >= 0) && (sfb_prev >= 0 || sfb_next < pstr_psy_out->sfb_count) &&
397         (scf_act > min_scf) && (scf_act <= min_scf + MAX_SCF_DELTA) &&
398         (scf_act >= max_scf - MAX_SCF_DELTA) &&
399         (*scf_prev != prev_scf_last[sfb_act] || *scf_next != prev_scf_next[sfb_act] ||
400          delta_pe < delta_pe_last[sfb_act])) {
401       success = 0;
402 
403       sfb_width = pstr_psy_out->sfb_offsets[sfb_act + 1] - pstr_psy_out->sfb_offsets[sfb_act];
404 
405       sfb_offs = pstr_psy_out->sfb_offsets[sfb_act];
406 
407       energy = pstr_psy_out->ptr_sfb_energy[sfb_act];
408 
409       if (ptr_sfb_const_pe_part[sfb_act] == MIN_FLT_VAL) {
410         ptr_sfb_const_pe_part[sfb_act] =
411             (FLOAT32)log(energy * (FLOAT32)6.75f / ptr_sfb_form_fac[sfb_act]) * LOG2_1;
412       }
413 
414       sfb_pe_prev = iaace_calc_single_spec_pe(scf_act, ptr_sfb_const_pe_part[sfb_act],
415                                               ptr_sfb_num_lines[sfb_act]) +
416                     (FLOAT32)iaace_count_single_scf_bits(scf_act, *scf_prev, *scf_next);
417 
418       delta_pe_new = delta_pe;
419       update_min_scf = 1;
420 
421       do {
422         scf_act--;
423 
424         if (scf_act < ptr_min_calc_scf[sfb_act] && scf_act >= max_scf - MAX_SCF_DELTA) {
425           sfb_pe_new = iaace_calc_single_spec_pe(scf_act, ptr_sfb_const_pe_part[sfb_act],
426                                                  ptr_sfb_num_lines[sfb_act]) +
427                        (FLOAT32)iaace_count_single_scf_bits(scf_act, *scf_prev, *scf_next);
428 
429           delta_pe_temp = delta_pe + sfb_pe_new - sfb_pe_prev;
430 
431           if (delta_pe_temp < (FLOAT32)10.0f) {
432             sfb_dist_new =
433                 iaace_calc_sfb_dist(ptr_ptr_mdct_spec + sfb_offs, ptr_exp_spec + sfb_offs,
434                                     ptr_quant_spec_temp + sfb_offs, sfb_width, scf_act);
435 
436             if (sfb_dist_new < ptr_sfb_dist[sfb_act]) {
437               ptr_scf[sfb_act] = scf_act;
438               ptr_sfb_dist[sfb_act] = sfb_dist_new;
439 
440               for (j = sfb_offs; j < sfb_offs + sfb_width; j++) {
441                 ptr_quant_spec[j] = ptr_quant_spec_temp[j];
442 
443                 if (ptr_ptr_mdct_spec[j] < 0.0f) {
444                   ptr_quant_spec[j] = -ptr_quant_spec[j];
445                 }
446               }
447               delta_pe_new = delta_pe_temp;
448               success = 1;
449             }
450 
451             if (update_min_scf) {
452               ptr_min_calc_scf[sfb_act] = scf_act;
453             }
454           } else {
455             update_min_scf = 0;
456           }
457         }
458       } while (scf_act > min_scf);
459 
460       delta_pe = delta_pe_new;
461 
462       prev_scf_last[sfb_act] = *scf_prev;
463       prev_scf_next[sfb_act] = *scf_next;
464       delta_pe_last[sfb_act] = delta_pe;
465     }
466 
467     if (success) {
468       sfb_prev = -1;
469       sfb_act = -1;
470       sfb_next = -1;
471       scf_prev = 0;
472       scf_next = 0;
473       min_scf = SHRT_MAX;
474       max_scf = SHRT_MAX;
475       success = 0;
476     } else {
477       sfb_prev = sfb_act;
478       sfb_act = sfb_next;
479     }
480   } while (sfb_next < pstr_psy_out->sfb_count);
481 }
482 
iaace_assimilate_multiple_scf(ixheaace_psy_out_channel * pstr_psy_out,FLOAT32 * ptr_exp_spec,WORD16 * ptr_quant_spec,WORD16 * ptr_quant_spec_temp,WORD16 * ptr_scf,WORD16 * ptr_min_scf,FLOAT32 * ptr_sfb_dist,FLOAT32 * ptr_sfb_const_pe_part,FLOAT32 * ptr_sfb_form_fac,FLOAT32 * ptr_sfb_num_lines,FLOAT32 * ptr_ptr_mdct_spec)483 static VOID iaace_assimilate_multiple_scf(ixheaace_psy_out_channel *pstr_psy_out,
484                                           FLOAT32 *ptr_exp_spec, WORD16 *ptr_quant_spec,
485                                           WORD16 *ptr_quant_spec_temp, WORD16 *ptr_scf,
486                                           WORD16 *ptr_min_scf, FLOAT32 *ptr_sfb_dist,
487                                           FLOAT32 *ptr_sfb_const_pe_part,
488                                           FLOAT32 *ptr_sfb_form_fac, FLOAT32 *ptr_sfb_num_lines,
489                                           FLOAT32 *ptr_ptr_mdct_spec) {
490   WORD32 sfb, start_sfb, stop_sfb;
491   WORD16 scf_temp[MAXIMUM_GROUPED_SCALE_FACTOR_BAND], min_scf, max_scf, scf_act;
492   WORD32 possible_region_found;
493   WORD32 sfb_width, sfb_offs, j;
494   FLOAT32 sfb_dist_new[MAXIMUM_GROUPED_SCALE_FACTOR_BAND] = {0};
495   FLOAT32 prev_dist_sum, new_dist_sum;
496   WORD32 delta_scf_bits;
497   FLOAT32 delta_spec_pe;
498   FLOAT32 delta_pe = 0.0f, delta_pe_new;
499   WORD32 sfb_count = pstr_psy_out->sfb_count;
500 
501   min_scf = SHRT_MAX;
502   max_scf = SHRT_MIN;
503 
504   for (sfb = 0; sfb < sfb_count; sfb++) {
505     if (ptr_scf[sfb] != SHRT_MIN) {
506       min_scf = MIN(min_scf, ptr_scf[sfb]);
507 
508       max_scf = MAX(max_scf, ptr_scf[sfb]);
509     }
510   }
511 
512   if (max_scf != SHRT_MIN && max_scf <= min_scf + MAX_SCF_DELTA) {
513     scf_act = max_scf;
514     do {
515       scf_act = scf_act - 2;
516 
517       memcpy(scf_temp, ptr_scf, MAXIMUM_GROUPED_SCALE_FACTOR_BAND * sizeof(*ptr_scf));
518 
519       stop_sfb = 0;
520 
521       do {
522         sfb = stop_sfb;
523 
524         while (sfb < sfb_count && (ptr_scf[sfb] == SHRT_MIN || ptr_scf[sfb] <= scf_act)) {
525           sfb++;
526         }
527 
528         start_sfb = sfb;
529 
530         sfb++;
531 
532         while (sfb < sfb_count && (ptr_scf[sfb] == SHRT_MIN || ptr_scf[sfb] > scf_act)) {
533           sfb++;
534         }
535 
536         stop_sfb = sfb;
537 
538         possible_region_found = 0;
539 
540         if (start_sfb < sfb_count) {
541           possible_region_found = 1;
542 
543           for (sfb = start_sfb; sfb < stop_sfb; sfb++) {
544             if (ptr_scf[sfb] != SHRT_MIN) {
545               if (scf_act < ptr_min_scf[sfb]) {
546                 possible_region_found = 0;
547                 break;
548               }
549             }
550           }
551         }
552 
553         if (possible_region_found) {
554           for (sfb = start_sfb; sfb < stop_sfb; sfb++) {
555             if (scf_temp[sfb] != SHRT_MIN) {
556               scf_temp[sfb] = scf_act;
557             }
558           }
559 
560           delta_scf_bits =
561               iaace_count_scf_bits_diff(ptr_scf, scf_temp, sfb_count, start_sfb, stop_sfb);
562 
563           delta_spec_pe =
564               iaace_calc_spec_pe_diff(pstr_psy_out, ptr_scf, scf_temp, ptr_sfb_const_pe_part,
565                                       ptr_sfb_form_fac, ptr_sfb_num_lines, start_sfb, stop_sfb);
566 
567           delta_pe_new = delta_pe + (FLOAT32)delta_scf_bits + delta_spec_pe;
568 
569           if (delta_pe_new < (FLOAT32)10.0f) {
570             prev_dist_sum = new_dist_sum = 0.0f;
571 
572             for (sfb = start_sfb; sfb < stop_sfb; sfb++) {
573               if (scf_temp[sfb] != SHRT_MIN) {
574                 prev_dist_sum += ptr_sfb_dist[sfb];
575 
576                 sfb_width = pstr_psy_out->sfb_offsets[sfb + 1] - pstr_psy_out->sfb_offsets[sfb];
577 
578                 sfb_offs = pstr_psy_out->sfb_offsets[sfb];
579 
580                 sfb_dist_new[sfb] =
581                     iaace_calc_sfb_dist(ptr_ptr_mdct_spec + sfb_offs, ptr_exp_spec + sfb_offs,
582                                         ptr_quant_spec_temp + sfb_offs, sfb_width, scf_act);
583 
584                 if (sfb_dist_new[sfb] > pstr_psy_out->ptr_sfb_thr[sfb]) {
585                   new_dist_sum = (FLOAT32)2.0f * prev_dist_sum;
586                   break;
587                 }
588 
589                 new_dist_sum += sfb_dist_new[sfb];
590               }
591             }
592 
593             if (new_dist_sum < prev_dist_sum) {
594               delta_pe = delta_pe_new;
595 
596               for (sfb = start_sfb; sfb < stop_sfb; sfb++) {
597                 if (ptr_scf[sfb] != SHRT_MIN) {
598                   sfb_width = pstr_psy_out->sfb_offsets[sfb + 1] - pstr_psy_out->sfb_offsets[sfb];
599 
600                   sfb_offs = pstr_psy_out->sfb_offsets[sfb];
601                   ptr_scf[sfb] = scf_act;
602                   ptr_sfb_dist[sfb] = sfb_dist_new[sfb];
603 
604                   for (j = sfb_offs; j < sfb_offs + sfb_width; j++) {
605                     ptr_quant_spec[j] = ptr_quant_spec_temp[j];
606 
607                     if (ptr_ptr_mdct_spec[j] < 0.0f) {
608                       ptr_quant_spec[j] = -ptr_quant_spec[j];
609                     }
610                   }
611                 }
612               }
613             }
614           }
615         }
616 
617       } while (stop_sfb <= sfb_count);
618 
619     } while (scf_act > min_scf);
620   }
621 }
622 
iaace_estimate_scfs_chan(ixheaace_psy_out_channel ** pstr_psy_out,ixheaace_qc_out_channel ** pstr_qc_out_chan,FLOAT32 sfb_form_factor_ch[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],FLOAT32 sfb_num_relevant_lines_ch[][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],WORD32 num_channels,WORD32 chn,WORD32 frame_len_long)623 VOID iaace_estimate_scfs_chan(
624     ixheaace_psy_out_channel **pstr_psy_out,
625     ixheaace_qc_out_channel **pstr_qc_out_chan,
626     FLOAT32 sfb_form_factor_ch[IXHEAACE_MAX_CH_IN_BS_ELE][MAXIMUM_GROUPED_SCALE_FACTOR_BAND],
627     FLOAT32 sfb_num_relevant_lines_ch[][MAXIMUM_GROUPED_SCALE_FACTOR_BAND], WORD32 num_channels,
628     WORD32 chn, WORD32 frame_len_long) {
629   WORD16 *ptr_scalefactor;
630   WORD32 *global_gain;
631   FLOAT32 *ptr_sfb_form_factor;
632   FLOAT32 *ptr_sfb_num_relevant_lines_ch;
633   WORD16 *ptr_quant_spec;
634   WORD32 i, ch, j;
635   FLOAT32 thresh, energy, energy_part, thr_part;
636   FLOAT32 scf_float;
637   WORD16 scf_int = 0, min_scf = 0, max_scf = 0;
638   FLOAT32 max_spec = 0.0f;
639   WORD16 min_sf_max_quant[MAXIMUM_GROUPED_SCALE_FACTOR_BAND] = {0};
640   FLOAT32 sfb_dist[MAXIMUM_GROUPED_SCALE_FACTOR_BAND] = {0};
641   WORD16 min_calc_scf[MAXIMUM_GROUPED_SCALE_FACTOR_BAND] = {0};
642   WORD16 quant_spec_temp[FRAME_LEN_1024];
643   FLOAT32 ptr_exp_spec[FRAME_LEN_1024];
644   FLOAT32 ptr_mdct_spec[FRAME_LEN_1024];
645 
646   memset(quant_spec_temp, 0, frame_len_long * sizeof(quant_spec_temp[0]));
647   memset(ptr_mdct_spec, 0, frame_len_long * sizeof(ptr_mdct_spec[0]));
648   memset(ptr_exp_spec, 0, frame_len_long * sizeof(ptr_exp_spec[0]));
649 
650   for (ch = chn; ch < chn + num_channels; ch++) {
651     ixheaace_psy_out_channel *pstr_psy_out_chan = pstr_psy_out[ch];
652     pstr_qc_out_chan[ch]->global_gain = 0;
653 
654     memset(pstr_qc_out_chan[ch]->scalefactor, 0,
655            sizeof(*pstr_qc_out_chan[ch]->scalefactor) * pstr_psy_out[ch]->sfb_count);
656     memset(pstr_qc_out_chan[ch]->quant_spec, 0,
657            sizeof(*pstr_qc_out_chan[ch]->quant_spec) * frame_len_long);
658 
659     ptr_scalefactor = pstr_qc_out_chan[ch]->scalefactor;
660     global_gain = &pstr_qc_out_chan[ch]->global_gain;
661     ptr_sfb_form_factor = &sfb_form_factor_ch[ch][0];
662     ptr_sfb_num_relevant_lines_ch = &sfb_num_relevant_lines_ch[ch][0];
663     ptr_quant_spec = pstr_qc_out_chan[ch]->quant_spec;
664 
665     for (i = 0; i < pstr_psy_out_chan->sfb_count; i++) {
666       thresh = pstr_psy_out_chan->ptr_sfb_thr[i];
667       energy = pstr_psy_out_chan->ptr_sfb_energy[i];
668       max_spec = 0.0f;
669 
670       for (j = pstr_psy_out_chan->sfb_offsets[i]; j < pstr_psy_out_chan->sfb_offsets[i + 1];
671            j++) {
672         max_spec = (FLOAT32)MAX(max_spec, fabsf(pstr_psy_out_chan->ptr_spec_coeffs[j]));
673       }
674 
675       ptr_scalefactor[i] = MIN_SHRT_VAL;
676       min_sf_max_quant[i] = MIN_SHRT_VAL;
677 
678       if ((max_spec > 0.0) && (energy > thresh) && (ptr_sfb_form_factor[i] != MIN_FLT_VAL)) {
679         energy_part = (FLOAT32)log10(ptr_sfb_form_factor[i]);
680 
681         thr_part = (FLOAT32)log10(6.75 * thresh + MIN_FLT_VAL);
682         scf_float = 8.8585f * (thr_part - energy_part);
683         scf_int = (WORD16)floor(scf_float);
684         min_sf_max_quant[i] = (WORD16)floor(C1_SF + C2_SF * log(max_spec));
685         scf_int = MAX(scf_int, min_sf_max_quant[i]);
686         scf_int = MAX(scf_int, MIN_GAIN_INDEX_AAC);
687         scf_int = MIN(scf_int, (MAX_GAIN_INDEX_AAC - SCF_COUNT_LIMIT_AAC - 1));
688         for (j = 0; j < pstr_psy_out_chan->sfb_offsets[i + 1] - pstr_psy_out_chan->sfb_offsets[i];
689              j++) {
690           ptr_exp_spec[pstr_psy_out_chan->sfb_offsets[i] + j] = (FLOAT32)(
691               pstr_psy_out_chan->ptr_spec_coeffs[pstr_psy_out_chan->sfb_offsets[i] + j]);
692           ptr_mdct_spec[pstr_psy_out_chan->sfb_offsets[i] + j] = (FLOAT32)(
693               pstr_psy_out_chan->ptr_spec_coeffs[pstr_psy_out_chan->sfb_offsets[i] + j]);
694         }
695 
696         iaace_calculate_exp_spec(
697             pstr_psy_out_chan->sfb_offsets[i + 1] - pstr_psy_out_chan->sfb_offsets[i],
698             ptr_exp_spec + pstr_psy_out_chan->sfb_offsets[i],
699             ptr_mdct_spec + pstr_psy_out_chan->sfb_offsets[i]);
700 
701         scf_int = iaace_improve_scf(
702             ptr_mdct_spec + pstr_psy_out_chan->sfb_offsets[i],
703             ptr_exp_spec + pstr_psy_out_chan->sfb_offsets[i],
704             ptr_quant_spec + pstr_psy_out_chan->sfb_offsets[i],
705             quant_spec_temp + pstr_psy_out_chan->sfb_offsets[i],
706             pstr_psy_out_chan->sfb_offsets[i + 1] - pstr_psy_out_chan->sfb_offsets[i], thresh,
707             scf_int, min_sf_max_quant[i], &sfb_dist[i], &min_calc_scf[i]);
708 
709         ptr_scalefactor[i] = scf_int;
710       }
711     }
712 
713     {
714       FLOAT32 sfb_const_pe_part[MAXIMUM_GROUPED_SCALE_FACTOR_BAND];
715 
716       for (i = 0; i < pstr_psy_out_chan->sfb_count; i++) {
717         sfb_const_pe_part[i] = MIN_FLT_VAL;
718       }
719 
720       iaace_assimilate_single_scf(pstr_psy_out_chan, ptr_exp_spec, ptr_quant_spec,
721                                   quant_spec_temp, ptr_scalefactor, min_sf_max_quant, sfb_dist,
722                                   sfb_const_pe_part, ptr_sfb_form_factor,
723                                   ptr_sfb_num_relevant_lines_ch, min_calc_scf, ptr_mdct_spec);
724 
725       iaace_assimilate_multiple_scf(pstr_psy_out_chan, ptr_exp_spec, ptr_quant_spec,
726                                     quant_spec_temp, ptr_scalefactor, min_sf_max_quant, sfb_dist,
727                                     sfb_const_pe_part, ptr_sfb_form_factor,
728                                     ptr_sfb_num_relevant_lines_ch, ptr_mdct_spec);
729     }
730 
731     max_scf = MIN_SHRT_VAL;
732     min_scf = MAX_SHRT_VAL;
733     for (i = 0; i < pstr_psy_out_chan->sfb_count; i++) {
734       if (max_scf < ptr_scalefactor[i]) {
735         max_scf = ptr_scalefactor[i];
736       }
737       if ((ptr_scalefactor[i] != MIN_SHRT_VAL) && (min_scf > ptr_scalefactor[i])) {
738         min_scf = ptr_scalefactor[i];
739       }
740     }
741 
742     for (i = 0; i < pstr_psy_out[ch]->sfb_count; i++) {
743       if ((ptr_scalefactor[i] != MIN_SHRT_VAL) &&
744           (min_scf + MAX_SCF_DELTA) < ptr_scalefactor[i]) {
745         ptr_scalefactor[i] = min_scf + MAX_SCF_DELTA;
746 
747         iaace_calc_sfb_dist(
748             ptr_mdct_spec + pstr_psy_out_chan->sfb_offsets[i],
749             ptr_exp_spec + pstr_psy_out_chan->sfb_offsets[i],
750             ptr_quant_spec + pstr_psy_out_chan->sfb_offsets[i],
751             pstr_psy_out_chan->sfb_offsets[i + 1] - pstr_psy_out_chan->sfb_offsets[i],
752             ptr_scalefactor[i]);
753       }
754     }
755 
756     max_scf = MIN((min_scf + MAX_SCF_DELTA), max_scf);
757 
758     if (max_scf > MIN_SHRT_VAL) {
759       *global_gain = max_scf;
760       for (i = 0; i < pstr_psy_out_chan->sfb_count; i++) {
761         if (ptr_scalefactor[i] == MIN_SHRT_VAL) {
762           ptr_scalefactor[i] = 0;
763           for (j = pstr_psy_out_chan->sfb_offsets[i]; j < pstr_psy_out_chan->sfb_offsets[i + 1];
764                j++) {
765             pstr_psy_out_chan->ptr_spec_coeffs[j] = 0.0f;
766           }
767         } else {
768           ptr_scalefactor[i] = max_scf - ptr_scalefactor[i];
769         }
770       }
771     } else {
772       *global_gain = 0;
773       for (i = 0; i < pstr_psy_out_chan->sfb_count; i++) {
774         ptr_scalefactor[i] = 0;
775         for (j = pstr_psy_out_chan->sfb_offsets[i]; j < pstr_psy_out_chan->sfb_offsets[i + 1];
776              j++) {
777           pstr_psy_out_chan->ptr_spec_coeffs[j] = 0.0f;
778         }
779       }
780     }
781   }
782 }
783