/src/libxaac/encoder/ixheaace_sbr_tran_det.c
Line | Count | Source (jump to first uncovered line) |
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 | | |
42 | | static IA_ERRORCODE ixheaace_spectral_change(FLOAT32 *ptr_energies[16], FLOAT32 total_energy, |
43 | | WORD32 num_sfb, WORD32 start, WORD32 border, |
44 | 517k | WORD32 stop, WORD32 is_ld_sbr, FLOAT32 *ptr_delta) { |
45 | 517k | WORD32 i, j; |
46 | 517k | WORD32 len1 = border - start; |
47 | 517k | WORD32 len2 = stop - border; |
48 | 517k | FLOAT32 energy_1[MAXIMUM_FREQ_COEFFS] = {0}; |
49 | 517k | FLOAT32 energy_2[MAXIMUM_FREQ_COEFFS] = {0}; |
50 | 517k | FLOAT32 len_ratio = (FLOAT32)len1 / (FLOAT32)(len2); |
51 | 517k | FLOAT32 delta, delta_sum = 0.0f; |
52 | 517k | FLOAT32 pos_wt = (0.5f - (FLOAT32)len1 / (FLOAT32)(len1 + len2)); |
53 | 517k | pos_wt = 1.0f - 4.0f * pos_wt * pos_wt; |
54 | | |
55 | 517k | if (total_energy < SBR_EPS) { |
56 | 0 | *ptr_delta = 0.0f; |
57 | 0 | return IA_NO_ERROR; |
58 | 0 | } |
59 | | |
60 | 517k | if (!is_ld_sbr) { |
61 | 5.87M | for (j = 0; j < num_sfb; j++) { |
62 | 5.44M | energy_1[j] = 1.0e6f * len1; |
63 | 5.44M | energy_2[j] = 1.0e6f * len2; |
64 | 5.44M | } |
65 | 422k | } |
66 | | |
67 | 7.30M | for (j = 0; j < num_sfb; j++) { |
68 | 61.1M | for (i = start; i < border; i++) { |
69 | 54.3M | energy_1[j] += ptr_energies[i][j]; |
70 | 54.3M | } |
71 | | |
72 | 60.4M | for (i = border; i < stop; i++) { |
73 | 53.6M | energy_2[j] += ptr_energies[i][j]; |
74 | 53.6M | } |
75 | 6.79M | if (energy_1[j] <= EPS) { |
76 | 2.74k | energy_1[j] = (FLOAT32)len1; |
77 | 2.74k | } |
78 | 6.79M | if (energy_2[j] <= EPS) { |
79 | 20.1k | energy_2[j] = (FLOAT32)len2; |
80 | 20.1k | } |
81 | 6.79M | delta = (FLOAT32)fabs(log((energy_2[j] / energy_1[j]) * len_ratio)); |
82 | 6.79M | delta_sum += (FLOAT32)(sqrt((energy_1[j] + energy_2[j]) / total_energy) * delta); |
83 | 6.79M | } |
84 | | |
85 | 517k | *ptr_delta = delta_sum * pos_wt; |
86 | 517k | return IA_NO_ERROR; |
87 | 517k | } |
88 | | |
89 | | FLOAT32 ixheaace_add_lowband_energies(FLOAT32 **ptr_energies, UWORD8 *ptr_freq_band_tab, |
90 | 547k | WORD32 time_slots, WORD32 is_ld_sbr, WORD32 time_step) { |
91 | 547k | WORD32 band, ts; |
92 | 547k | FLOAT32 energy = 1.0f; |
93 | 547k | WORD32 tran_offset = 0; |
94 | 547k | if (is_ld_sbr) { |
95 | 124k | tran_offset = 7; |
96 | 124k | energy = 0.0f; |
97 | 422k | } else { |
98 | 422k | tran_offset = time_slots / 2; |
99 | 422k | } |
100 | | |
101 | 9.23M | for (ts = tran_offset; ts < time_slots + tran_offset; ts++) { |
102 | 184M | for (band = 0; band < ptr_freq_band_tab[0]; band++) { |
103 | 175M | energy += ptr_energies[ts][band]; |
104 | 175M | } |
105 | 8.68M | } |
106 | | |
107 | 547k | energy *= time_step; |
108 | | |
109 | 547k | return energy; |
110 | 547k | } |
111 | | |
112 | | static FLOAT32 ixheaace_add_highband_energies(FLOAT32 **ptr_energies, FLOAT32 *ptr_energies_m[16], |
113 | | UWORD8 *ptr_freq_band_tab, WORD32 num_sfb, |
114 | | WORD32 time_slots, WORD32 time_step, |
115 | 547k | WORD32 is_ld_sbr) { |
116 | 547k | WORD32 band, ts, sfb, low_band, high_band; |
117 | 547k | FLOAT32 energy = 1.0f, tmp; |
118 | 547k | if (is_ld_sbr) { |
119 | 124k | energy = 0.0f; |
120 | 124k | } |
121 | 9.23M | for (ts = 0; ts < time_slots; ts++) { |
122 | 122M | for (sfb = 0; sfb < num_sfb; sfb++) { |
123 | 114M | tmp = 0; |
124 | 114M | low_band = ptr_freq_band_tab[sfb]; |
125 | 114M | high_band = ptr_freq_band_tab[sfb + 1]; |
126 | 114M | band = low_band; |
127 | 368M | while (band < high_band) { |
128 | 254M | tmp += (ptr_energies[ts][band] * time_step); |
129 | 254M | band++; |
130 | 254M | } |
131 | 114M | ptr_energies_m[ts][sfb] = tmp; |
132 | 114M | if (is_ld_sbr || time_step == 4) { |
133 | 41.7M | energy += tmp; |
134 | 72.3M | } else { |
135 | 72.3M | energy += ptr_energies[ts][sfb]; |
136 | 72.3M | } |
137 | 114M | } |
138 | 8.68M | } |
139 | 547k | return energy; |
140 | 547k | } |
141 | | |
142 | | IA_ERRORCODE |
143 | | ixheaace_frame_splitter(FLOAT32 **ptr_energies, |
144 | | ixheaace_pstr_sbr_trans_detector pstr_sbr_trans_detector, |
145 | | UWORD8 *ptr_freq_band_tab, WORD32 num_scf, WORD32 time_step, |
146 | | WORD32 no_cols, WORD32 *ptr_tran_vector, |
147 | 547k | FLOAT32 *ptr_frame_splitter_scratch, WORD32 is_ld_sbr) { |
148 | 547k | WORD32 border, i; |
149 | 547k | WORD32 num_sbr_slots = no_cols / time_step; |
150 | 547k | FLOAT32 *ptr_energies_m[16] = {0}; |
151 | 547k | FLOAT32 low_band_energy, high_band_energy, total_energy; |
152 | 547k | FLOAT32 delta = 0.0f; |
153 | 547k | IA_ERRORCODE err_code = IA_NO_ERROR; |
154 | | |
155 | 547k | if ((num_sbr_slots <= 0) || (num_sbr_slots * time_step != no_cols)) { |
156 | 0 | return IA_EXHEAACE_EXE_FATAL_SBR_INVALID_TIME_SLOTS; |
157 | 0 | } |
158 | | |
159 | 547k | memset(ptr_frame_splitter_scratch, 0, |
160 | 547k | sizeof(ptr_energies_m[0][0]) * MAXIMUM_FREQ_COEFFS * num_sbr_slots); |
161 | | |
162 | 9.23M | for (i = 0; i < num_sbr_slots; i++) { |
163 | 8.68M | ptr_energies_m[i] = ptr_frame_splitter_scratch; |
164 | 8.68M | ptr_frame_splitter_scratch += MAXIMUM_FREQ_COEFFS; |
165 | 8.68M | } |
166 | | |
167 | 547k | low_band_energy = ixheaace_add_lowband_energies(ptr_energies, ptr_freq_band_tab, num_sbr_slots, |
168 | 547k | is_ld_sbr, time_step); |
169 | | |
170 | 547k | high_band_energy = |
171 | 547k | ixheaace_add_highband_energies(ptr_energies, ptr_energies_m, ptr_freq_band_tab, num_scf, |
172 | 547k | num_sbr_slots, time_step, is_ld_sbr); |
173 | 547k | border = (num_sbr_slots + 1) >> 1; |
174 | | |
175 | 547k | total_energy = 0.5f * (low_band_energy + pstr_sbr_trans_detector->prev_low_band_energy); |
176 | 547k | total_energy += high_band_energy; |
177 | 547k | if ((total_energy > IXHEAACE_SBR_ENERGY_THRESHOLD) || (!is_ld_sbr)) { |
178 | 517k | err_code = ixheaace_spectral_change(ptr_energies_m, total_energy, num_scf, 0, border, |
179 | 517k | num_sbr_slots, is_ld_sbr, &delta); |
180 | 517k | if (err_code) { |
181 | 0 | return err_code; |
182 | 0 | } |
183 | 517k | } else if (is_ld_sbr) { |
184 | 29.6k | delta = 0; |
185 | 29.6k | } |
186 | | |
187 | 547k | if (delta > pstr_sbr_trans_detector->split_thr) { |
188 | 50.8k | ptr_tran_vector[0] = 1; |
189 | 496k | } else { |
190 | 496k | ptr_tran_vector[0] = 0; |
191 | 496k | } |
192 | 547k | pstr_sbr_trans_detector->prev_low_band_energy = low_band_energy; |
193 | 547k | return err_code; |
194 | 547k | } |
195 | | |
196 | | VOID ixheaace_create_sbr_transient_detector( |
197 | | ixheaace_pstr_sbr_trans_detector pstr_sbr_trans_detector, WORD32 sample_freq, |
198 | | WORD32 total_bitrate, WORD32 codec_bitrate, WORD32 tran_thr, WORD32 mode, WORD32 tran_fc, |
199 | | WORD32 frame_flag_480, WORD32 is_ld_sbr, WORD32 sbr_ratio_idx, |
200 | 12.6k | ixheaace_sbr_codec_type sbr_codec, WORD32 start_band) { |
201 | 12.6k | WORD32 no_cols = 32, buffer_length = 96; |
202 | 12.6k | FLOAT32 br_fac; |
203 | 12.6k | FLOAT32 frm_dur = 2048.0f / (FLOAT32)sample_freq; |
204 | 12.6k | FLOAT32 split_thr_fac = frm_dur - 0.01f; |
205 | 12.6k | if ((sbr_codec == USAC_SBR) && (sbr_ratio_idx == USAC_SBR_RATIO_INDEX_4_1)) { |
206 | 750 | frm_dur = frm_dur * 2; |
207 | 750 | split_thr_fac = frm_dur - 0.01f; |
208 | 750 | no_cols = 64; |
209 | 750 | } |
210 | 12.6k | if ((1 == is_ld_sbr) && (1 == frame_flag_480)) { |
211 | 1.58k | no_cols = 30; |
212 | 1.58k | buffer_length = 90; |
213 | 1.58k | } |
214 | | |
215 | 12.6k | memset(pstr_sbr_trans_detector, 0, sizeof(ixheaace_str_sbr_trans_detector)); |
216 | | |
217 | 12.6k | br_fac = codec_bitrate ? (FLOAT32)total_bitrate / (FLOAT32)codec_bitrate : 1.0f; |
218 | | |
219 | 12.6k | split_thr_fac = MAX(split_thr_fac, 0.0001f); |
220 | 12.6k | split_thr_fac = 0.000075f / (split_thr_fac * split_thr_fac); |
221 | | |
222 | 12.6k | pstr_sbr_trans_detector->split_thr = split_thr_fac * br_fac; |
223 | | |
224 | 12.6k | if (is_ld_sbr) { |
225 | 2.97k | WORD32 i; |
226 | 2.97k | FLOAT32 ratio = ((sample_freq / 2) / IXHEAACE_QMF_CHANNELS) * 0.00075275f; |
227 | | |
228 | 2.97k | FLOAT32 tmp = 1024.0f / sample_freq; |
229 | 2.97k | tmp -= 0.01f; |
230 | 2.97k | tmp = MAX(tmp, 0.001f); |
231 | | |
232 | 2.97k | if (1 == frame_flag_480) { |
233 | 1.58k | no_cols = 30; |
234 | 1.58k | buffer_length = 90; |
235 | 1.58k | } |
236 | 2.97k | pstr_sbr_trans_detector->split_thr = (br_fac * 0.000075f) / (tmp * tmp) / 2.0f; |
237 | 2.97k | pstr_sbr_trans_detector->look_ahead = 2; |
238 | 2.97k | pstr_sbr_trans_detector->time_slots = no_cols / 2; |
239 | 2.97k | pstr_sbr_trans_detector->buffer_size = |
240 | 2.97k | pstr_sbr_trans_detector->look_ahead + pstr_sbr_trans_detector->time_slots; |
241 | 2.97k | pstr_sbr_trans_detector->stop_band = |
242 | 2.97k | (WORD32)fmin(13500 / ((sample_freq >> 1) / IXHEAACE_QMF_CHANNELS), IXHEAACE_QMF_CHANNELS); |
243 | 2.97k | pstr_sbr_trans_detector->start_band = |
244 | 2.97k | (WORD32)fmin(start_band, pstr_sbr_trans_detector->stop_band - 4); |
245 | | |
246 | 2.97k | memset(pstr_sbr_trans_detector->energy, 0, |
247 | 2.97k | pstr_sbr_trans_detector->buffer_size * sizeof(pstr_sbr_trans_detector->energy[0])); |
248 | 2.97k | memset(pstr_sbr_trans_detector->sbr_transients, 0, |
249 | 2.97k | pstr_sbr_trans_detector->buffer_size * |
250 | 2.97k | sizeof(pstr_sbr_trans_detector->sbr_transients[0])); |
251 | 2.97k | memset( |
252 | 2.97k | pstr_sbr_trans_detector->delta_energy, 0, |
253 | 2.97k | pstr_sbr_trans_detector->buffer_size * sizeof(pstr_sbr_trans_detector->delta_energy[0])); |
254 | | |
255 | 193k | for (i = 0; i < 64; i++) { |
256 | 190k | pstr_sbr_trans_detector->coeff[i] = (FLOAT32)pow(2.0, ratio * (i + 1)); |
257 | 190k | } |
258 | 2.97k | } |
259 | 12.6k | pstr_sbr_trans_detector->no_cols = no_cols; |
260 | 12.6k | pstr_sbr_trans_detector->tran_fc = tran_fc; |
261 | | |
262 | 12.6k | pstr_sbr_trans_detector->buffer_length = buffer_length; |
263 | | |
264 | 12.6k | pstr_sbr_trans_detector->no_rows = 64; |
265 | 12.6k | pstr_sbr_trans_detector->mode = mode; |
266 | | |
267 | 12.6k | pstr_sbr_trans_detector->prev_low_band_energy = 0; |
268 | 12.6k | pstr_sbr_trans_detector->tran_thr = (FLOAT32)tran_thr; |
269 | | |
270 | 12.6k | pstr_sbr_trans_detector->ptr_thresholds = &(pstr_sbr_trans_detector->sbr_thresholds[0]); |
271 | | |
272 | 12.6k | memset(pstr_sbr_trans_detector->ptr_thresholds, 0, |
273 | 12.6k | sizeof(pstr_sbr_trans_detector->ptr_thresholds[0]) * IXHEAACE_QMF_CHANNELS); |
274 | | |
275 | 12.6k | pstr_sbr_trans_detector->ptr_transients = &(pstr_sbr_trans_detector->sbr_transients[0]); |
276 | 12.6k | memset(pstr_sbr_trans_detector->ptr_transients, 0, |
277 | 12.6k | sizeof(pstr_sbr_trans_detector->ptr_transients[0]) * |
278 | 12.6k | pstr_sbr_trans_detector->buffer_length); |
279 | 12.6k | } |