xref: /aosp_15_r20/external/libxaac/encoder/iusace_psy_mod.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 "iusace_cnst.h"
23 #include "iusace_type_def.h"
24 #include "iusace_block_switch_const.h"
25 #include "iusace_block_switch_struct_def.h"
26 #include "iusace_bitbuffer.h"
27 #include "iusace_tns_usac.h"
28 #include "impd_drc_common_enc.h"
29 #include "impd_drc_uni_drc.h"
30 #include "impd_drc_api.h"
31 #include "impd_drc_uni_drc_eq.h"
32 #include "impd_drc_uni_drc_filter_bank.h"
33 #include "impd_drc_gain_enc.h"
34 #include "impd_drc_struct_def.h"
35 #include "iusace_cnst.h"
36 #include "iusace_tns_usac.h"
37 #include "iusace_psy_mod.h"
38 #include "iusace_psy_utils.h"
39 
40 #include "ixheaac_error_standards.h"
41 #include "iusace_type_def.h"
42 #include "iusace_cnst.h"
43 
44 #include "iusace_ms.h"
45 
46 #include "iusace_psy_utils.h"
47 #include "ixheaace_adjust_threshold_data.h"
48 #include "iusace_fd_qc_util.h"
49 #include "ixheaace_memory_standards.h"
50 #include "iusace_config.h"
51 #include "iusace_arith_enc.h"
52 #include "iusace_fd_quant.h"
53 #include "iusace_signal_classifier.h"
54 #include "iusace_block_switch_const.h"
55 #include "ixheaace_sbr_header.h"
56 #include "ixheaace_config.h"
57 #include "ixheaace_asc_write.h"
58 #include "iusace_main.h"
59 
iusace_psy_mod_init(ia_psy_mod_struct * pstr_psy_mod,WORD32 sample_rate,WORD32 bit_rate,WORD32 band_width,WORD32 num_channels,WORD32 ch,WORD32 ele_id,WORD32 ccfl)60 VOID iusace_psy_mod_init(ia_psy_mod_struct *pstr_psy_mod, WORD32 sample_rate, WORD32 bit_rate,
61                          WORD32 band_width, WORD32 num_channels, WORD32 ch, WORD32 ele_id,
62                          WORD32 ccfl) {
63   WORD32 i;
64 
65   for (i = 0; i < num_channels; i++) {
66     iusace_psy_long_config_init(bit_rate / num_channels, sample_rate, band_width,
67                                 &(pstr_psy_mod->str_psy_long_config[ele_id]), ccfl);
68 
69     iusace_psy_short_config_init(bit_rate / num_channels, sample_rate, band_width,
70                                  &(pstr_psy_mod->str_psy_short_config[ele_id]), ccfl);
71 
72     pstr_psy_mod->str_psy_data[ch].ptr_sfb_thr_long =
73         (FLOAT32 *)pstr_psy_mod->str_psy_data[ch].sfb_thr_short;
74     pstr_psy_mod->str_psy_data[ch].ptr_sfb_energy_long =
75         (FLOAT32 *)pstr_psy_mod->str_psy_data[ch].sfb_energy_short;
76     pstr_psy_mod->str_psy_data[ch].ptr_sfb_spreaded_energy_long =
77         (FLOAT32 *)pstr_psy_mod->str_psy_data[ch].sfb_spreaded_energy_short;
78 
79     memcpy(pstr_psy_mod->str_psy_data[ch].sfb_thr_nm1,
80            pstr_psy_mod->str_psy_long_config[ele_id].sfb_thr_quiet,
81            pstr_psy_mod->str_psy_long_config[ele_id].sfb_count * sizeof(FLOAT32));
82 
83     ch++;
84   }
85 
86   return;
87 }
88 
iusace_psy_mod_lb(ia_psy_mod_struct * pstr_psy_mod,ia_sfb_params_struct * pstr_sfb_prms,FLOAT64 * ptr_spec_in,ia_tns_info * pstr_tns_info[MAX_TIME_CHANNELS],WORD32 tns_select,WORD32 i_ch,WORD32 chn,WORD32 channel_type,FLOAT64 * scratch_tns_filter,WORD32 elem_idx,FLOAT64 * ptr_tns_scratch,WORD32 ccfl)89 VOID iusace_psy_mod_lb(ia_psy_mod_struct *pstr_psy_mod, ia_sfb_params_struct *pstr_sfb_prms,
90                        FLOAT64 *ptr_spec_in, ia_tns_info *pstr_tns_info[MAX_TIME_CHANNELS],
91                        WORD32 tns_select, WORD32 i_ch, WORD32 chn, WORD32 channel_type,
92                        FLOAT64 *scratch_tns_filter, WORD32 elem_idx, FLOAT64 *ptr_tns_scratch,
93                        WORD32 ccfl) {
94   ia_psy_mod_data_struct *pstr_psy_data = &(pstr_psy_mod->str_psy_data[i_ch]);
95   ia_psy_mod_long_config_struct *pstr_psy_config = &(pstr_psy_mod->str_psy_long_config[elem_idx]);
96   WORD32 window_sequence = pstr_sfb_prms->window_sequence[i_ch];
97   WORD32 num_sfb = pstr_sfb_prms->num_sfb[i_ch];
98   ia_tns_info *ptr_tns_info = pstr_tns_info[i_ch];
99   WORD32 sfb, line;
100   WORD32 i;
101   WORD32 frame_len_long = ccfl;
102   FLOAT32 energy_shift = 0.25f;
103   FLOAT32 clip_energy = pstr_psy_config->clip_energy * energy_shift;
104   (VOID) channel_type;
105 
106   pstr_psy_data->window_sequence = window_sequence;
107   memset(&ptr_spec_in[pstr_psy_config->low_pass_line], 0,
108          (frame_len_long - pstr_psy_config->low_pass_line) * sizeof(FLOAT64));
109 
110   iusace_calc_band_energy(ptr_spec_in, pstr_psy_config->sfb_offset, pstr_psy_config->sfb_active,
111                           pstr_psy_data->ptr_sfb_energy_long, pstr_psy_config->sfb_count);
112 
113   if (tns_select != 0) {
114     ia_tns_info *ptr_tns_info_ch2 = pstr_tns_info[i_ch - chn];
115     ptr_tns_info->number_of_bands = num_sfb;
116     ptr_tns_info->block_type = window_sequence;
117     ptr_tns_info->spec = ptr_spec_in;
118     iusace_tns_encode(ptr_tns_info_ch2, ptr_tns_info, pstr_psy_data->ptr_sfb_energy_long, 0, chn,
119                       pstr_psy_config->low_pass_line, scratch_tns_filter, 0, ptr_tns_scratch);
120   }
121 
122   for (i = 0; i < pstr_psy_config->sfb_count; i++) {
123     pstr_psy_data->ptr_sfb_thr_long[i] =
124         pstr_psy_data->ptr_sfb_energy_long[i] * pstr_psy_config->ratio;
125     pstr_psy_data->ptr_sfb_thr_long[i] = MIN(pstr_psy_data->ptr_sfb_thr_long[i], clip_energy);
126   }
127 
128   if (tns_select != 0) {
129     if (ptr_tns_info->tns_data_present == 1) {
130       iusace_calc_band_energy(ptr_spec_in, pstr_psy_config->sfb_offset,
131                               pstr_psy_config->sfb_active, pstr_psy_data->ptr_sfb_energy_long,
132                               pstr_psy_config->sfb_count);
133     }
134   }
135 
136   iusace_find_max_spreading(pstr_psy_config->sfb_count, pstr_psy_config->sfb_mask_low_fac,
137                             pstr_psy_config->sfb_mask_high_fac, pstr_psy_data->ptr_sfb_thr_long);
138 
139   for (i = 0; i < pstr_psy_config->sfb_count; i++) {
140     pstr_psy_data->ptr_sfb_thr_long[i] = MAX(pstr_psy_data->ptr_sfb_thr_long[i],
141                                              (pstr_psy_config->sfb_thr_quiet[i] * energy_shift));
142   }
143 
144   if (pstr_psy_data->window_sequence == LONG_STOP_SEQUENCE) {
145     for (i = 0; i < pstr_psy_config->sfb_count; i++) {
146       pstr_psy_data->sfb_thr_nm1[i] = 1.0e20f;
147     }
148   }
149 
150   iusace_pre_echo_control(pstr_psy_data->sfb_thr_nm1, pstr_psy_config->sfb_count,
151                           pstr_psy_config->max_allowed_inc_fac,
152                           pstr_psy_config->min_remaining_thr_fac,
153                           pstr_psy_data->ptr_sfb_thr_long);
154 
155   if (pstr_psy_data->window_sequence == LONG_START_SEQUENCE) {
156     for (i = 0; i < pstr_psy_config->sfb_count; i++) {
157       pstr_psy_data->sfb_thr_nm1[i] = 1.0e20f;
158     }
159   }
160 
161   for (i = 0; i < pstr_psy_config->sfb_count; i++) {
162     pstr_psy_data->ptr_sfb_spreaded_energy_long[i] = pstr_psy_data->ptr_sfb_energy_long[i];
163   }
164   iusace_find_max_spreading(
165       pstr_psy_config->sfb_count, pstr_psy_config->sfb_mask_low_fac_spr_ener,
166       pstr_psy_config->sfb_mask_high_fac_spr_ener, pstr_psy_data->ptr_sfb_spreaded_energy_long);
167 
168   for (sfb = pstr_psy_config->sfb_count - 1; sfb >= 0; sfb--) {
169     for (line = pstr_psy_config->sfb_offset[sfb + 1] - 1;
170          line >= pstr_psy_config->sfb_offset[sfb]; line--) {
171       if (ptr_spec_in[line] != 0) break;
172     }
173     if (line >= pstr_psy_config->sfb_offset[sfb]) break;
174   }
175 
176   pstr_psy_mod->str_psy_out_data[i_ch].max_sfb_per_grp = sfb + 1;
177 
178   return;
179 }
180 
iusace_psy_mod_sb(ia_psy_mod_struct * pstr_psy_mod,ia_sfb_params_struct * pstr_sfb_prms,FLOAT64 * ptr_spec_in,ia_tns_info * pstr_tns_info[MAX_TIME_CHANNELS],WORD32 tns_select,WORD32 i_ch,WORD32 chn,WORD32 channel_type,FLOAT64 * scratch_tns_filter,WORD32 elem_idx,FLOAT64 * ptr_tns_scratch,WORD32 ccfl)181 VOID iusace_psy_mod_sb(ia_psy_mod_struct *pstr_psy_mod, ia_sfb_params_struct *pstr_sfb_prms,
182                        FLOAT64 *ptr_spec_in, ia_tns_info *pstr_tns_info[MAX_TIME_CHANNELS],
183                        WORD32 tns_select, WORD32 i_ch, WORD32 chn, WORD32 channel_type,
184                        FLOAT64 *scratch_tns_filter, WORD32 elem_idx, FLOAT64 *ptr_tns_scratch,
185                        WORD32 ccfl) {
186   ia_psy_mod_data_struct *pstr_psy_data = &(pstr_psy_mod->str_psy_data[i_ch]);
187   ia_psy_mod_short_config_struct *pstr_psy_config =
188       &(pstr_psy_mod->str_psy_short_config[elem_idx]);
189   WORD32 max_sfb = 0, sfb, line;
190   WORD32 window_sequence = pstr_sfb_prms->window_sequence[i_ch];
191   WORD32 num_sfb = pstr_sfb_prms->num_sfb[i_ch];
192   ia_tns_info *ptr_tns_info = pstr_tns_info[i_ch];
193   WORD32 i, w;
194   WORD32 frame_len_short = (ccfl * FRAME_LEN_SHORT_128) / FRAME_LEN_LONG;
195   FLOAT32 energy_shift = 0.25f;
196   FLOAT32 clip_energy = pstr_psy_config->clip_energy * energy_shift;
197   (VOID) channel_type;
198 
199   pstr_psy_data->window_sequence = window_sequence;
200 
201   for (w = 0; w < MAX_SHORT_WINDOWS; w++) {
202     WORD32 w_offset = w * frame_len_short;
203     WORD32 offset;
204     FLOAT64 *pmdct_double = &ptr_spec_in[pstr_psy_config->low_pass_line + w_offset];
205 
206     offset = frame_len_short - pstr_psy_config->low_pass_line;
207 
208     memset(pmdct_double, 0, sizeof(FLOAT64) * offset);
209 
210     iusace_calc_band_energy(ptr_spec_in + w_offset, pstr_psy_config->sfb_offset,
211                             pstr_psy_config->sfb_active, pstr_psy_data->sfb_energy_short[w],
212                             pstr_psy_config->sfb_count);
213 
214     if (tns_select != 0) {
215       ia_tns_info *ptr_tns_info_ch2 = pstr_tns_info[i_ch - chn];
216       ptr_tns_info->number_of_bands = num_sfb;
217       ptr_tns_info->block_type = window_sequence;
218       ptr_tns_info->spec = ptr_spec_in + w_offset;
219       iusace_tns_encode(ptr_tns_info_ch2, ptr_tns_info, pstr_psy_data->sfb_energy_short[w], w,
220                         chn, pstr_psy_config->low_pass_line, scratch_tns_filter, 0,
221                         ptr_tns_scratch);
222     }
223 
224     for (i = 0; i < pstr_psy_config->sfb_count; i++) {
225       pstr_psy_data->sfb_thr_short[w][i] =
226           pstr_psy_data->sfb_energy_short[w][i] * pstr_psy_config->ratio;
227       pstr_psy_data->sfb_thr_short[w][i] = MIN(pstr_psy_data->sfb_thr_short[w][i], clip_energy);
228     }
229 
230     if (tns_select != 0) {
231       if (ptr_tns_info->tns_data_present == 1) {
232         iusace_calc_band_energy(ptr_spec_in + w_offset, pstr_psy_config->sfb_offset,
233                                 pstr_psy_config->sfb_active, pstr_psy_data->sfb_energy_short[w],
234                                 pstr_psy_config->sfb_count);
235       }
236     }
237 
238     iusace_find_max_spreading(pstr_psy_config->sfb_count, pstr_psy_config->sfb_mask_low_fac,
239                               pstr_psy_config->sfb_mask_high_fac,
240                               pstr_psy_data->sfb_thr_short[w]);
241 
242     for (i = 0; i < pstr_psy_config->sfb_count; i++) {
243       pstr_psy_data->sfb_thr_short[w][i] =
244           MAX(pstr_psy_data->sfb_thr_short[w][i], (pstr_psy_config->sfb_thr_quiet[i] * 0.25f));
245     }
246 
247     iusace_pre_echo_control(pstr_psy_data->sfb_thr_nm1, pstr_psy_config->sfb_count,
248                             pstr_psy_config->max_allowed_inc_fac,
249                             pstr_psy_config->min_remaining_thr_fac,
250                             pstr_psy_data->sfb_thr_short[w]);
251 
252     for (i = 0; i < pstr_psy_config->sfb_count; i++) {
253       pstr_psy_data->sfb_spreaded_energy_short[w][i] = pstr_psy_data->sfb_energy_short[w][i];
254     }
255     iusace_find_max_spreading(
256         pstr_psy_config->sfb_count, pstr_psy_config->sfb_mask_low_fac_spr_ener,
257         pstr_psy_config->sfb_mask_high_fac_spr_ener, pstr_psy_data->sfb_spreaded_energy_short[w]);
258   }
259 
260   for (WORD32 wnd = 0; wnd < MAX_SHORT_WINDOWS; wnd++) {
261     for (sfb = pstr_psy_config->sfb_count - 1; sfb >= max_sfb; sfb--) {
262       for (line = pstr_psy_config->sfb_offset[sfb + 1] - 1;
263            line >= pstr_psy_config->sfb_offset[sfb]; line--) {
264         if (ptr_spec_in[wnd * frame_len_short + line] != 0.0) break;
265       }
266       if (line >= pstr_psy_config->sfb_offset[sfb]) break;
267     }
268     max_sfb = MAX(max_sfb, sfb);
269   }
270   max_sfb = max_sfb > 0 ? max_sfb : 0;
271 
272   pstr_psy_mod->str_psy_out_data[i_ch].max_sfb_per_grp = max_sfb + 1;
273 
274   return;
275 }
276