xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_mps_frame_windowing.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 <stdlib.h>
22 #include <string.h>
23 #include "ixheaac_type_def.h"
24 #include "ixheaac_error_standards.h"
25 #include "ixheaace_error_codes.h"
26 #include "ixheaace_mps_common_fix.h"
27 #include "ixheaace_mps_defines.h"
28 
29 #include "ixheaace_mps_common_define.h"
30 #include "ixheaace_mps_bitstream.h"
31 #include "ixheaace_mps_frame_windowing.h"
32 
ixheaace_mps_212_frame_window_list_limit(ixheaace_mps_pstr_frame_win_list const pstr_frame_win_list,const WORD32 lower_limit,const WORD32 upper_limit)33 static IA_ERRORCODE ixheaace_mps_212_frame_window_list_limit(
34     ixheaace_mps_pstr_frame_win_list const pstr_frame_win_list, const WORD32 lower_limit,
35     const WORD32 upper_limit) {
36   IA_ERRORCODE error = IA_NO_ERROR;
37   WORD32 list_cnt = 0;
38   for (list_cnt = 0; list_cnt < pstr_frame_win_list->win_list_cnt; list_cnt++) {
39     if (pstr_frame_win_list->dat[list_cnt].slot < lower_limit ||
40         pstr_frame_win_list->dat[list_cnt].slot > upper_limit) {
41       if (list_cnt == MAX_NUM_PARAMS - 1) {
42         pstr_frame_win_list->dat[list_cnt].hold = IXHEAACE_MPS_FRAME_WINDOWING_INTP;
43         pstr_frame_win_list->dat[list_cnt].slot = -1;
44       } else {
45         WORD32 param = 0;
46         for (param = list_cnt; param < MAX_NUM_PARAMS - 1; param++) {
47           pstr_frame_win_list->dat[param] = pstr_frame_win_list->dat[param + 1];
48         }
49       }
50 
51       pstr_frame_win_list->win_list_cnt--;
52       --list_cnt;
53     }
54   }
55   return error;
56 }
57 
ixheaace_mps_212_frame_window_list_add(ixheaace_mps_pstr_frame_win_list const pstr_frame_win_list,const WORD32 slot,const WORD32 hold)58 static IA_ERRORCODE ixheaace_mps_212_frame_window_list_add(
59     ixheaace_mps_pstr_frame_win_list const pstr_frame_win_list, const WORD32 slot,
60     const WORD32 hold) {
61   IA_ERRORCODE error = IA_NO_ERROR;
62 
63   if (pstr_frame_win_list->win_list_cnt >= MAX_NUM_PARAMS) {
64     return IA_EXHEAACE_CONFIG_NONFATAL_MPS_PARAM_ERROR;
65   } else if (pstr_frame_win_list->win_list_cnt > 0 &&
66              pstr_frame_win_list->dat[pstr_frame_win_list->win_list_cnt - 1].slot - slot > 0) {
67     return IA_EXHEAACE_CONFIG_NONFATAL_MPS_PARAM_ERROR;
68   } else {
69     pstr_frame_win_list->dat[pstr_frame_win_list->win_list_cnt].hold = hold;
70     pstr_frame_win_list->dat[pstr_frame_win_list->win_list_cnt].slot = slot;
71     pstr_frame_win_list->win_list_cnt++;
72   }
73   return error;
74 }
75 
76 IA_ERRORCODE
ixheaace_mps_212_frame_window_init(ixheaace_mps_pstr_frame_win pstr_frame_win,const ixheaace_mps_pstr_frame_win_config pstr_frame_win_config)77 ixheaace_mps_212_frame_window_init(
78     ixheaace_mps_pstr_frame_win pstr_frame_win,
79     const ixheaace_mps_pstr_frame_win_config pstr_frame_win_config) {
80   IA_ERRORCODE error = IA_NO_ERROR;
81   WORD32 slot;
82   WORD32 time_slots = pstr_frame_win_config->num_time_slots_max;
83   pstr_frame_win->frame_keep_flag = pstr_frame_win_config->frame_keep_flag;
84   pstr_frame_win->num_time_slots_max = pstr_frame_win_config->num_time_slots_max;
85   pstr_frame_win->start_slope = 0;
86   pstr_frame_win->start_rect = time_slots >> 1;
87   pstr_frame_win->stop_slope = ((3 * time_slots) >> 1) - 1;
88   pstr_frame_win->stop_rect = time_slots;
89   for (slot = 0; slot<time_slots>> 1; slot++) {
90     pstr_frame_win->p_tapper_sync_flt[slot] = (FLOAT32)slot / time_slots;
91   }
92   pstr_frame_win->p_tapper_sync_flt[time_slots >> 1] = 1.0f;
93   pstr_frame_win->taper_syn_len = time_slots >> 1;
94   pstr_frame_win->taper_ana_len = pstr_frame_win->start_rect - pstr_frame_win->start_slope;
95   for (slot = 0; slot < pstr_frame_win->taper_ana_len; slot++) {
96     pstr_frame_win->p_taper_ana_flt[slot] = 1.0f;
97   }
98 
99   return error;
100 }
101 
ixheaace_mps_212_frame_window_get_window(ixheaace_mps_pstr_frame_win pstr_frame_win,WORD32 tr_pos[MAX_NUM_PARAMS],const WORD32 time_slots,ixheaace_mps_framing_info * const pstr_framing_info,FLOAT32 * ptr_window_ana[MAX_NUM_PARAMS],ixheaace_mps_pstr_frame_win_list const pstr_frame_win_list,const WORD32 avoid_keep)102 IA_ERRORCODE ixheaace_mps_212_frame_window_get_window(
103     ixheaace_mps_pstr_frame_win pstr_frame_win, WORD32 tr_pos[MAX_NUM_PARAMS],
104     const WORD32 time_slots, ixheaace_mps_framing_info *const pstr_framing_info,
105     FLOAT32 *ptr_window_ana[MAX_NUM_PARAMS],
106     ixheaace_mps_pstr_frame_win_list const pstr_frame_win_list, const WORD32 avoid_keep) {
107   IA_ERRORCODE error = IA_NO_ERROR;
108   WORD32 win_cnt = 0;
109   WORD32 w, ps;
110   WORD32 idx;
111   WORD32 param;
112   WORD32 start_slope = pstr_frame_win->start_slope;
113   WORD32 start_rect = pstr_frame_win->start_rect;
114   WORD32 stop_slope = pstr_frame_win->stop_slope;
115   WORD32 stop_rect = pstr_frame_win->stop_rect;
116   WORD32 taper_ana_len = pstr_frame_win->taper_ana_len;
117   FLOAT32 apply_right_window_gain[MAX_NUM_PARAMS];
118   FLOAT32 *p_taper_ana = pstr_frame_win->p_taper_ana_flt;
119 
120   if ((time_slots > pstr_frame_win->num_time_slots_max) || (time_slots < 0)) {
121     return IA_EXHEAACE_CONFIG_NONFATAL_MPS_INVALID_CONFIG;
122   }
123 
124   pstr_frame_win_list->win_list_cnt = 0;
125   for (param = 0; param < MAX_NUM_PARAMS; param++) {
126     pstr_frame_win_list->dat[param].slot = -1;
127     pstr_frame_win_list->dat[param].hold = IXHEAACE_MPS_FRAME_WINDOWING_INTP;
128   }
129   memset(apply_right_window_gain, 0, sizeof(apply_right_window_gain));
130   if (tr_pos[0] <= 0) {
131     win_cnt = 0;
132     error = ixheaace_mps_212_frame_window_list_add(pstr_frame_win_list, time_slots - 1,
133                                                    IXHEAACE_MPS_FRAME_WINDOWING_INTP);
134     if (error) {
135       return error;
136     }
137     for (idx = 0; idx < start_slope; idx++) {
138       ptr_window_ana[win_cnt][idx] = 0.0f;
139     }
140     for (idx = 0; idx < taper_ana_len; idx++) {
141       ptr_window_ana[win_cnt][start_slope + idx] = p_taper_ana[idx];
142     }
143 
144     for (idx = 0; idx < time_slots - start_rect; idx++) {
145       ptr_window_ana[win_cnt][start_rect + idx] = 1.0f;
146     }
147 
148     apply_right_window_gain[win_cnt] = 1.0f;
149     win_cnt++;
150   } else {
151     WORD32 p_l = tr_pos[0];
152     win_cnt = 0;
153     error = ixheaace_mps_212_frame_window_list_add(pstr_frame_win_list, p_l - 1,
154                                                    IXHEAACE_MPS_FRAME_WINDOWING_HOLD);
155     if (error) {
156       return error;
157     }
158     error = ixheaace_mps_212_frame_window_list_add(pstr_frame_win_list, p_l,
159                                                    IXHEAACE_MPS_FRAME_WINDOWING_INTP);
160     if (error) {
161       return error;
162     }
163 
164     error = ixheaace_mps_212_frame_window_list_limit(pstr_frame_win_list, 0, time_slots - 1);
165     if (error) {
166       return error;
167     }
168 
169     error = ixheaace_mps_212_frame_window_list_add(pstr_frame_win_list, time_slots - 1,
170                                                    IXHEAACE_MPS_FRAME_WINDOWING_HOLD);
171     if (error) {
172       return error;
173     }
174 
175     if (pstr_frame_win_list->win_list_cnt > MAX_NUM_PARAMS) {
176       return IA_EXHEAACE_CONFIG_NONFATAL_MPS_INVALID_CONFIG;
177     }
178     for (ps = 0; ps < pstr_frame_win_list->win_list_cnt - 1; ps++) {
179       if (IXHEAACE_MPS_FRAME_WINDOWING_HOLD != pstr_frame_win_list->dat[ps].hold) {
180         WORD32 start = pstr_frame_win_list->dat[ps].slot;
181         WORD32 stop = pstr_frame_win_list->dat[ps + 1].slot;
182 
183         for (idx = 0; idx < start; idx++) {
184           ptr_window_ana[win_cnt][idx] = 0.0f;
185         }
186         for (idx = 0; idx < stop - start + 1; idx++) {
187           ptr_window_ana[win_cnt][start + idx] = 1.0f;
188         }
189         for (idx = 0; idx < time_slots - stop - 1; idx++) {
190           ptr_window_ana[win_cnt][stop + 1 + idx] = 0.0f;
191         }
192 
193         apply_right_window_gain[win_cnt] = ptr_window_ana[win_cnt][time_slots - 1];
194         win_cnt++;
195       }
196     }
197 
198     if (pstr_frame_win_list->win_list_cnt - 1 < 0 ||
199         pstr_frame_win_list->win_list_cnt - 1 >= MAX_NUM_PARAMS) {
200       return IA_EXHEAACE_CONFIG_NONFATAL_MPS_PARAM_ERROR;
201     } else if (pstr_frame_win_list->win_list_cnt > 0) {
202       if (pstr_frame_win_list->win_list_cnt - 1 == MAX_NUM_PARAMS - 1) {
203         pstr_frame_win_list->dat[pstr_frame_win_list->win_list_cnt - 1].slot = -1;
204         pstr_frame_win_list->dat[pstr_frame_win_list->win_list_cnt - 1].hold =
205             IXHEAACE_MPS_FRAME_WINDOWING_INTP;
206       } else {
207         for (param = pstr_frame_win_list->win_list_cnt - 1; param < MAX_NUM_PARAMS - 1; param++) {
208           pstr_frame_win_list->dat[param] = pstr_frame_win_list->dat[param + 1];
209         }
210       }
211       pstr_frame_win_list->win_list_cnt--;
212     }
213     if (error) {
214       return error;
215     }
216   }
217 
218   for (w = 0; w < win_cnt; w++) {
219     if (apply_right_window_gain[w] <= 0) {
220       for (idx = 0; idx < time_slots; idx++) {
221         ptr_window_ana[w][time_slots + idx] = 0.0f;
222       }
223     } else {
224       if (tr_pos[1] < 0) {
225         for (idx = 0; idx < stop_rect - time_slots + 1; idx++) {
226           ptr_window_ana[w][time_slots + idx] = 1.0f;
227         }
228         for (idx = 0; idx < taper_ana_len; idx++) {
229           ptr_window_ana[w][stop_rect + idx] = p_taper_ana[taper_ana_len - 1 - idx];
230         }
231         for (idx = 0; idx < 2 * time_slots - stop_slope - 1; idx++) {
232           ptr_window_ana[w][stop_slope + 1 + idx] = 0.0f;
233         }
234       } else {
235         WORD32 p_r = tr_pos[1];
236         for (idx = 0; idx < p_r - time_slots; idx++) {
237           ptr_window_ana[w][time_slots + idx] = 1.0f;
238         }
239         for (idx = 0; idx < 2 * time_slots - p_r; idx++) {
240           ptr_window_ana[w][p_r + idx] = 0.0f;
241         }
242       }
243       if (apply_right_window_gain[w] < 1.0f) {
244         WORD32 slot;
245         for (slot = 0; slot < time_slots; slot++) {
246           ptr_window_ana[w][time_slots + slot] =
247               ptr_window_ana[w][time_slots + slot] * apply_right_window_gain[w];
248         }
249       }
250     }
251   }
252   if (pstr_frame_win->frame_keep_flag == 1) {
253     for (idx = 0; idx < time_slots; idx++) {
254       ptr_window_ana[0][2 * time_slots + idx] = ptr_window_ana[0][time_slots + idx];
255       ptr_window_ana[0][time_slots + idx] = ptr_window_ana[0][idx];
256     }
257     if (avoid_keep == 0) {
258       for (idx = 0; idx < time_slots; idx++) {
259         ptr_window_ana[0][idx] = 1.0f;
260       }
261     } else {
262       for (idx = 0; idx < time_slots; idx++) {
263         ptr_window_ana[0][idx] = 0.0f;
264       }
265     }
266   }
267   pstr_framing_info->num_param_sets = pstr_frame_win_list->win_list_cnt;
268   pstr_framing_info->bs_framing_type = 1;
269   for (ps = 0; ps < pstr_framing_info->num_param_sets; ps++) {
270     pstr_framing_info->bs_param_slots[ps] = pstr_frame_win_list->dat[ps].slot;
271   }
272   if ((pstr_framing_info->num_param_sets == 1) &&
273       (pstr_framing_info->bs_param_slots[0] == time_slots - 1)) {
274     pstr_framing_info->bs_framing_type = 0;
275   }
276   return error;
277 }
278 
ixheaace_mps_212_analysis_windowing(const WORD32 num_time_slots,const WORD32 start_time_slot,FLOAT32 * ptr_window_ana,ixheaace_cmplx_str pp_cmplx_data_in[MAX_ANA_TIME_SLOT][MAX_QMF_BANDS],ixheaace_cmplx_str pp_cmplx_data_out[MAX_ANA_TIME_SLOT][MAX_QMF_BANDS],const WORD32 num_hybrid_bands)279 VOID ixheaace_mps_212_analysis_windowing(
280     const WORD32 num_time_slots, const WORD32 start_time_slot, FLOAT32 *ptr_window_ana,
281     ixheaace_cmplx_str pp_cmplx_data_in[MAX_ANA_TIME_SLOT][MAX_QMF_BANDS],
282     ixheaace_cmplx_str pp_cmplx_data_out[MAX_ANA_TIME_SLOT][MAX_QMF_BANDS],
283     const WORD32 num_hybrid_bands) {
284   WORD32 band, slot;
285   FLOAT32 win;
286 
287   for (slot = start_time_slot; slot < num_time_slots; slot++) {
288     win = ptr_window_ana[slot];
289     if (win != 1.0f) {
290       for (band = 0; band < num_hybrid_bands; band++) {
291         pp_cmplx_data_out[slot][band].re = win * pp_cmplx_data_in[slot][band].re;
292         pp_cmplx_data_out[slot][band].im = win * pp_cmplx_data_in[slot][band].im;
293       }
294     } else {
295       for (band = 0; band < num_hybrid_bands; band++) {
296         pp_cmplx_data_out[slot][band].re = pp_cmplx_data_in[slot][band].re;
297         pp_cmplx_data_out[slot][band].im = pp_cmplx_data_in[slot][band].im;
298       }
299     }
300   }
301 }
302