xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_psy_configuration.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 <math.h>
23 
24 #include "ixheaac_type_def.h"
25 #include "ixheaac_constants.h"
26 #include "impd_drc_common_enc.h"
27 #include "impd_drc_uni_drc.h"
28 #include "impd_drc_tables.h"
29 #include "impd_drc_api.h"
30 #include "ixheaace_api.h"
31 #include "ixheaace_aac_constants.h"
32 #include "ixheaac_basic_ops32.h"
33 #include "ixheaac_basic_ops16.h"
34 #include "ixheaac_basic_ops40.h"
35 #include "ixheaac_basic_ops.h"
36 #include "ixheaac_error_standards.h"
37 #include "ixheaace_error_codes.h"
38 #include "ixheaace_psy_const.h"
39 #include "ixheaace_tns.h"
40 #include "ixheaace_tns_params.h"
41 #include "ixheaace_rom.h"
42 #include "ixheaace_common_rom.h"
43 #include "ixheaace_bitbuffer.h"
44 #include "ixheaace_psy_configuration.h"
45 
46 #include "ixheaace_adjust_threshold_data.h"
47 #include "ixheaace_tns_params.h"
48 #include "ixheaace_dynamic_bits.h"
49 #include "ixheaace_qc_data.h"
50 #include "ixheaace_block_switch.h"
51 #include "ixheaace_psy_data.h"
52 #include "ixheaace_interface.h"
53 #include "ixheaace_adjust_threshold.h"
54 #include "ixheaace_common_utils.h"
55 
ia_enhaacplus_enc_init_sfb_table(ixheaace_psycho_tables * pstr_psycho_tab,WORD32 sample_rate,WORD32 aot,WORD32 block_type,WORD32 * ptr_sfb_offset,WORD32 * sfb_cnt,WORD32 long_frame_len)56 static IA_ERRORCODE ia_enhaacplus_enc_init_sfb_table(ixheaace_psycho_tables *pstr_psycho_tab,
57                                                      WORD32 sample_rate, WORD32 aot,
58                                                      WORD32 block_type, WORD32 *ptr_sfb_offset,
59                                                      WORD32 *sfb_cnt, WORD32 long_frame_len) {
60   const UWORD8 *ptr_sfb_param = NULL;
61   UWORD32 i;
62   WORD32 spec_start_offset, spec_lines = 0;
63 
64   /* sfb_info_tab[] */
65   for (i = 0; i < sizeof(pstr_psycho_tab->sfb_info_tab) / sizeof(ixheaace_sfb_info_tab); i++) {
66     if (pstr_psycho_tab->sfb_info_tab[i].sample_rate == sample_rate) {
67       switch (block_type) {
68         case LONG_WINDOW:
69         case START_WINDOW:
70         case STOP_WINDOW:
71           if (aot == AOT_AAC_LC || aot == AOT_SBR || aot == AOT_PS) {
72             if (long_frame_len == FRAME_LEN_960) {
73               ptr_sfb_param = pstr_psycho_tab->sfb_info_tab[i].param_long_960;
74             } else {
75               ptr_sfb_param = pstr_psycho_tab->sfb_info_tab[i].param_long;
76             }
77             spec_lines = long_frame_len;
78             break;
79           } else if (aot == AOT_AAC_LD || aot == AOT_AAC_ELD) {
80             if (long_frame_len == FRAME_LEN_480)
81               ptr_sfb_param = pstr_psycho_tab->sfb_info_tab[i].param_long_480_ld;
82             else
83               ptr_sfb_param = pstr_psycho_tab->sfb_info_tab[i].param_long_512_ld;
84             spec_lines = long_frame_len;
85             break;
86           }
87 
88         case SHORT_WINDOW:
89           if (long_frame_len == FRAME_LEN_SHORT_120) {
90             ptr_sfb_param = pstr_psycho_tab->sfb_info_tab[i].param_short_120;
91           } else {
92             ptr_sfb_param = pstr_psycho_tab->sfb_info_tab[i].param_short;
93           }
94           spec_lines = long_frame_len;
95           break;
96       }
97       break;
98     }
99   }
100 
101   if (ptr_sfb_param == NULL) {
102     return IA_EXHEAACE_INIT_FATAL_SCALE_FACTOR_BAND_NOT_SUPPORTED;
103   }
104 
105   *sfb_cnt = 0;
106   spec_start_offset = 0;
107 
108   do {
109     ptr_sfb_offset[*sfb_cnt] = spec_start_offset;
110 
111     spec_start_offset += ptr_sfb_param[*sfb_cnt];
112 
113     (*sfb_cnt)++;
114   } while (spec_start_offset < spec_lines);
115 
116   if (spec_start_offset != spec_lines) {
117     return IA_EXHEAACE_INIT_FATAL_SFB_TABLE_INIT_FAILED;
118   }
119 
120   ptr_sfb_offset[*sfb_cnt] = spec_start_offset;
121 
122   return IA_NO_ERROR;
123 }
124 
iaace_atan_approx(FLOAT32 val)125 FLOAT32 iaace_atan_approx(FLOAT32 val) {
126   if (val < (FLOAT32)1.0f) {
127     return (val / ((FLOAT32)1.0f + (FLOAT32)0.280872f * val * val));
128   } else {
129     return ((FLOAT32)1.57079633f - val / ((FLOAT32)0.280872f + val * val));
130   }
131 }
132 
iaace_calc_bark_line_value(WORD32 num_lines,WORD32 fft_line,WORD32 sample_rate)133 static FLOAT32 iaace_calc_bark_line_value(WORD32 num_lines, WORD32 fft_line, WORD32 sample_rate) {
134   FLOAT32 center_freq, temp, b_value;
135   center_freq = (FLOAT32)fft_line * ((FLOAT32)sample_rate * (FLOAT32)0.5f) / (FLOAT32)num_lines;
136   temp = (FLOAT32)iaace_atan_approx((FLOAT32)1.3333333e-4f * center_freq);
137   b_value = (FLOAT32)13.3f * iaace_atan_approx((FLOAT32)0.00076f * center_freq) +
138             (FLOAT32)3.5f * temp * temp;
139   return (b_value);
140 }
141 
iaace_thr_quiet_init(WORD32 sfb_count,WORD32 * ptr_sfb_offset,FLOAT32 * ptr_bark_val,FLOAT32 * ptr_thr_quiet,const FLOAT32 * ptr_bark_quiet_thr_val,WORD32 aot)142 static VOID iaace_thr_quiet_init(WORD32 sfb_count, WORD32 *ptr_sfb_offset, FLOAT32 *ptr_bark_val,
143                                  FLOAT32 *ptr_thr_quiet, const FLOAT32 *ptr_bark_quiet_thr_val,
144                                  WORD32 aot) {
145   WORD32 i;
146   FLOAT32 bark_thr_quiet;
147 
148   for (i = 0; i < sfb_count; i++) {
149     if (aot == AOT_AAC_ELD) {
150       ptr_thr_quiet[i] = (FLOAT32)(ptr_sfb_offset[i + 1] - ptr_sfb_offset[i]) * 42;
151     } else {
152       WORD32 b_val1, b_val2;
153 
154       if (i > 0) {
155         b_val1 = (WORD32)(ptr_bark_val[i] + ptr_bark_val[i - 1]) >> 1;
156       } else {
157         b_val1 = (WORD32)(ptr_bark_val[i]) >> 1;
158       }
159 
160       if (i < sfb_count - 1) {
161         b_val2 = (WORD32)(ptr_bark_val[i] + ptr_bark_val[i + 1]) >> 1;
162       } else {
163         b_val2 = (WORD32)(ptr_bark_val[i]);
164       }
165       b_val1 = MIN(b_val1, (WORD32)MAX_BARK_VALUE);
166       b_val2 = MIN(b_val2, (WORD32)MAX_BARK_VALUE);
167       bark_thr_quiet = MIN(ptr_bark_quiet_thr_val[b_val1], ptr_bark_quiet_thr_val[b_val2]);
168 
169       ptr_thr_quiet[i] = (FLOAT32)db_lin_scale(bark_thr_quiet - 20.0f) * 16887.8f *
170                          (FLOAT32)(ptr_sfb_offset[i + 1] - ptr_sfb_offset[i]);
171     }
172   }
173 }
174 
iaace_spreading_init(WORD32 sfb_count,FLOAT32 * ptr_bark_val,FLOAT32 * ptr_mask_low_fac,FLOAT32 * ptr_mask_high_fac,FLOAT32 * ptr_mask_low_fac_spr_energy,FLOAT32 * ptr_mask_high_fac_spr_energy,const WORD32 bit_rate,WORD32 block_type)175 static VOID iaace_spreading_init(WORD32 sfb_count, FLOAT32 *ptr_bark_val,
176                                  FLOAT32 *ptr_mask_low_fac, FLOAT32 *ptr_mask_high_fac,
177                                  FLOAT32 *ptr_mask_low_fac_spr_energy,
178                                  FLOAT32 *ptr_mask_high_fac_spr_energy, const WORD32 bit_rate,
179                                  WORD32 block_type) {
180   WORD32 i;
181   FLOAT32 mask_low_spr_energy, mask_high_spr_energy;
182 
183   if (block_type != SHORT_WINDOW) {
184     mask_low_spr_energy = MASK_LOW_SP_ENERGY_L;
185     mask_high_spr_energy = (bit_rate > MASK_HIGH_SP_BITRATE_THRESH) ? MASK_HIGH_SP_ENERGY_L
186                                                                     : MASK_HIGH_SP_ENERGY_L_LBR;
187   } else {
188     mask_low_spr_energy = MASK_LOW_SP_ENERGY_S;
189     mask_high_spr_energy = MASK_HIGH_SP_ENERGY_S;
190   }
191 
192   for (i = 0; i < sfb_count; i++) {
193     if (i > 0) {
194       FLOAT32 db_val;
195       FLOAT32 diff_val = (ptr_bark_val[i] - ptr_bark_val[i - 1]);
196 
197       db_val = MASK_HIGH_FAC * diff_val;
198       ptr_mask_high_fac[i] = (FLOAT32)pow(10.0f, -db_val);
199       db_val = MASK_LOW_FAC * diff_val;
200       ptr_mask_low_fac[i - 1] = (FLOAT32)pow(10.0f, -db_val);
201       db_val = mask_high_spr_energy * diff_val;
202       ptr_mask_high_fac_spr_energy[i] = (FLOAT32)pow(10.0f, -db_val);
203       db_val = mask_low_spr_energy * diff_val;
204       ptr_mask_low_fac_spr_energy[i - 1] = (FLOAT32)pow(10.0f, -db_val);
205     } else {
206       ptr_mask_high_fac[i] = 0.0f;
207       ptr_mask_low_fac[sfb_count - 1] = 0.0f;
208       ptr_mask_high_fac_spr_energy[i] = 0.0f;
209       ptr_mask_low_fac_spr_energy[sfb_count - 1] = 0.0f;
210     }
211   }
212   return;
213 }
214 
iaace_bark_values_init(WORD32 sfb_count,WORD32 * ptr_sfb_offset,WORD32 num_lines,WORD32 sample_rate,FLOAT32 * ptr_b_value,WORD32 aot)215 static VOID iaace_bark_values_init(WORD32 sfb_count, WORD32 *ptr_sfb_offset, WORD32 num_lines,
216                                    WORD32 sample_rate, FLOAT32 *ptr_b_value, WORD32 aot) {
217   WORD32 i;
218   FLOAT32 b_val0, b_val1;
219   b_val0 = 0.0f;
220 
221   for (i = 0; i < sfb_count; i++) {
222     b_val1 = iaace_calc_bark_line_value(num_lines, ptr_sfb_offset[i + 1], sample_rate);
223     ptr_b_value[i] = (b_val0 + b_val1) * (FLOAT32)0.5f;
224     if (aot == AOT_AAC_ELD) {
225       if (ptr_b_value[i] > MAX_BARK_VALUE) {
226         ptr_b_value[i] = MAX_BARK_VALUE;
227       }
228     }
229 
230     b_val0 = b_val1;
231   }
232 }
233 
iaace_bits_to_pe(const FLOAT32 bits)234 static FLOAT32 iaace_bits_to_pe(const FLOAT32 bits) { return (bits * 1.18f); }
iaace_min_snr_init(const WORD32 bit_rate,const WORD32 sample_rate,const WORD32 num_lines,const WORD32 * ptr_sfb_offset,const FLOAT32 * ptr_bark_value,const WORD32 sfb_active,FLOAT32 * ptr_sfb_min_snr)235 static VOID iaace_min_snr_init(const WORD32 bit_rate, const WORD32 sample_rate,
236                                const WORD32 num_lines, const WORD32 *ptr_sfb_offset,
237                                const FLOAT32 *ptr_bark_value, const WORD32 sfb_active,
238                                FLOAT32 *ptr_sfb_min_snr) {
239   WORD32 sfb;
240   FLOAT32 bark_fac;
241   FLOAT32 bark_width;
242   FLOAT32 pe_per_window, pe_part;
243   FLOAT32 snr;
244   FLOAT32 b_val0, b_val1;
245 
246   bark_fac = (FLOAT32)1.0 / MIN(ptr_bark_value[sfb_active - 1] / MAX_BARK_VALUE, (FLOAT32)1.0);
247   pe_per_window = iaace_bits_to_pe((FLOAT32)bit_rate / (FLOAT32)sample_rate * (FLOAT32)num_lines);
248   b_val0 = (FLOAT32)0.0f;
249 
250   for (sfb = 0; sfb < sfb_active; sfb++) {
251     b_val1 = (FLOAT32)2.0 * ptr_bark_value[sfb] - b_val0;
252     bark_width = b_val1 - b_val0;
253     b_val0 = b_val1;
254 
255     pe_part = pe_per_window * (FLOAT32)0.024f * bark_fac;
256     pe_part *= bark_width;
257     pe_part /= (FLOAT32)(ptr_sfb_offset[sfb + 1] - ptr_sfb_offset[sfb]);
258     snr = (FLOAT32)pow(2.0f, pe_part) - 1.5f;
259     snr = 1.0f / MAX(snr, 1.0f);
260     snr = MIN(snr, 0.8f);
261     snr = MAX(snr, 0.003f);
262     ptr_sfb_min_snr[sfb] = snr;
263   }
264 }
265 
ia_enhaacplus_enc_init_psy_configuration(WORD32 bit_rate,WORD32 sample_rate,WORD32 bandwidth,WORD32 aot,ixheaace_psy_configuration_long * pstr_psy_conf,ixheaace_aac_tables * pstr_aac_tables,WORD32 long_frame_len)266 IA_ERRORCODE ia_enhaacplus_enc_init_psy_configuration(
267     WORD32 bit_rate, WORD32 sample_rate, WORD32 bandwidth, WORD32 aot,
268     ixheaace_psy_configuration_long *pstr_psy_conf, ixheaace_aac_tables *pstr_aac_tables,
269     WORD32 long_frame_len) {
270   WORD32 sfb;
271   FLOAT32 sfb_bark_val[MAXIMUM_SCALE_FACTOR_BAND_LONG];
272   IA_ERRORCODE error;
273   error = ia_enhaacplus_enc_init_sfb_table(pstr_aac_tables->pstr_psycho_tab, sample_rate, aot,
274                                            LONG_WINDOW, pstr_psy_conf->sfb_offsets,
275                                            &(pstr_psy_conf->sfb_cnt), long_frame_len);
276   if (error != IA_NO_ERROR) {
277     return error;
278   }
279 
280   /*   calculate bark values for each pb */
281   iaace_bark_values_init(pstr_psy_conf->sfb_cnt, pstr_psy_conf->sfb_offsets,
282                          pstr_psy_conf->sfb_offsets[pstr_psy_conf->sfb_cnt], sample_rate,
283                          sfb_bark_val, aot);
284 
285   /*init thresholds in quiet  */
286 
287   iaace_thr_quiet_init(pstr_psy_conf->sfb_cnt, pstr_psy_conf->sfb_offsets, sfb_bark_val,
288                        pstr_psy_conf->sfb_threshold_quiet,
289                        pstr_aac_tables->pstr_psycho_tab->ixheaace_bark_quiet_thr_val, aot);
290 
291   /*  calculate spreading function */
292 
293   iaace_spreading_init(pstr_psy_conf->sfb_cnt, sfb_bark_val, pstr_psy_conf->sfb_mask_low_factor,
294                        pstr_psy_conf->sfb_mask_high_factor,
295                        pstr_psy_conf->sfb_mask_low_factor_spread_nrg,
296                        pstr_psy_conf->sfb_mask_high_factor_spread_nrg, bit_rate, LONG_WINDOW);
297 
298   /*
299     init ratio
300   */
301 
302   pstr_psy_conf->min_remaining_threshold_factor = MIN_THRESH_FAC;
303 
304   pstr_psy_conf->clip_energy = CLIP_ENERGY_VALUE_LONG;
305   if (aot == AOT_AAC_LC || aot == AOT_SBR || aot == AOT_PS) {
306     pstr_psy_conf->ratio_float = C_RATIO;
307   } else if (aot == AOT_AAC_LD || aot == AOT_AAC_ELD) {
308     if (aot == AOT_AAC_ELD) {
309       pstr_psy_conf->ratio_float = C_RATIO;
310     } else {
311       pstr_psy_conf->ratio_float = SNR_FLOAT;
312     }
313   }
314 
315   pstr_psy_conf->lowpass_line = (WORD32)((2 * bandwidth * long_frame_len) / sample_rate);
316 
317   /* pstr_psy_conf->pstr_sfb_offset[] */
318   for (sfb = 0; sfb < pstr_psy_conf->sfb_cnt; sfb++) {
319     if (pstr_psy_conf->sfb_offsets[sfb] >= pstr_psy_conf->lowpass_line) break;
320   }
321   pstr_psy_conf->sfb_active = sfb;
322 
323   /*
324     calculate minSnr
325   */
326   iaace_min_snr_init(bit_rate, sample_rate, pstr_psy_conf->sfb_offsets[pstr_psy_conf->sfb_cnt],
327                      pstr_psy_conf->sfb_offsets, sfb_bark_val, pstr_psy_conf->sfb_active,
328                      pstr_psy_conf->sfb_min_snr);
329 
330   return IA_NO_ERROR;
331 }
332 
ia_enhaacplus_enc_init_psy_configuration_short(WORD32 bit_rate,WORD32 sample_rate,WORD32 bandwidth,WORD32 aot,ixheaace_psy_configuration_short * pstr_psy_conf,ixheaace_aac_tables * pstr_aac_tables,WORD32 long_frame_len)333 IA_ERRORCODE ia_enhaacplus_enc_init_psy_configuration_short(
334     WORD32 bit_rate, WORD32 sample_rate, WORD32 bandwidth, WORD32 aot,
335     ixheaace_psy_configuration_short *pstr_psy_conf, ixheaace_aac_tables *pstr_aac_tables,
336     WORD32 long_frame_len) {
337   WORD32 sfb;
338   FLOAT32 sfb_bark_val[MAXIMUM_SCALE_FACTOR_BAND_SHORT] = {0};
339   IA_ERRORCODE error;
340   /*
341     init sfb table
342   */
343   error = ia_enhaacplus_enc_init_sfb_table(pstr_aac_tables->pstr_psycho_tab, sample_rate, aot,
344                                            SHORT_WINDOW, pstr_psy_conf->sfb_offsets,
345                                            &(pstr_psy_conf->sfb_cnt), long_frame_len);
346 
347   if (error != IA_NO_ERROR) {
348     return error;
349   }
350 
351   iaace_bark_values_init(pstr_psy_conf->sfb_cnt, pstr_psy_conf->sfb_offsets,
352                          pstr_psy_conf->sfb_offsets[pstr_psy_conf->sfb_cnt], sample_rate,
353                          sfb_bark_val, aot);
354 
355   iaace_thr_quiet_init(pstr_psy_conf->sfb_cnt, pstr_psy_conf->sfb_offsets, sfb_bark_val,
356                        pstr_psy_conf->sfb_threshold_quiet,
357                        pstr_aac_tables->pstr_psycho_tab->ixheaace_bark_quiet_thr_val, aot);
358 
359   /*
360     calculate spreading function
361   */
362   iaace_spreading_init(pstr_psy_conf->sfb_cnt, sfb_bark_val, pstr_psy_conf->sfb_mask_low_factor,
363                        pstr_psy_conf->sfb_mask_high_factor,
364                        pstr_psy_conf->sfb_mask_low_factor_spread_nrg,
365                        pstr_psy_conf->sfb_mask_high_factor_spread_nrg, bit_rate, SHORT_WINDOW);
366 
367   /*
368     init ratio
369   */
370 
371   pstr_psy_conf->min_remaining_threshold_factor = 0.01f;
372 
373   pstr_psy_conf->clip_energy = CLIP_ENERGY_VALUE_LONG / (TRANS_FAC * TRANS_FAC);
374   switch (aot) {
375     case AOT_AAC_LC:
376     case AOT_SBR:
377     case AOT_PS:
378       pstr_psy_conf->ratio_float = C_RATIO;
379       break;
380 
381     case AOT_AAC_LD:
382     case AOT_AAC_ELD:
383       pstr_psy_conf->ratio_float = SNR_FLOAT;
384       break;
385   }
386 
387   pstr_psy_conf->lowpass_line = (WORD32)((2 * bandwidth * long_frame_len) / sample_rate);
388   for (sfb = 0; sfb < pstr_psy_conf->sfb_cnt; sfb++) {
389     if (pstr_psy_conf->sfb_offsets[sfb] >= pstr_psy_conf->lowpass_line) break;
390   }
391   pstr_psy_conf->sfb_active = sfb;
392 
393   iaace_min_snr_init(bit_rate, sample_rate, pstr_psy_conf->sfb_offsets[pstr_psy_conf->sfb_cnt],
394                      pstr_psy_conf->sfb_offsets, sfb_bark_val, pstr_psy_conf->sfb_active,
395                      pstr_psy_conf->sfb_min_snr);
396 
397   return IA_NO_ERROR;
398 }
399 
ia_enhaacplus_enc_power2(WORD32 power,WORD q_power,WORD * q_result,const WORD32 * power_of_2_table_neg,const WORD32 * power_of_2_table_pos)400 WORD32 ia_enhaacplus_enc_power2(WORD32 power, WORD q_power, WORD *q_result,
401                                 const WORD32 *power_of_2_table_neg,
402                                 const WORD32 *power_of_2_table_pos) {
403   WORD32 int_part, frac_part;
404   WORD32 result;
405   WORD16 sign = 0;
406 
407   if (power < 0) {
408     sign = 1;
409     power = ixheaac_negate32(power);
410   }
411 
412   if (q_power < 32)
413     int_part = ixheaac_shr32(power, q_power);
414   else
415     int_part = 0;
416 
417   if (q_power < 39) {
418     power = ixheaac_shr32_dir(power, q_power - 8);
419     frac_part = power & 0xFF;
420   } else
421     frac_part = 0;
422 
423   if (!sign) {
424     result = power_of_2_table_pos[frac_part];
425     *q_result = Q_POWER2_TABLE - int_part;
426   } else {
427     result = power_of_2_table_neg[frac_part];
428     *q_result = Q_POWER2_TABLE + int_part;
429   }
430 
431   return (result);
432 }
433