xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_sbr_ton_corr.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 "ixheaac_type_def.h"
23 #include "ixheaac_constants.h"
24 #include "ixheaace_aac_constants.h"
25 #include "ixheaac_basic_ops32.h"
26 #include "ixheaac_basic_ops16.h"
27 #include "ixheaac_basic_ops40.h"
28 #include "ixheaac_basic_ops.h"
29 #include "ixheaac_error_standards.h"
30 #include "ixheaace_error_codes.h"
31 
32 #include "ixheaace_sbr_header.h"
33 #include "ixheaace_sbr_def.h"
34 #include "ixheaace_resampler.h"
35 #include "ixheaace_sbr_rom.h"
36 #include "ixheaace_common_rom.h"
37 #include "ixheaace_sbr_hbe.h"
38 #include "ixheaace_sbr_qmf_enc.h"
39 #include "ixheaace_sbr_tran_det.h"
40 #include "ixheaace_sbr_frame_info_gen.h"
41 #include "ixheaace_sbr_env_est.h"
42 #include "ixheaace_sbr_code_envelope.h"
43 #include "ixheaace_sbr_main.h"
44 #include "ixheaace_sbr_missing_harmonics_det.h"
45 #include "ixheaace_sbr_inv_filtering_estimation.h"
46 #include "ixheaace_sbr_noise_floor_est.h"
47 #include "ixheaace_sbr_ton_corr.h"
48 #include "iusace_esbr_pvc.h"
49 #include "iusace_esbr_inter_tes.h"
50 #include "ixheaace_sbr.h"
51 
52 #include "ixheaace_sbr_misc.h"
53 
ixheaace_ton_corr_param_extr(ixheaace_pstr_sbr_ton_corr_est pstr_ton_corr,ixheaace_invf_mode * pstr_inf_vec,FLOAT32 * ptr_noise_lvls,WORD32 * ptr_missing_harmonic_flag,UWORD8 * ptr_missing_harmonic_index,WORD8 * ptr_env_compensation,const ixheaace_str_frame_info_sbr * pstr_frame_info,WORD32 * ptr_trans_info,UWORD8 * ptr_freq_band_tab,WORD32 ptr_num_scf,ixheaace_sbr_xpos_mode xpos_type,WORD8 * ptr_sbr_scratch,WORD32 is_ld_sbr)54 VOID ixheaace_ton_corr_param_extr(ixheaace_pstr_sbr_ton_corr_est pstr_ton_corr,
55                                   ixheaace_invf_mode *pstr_inf_vec, FLOAT32 *ptr_noise_lvls,
56                                   WORD32 *ptr_missing_harmonic_flag,
57                                   UWORD8 *ptr_missing_harmonic_index, WORD8 *ptr_env_compensation,
58                                   const ixheaace_str_frame_info_sbr *pstr_frame_info,
59                                   WORD32 *ptr_trans_info, UWORD8 *ptr_freq_band_tab,
60                                   WORD32 ptr_num_scf, ixheaace_sbr_xpos_mode xpos_type,
61                                   WORD8 *ptr_sbr_scratch, WORD32 is_ld_sbr) {
62   (VOID) ptr_sbr_scratch;
63   WORD32 transient_flag = ptr_trans_info[1];
64   WORD32 transient_pos = ptr_trans_info[0];
65   WORD32 transient_frame_invf_est;
66   ixheaace_invf_mode *pstr_inf_vec_lcl;
67   WORD32 transient_frame = 0;
68 
69   if (pstr_ton_corr->trans_nxt_frame) {
70     transient_frame = 1;
71     pstr_ton_corr->trans_nxt_frame = 0;
72 
73     if ((transient_flag) && (transient_pos + pstr_ton_corr->trans_pos_offset >=
74                              pstr_frame_info->borders[pstr_frame_info->n_envelopes])) {
75       pstr_ton_corr->trans_nxt_frame = 1;
76     }
77   } else {
78     if (transient_flag) {
79       if (transient_pos + pstr_ton_corr->trans_pos_offset <
80           pstr_frame_info->borders[pstr_frame_info->n_envelopes]) {
81         transient_frame = 1;
82         pstr_ton_corr->trans_nxt_frame = 0;
83       } else {
84         pstr_ton_corr->trans_nxt_frame = 1;
85       }
86     }
87   }
88   transient_frame_invf_est = is_ld_sbr ? transient_frame : pstr_ton_corr->trans_nxt_frame;
89   if (pstr_ton_corr->switch_inverse_filt) {
90     ixheaace_qmf_inverse_filtering_detector(
91         &pstr_ton_corr->sbr_noise_inv_filt, pstr_ton_corr->ptr_quota_mtx,
92         pstr_ton_corr->energy_vec, pstr_ton_corr->idx_vx,
93         pstr_ton_corr->frame_start_index_invf_est,
94         pstr_ton_corr->est_cnt_per_frame + pstr_ton_corr->frame_start_index_invf_est,
95         transient_frame_invf_est, pstr_inf_vec, is_ld_sbr);
96   }
97 
98   if (xpos_type == IXHEAACE_XPOS_LC) {
99     ixheaace_sbr_missing_harmonics_detector_qmf(
100         &pstr_ton_corr->sbr_missing_har_detector, pstr_ton_corr->ptr_quota_mtx,
101         pstr_ton_corr->idx_vx, pstr_frame_info, ptr_trans_info, ptr_missing_harmonic_flag,
102         ptr_missing_harmonic_index, ptr_freq_band_tab, ptr_num_scf, ptr_env_compensation);
103   } else {
104     *ptr_missing_harmonic_flag = 0;
105     memset(ptr_missing_harmonic_index, 0, ptr_num_scf * sizeof(ptr_missing_harmonic_index[0]));
106   }
107 
108   pstr_inf_vec_lcl = pstr_ton_corr->sbr_noise_inv_filt.prev_invf_mode;
109 
110   ixheaace_sbr_noise_floor_estimate_qmf(
111       &pstr_ton_corr->sbr_noise_floor_est, pstr_frame_info, ptr_noise_lvls,
112       pstr_ton_corr->ptr_quota_mtx, pstr_ton_corr->idx_vx, *ptr_missing_harmonic_flag,
113       pstr_ton_corr->frame_start_index, transient_frame, pstr_inf_vec_lcl, is_ld_sbr);
114 
115   memcpy(pstr_ton_corr->sbr_noise_inv_filt.prev_invf_mode, pstr_inf_vec,
116          pstr_ton_corr->sbr_noise_inv_filt.no_detector_bands * sizeof(pstr_inf_vec[0]));
117 }
118 
ia_enhaacplus_enc_find_closest_entry(WORD32 goal_sb,UWORD8 * ptr_vk_master,WORD32 num_master,WORD32 direction)119 static WORD32 ia_enhaacplus_enc_find_closest_entry(WORD32 goal_sb, UWORD8 *ptr_vk_master,
120                                                    WORD32 num_master, WORD32 direction) {
121   WORD32 index;
122 
123   if (goal_sb <= ptr_vk_master[0]) {
124     return ptr_vk_master[0];
125   }
126 
127   if (goal_sb >= ptr_vk_master[num_master]) {
128     return ptr_vk_master[num_master];
129   }
130 
131   if (direction) {
132     index = 0;
133 
134     while (ptr_vk_master[index] < goal_sb) {
135       index++;
136     }
137   } else {
138     index = num_master;
139     while (ptr_vk_master[index] > goal_sb) {
140       index--;
141     }
142   }
143 
144   return ptr_vk_master[index];
145 }
146 
ia_enhaacplus_enc_reset_patch(ixheaace_pstr_sbr_ton_corr_est pstr_ton_corr,WORD32 xpos_ctrl,WORD32 high_band_start_sb,UWORD8 * ptr_vk_master,WORD32 num_master,WORD32 fs,WORD32 num_channels)147 static IA_ERRORCODE ia_enhaacplus_enc_reset_patch(ixheaace_pstr_sbr_ton_corr_est pstr_ton_corr,
148                                                   WORD32 xpos_ctrl, WORD32 high_band_start_sb,
149                                                   UWORD8 *ptr_vk_master, WORD32 num_master,
150                                                   WORD32 fs, WORD32 num_channels) {
151   WORD32 patch, k, i;
152   WORD32 target_stop_band;
153 
154   ixheaace_patch_param *ptr_patch_param = pstr_ton_corr->str_patch_param;
155 
156   WORD32 sb_guard = pstr_ton_corr->guard;
157   WORD32 source_start_band;
158   WORD32 patch_distance;
159   WORD32 num_bands_in_patch;
160 
161   WORD32 lsb = ptr_vk_master[0];
162   WORD32 usb = ptr_vk_master[num_master];
163   WORD32 xover_offset = high_band_start_sb - ptr_vk_master[0];
164 
165   WORD32 goal_sb;
166 
167   if (xpos_ctrl == 1) {
168     lsb += xover_offset;
169     xover_offset = 0;
170   }
171 
172   goal_sb = (WORD32)(2 * num_channels * 16000.0f / fs + 0.5f);
173   goal_sb = ia_enhaacplus_enc_find_closest_entry(goal_sb, ptr_vk_master, num_master, 1);
174 
175   source_start_band = pstr_ton_corr->shift_start_sb + xover_offset;
176 
177   target_stop_band = lsb + xover_offset;
178 
179   patch = 0;
180 
181   while (target_stop_band < usb) {
182     if (patch >= IXHEAACE_MAXIMUM_NUM_PATCHES) {
183       return IA_EXHEAACE_EXE_NONFATAL_ESBR_INVALID_NUM_PATCH;
184     }
185 
186     ptr_patch_param[patch].guard_start_band = target_stop_band;
187 
188     target_stop_band += sb_guard;
189 
190     ptr_patch_param[patch].target_start_band = target_stop_band;
191 
192     num_bands_in_patch = goal_sb - target_stop_band;
193 
194     if (num_bands_in_patch >= lsb - source_start_band) {
195       patch_distance = target_stop_band - source_start_band;
196 
197       patch_distance = patch_distance & ~1;
198 
199       num_bands_in_patch = lsb - (target_stop_band - patch_distance);
200 
201       num_bands_in_patch =
202           ia_enhaacplus_enc_find_closest_entry(target_stop_band + num_bands_in_patch,
203                                                ptr_vk_master, num_master, 0) -
204           target_stop_band;
205     }
206 
207     patch_distance = num_bands_in_patch + target_stop_band - lsb;
208 
209     patch_distance = (patch_distance + 1) & ~1;
210 
211     if (num_bands_in_patch <= 0) {
212       patch--;
213     } else {
214       ptr_patch_param[patch].source_start_band = target_stop_band - patch_distance;
215 
216       ptr_patch_param[patch].target_band_offs = patch_distance;
217       ptr_patch_param[patch].num_bands_in_patch = num_bands_in_patch;
218 
219       ptr_patch_param[patch].source_stop_band =
220           ptr_patch_param[patch].source_start_band + num_bands_in_patch;
221 
222       target_stop_band += ptr_patch_param[patch].num_bands_in_patch;
223     }
224 
225     source_start_band = pstr_ton_corr->shift_start_sb;
226 
227     if (ixheaac_abs32(target_stop_band - goal_sb) < 3) {
228       goal_sb = usb;
229     }
230     patch++;
231   }
232 
233   patch--;
234 
235   if (ptr_patch_param[patch].num_bands_in_patch < 3 && patch > 0) {
236     patch--;
237   }
238 
239   pstr_ton_corr->no_of_patches = patch + 1;
240 
241   for (k = 0; k < pstr_ton_corr->str_patch_param[0].guard_start_band; k++) {
242     pstr_ton_corr->idx_vx[k] = (WORD8)k;
243   }
244 
245   for (i = 0; i < pstr_ton_corr->no_of_patches; i++) {
246     WORD32 source_start = pstr_ton_corr->str_patch_param[i].source_start_band;
247     WORD32 target_start = pstr_ton_corr->str_patch_param[i].target_start_band;
248     WORD32 number_of_bands = pstr_ton_corr->str_patch_param[i].num_bands_in_patch;
249     WORD32 start_guard_band = pstr_ton_corr->str_patch_param[i].guard_start_band;
250 
251     for (k = 0; k < (target_start - start_guard_band); k++) {
252       pstr_ton_corr->idx_vx[start_guard_band + k] = -1;
253     }
254 
255     for (k = 0; k < number_of_bands; k++) {
256       pstr_ton_corr->idx_vx[target_start + k] = (WORD8)(source_start + k);
257     }
258   }
259 
260   return IA_NO_ERROR;
261 }
262 
263 IA_ERRORCODE
ixheaace_create_ton_corr_param_extr(WORD32 ch,ixheaace_pstr_sbr_ton_corr_est pstr_ton_corr,WORD32 fs,WORD32 num_qmf_ch,WORD32 xpos_ctrl,WORD32 high_band_start_sb,UWORD8 * ptr_vk_master,WORD32 num_master,WORD32 ana_max_level,UWORD8 * ptr_freq_band_tab[2],WORD32 * ptr_num_scf,WORD32 noise_groups,UWORD32 use_speech_config,WORD32 * ptr_common_buffer,ixheaace_str_qmf_tabs * pstr_qmf_tab,WORD32 is_ld_sbr)264 ixheaace_create_ton_corr_param_extr(WORD32 ch, ixheaace_pstr_sbr_ton_corr_est pstr_ton_corr,
265                                     WORD32 fs, WORD32 num_qmf_ch, WORD32 xpos_ctrl,
266                                     WORD32 high_band_start_sb, UWORD8 *ptr_vk_master,
267                                     WORD32 num_master, WORD32 ana_max_level,
268                                     UWORD8 *ptr_freq_band_tab[2], WORD32 *ptr_num_scf,
269                                     WORD32 noise_groups, UWORD32 use_speech_config,
270                                     WORD32 *ptr_common_buffer,
271                                     ixheaace_str_qmf_tabs *pstr_qmf_tab, WORD32 is_ld_sbr) {
272   WORD32 i, loop_cnt;
273   IA_ERRORCODE err_code = IA_NO_ERROR;
274 
275   memset(pstr_ton_corr, 0, sizeof(ixheaace_str_sbr_ton_corr_est));
276 
277   pstr_ton_corr->est_cnt_per_frame = 2;
278   /* The code is modified to handle 480 frame size  */
279   if (0 == is_ld_sbr) {
280     pstr_ton_corr->est_cnt = NO_OF_ESTIMATES;
281     pstr_ton_corr->move = 2;
282     pstr_ton_corr->start_index_matrix = 2;
283   } else {
284     pstr_ton_corr->est_cnt = NO_OF_ESTIMATES_ELD;
285     pstr_ton_corr->move = 1;
286     pstr_ton_corr->start_index_matrix = 1;
287   }
288 
289   pstr_ton_corr->frame_start_index_invf_est = 0;
290   pstr_ton_corr->trans_pos_offset = 4;
291   pstr_ton_corr->frame_start_index = 0;
292   pstr_ton_corr->prev_trans_flag = 0;
293   pstr_ton_corr->trans_nxt_frame = 0;
294   pstr_ton_corr->num_qmf_ch = num_qmf_ch;
295   pstr_ton_corr->guard = 0;
296   pstr_ton_corr->shift_start_sb = 1;
297 
298   loop_cnt = is_ld_sbr ? NO_OF_ESTIMATES : pstr_ton_corr->est_cnt;
299 
300   for (i = 0; i < loop_cnt; i++) {
301     pstr_ton_corr->ptr_quota_mtx[i] = &(pstr_ton_corr->sbr_quota_mtx[i * num_qmf_ch]);
302     memset(pstr_ton_corr->ptr_quota_mtx[i], 0,
303            sizeof(pstr_ton_corr->ptr_quota_mtx[0][0]) * num_qmf_ch);
304   }
305 
306   err_code = ia_enhaacplus_enc_reset_patch(pstr_ton_corr, xpos_ctrl, high_band_start_sb,
307                                            ptr_vk_master, num_master, fs, num_qmf_ch);
308   if (err_code) {
309     return err_code;
310   }
311 
312   err_code = ixheaace_create_sbr_noise_floor_estimate(
313       &pstr_ton_corr->sbr_noise_floor_est, ana_max_level, ptr_freq_band_tab[LO], ptr_num_scf[LO],
314       noise_groups, use_speech_config, pstr_qmf_tab);
315   if (err_code) {
316     return err_code;
317   }
318 
319   ixheaace_create_inv_filt_detector(
320       &pstr_ton_corr->sbr_noise_inv_filt, pstr_ton_corr->sbr_noise_floor_est.s_freq_qmf_band_tbl,
321       pstr_ton_corr->sbr_noise_floor_est.num_of_noise_bands, use_speech_config, pstr_qmf_tab);
322 
323   ixheaace_create_sbr_missing_harmonics_detector(
324       ch, &pstr_ton_corr->sbr_missing_har_detector, fs, ptr_num_scf[HI], num_qmf_ch,
325       pstr_ton_corr->est_cnt, pstr_ton_corr->move, pstr_ton_corr->est_cnt_per_frame,
326       ptr_common_buffer);
327 
328   return err_code;
329 }
330