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