xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_sbr_missing_harmonics_det.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 <string.h>
22 #include <math.h>
23 #include <float.h>
24 #include "ixheaac_type_def.h"
25 #include "ixheaac_constants.h"
26 #include "ixheaac_error_standards.h"
27 #include "ixheaace_aac_constants.h"
28 #include "ixheaac_basic_ops32.h"
29 #include "ixheaac_basic_ops16.h"
30 #include "ixheaac_basic_ops40.h"
31 #include "ixheaac_basic_ops.h"
32 
33 #include "ixheaace_sbr_header.h"
34 #include "ixheaace_sbr_def.h"
35 #include "ixheaace_resampler.h"
36 #include "ixheaace_sbr_rom.h"
37 #include "ixheaace_common_rom.h"
38 #include "ixheaace_sbr_hbe.h"
39 #include "ixheaace_sbr_qmf_enc.h"
40 #include "ixheaace_sbr_tran_det.h"
41 #include "ixheaace_sbr_frame_info_gen.h"
42 #include "ixheaace_sbr_env_est.h"
43 #include "ixheaace_sbr_code_envelope.h"
44 #include "ixheaace_sbr_main.h"
45 #include "ixheaace_sbr_missing_harmonics_det.h"
46 #include "ixheaace_sbr_inv_filtering_estimation.h"
47 #include "ixheaace_sbr_noise_floor_est.h"
48 
49 #include "ixheaace_sbr_ton_corr.h"
50 #include "iusace_esbr_pvc.h"
51 #include "iusace_esbr_inter_tes.h"
52 #include "ixheaace_sbr.h"
53 #include "ixheaace_common_utils.h"
54 
ia_enhaacplus_enc_diff(FLOAT32 * ptr_tonal_orig,FLOAT32 * ptr_diff_map_2_scfb,const UWORD8 * ptr_freq_band_tab,WORD32 n_scfb,WORD8 * ptr_idx_vx)55 static VOID ia_enhaacplus_enc_diff(FLOAT32 *ptr_tonal_orig, FLOAT32 *ptr_diff_map_2_scfb,
56                                    const UWORD8 *ptr_freq_band_tab, WORD32 n_scfb,
57                                    WORD8 *ptr_idx_vx) {
58   WORD32 i, ll, lu, k;
59   FLOAT32 max_val_orig, max_val_sbr;
60   for (i = 0; i < n_scfb; i++) {
61     ll = ptr_freq_band_tab[i];
62     lu = ptr_freq_band_tab[i + 1];
63     max_val_orig = max_val_sbr = 0;
64 
65     for (k = ll; k < lu; k++) {
66       if (ptr_tonal_orig[k] > max_val_orig) {
67         max_val_orig = ptr_tonal_orig[k];
68       }
69       if (ptr_tonal_orig[ptr_idx_vx[k]] > max_val_sbr) {
70         max_val_sbr = ptr_tonal_orig[ptr_idx_vx[k]];
71       }
72     }
73 
74     ptr_diff_map_2_scfb[i] = (max_val_sbr > 1) ? max_val_orig / max_val_sbr : max_val_orig;
75   }
76 }
77 
ia_enhaacplus_enc_calculate_flatness_measure(FLOAT32 * ptr_quota_buf,WORD8 * ptr_idx_vx,FLOAT32 * ptr_sfm_orig,FLOAT32 * ptr_sfm_sbr,const UWORD8 * ptr_freq_band_tab,WORD32 num_sfb)78 static VOID ia_enhaacplus_enc_calculate_flatness_measure(FLOAT32 *ptr_quota_buf,
79                                                          WORD8 *ptr_idx_vx, FLOAT32 *ptr_sfm_orig,
80                                                          FLOAT32 *ptr_sfm_sbr,
81                                                          const UWORD8 *ptr_freq_band_tab,
82                                                          WORD32 num_sfb) {
83   WORD32 i, j;
84 
85   FLOAT32 am_org, am_transp, gm_org, gm_transp, sfm_org, sfm_transp;
86 
87   i = 0;
88   while (i < num_sfb) {
89     WORD32 band_low = ptr_freq_band_tab[i];
90     WORD32 band_high = ptr_freq_band_tab[i + 1];
91 
92     ptr_sfm_orig[i] = 1.0f;
93     ptr_sfm_sbr[i] = 1.0f;
94 
95     if (band_high - band_low > 1) {
96       am_org = 0;
97       am_transp = 0;
98       gm_org = 1.0f;
99       gm_transp = 1.0f;
100 
101       for (j = band_low; j < band_high; j++) {
102         sfm_org = ptr_quota_buf[j];
103         sfm_transp = ptr_quota_buf[ptr_idx_vx[j]];
104 
105         am_org += sfm_org;
106         gm_org += sfm_org;
107         am_transp += sfm_transp;
108         gm_transp += sfm_transp;
109       }
110 
111       am_org /= band_high - band_low;
112       am_transp /= band_high - band_low;
113       gm_org = (FLOAT32)pow(gm_org, 1.0f / (band_high - band_low));
114       gm_transp = (FLOAT32)pow(gm_transp, 1.0f / (band_high - band_low));
115 
116       if (am_org) {
117         ptr_sfm_orig[i] = gm_org / am_org;
118       }
119 
120       if (am_transp) {
121         ptr_sfm_sbr[i] = gm_transp / am_transp;
122       }
123     }
124     i++;
125   }
126 }
127 
ia_enhaacplus_enc_calculate_detector_input(FLOAT32 ** ptr_quota_buf,WORD8 * ptr_idx_vx,FLOAT32 ** ptr_tonal_diff,FLOAT32 ** ptr_sfm_orig,FLOAT32 ** ptr_sfm_sbr,const UWORD8 * ptr_freq_band_tab,WORD32 num_sfb,WORD32 no_est_per_frame,WORD32 move,WORD32 no_qmf_bands)128 static VOID ia_enhaacplus_enc_calculate_detector_input(
129     FLOAT32 **ptr_quota_buf, WORD8 *ptr_idx_vx, FLOAT32 **ptr_tonal_diff, FLOAT32 **ptr_sfm_orig,
130     FLOAT32 **ptr_sfm_sbr, const UWORD8 *ptr_freq_band_tab, WORD32 num_sfb,
131     WORD32 no_est_per_frame, WORD32 move, WORD32 no_qmf_bands) {
132   WORD32 est;
133 
134   for (est = 0; est < move; est++) {
135     memcpy(ptr_tonal_diff[est], ptr_tonal_diff[est + no_est_per_frame],
136            no_qmf_bands * sizeof(ptr_tonal_diff[est][0]));
137 
138     memcpy(ptr_sfm_orig[est], ptr_sfm_orig[est + no_est_per_frame],
139            no_qmf_bands * sizeof(ptr_sfm_orig[est][0]));
140 
141     memcpy(ptr_sfm_sbr[est], ptr_sfm_sbr[est + no_est_per_frame],
142            no_qmf_bands * sizeof(ptr_sfm_sbr[est][0]));
143   }
144 
145   for (est = 0; est < no_est_per_frame; est++) {
146     ia_enhaacplus_enc_diff(ptr_quota_buf[est + move], ptr_tonal_diff[est + move],
147                            ptr_freq_band_tab, num_sfb, ptr_idx_vx);
148 
149     ia_enhaacplus_enc_calculate_flatness_measure(
150         ptr_quota_buf[est + move], ptr_idx_vx, ptr_sfm_orig[est + move], ptr_sfm_sbr[est + move],
151         ptr_freq_band_tab, num_sfb);
152   }
153 }
154 
ia_enhaacplus_enc_isDetectionOfNewToneAllowed(const ixheaace_str_frame_info_sbr * ptr_frame_info,WORD32 prev_transient_frame,WORD32 prev_transient_pos,WORD32 prev_trans_flag,WORD32 trans_pos_offset,WORD32 transient_flag,WORD32 transient_pos,ixheaace_pstr_sbr_missing_harmonics_detector pstr_sbr_missing_harmonics_detector)155 static WORD32 ia_enhaacplus_enc_isDetectionOfNewToneAllowed(
156     const ixheaace_str_frame_info_sbr *ptr_frame_info, WORD32 prev_transient_frame,
157     WORD32 prev_transient_pos, WORD32 prev_trans_flag, WORD32 trans_pos_offset,
158     WORD32 transient_flag, WORD32 transient_pos,
159     ixheaace_pstr_sbr_missing_harmonics_detector pstr_sbr_missing_harmonics_detector) {
160   WORD32 transient_frame, new_detection_allowed;
161 
162   transient_frame = 0;
163 
164   if (transient_flag) {
165     if (transient_pos + trans_pos_offset < ptr_frame_info->borders[ptr_frame_info->n_envelopes]) {
166       transient_frame = 1;
167     }
168   } else {
169     if (prev_trans_flag && !prev_transient_frame) {
170       transient_frame = 1;
171     }
172   }
173 
174   new_detection_allowed = 0;
175 
176   if (transient_frame) {
177     new_detection_allowed = 1;
178   } else {
179     if (prev_transient_frame &&
180         ixheaac_abs32(ptr_frame_info->borders[0] -
181                       (prev_transient_pos + trans_pos_offset -
182                        pstr_sbr_missing_harmonics_detector->time_slots)) < DELTA_TIME) {
183       new_detection_allowed = 1;
184     }
185   }
186 
187   pstr_sbr_missing_harmonics_detector->prev_trans_flag = transient_flag;
188   pstr_sbr_missing_harmonics_detector->prev_trans_frame = transient_frame;
189   pstr_sbr_missing_harmonics_detector->prev_trans_pos = transient_pos;
190 
191   return (new_detection_allowed);
192 }
193 
ia_enhaacplus_enc_transient_cleanup(FLOAT32 ** ptr_quota_buf,WORD32 num_sfb,UWORD8 ** ptr_detection_vectors,const UWORD8 * ptr_freq_band_tab,ixheaace_str_guide_vectors ptr_guide_vectors,WORD32 start,WORD32 stop)194 static VOID ia_enhaacplus_enc_transient_cleanup(FLOAT32 **ptr_quota_buf, WORD32 num_sfb,
195                                                 UWORD8 **ptr_detection_vectors,
196                                                 const UWORD8 *ptr_freq_band_tab,
197                                                 ixheaace_str_guide_vectors ptr_guide_vectors,
198                                                 WORD32 start, WORD32 stop) {
199   WORD32 sfb, band, low_band, up_band, est;
200 
201   UWORD8 ptr_harm_vec[MAXIMUM_FREQ_COEFFS];
202 
203   memset(ptr_harm_vec, 0, sizeof(ptr_harm_vec));
204 
205   for (est = start; est < stop; est++) {
206     for (sfb = 0; sfb < num_sfb - 1; sfb++) {
207       ptr_harm_vec[sfb] = ptr_harm_vec[sfb] || ptr_detection_vectors[est][sfb];
208     }
209   }
210 
211   for (sfb = 0; sfb < num_sfb - 1; sfb++) {
212     if (ptr_harm_vec[sfb] && ptr_harm_vec[sfb + 1]) {
213       FLOAT32 max_val_1, max_val_2;
214       WORD32 maxPos1, maxPos2;
215 
216       low_band = ptr_freq_band_tab[sfb];
217       up_band = ptr_freq_band_tab[sfb + 1];
218       maxPos1 = low_band;
219 
220       max_val_1 = ptr_quota_buf[start][low_band];
221       for (band = low_band; band < up_band; band++) {
222         if (ptr_quota_buf[start][band] > max_val_1) {
223           max_val_1 = ptr_quota_buf[start][band];
224           maxPos1 = band;
225         }
226       }
227 
228       for (est = start + 1; est < stop; est++) {
229         for (band = low_band; band < up_band; band++) {
230           if (ptr_quota_buf[est][band] > max_val_1) {
231             max_val_1 = ptr_quota_buf[est][band];
232             maxPos1 = band;
233           }
234         }
235       }
236 
237       low_band = ptr_freq_band_tab[sfb + 1];
238       up_band = ptr_freq_band_tab[sfb + 2];
239 
240       maxPos2 = low_band;
241       max_val_2 = ptr_quota_buf[start][low_band];
242 
243       for (band = low_band; band < up_band; band++) {
244         if (ptr_quota_buf[start][band] > max_val_2) {
245           max_val_2 = ptr_quota_buf[start][band];
246           maxPos2 = band;
247         }
248       }
249 
250       for (est = start + 1; est < stop; est++) {
251         for (band = low_band; band < up_band; band++) {
252           if (ptr_quota_buf[est][band] > max_val_2) {
253             max_val_2 = ptr_quota_buf[est][band];
254             maxPos2 = band;
255           }
256         }
257       }
258 
259       if (maxPos2 - maxPos1 < 2) {
260         if (max_val_1 > max_val_2) {
261           ptr_guide_vectors.ptr_guide_vector_detected[sfb + 1] = 0;
262           ptr_guide_vectors.ptr_guide_vec_orig[sfb + 1] = 0;
263           ptr_guide_vectors.ptr_guide_vec_diff[sfb + 1] = 0;
264 
265           for (est = start; est < stop; est++) {
266             ptr_detection_vectors[est][sfb + 1] = 0;
267           }
268         } else {
269           ptr_guide_vectors.ptr_guide_vector_detected[sfb] = 0;
270           ptr_guide_vectors.ptr_guide_vec_diff[sfb] = 0;
271           ptr_guide_vectors.ptr_guide_vec_orig[sfb] = 0;
272 
273           for (est = start; est < stop; est++) {
274             ptr_detection_vectors[est][sfb] = 0;
275           }
276         }
277       }
278     }
279   }
280 }
281 
ia_enhaacplus_enc_detection(FLOAT32 * ptr_quota_buf,FLOAT32 * ptr_diff_vec_scfb,WORD32 num_sfb,UWORD8 * ptr_harm_vec,const UWORD8 * ptr_freq_band_tab,FLOAT32 * ptr_sfm_orig,FLOAT32 * ptr_sfm_sbr,ixheaace_str_guide_vectors * ptr_guide_vectors,ixheaace_str_guide_vectors * ptr_new_guide_vectors)282 static VOID ia_enhaacplus_enc_detection(FLOAT32 *ptr_quota_buf, FLOAT32 *ptr_diff_vec_scfb,
283                                         WORD32 num_sfb, UWORD8 *ptr_harm_vec,
284                                         const UWORD8 *ptr_freq_band_tab, FLOAT32 *ptr_sfm_orig,
285                                         FLOAT32 *ptr_sfm_sbr,
286                                         ixheaace_str_guide_vectors *ptr_guide_vectors,
287                                         ixheaace_str_guide_vectors *ptr_new_guide_vectors) {
288   WORD32 i, j;
289   WORD32 lower_band, upper_band;
290   FLOAT32 thr, thr_org;
291 
292   for (i = 0; i < num_sfb; i++) {
293     if (ptr_guide_vectors->ptr_guide_vec_diff[i]) {
294       if (SBR_DECAY_GUIDE_DIFF * ptr_guide_vectors->ptr_guide_vec_diff[i] > SBR_THR_DIFF_GUIDE) {
295         thr = SBR_DECAY_GUIDE_DIFF * ptr_guide_vectors->ptr_guide_vec_diff[i];
296       } else {
297         thr = SBR_THR_DIFF_GUIDE;
298       }
299       if (thr > SBR_THR_DIFF) {
300         thr = SBR_THR_DIFF;
301       }
302     } else {
303       thr = SBR_THR_DIFF;
304     }
305 
306     if (ptr_diff_vec_scfb[i] > thr) {
307       ptr_harm_vec[i] = 1;
308       ptr_new_guide_vectors->ptr_guide_vec_diff[i] = ptr_diff_vec_scfb[i];
309     } else {
310       if (ptr_guide_vectors->ptr_guide_vec_diff[i]) {
311         ptr_guide_vectors->ptr_guide_vec_orig[i] = SBR_THR_TONE_GUIDE;
312       }
313     }
314   }
315 
316   for (i = 0; i < num_sfb; i++) {
317     lower_band = ptr_freq_band_tab[i];
318     upper_band = ptr_freq_band_tab[i + 1];
319 
320     if (ptr_guide_vectors->ptr_guide_vec_orig[i] * SBR_DECAY_GUIDE_ORIG > SBR_THR_TONE_GUIDE) {
321       thr_org = ptr_guide_vectors->ptr_guide_vec_orig[i] * SBR_DECAY_GUIDE_ORIG;
322     } else {
323       thr_org = SBR_THR_TONE_GUIDE;
324     }
325     if (thr_org > SBR_THR_TONE) {
326       thr_org = SBR_THR_TONE;
327     }
328     if (ptr_guide_vectors->ptr_guide_vec_orig[i]) {
329       for (j = lower_band; j < upper_band; j++) {
330         if (ptr_quota_buf[j] > thr_org) {
331           ptr_harm_vec[i] = 1;
332           ptr_new_guide_vectors->ptr_guide_vec_orig[i] = ptr_quota_buf[j];
333         }
334       }
335     }
336   }
337 
338   thr_org = SBR_THR_TONE;
339 
340   for (i = 0; i < num_sfb; i++) {
341     lower_band = ptr_freq_band_tab[i];
342     upper_band = ptr_freq_band_tab[i + 1];
343 
344     if (upper_band - lower_band > 1) {
345       for (j = lower_band; j < upper_band; j++) {
346         if (ptr_quota_buf[j] > thr_org && ptr_sfm_sbr[i] > SBR_THR_SFM_SBR &&
347             ptr_sfm_orig[i] > SBR_THR_SFM_ORG) {
348           ptr_harm_vec[i] = 1;
349           ptr_new_guide_vectors->ptr_guide_vec_orig[i] = ptr_quota_buf[j];
350         }
351       }
352     } else {
353       if (1 < (num_sfb - 1)) {
354         lower_band = ptr_freq_band_tab[i];
355 
356         if (i > 0) {
357           if (ptr_quota_buf[lower_band] > SBR_THR_TONE &&
358               (ptr_diff_vec_scfb[i - 1] < SBR_INV_THR_TONE ||
359                ptr_diff_vec_scfb[i + 1] < SBR_INV_THR_TONE)) {
360             ptr_harm_vec[i] = 1;
361             ptr_new_guide_vectors->ptr_guide_vec_orig[i] = ptr_quota_buf[lower_band];
362           }
363         } else {
364           if (ptr_quota_buf[lower_band] > SBR_THR_TONE &&
365               ptr_diff_vec_scfb[i + 1] < SBR_INV_THR_TONE) {
366             ptr_harm_vec[i] = 1;
367             ptr_new_guide_vectors->ptr_guide_vec_orig[i] = ptr_quota_buf[lower_band];
368           }
369         }
370       }
371     }
372   }
373 }
374 
ia_enhaacplus_enc_detection_with_prediction(FLOAT32 ** ptr_quota_buf,FLOAT32 ** ptr_diff_vec_sfb,WORD32 num_sfb,const UWORD8 * ptr_freq_band_tab,FLOAT32 ** ptr_sfm_orig,FLOAT32 ** ptr_sfm_sbr,UWORD8 ** ptr_detection_vectors,UWORD8 * ptr_prev_frame_sfb_harm,ixheaace_str_guide_vectors * ptr_guide_vectors,WORD32 no_est_per_frame,WORD32 tot_no_est,WORD32 new_detection_allowed,UWORD8 * ptr_add_harmonics_sfbs)375 static VOID ia_enhaacplus_enc_detection_with_prediction(
376     FLOAT32 **ptr_quota_buf, FLOAT32 **ptr_diff_vec_sfb, WORD32 num_sfb,
377     const UWORD8 *ptr_freq_band_tab, FLOAT32 **ptr_sfm_orig, FLOAT32 **ptr_sfm_sbr,
378     UWORD8 **ptr_detection_vectors, UWORD8 *ptr_prev_frame_sfb_harm,
379     ixheaace_str_guide_vectors *ptr_guide_vectors, WORD32 no_est_per_frame, WORD32 tot_no_est,
380     WORD32 new_detection_allowed, UWORD8 *ptr_add_harmonics_sfbs) {
381   WORD32 est = 0, i;
382   WORD32 start;
383 
384   memset(ptr_add_harmonics_sfbs, 0, num_sfb * sizeof(ptr_add_harmonics_sfbs[0]));
385 
386   if (new_detection_allowed) {
387     if (tot_no_est > 1) {
388       start = no_est_per_frame;
389       memcpy(ptr_guide_vectors[no_est_per_frame].ptr_guide_vec_diff,
390              ptr_guide_vectors[0].ptr_guide_vec_diff,
391              num_sfb * sizeof(ptr_guide_vectors[no_est_per_frame].ptr_guide_vec_diff[0]));
392 
393       memcpy(ptr_guide_vectors[no_est_per_frame].ptr_guide_vec_orig,
394              ptr_guide_vectors[0].ptr_guide_vec_orig,
395              num_sfb * sizeof(ptr_guide_vectors[no_est_per_frame].ptr_guide_vec_orig[0]));
396 
397       memset(
398           ptr_guide_vectors[no_est_per_frame - 1].ptr_guide_vector_detected, 0,
399           num_sfb * sizeof(ptr_guide_vectors[no_est_per_frame - 1].ptr_guide_vector_detected[0]));
400     } else {
401       start = 0;
402     }
403   } else {
404     start = 0;
405   }
406 
407   for (est = start; est < tot_no_est; est++) {
408     if (est > 0) {
409       memcpy(ptr_guide_vectors[est].ptr_guide_vector_detected, ptr_detection_vectors[est - 1],
410              num_sfb * sizeof(ptr_guide_vectors[est].ptr_guide_vector_detected[0]));
411     }
412 
413     memset(ptr_detection_vectors[est], 0, num_sfb * sizeof(ptr_detection_vectors[est][0]));
414 
415     if (est < tot_no_est - 1) {
416       memset(ptr_guide_vectors[est + 1].ptr_guide_vec_diff, 0,
417              num_sfb * sizeof(ptr_guide_vectors[est + 1].ptr_guide_vec_diff[0]));
418 
419       memset(ptr_guide_vectors[est + 1].ptr_guide_vec_orig, 0,
420              num_sfb * sizeof(ptr_guide_vectors[est + 1].ptr_guide_vec_orig[0]));
421 
422       memset(ptr_guide_vectors[est + 1].ptr_guide_vector_detected, 0,
423              num_sfb * sizeof(ptr_guide_vectors[est + 1].ptr_guide_vector_detected[0]));
424 
425       ia_enhaacplus_enc_detection(ptr_quota_buf[est], ptr_diff_vec_sfb[est], num_sfb,
426                                   ptr_detection_vectors[est], ptr_freq_band_tab,
427                                   ptr_sfm_orig[est], ptr_sfm_sbr[est], &(ptr_guide_vectors[est]),
428                                   &(ptr_guide_vectors[est + 1]));
429     } else {
430       memset(ptr_guide_vectors[est].ptr_guide_vec_diff, 0,
431              num_sfb * sizeof(ptr_guide_vectors[est].ptr_guide_vec_diff[0]));
432 
433       memset(ptr_guide_vectors[est].ptr_guide_vec_orig, 0,
434              num_sfb * sizeof(ptr_guide_vectors[est].ptr_guide_vec_orig[0]));
435 
436       memset(ptr_guide_vectors[est].ptr_guide_vector_detected, 0,
437              num_sfb * sizeof(ptr_guide_vectors[est].ptr_guide_vector_detected[0]));
438 
439       ia_enhaacplus_enc_detection(ptr_quota_buf[est], ptr_diff_vec_sfb[est], num_sfb,
440                                   ptr_detection_vectors[est], ptr_freq_band_tab,
441                                   ptr_sfm_orig[est], ptr_sfm_sbr[est], &(ptr_guide_vectors[est]),
442                                   &(ptr_guide_vectors[est]));
443     }
444   }
445 
446   if (new_detection_allowed) {
447     if (tot_no_est > 1) {
448       ia_enhaacplus_enc_transient_cleanup(ptr_quota_buf, num_sfb, ptr_detection_vectors,
449                                           ptr_freq_band_tab, ptr_guide_vectors[no_est_per_frame],
450                                           start, tot_no_est);
451     } else {
452       ia_enhaacplus_enc_transient_cleanup(ptr_quota_buf, num_sfb, ptr_detection_vectors,
453                                           ptr_freq_band_tab, ptr_guide_vectors[0], start,
454                                           tot_no_est);
455     }
456   }
457 
458   for (i = 0; i < num_sfb; i++) {
459     for (est = start; est < tot_no_est; est++) {
460       ptr_add_harmonics_sfbs[i] = ptr_add_harmonics_sfbs[i] || ptr_detection_vectors[est][i];
461     }
462   }
463 
464   if (!new_detection_allowed) {
465     for (i = 0; i < num_sfb; i++) {
466       if (ptr_add_harmonics_sfbs[i] - ptr_prev_frame_sfb_harm[i] > 0) {
467         ptr_add_harmonics_sfbs[i] = 0;
468       }
469     }
470   }
471 }
472 
ia_enhaacplus_enc_calculate_comp_vector(UWORD8 * ptr_add_harmonics_sfbs,FLOAT32 ** ptr_tonality,WORD8 * ptr_env_compensation,WORD32 num_sfb,const UWORD8 * ptr_freq_band_tab,FLOAT32 ** ptr_diff,WORD32 tot_no_est,WORD8 * ptr_prev_env_compensation,WORD32 new_detection_allowed)473 static VOID ia_enhaacplus_enc_calculate_comp_vector(
474     UWORD8 *ptr_add_harmonics_sfbs, FLOAT32 **ptr_tonality, WORD8 *ptr_env_compensation,
475     WORD32 num_sfb, const UWORD8 *ptr_freq_band_tab, FLOAT32 **ptr_diff, WORD32 tot_no_est,
476     WORD8 *ptr_prev_env_compensation, WORD32 new_detection_allowed) {
477   WORD32 i, j, l;
478 
479   memset(ptr_env_compensation, 0, num_sfb * sizeof(ptr_env_compensation[0]));
480 
481   FLOAT32 max_val;
482   WORD32 lower_band, upper_band;
483   WORD32 max_pos_band, max_pos_est;
484   WORD8 comp_val;
485 
486   for (i = 0; i < num_sfb; i++) {
487     if (ptr_add_harmonics_sfbs[i]) {
488       lower_band = ptr_freq_band_tab[i];
489       upper_band = ptr_freq_band_tab[i + 1];
490 
491       max_pos_band = 0;
492       max_pos_est = 0;
493       max_val = 0;
494 
495       for (j = 0; j < tot_no_est; j++) {
496         for (l = lower_band; l < upper_band; l++) {
497           if (ptr_tonality[j][l] > max_val) {
498             max_val = ptr_tonality[j][l];
499             max_pos_band = l;
500             max_pos_est = j;
501           }
502         }
503       }
504 
505       if (max_pos_band == lower_band && i) {
506         comp_val =
507             (WORD8)(fabs(SBR_INV_LOG_2 * log(ptr_diff[max_pos_est][i - 1] + SBR_EPS)) + 0.5f);
508         if (comp_val > SBR_MAX_COMP) {
509           comp_val = SBR_MAX_COMP;
510         }
511 
512         if (!ptr_add_harmonics_sfbs[i - 1]) {
513           if (ptr_tonality[max_pos_est][max_pos_band - 1] >
514               SBR_TONALITY_QUOTA * ptr_tonality[max_pos_est][max_pos_band]) {
515             ptr_env_compensation[i - 1] = -1 * comp_val;
516           }
517         }
518       }
519 
520       if (max_pos_band == (upper_band - 1) && (i + 1) < num_sfb) {
521         comp_val =
522             (WORD8)(fabs(SBR_INV_LOG_2 * log(ptr_diff[max_pos_est][i + 1] + SBR_EPS)) + 0.5f);
523         if (comp_val > SBR_MAX_COMP) {
524           comp_val = SBR_MAX_COMP;
525         }
526 
527         if (!ptr_add_harmonics_sfbs[i + 1]) {
528           if (ptr_tonality[max_pos_est][max_pos_band + 1] >
529               SBR_TONALITY_QUOTA * ptr_tonality[max_pos_est][max_pos_band]) {
530             ptr_env_compensation[i + 1] = comp_val;
531           }
532         }
533       }
534 
535       if (i && i < (num_sfb - 1)) {
536         comp_val =
537             (WORD8)(fabs(SBR_INV_LOG_2 * log(ptr_diff[max_pos_est][i - 1] + SBR_EPS)) + 0.5f);
538         if (comp_val > SBR_MAX_COMP) {
539           comp_val = SBR_MAX_COMP;
540         }
541 
542         if (ixheaace_div32((FLOAT32)1.0f, ptr_diff[max_pos_est][i - 1]) >
543             (SBR_DIFF_QUOTA * ptr_diff[max_pos_est][i])) {
544           ptr_env_compensation[i - 1] = -1 * comp_val;
545         }
546 
547         comp_val =
548             (WORD8)(fabs(SBR_INV_LOG_2 * log(ptr_diff[max_pos_est][i + 1] + SBR_EPS)) + 0.5f);
549         if (comp_val > SBR_MAX_COMP) {
550           comp_val = SBR_MAX_COMP;
551         }
552 
553         if (ixheaace_div32((FLOAT32)1.0f, ptr_diff[max_pos_est][i + 1]) >
554             (SBR_DIFF_QUOTA * ptr_diff[max_pos_est][i])) {
555           ptr_env_compensation[i + 1] = comp_val;
556         }
557       }
558     }
559   }
560 
561   if (!new_detection_allowed) {
562     for (i = 0; i < num_sfb; i++) {
563       if (ptr_env_compensation[i] != 0 && ptr_prev_env_compensation[i] == 0) {
564         ptr_env_compensation[i] = 0;
565       }
566     }
567   }
568 }
569 
ixheaace_sbr_missing_harmonics_detector_qmf(ixheaace_pstr_sbr_missing_harmonics_detector pstr_sbr_mhd_et,FLOAT32 ** ptr_quota_buf,WORD8 * ptr_idx_vx,const ixheaace_str_frame_info_sbr * ptr_frame_info,const WORD32 * ptr_tran_info,WORD32 * ptr_add_harmonics_flag,UWORD8 * ptr_add_harmonics_sfbs,const UWORD8 * ptr_freq_band_tab,WORD32 num_sfb,WORD8 * ptr_env_compensation)570 VOID ixheaace_sbr_missing_harmonics_detector_qmf(
571     ixheaace_pstr_sbr_missing_harmonics_detector pstr_sbr_mhd_et, FLOAT32 **ptr_quota_buf,
572     WORD8 *ptr_idx_vx, const ixheaace_str_frame_info_sbr *ptr_frame_info,
573     const WORD32 *ptr_tran_info, WORD32 *ptr_add_harmonics_flag, UWORD8 *ptr_add_harmonics_sfbs,
574     const UWORD8 *ptr_freq_band_tab, WORD32 num_sfb, WORD8 *ptr_env_compensation) {
575   WORD32 i;
576   WORD32 transient_flag = ptr_tran_info[1];
577   WORD32 transient_pos = ptr_tran_info[0];
578   WORD32 new_detection_allowed;
579 
580   UWORD8 **ptr_detection_vectors = pstr_sbr_mhd_et->ptr_detection_vectors;
581   WORD32 move = pstr_sbr_mhd_et->move;
582   WORD32 no_est_per_frame = pstr_sbr_mhd_et->no_est_per_frame;
583   WORD32 tot_no_est = pstr_sbr_mhd_et->tot_no_est;
584   WORD32 prev_trans_flag = pstr_sbr_mhd_et->prev_trans_flag;
585   WORD32 prev_transient_frame = pstr_sbr_mhd_et->prev_trans_frame;
586   WORD32 trans_pos_offset = pstr_sbr_mhd_et->trans_pos_offset;
587   WORD32 prev_transient_pos = pstr_sbr_mhd_et->prev_trans_pos;
588   ixheaace_str_guide_vectors *ptr_guide_vectors = pstr_sbr_mhd_et->guide_vectors;
589 
590   FLOAT32 **ptr_sfm_sbr = pstr_sbr_mhd_et->ptr_sfm_sbr;
591   FLOAT32 **ptr_sfm_orig = pstr_sbr_mhd_et->ptr_sfm_orig;
592   FLOAT32 **ptr_tonal_diff = pstr_sbr_mhd_et->ptr_tonal_diff;
593 
594   WORD32 no_qmf_bands = ptr_freq_band_tab[num_sfb] - ptr_freq_band_tab[0];
595 
596   new_detection_allowed = ia_enhaacplus_enc_isDetectionOfNewToneAllowed(
597       ptr_frame_info, prev_transient_frame, prev_transient_pos, prev_trans_flag, trans_pos_offset,
598       transient_flag, transient_pos, pstr_sbr_mhd_et);
599 
600   ia_enhaacplus_enc_calculate_detector_input(ptr_quota_buf, ptr_idx_vx, ptr_tonal_diff,
601                                              ptr_sfm_orig, ptr_sfm_sbr, ptr_freq_band_tab,
602                                              num_sfb, no_est_per_frame, move, no_qmf_bands);
603 
604   ia_enhaacplus_enc_detection_with_prediction(
605       ptr_quota_buf, ptr_tonal_diff, num_sfb, ptr_freq_band_tab, ptr_sfm_orig, ptr_sfm_sbr,
606       ptr_detection_vectors, pstr_sbr_mhd_et->ptr_guide_scfb, ptr_guide_vectors, no_est_per_frame,
607       tot_no_est, new_detection_allowed, ptr_add_harmonics_sfbs);
608 
609   ia_enhaacplus_enc_calculate_comp_vector(
610       ptr_add_harmonics_sfbs, ptr_quota_buf, ptr_env_compensation, num_sfb, ptr_freq_band_tab,
611       ptr_tonal_diff, tot_no_est, pstr_sbr_mhd_et->sbr_prev_env_compensation,
612       new_detection_allowed);
613 
614   *ptr_add_harmonics_flag = 0;
615 
616   for (i = 0; i < num_sfb; i++) {
617     if (ptr_add_harmonics_sfbs[i]) {
618       *ptr_add_harmonics_flag = 1;
619       break;
620     }
621   }
622 
623   memcpy(pstr_sbr_mhd_et->sbr_prev_env_compensation, ptr_env_compensation,
624          num_sfb * sizeof(pstr_sbr_mhd_et->sbr_prev_env_compensation[0]));
625 
626   memcpy(pstr_sbr_mhd_et->ptr_guide_scfb, ptr_add_harmonics_sfbs,
627          num_sfb * sizeof(pstr_sbr_mhd_et->ptr_guide_scfb[0]));
628 
629   memcpy(ptr_guide_vectors[0].ptr_guide_vector_detected, ptr_add_harmonics_sfbs,
630          num_sfb * sizeof(ptr_guide_vectors[0].ptr_guide_vector_detected[0]));
631 
632   if (tot_no_est > no_est_per_frame) {
633     memcpy(ptr_guide_vectors[0].ptr_guide_vec_diff,
634            ptr_guide_vectors[no_est_per_frame].ptr_guide_vec_diff,
635            num_sfb * sizeof(ptr_guide_vectors[0].ptr_guide_vec_diff[0]));
636     memcpy(ptr_guide_vectors[0].ptr_guide_vec_orig,
637            ptr_guide_vectors[no_est_per_frame].ptr_guide_vec_orig,
638            num_sfb * sizeof(ptr_guide_vectors[0].ptr_guide_vec_orig[0]));
639   } else {
640     memcpy(ptr_guide_vectors[0].ptr_guide_vec_diff,
641            ptr_guide_vectors[no_est_per_frame - 1].ptr_guide_vec_diff,
642            num_sfb * sizeof(ptr_guide_vectors[0].ptr_guide_vec_diff[0]));
643 
644     memcpy(ptr_guide_vectors[0].ptr_guide_vec_orig,
645            ptr_guide_vectors[no_est_per_frame - 1].ptr_guide_vec_orig,
646            num_sfb * sizeof(ptr_guide_vectors[0].ptr_guide_vec_orig[0]));
647   }
648 
649   for (i = 0; i < num_sfb; i++) {
650 #ifdef _WIN32
651 #pragma warning(suppress : 6385)
652 #endif
653     if ((ptr_guide_vectors[0].ptr_guide_vec_diff[i] ||
654          ptr_guide_vectors[0].ptr_guide_vec_orig[i]) &&
655         !ptr_add_harmonics_sfbs[i]) {
656       ptr_guide_vectors[0].ptr_guide_vec_diff[i] = 0;
657       ptr_guide_vectors[0].ptr_guide_vec_orig[i] = 0;
658     }
659   }
660 }
661 
ixheaace_create_sbr_missing_harmonics_detector(WORD32 ch,ixheaace_pstr_sbr_missing_harmonics_detector pstr_sbr_mhdet,WORD32 sample_freq,WORD32 num_sfb,WORD32 qmf_num_ch,WORD32 tot_no_est,WORD32 move,WORD32 no_est_per_frame,WORD32 * ptr_common_buffer)662 VOID ixheaace_create_sbr_missing_harmonics_detector(
663     WORD32 ch, ixheaace_pstr_sbr_missing_harmonics_detector pstr_sbr_mhdet, WORD32 sample_freq,
664     WORD32 num_sfb, WORD32 qmf_num_ch, WORD32 tot_no_est, WORD32 move, WORD32 no_est_per_frame,
665     WORD32 *ptr_common_buffer) {
666   WORD32 i;
667   WORD32 *ptr_fix;
668   FLOAT32 *ptr_mem;
669   ixheaace_pstr_sbr_missing_harmonics_detector pstr_sbr_detector_handle = pstr_sbr_mhdet;
670 
671   memset(pstr_sbr_detector_handle, 0, sizeof(ixheaace_str_sbr_missing_har_detector));
672 
673   pstr_sbr_detector_handle->trans_pos_offset = 4;
674   pstr_sbr_detector_handle->time_slots = 16;
675 
676   pstr_sbr_detector_handle->qmf_num_ch = qmf_num_ch;
677   pstr_sbr_detector_handle->sample_freq = sample_freq;
678   pstr_sbr_detector_handle->num_scf = num_sfb;
679 
680   pstr_sbr_detector_handle->tot_no_est = tot_no_est;
681   pstr_sbr_detector_handle->move = move;
682   pstr_sbr_detector_handle->no_est_per_frame = no_est_per_frame;
683 
684   ptr_fix = &ptr_common_buffer[ch * 5 * NO_OF_ESTIMATES * MAXIMUM_FREQ_COEFFS];
685   ptr_mem = (FLOAT32 *)ptr_fix;
686   for (i = 0; i < tot_no_est; i++) {
687     pstr_sbr_detector_handle->ptr_tonal_diff[i] = ptr_mem;
688     ptr_mem += MAXIMUM_FREQ_COEFFS;
689 
690     memset(pstr_sbr_detector_handle->ptr_tonal_diff[i], 0,
691            sizeof(pstr_sbr_detector_handle->ptr_tonal_diff[0][0]) * MAXIMUM_FREQ_COEFFS);
692 
693     pstr_sbr_detector_handle->ptr_sfm_orig[i] = ptr_mem;
694     ptr_mem += MAXIMUM_FREQ_COEFFS;
695 
696     memset(pstr_sbr_detector_handle->ptr_sfm_orig[i], 0,
697            sizeof(pstr_sbr_detector_handle->ptr_sfm_orig[0][0]) * MAXIMUM_FREQ_COEFFS);
698 
699     pstr_sbr_detector_handle->ptr_sfm_sbr[i] = ptr_mem;
700     ptr_mem += MAXIMUM_FREQ_COEFFS;
701 
702     memset(pstr_sbr_detector_handle->ptr_sfm_sbr[i], 0,
703            sizeof(pstr_sbr_detector_handle->ptr_sfm_sbr[0][0]) * MAXIMUM_FREQ_COEFFS);
704 
705     pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vec_diff = ptr_mem;
706     ptr_mem += MAXIMUM_FREQ_COEFFS;
707 
708     memset(pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vec_diff, 0,
709            sizeof(pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vec_diff[0]) *
710                MAXIMUM_FREQ_COEFFS);
711 
712     pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vec_orig = ptr_mem;
713     ptr_mem += MAXIMUM_FREQ_COEFFS;
714 
715     memset(pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vec_orig, 0,
716            sizeof(pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vec_orig[0]) *
717                MAXIMUM_FREQ_COEFFS);
718 
719     pstr_sbr_detector_handle->ptr_detection_vectors[i] =
720         &(pstr_sbr_detector_handle->sbr_detection_vectors[i * MAXIMUM_FREQ_COEFFS]);
721 
722     memset(pstr_sbr_detector_handle->ptr_detection_vectors[i], 0,
723            sizeof(pstr_sbr_detector_handle->ptr_detection_vectors[0][0]) * MAXIMUM_FREQ_COEFFS);
724 
725     pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vector_detected =
726         &(pstr_sbr_detector_handle->sbr_guide_vector_detected[i * MAXIMUM_FREQ_COEFFS]);
727 
728     memset(pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vector_detected, 0,
729            sizeof(pstr_sbr_detector_handle->guide_vectors[i].ptr_guide_vector_detected[0]) *
730                MAXIMUM_FREQ_COEFFS);
731   }
732 
733   pstr_sbr_detector_handle->ptr_prev_env_compensation =
734       &(pstr_sbr_detector_handle->sbr_prev_env_compensation[0]);
735 
736   memset(pstr_sbr_detector_handle->ptr_prev_env_compensation, 0,
737          sizeof(pstr_sbr_detector_handle->ptr_prev_env_compensation[0]) * MAXIMUM_FREQ_COEFFS);
738 
739   pstr_sbr_detector_handle->ptr_guide_scfb = &(pstr_sbr_detector_handle->sbr_guide_scfb[0]);
740 
741   memset(pstr_sbr_detector_handle->ptr_guide_scfb, 0,
742          sizeof(pstr_sbr_detector_handle->ptr_guide_scfb[0]) * MAXIMUM_FREQ_COEFFS);
743 
744   pstr_sbr_detector_handle->prev_trans_flag = 0;
745   pstr_sbr_detector_handle->prev_trans_frame = 0;
746   pstr_sbr_detector_handle->prev_trans_pos = 0;
747 }
748