xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_sbr_tran_det.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 <math.h>
22 #include <string.h>
23 #include "ixheaac_type_def.h"
24 #include "ixheaac_constants.h"
25 #include "ixheaace_aac_constants.h"
26 #include "ixheaac_error_standards.h"
27 #include "ixheaace_error_codes.h"
28 #include "ixheaac_basic_ops32.h"
29 #include "ixheaac_basic_ops16.h"
30 #include "ixheaac_basic_ops40.h"
31 #include "ixheaac_basic_ops.h"
32 
33 #include "ixheaace_common_rom.h"
34 #include "ixheaace_sbr_header.h"
35 #include "ixheaace_sbr_def.h"
36 #include "ixheaace_resampler.h"
37 #include "ixheaace_sbr_rom.h"
38 #include "ixheaace_sbr_tran_det.h"
39 #include "ixheaace_sbr_main.h"
40 #include "ixheaace_sbr_frame_info_gen.h"
41 
ixheaace_spectral_change(FLOAT32 * ptr_energies[16],FLOAT32 total_energy,WORD32 num_sfb,WORD32 start,WORD32 border,WORD32 stop,WORD32 is_ld_sbr,FLOAT32 * ptr_delta)42 static IA_ERRORCODE ixheaace_spectral_change(FLOAT32 *ptr_energies[16], FLOAT32 total_energy,
43                                              WORD32 num_sfb, WORD32 start, WORD32 border,
44                                              WORD32 stop, WORD32 is_ld_sbr, FLOAT32 *ptr_delta) {
45   WORD32 i, j;
46   WORD32 len1 = border - start;
47   WORD32 len2 = stop - border;
48   FLOAT32 energy_1[MAXIMUM_FREQ_COEFFS] = {0};
49   FLOAT32 energy_2[MAXIMUM_FREQ_COEFFS] = {0};
50   FLOAT32 len_ratio = (FLOAT32)len1 / (FLOAT32)(len2);
51   FLOAT32 delta, delta_sum = 0.0f;
52   FLOAT32 pos_wt = (0.5f - (FLOAT32)len1 / (FLOAT32)(len1 + len2));
53   pos_wt = 1.0f - 4.0f * pos_wt * pos_wt;
54 
55   if (total_energy < SBR_EPS) {
56     *ptr_delta = 0.0f;
57     return IA_NO_ERROR;
58   }
59 
60   if (!is_ld_sbr) {
61     for (j = 0; j < num_sfb; j++) {
62       energy_1[j] = 1.0e6f * len1;
63       energy_2[j] = 1.0e6f * len2;
64     }
65   }
66 
67   for (j = 0; j < num_sfb; j++) {
68     for (i = start; i < border; i++) {
69       energy_1[j] += ptr_energies[i][j];
70     }
71 
72     for (i = border; i < stop; i++) {
73       energy_2[j] += ptr_energies[i][j];
74     }
75     if (energy_1[j] <= EPS) {
76       energy_1[j] = (FLOAT32)len1;
77     }
78     if (energy_2[j] <= EPS) {
79       energy_2[j] = (FLOAT32)len2;
80     }
81     delta = (FLOAT32)fabs(log((energy_2[j] / energy_1[j]) * len_ratio));
82     delta_sum += (FLOAT32)(sqrt((energy_1[j] + energy_2[j]) / total_energy) * delta);
83   }
84 
85   *ptr_delta = delta_sum * pos_wt;
86   return IA_NO_ERROR;
87 }
88 
ixheaace_add_lowband_energies(FLOAT32 ** ptr_energies,UWORD8 * ptr_freq_band_tab,WORD32 time_slots,WORD32 is_ld_sbr)89 FLOAT32 ixheaace_add_lowband_energies(FLOAT32 **ptr_energies, UWORD8 *ptr_freq_band_tab,
90                                       WORD32 time_slots, WORD32 is_ld_sbr) {
91   WORD32 band, ts;
92   FLOAT32 energy = 1.0f;
93   WORD32 tran_offset = 0;
94   if (is_ld_sbr) {
95     tran_offset = 7;
96     energy = 0.0f;
97 
98     for (ts = tran_offset; ts < time_slots + tran_offset; ts++) {
99       for (band = 0; band < ptr_freq_band_tab[0]; band++) {
100         energy += ptr_energies[ts][band];
101       }
102     }
103   } else {
104     for (ts = tran_offset; ts < time_slots + tran_offset; ts++) {
105       for (band = 0; band < ptr_freq_band_tab[0]; band++) {
106         energy += ptr_energies[(ts + time_slots / 2) / 2][band];
107       }
108     }
109   }
110   return energy;
111 }
112 
ixheaace_add_highband_energies(FLOAT32 ** ptr_energies,FLOAT32 * ptr_energies_m[16],UWORD8 * ptr_freq_band_tab,WORD32 num_sfb,WORD32 time_slots,WORD32 time_step,WORD32 is_ld_sbr)113 static FLOAT32 ixheaace_add_highband_energies(FLOAT32 **ptr_energies, FLOAT32 *ptr_energies_m[16],
114                                               UWORD8 *ptr_freq_band_tab, WORD32 num_sfb,
115                                               WORD32 time_slots, WORD32 time_step,
116                                               WORD32 is_ld_sbr) {
117   WORD32 band, ts, sfb, low_band, high_band, st;
118   FLOAT32 energy = 1.0f, tmp;
119   if (is_ld_sbr) {
120     energy = 0.0f;
121     for (ts = 0; ts < time_slots; ts++) {
122       for (sfb = 0; sfb < num_sfb; sfb++) {
123         tmp = 0;
124         low_band = ptr_freq_band_tab[sfb];
125         high_band = ptr_freq_band_tab[sfb + 1];
126         band = low_band;
127         while (band < high_band) {
128           tmp += ptr_energies[ts][band];
129           band++;
130         }
131         ptr_energies_m[ts][sfb] = tmp;
132         energy += tmp;
133       }
134     }
135   } else {
136     for (ts = 0; ts < time_slots; ts++) {
137       for (sfb = 0; sfb < num_sfb; sfb++) {
138         tmp = 0;
139         low_band = ptr_freq_band_tab[sfb];
140         high_band = ptr_freq_band_tab[sfb + 1];
141         band = low_band;
142         while (band < high_band) {
143           st = 0;
144           while (st < time_step) {
145             tmp += ptr_energies[ts + (st / 2)][band];
146             st++;
147           }
148           band++;
149         }
150         ptr_energies_m[ts][sfb] = tmp;
151 
152         energy += ptr_energies[ts][sfb];
153       }
154     }
155   }
156   return energy;
157 }
158 
159 IA_ERRORCODE
ixheaace_frame_splitter(FLOAT32 ** ptr_energies,ixheaace_pstr_sbr_trans_detector pstr_sbr_trans_detector,UWORD8 * ptr_freq_band_tab,WORD32 num_scf,WORD32 time_step,WORD32 no_cols,WORD32 * ptr_tran_vector,FLOAT32 * ptr_frame_splitter_scratch,WORD32 is_ld_sbr)160 ixheaace_frame_splitter(FLOAT32 **ptr_energies,
161                         ixheaace_pstr_sbr_trans_detector pstr_sbr_trans_detector,
162                         UWORD8 *ptr_freq_band_tab, WORD32 num_scf, WORD32 time_step,
163                         WORD32 no_cols, WORD32 *ptr_tran_vector,
164                         FLOAT32 *ptr_frame_splitter_scratch, WORD32 is_ld_sbr) {
165   WORD32 border, i;
166   WORD32 num_sbr_slots = no_cols / time_step;
167   FLOAT32 *ptr_energies_m[16] = {0};
168   FLOAT32 low_band_energy, high_band_energy, total_energy;
169   FLOAT32 delta = 0.0f;
170   IA_ERRORCODE err_code = IA_NO_ERROR;
171 
172   if ((num_sbr_slots <= 0) || (num_sbr_slots * time_step != no_cols)) {
173     return IA_EXHEAACE_EXE_FATAL_SBR_INVALID_TIME_SLOTS;
174   }
175 
176   memset(ptr_frame_splitter_scratch, 0,
177          sizeof(ptr_energies_m[0][0]) * MAXIMUM_FREQ_COEFFS * num_sbr_slots);
178 
179   for (i = 0; i < num_sbr_slots; i++) {
180     ptr_energies_m[i] = ptr_frame_splitter_scratch;
181     ptr_frame_splitter_scratch += MAXIMUM_FREQ_COEFFS;
182   }
183 
184   low_band_energy =
185       ixheaace_add_lowband_energies(ptr_energies, ptr_freq_band_tab, no_cols, is_ld_sbr);
186 
187   high_band_energy =
188       ixheaace_add_highband_energies(ptr_energies, ptr_energies_m, ptr_freq_band_tab, num_scf,
189                                      num_sbr_slots, time_step, is_ld_sbr);
190   border = (num_sbr_slots + 1) >> 1;
191 
192   total_energy = 0.5f * (low_band_energy + pstr_sbr_trans_detector->prev_low_band_energy);
193   total_energy += high_band_energy;
194   if ((total_energy > IXHEAACE_SBR_ENERGY_THRESHOLD) || (!is_ld_sbr)) {
195     err_code = ixheaace_spectral_change(ptr_energies_m, total_energy, num_scf, 0, border,
196                                         num_sbr_slots, is_ld_sbr, &delta);
197     if (err_code) {
198       return err_code;
199     }
200   } else if (is_ld_sbr) {
201     delta = 0;
202   }
203 
204   if (delta > pstr_sbr_trans_detector->split_thr) {
205     ptr_tran_vector[0] = 1;
206   } else {
207     ptr_tran_vector[0] = 0;
208   }
209   pstr_sbr_trans_detector->prev_low_band_energy = low_band_energy;
210   return err_code;
211 }
212 
ixheaace_create_sbr_transient_detector(ixheaace_pstr_sbr_trans_detector pstr_sbr_trans_detector,WORD32 sample_freq,WORD32 total_bitrate,WORD32 codec_bitrate,WORD32 tran_thr,WORD32 mode,WORD32 tran_fc,WORD32 frame_flag_480,WORD32 is_ld_sbr,WORD32 sbr_ratio_idx,ixheaace_sbr_codec_type sbr_codec,WORD32 start_band)213 VOID ixheaace_create_sbr_transient_detector(
214     ixheaace_pstr_sbr_trans_detector pstr_sbr_trans_detector, WORD32 sample_freq,
215     WORD32 total_bitrate, WORD32 codec_bitrate, WORD32 tran_thr, WORD32 mode, WORD32 tran_fc,
216     WORD32 frame_flag_480, WORD32 is_ld_sbr, WORD32 sbr_ratio_idx,
217     ixheaace_sbr_codec_type sbr_codec, WORD32 start_band) {
218   WORD32 no_cols = 32, buffer_length = 96;
219   FLOAT32 br_fac;
220   FLOAT32 frm_dur = 2048.0f / (FLOAT32)sample_freq;
221   FLOAT32 split_thr_fac = frm_dur - 0.01f;
222   if ((sbr_codec == USAC_SBR) && (sbr_ratio_idx == USAC_SBR_RATIO_INDEX_4_1)) {
223     frm_dur = frm_dur * 2;
224     split_thr_fac = frm_dur - 0.01f;
225   }
226   if ((1 == is_ld_sbr) && (1 == frame_flag_480)) {
227     no_cols = 30;
228     buffer_length = 90;
229   }
230 
231   memset(pstr_sbr_trans_detector, 0, sizeof(ixheaace_str_sbr_trans_detector));
232 
233   br_fac = codec_bitrate ? (FLOAT32)total_bitrate / (FLOAT32)codec_bitrate : 1.0f;
234 
235   split_thr_fac = MAX(split_thr_fac, 0.0001f);
236   split_thr_fac = 0.000075f / (split_thr_fac * split_thr_fac);
237 
238   pstr_sbr_trans_detector->split_thr = split_thr_fac * br_fac;
239 
240   if (is_ld_sbr) {
241     WORD32 i;
242     FLOAT32 ratio = ((sample_freq / 2) / IXHEAACE_QMF_CHANNELS) * 0.00075275f;
243 
244     FLOAT32 tmp = 1024.0f / sample_freq;
245     tmp -= 0.01f;
246     tmp = MAX(tmp, 0.001f);
247 
248     if (1 == frame_flag_480) {
249       no_cols = 30;
250       buffer_length = 90;
251     }
252     pstr_sbr_trans_detector->split_thr = (br_fac * 0.000075f) / (tmp * tmp) / 2.0f;
253     pstr_sbr_trans_detector->look_ahead = 2;
254     pstr_sbr_trans_detector->time_slots = no_cols / 2;
255     pstr_sbr_trans_detector->buffer_size =
256         pstr_sbr_trans_detector->look_ahead + pstr_sbr_trans_detector->time_slots;
257     pstr_sbr_trans_detector->stop_band =
258         (WORD32)fmin(13500 / ((sample_freq >> 1) / IXHEAACE_QMF_CHANNELS), IXHEAACE_QMF_CHANNELS);
259     pstr_sbr_trans_detector->start_band =
260         (WORD32)fmin(start_band, pstr_sbr_trans_detector->stop_band - 4);
261 
262     memset(pstr_sbr_trans_detector->energy, 0,
263            pstr_sbr_trans_detector->buffer_size * sizeof(pstr_sbr_trans_detector->energy[0]));
264     memset(pstr_sbr_trans_detector->sbr_transients, 0,
265            pstr_sbr_trans_detector->buffer_size *
266                sizeof(pstr_sbr_trans_detector->sbr_transients[0]));
267     memset(
268         pstr_sbr_trans_detector->delta_energy, 0,
269         pstr_sbr_trans_detector->buffer_size * sizeof(pstr_sbr_trans_detector->delta_energy[0]));
270 
271     for (i = 0; i < 64; i++) {
272       pstr_sbr_trans_detector->coeff[i] = (FLOAT32)pow(2.0, ratio * (i + 1));
273     }
274   }
275   pstr_sbr_trans_detector->no_cols = no_cols;
276   pstr_sbr_trans_detector->tran_fc = tran_fc;
277 
278   pstr_sbr_trans_detector->buffer_length = buffer_length;
279 
280   pstr_sbr_trans_detector->no_rows = 64;
281   pstr_sbr_trans_detector->mode = mode;
282 
283   pstr_sbr_trans_detector->prev_low_band_energy = 0;
284   pstr_sbr_trans_detector->tran_thr = (FLOAT32)tran_thr;
285 
286   pstr_sbr_trans_detector->ptr_thresholds = &(pstr_sbr_trans_detector->sbr_thresholds[0]);
287 
288   memset(pstr_sbr_trans_detector->ptr_thresholds, 0,
289          sizeof(pstr_sbr_trans_detector->ptr_thresholds[0]) * IXHEAACE_QMF_CHANNELS);
290 
291   pstr_sbr_trans_detector->ptr_transients = &(pstr_sbr_trans_detector->sbr_transients[0]);
292   memset(pstr_sbr_trans_detector->ptr_transients, 0,
293          sizeof(pstr_sbr_trans_detector->ptr_transients[0]) *
294              pstr_sbr_trans_detector->buffer_length);
295 }
296