/src/libxaac/encoder/ixheaace_sbr_tran_det_hp.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_basic_ops32.h" |
27 | | #include "ixheaac_basic_ops16.h" |
28 | | #include "ixheaac_basic_ops40.h" |
29 | | #include "ixheaac_basic_ops.h" |
30 | | |
31 | | #include "ixheaace_common_rom.h" |
32 | | #include "ixheaace_sbr_header.h" |
33 | | #include "ixheaace_sbr_def.h" |
34 | | #include "ixheaace_resampler.h" |
35 | | #include "ixheaace_sbr_rom.h" |
36 | | #include "ixheaace_sbr_tran_det.h" |
37 | | #include "ixheaace_sbr_main.h" |
38 | | #include "ixheaace_sbr_frame_info_gen.h" |
39 | | |
40 | | static VOID ixheaace_calc_thresholds(FLOAT32 **ptr_energies, WORD32 num_cols, WORD32 num_rows, |
41 | 366k | FLOAT32 *ptr_thresholds, ixheaace_sbr_codec_type sbr_codec) { |
42 | 366k | FLOAT32 mean_val, std_val, thr; |
43 | 366k | FLOAT32 *ptr_energy; |
44 | 366k | FLOAT32 inv_num_cols = 1.0f / (FLOAT32)(num_cols + num_cols / 2); |
45 | 366k | FLOAT32 inv_num_cols_1 = 1.0f / (FLOAT32)(num_cols + num_cols / 2 - 1); |
46 | | |
47 | 366k | WORD32 i = 0; |
48 | 366k | WORD32 j; |
49 | | |
50 | 23.8M | while (i < num_rows) { |
51 | 23.4M | mean_val = std_val = 0; |
52 | | |
53 | 23.4M | j = num_cols >> 2; |
54 | 304M | while (j < num_cols) { |
55 | 281M | ptr_energy = &ptr_energies[j][i]; |
56 | 281M | mean_val += (*ptr_energy); |
57 | 281M | ptr_energy += 64; |
58 | 281M | mean_val += (*ptr_energy); |
59 | 281M | j += 2; |
60 | 281M | } |
61 | | |
62 | 23.4M | mean_val *= inv_num_cols * 2.0f; |
63 | | |
64 | 23.4M | j = num_cols >> 2; |
65 | 586M | while (j < num_cols) { |
66 | 563M | FLOAT32 tmp_var; |
67 | 563M | tmp_var = (sbr_codec == HEAAC_SBR) ? mean_val - ptr_energies[j][i] : ptr_energies[j][i]; |
68 | 563M | std_val += tmp_var * tmp_var; |
69 | 563M | j++; |
70 | 563M | } |
71 | | |
72 | 23.4M | std_val = (FLOAT32)((sbr_codec == HEAAC_SBR) |
73 | 23.4M | ? sqrt(std_val * inv_num_cols_1) |
74 | 23.4M | : sqrt(fabs((mean_val * mean_val) - std_val * inv_num_cols * 2.0f))); |
75 | | |
76 | 23.4M | thr = 0.66f * ptr_thresholds[i] + 0.34f * IXHEAACE_SBR_TRAN_STD_FAC * std_val; |
77 | 23.4M | ptr_thresholds[i] = MAX(thr, IXHEAACE_SBR_TRAN_ABS_THR); |
78 | | |
79 | 23.4M | i++; |
80 | 23.4M | } |
81 | 366k | } |
82 | | |
83 | | static VOID ixheaace_extract_transient_candidates(FLOAT32 **ptr_energies, FLOAT32 *ptr_thresholds, |
84 | | FLOAT32 *ptr_transients, WORD32 num_cols, |
85 | | WORD32 start_band, WORD32 stop_band, |
86 | | WORD32 buf_len) |
87 | | |
88 | 366k | { |
89 | 366k | WORD32 idx; |
90 | 366k | WORD32 buf_move = buf_len >> 1; |
91 | 366k | FLOAT32 dt_1, dt_2, dt_3, inv_thr; |
92 | 366k | WORD32 len = num_cols + (num_cols >> 1) - 3; |
93 | 366k | WORD32 band = start_band; |
94 | | |
95 | 366k | memmove(ptr_transients, ptr_transients + num_cols, buf_move * sizeof(ptr_transients[0])); |
96 | 366k | memset(ptr_transients + buf_move, 0, (buf_len - buf_move) * sizeof(ptr_transients[0])); |
97 | | |
98 | 23.8M | while (band < stop_band) { |
99 | 23.4M | inv_thr = (FLOAT32)1.0f / ptr_thresholds[band]; |
100 | 23.4M | FLOAT32 temp_energy_1 = ptr_energies[((num_cols >> 1) - 2) / 2][band]; |
101 | 23.4M | FLOAT32 temp_energy_2 = ptr_energies[((num_cols >> 1)) / 2][band]; |
102 | 23.4M | FLOAT32 temp_energy_3 = ptr_energies[((num_cols >> 1) + 2) / 2][band]; |
103 | 1.07G | for (idx = 0; idx < len; idx++) { |
104 | 1.05G | if (!idx) { |
105 | 23.4M | dt_1 = temp_energy_2 - temp_energy_1; |
106 | 23.4M | dt_2 = temp_energy_3 - temp_energy_1; |
107 | 23.4M | dt_3 = temp_energy_3 - ptr_energies[((num_cols >> 1) - 4) / 2][band]; |
108 | 1.03G | } else { |
109 | 1.03G | FLOAT32 temp_energy_4 = ptr_energies[(idx + (num_cols >> 1) + 3) / 2][band]; |
110 | 1.03G | dt_1 = temp_energy_3 - temp_energy_2; |
111 | 1.03G | dt_2 = temp_energy_3 - temp_energy_1 + dt_1; |
112 | 1.03G | dt_3 = temp_energy_4 - temp_energy_1 + dt_2; |
113 | 1.03G | temp_energy_1 = temp_energy_2; |
114 | 1.03G | temp_energy_2 = temp_energy_3; |
115 | 1.03G | temp_energy_3 = temp_energy_4; |
116 | 1.03G | } |
117 | 1.05G | if (dt_1 > ptr_thresholds[band]) { |
118 | 15.4M | ptr_transients[idx + buf_move] += dt_1 * inv_thr - 1.0f; |
119 | 15.4M | } |
120 | 1.05G | if (dt_2 > ptr_thresholds[band]) { |
121 | 35.8M | ptr_transients[idx + buf_move] += dt_2 * inv_thr - 1.0f; |
122 | 35.8M | } |
123 | 1.05G | if (dt_3 > ptr_thresholds[band]) { |
124 | 50.5M | ptr_transients[idx + buf_move] += dt_3 * inv_thr - 1.0f; |
125 | 50.5M | } |
126 | 1.05G | } |
127 | 539M | for (idx = 1; idx < len; idx += 2) { |
128 | 516M | ptr_transients[idx + buf_move + 1] = ptr_transients[idx + buf_move]; |
129 | 516M | } |
130 | 23.4M | band++; |
131 | 23.4M | } |
132 | 366k | } |
133 | | |
134 | | VOID ixheaace_detect_transient(FLOAT32 **ptr_energies, |
135 | | ixheaace_pstr_sbr_trans_detector pstr_sbr_trans_det, |
136 | | WORD32 *ptr_tran_vector, WORD32 time_step, |
137 | 366k | ixheaace_sbr_codec_type sbr_codec) { |
138 | 366k | WORD32 i; |
139 | 366k | WORD32 no_cols = pstr_sbr_trans_det->no_cols; |
140 | 366k | WORD32 qmf_start_sample = no_cols + time_step * 4; |
141 | 366k | FLOAT32 int_thr = (FLOAT32)pstr_sbr_trans_det->tran_thr / (FLOAT32)pstr_sbr_trans_det->no_rows; |
142 | 366k | FLOAT32 *ptr_trans = &(pstr_sbr_trans_det->ptr_transients[qmf_start_sample]); |
143 | | |
144 | 366k | ptr_tran_vector[0] = 0; |
145 | 366k | ptr_tran_vector[1] = 0; |
146 | | |
147 | 366k | ixheaace_calc_thresholds(ptr_energies, pstr_sbr_trans_det->no_cols, pstr_sbr_trans_det->no_rows, |
148 | 366k | pstr_sbr_trans_det->ptr_thresholds, sbr_codec); |
149 | | |
150 | 366k | ixheaace_extract_transient_candidates( |
151 | 366k | ptr_energies, pstr_sbr_trans_det->ptr_thresholds, pstr_sbr_trans_det->ptr_transients, |
152 | 366k | pstr_sbr_trans_det->no_cols, 0, pstr_sbr_trans_det->no_rows, |
153 | 366k | pstr_sbr_trans_det->buffer_length); |
154 | | |
155 | 11.1M | for (i = 0; i < no_cols; i++) { |
156 | 10.8M | if ((ptr_trans[i] < 0.9f * ptr_trans[i - 1]) && (ptr_trans[i - 1] > int_thr)) { |
157 | 71.1k | ptr_tran_vector[0] = (WORD32)floor(i / time_step); |
158 | 71.1k | ptr_tran_vector[1] = 1; |
159 | 71.1k | break; |
160 | 71.1k | } |
161 | 10.8M | } |
162 | 366k | } |
163 | | |
164 | | static VOID ixheaace_calc_thresholds_4_1(FLOAT32 **ptr_energies, WORD32 num_cols, WORD32 num_rows, |
165 | | FLOAT32 *ptr_thresholds, |
166 | 62.6k | ixheaace_sbr_codec_type sbr_codec, WORD32 time_step) { |
167 | 62.6k | FLOAT32 mean_val, std_val, thr; |
168 | 62.6k | FLOAT32 *ptr_energy; |
169 | 62.6k | FLOAT32 inv_num_cols = 1.0f / (FLOAT32)((num_cols + num_cols / 2) / time_step); |
170 | 62.6k | FLOAT32 inv_num_cols_1 = 1.0f / (FLOAT32)((num_cols + num_cols / 2 - 1) / time_step); |
171 | | |
172 | 62.6k | WORD32 i = 0; |
173 | 62.6k | WORD32 j; |
174 | 62.6k | WORD32 start_band = 8; |
175 | 62.6k | WORD32 end_band = 32; |
176 | | |
177 | 4.07M | while (i < num_rows) { |
178 | 4.01M | mean_val = std_val = 0; |
179 | | |
180 | 4.01M | j = start_band; |
181 | 100M | while (j < end_band) { |
182 | 96.3M | ptr_energy = &ptr_energies[j][i]; |
183 | 96.3M | mean_val += (*ptr_energy); |
184 | 96.3M | j++; |
185 | 96.3M | } |
186 | | |
187 | 4.01M | mean_val *= inv_num_cols; |
188 | | |
189 | 4.01M | j = start_band; |
190 | 100M | while (j < end_band) { |
191 | 96.3M | FLOAT32 tmp_var; |
192 | 96.3M | tmp_var = mean_val - ptr_energies[j][i]; |
193 | 96.3M | std_val += tmp_var * tmp_var; |
194 | 96.3M | j++; |
195 | 96.3M | } |
196 | | |
197 | 4.01M | std_val = (FLOAT32)sqrt(std_val * inv_num_cols_1); |
198 | | |
199 | 4.01M | thr = 0.66f * ptr_thresholds[i] + 0.34f * IXHEAACE_SBR_TRAN_STD_FAC * std_val; |
200 | 4.01M | ptr_thresholds[i] = MAX(thr, IXHEAACE_SBR_TRAN_ABS_THR); |
201 | | |
202 | 4.01M | i++; |
203 | 4.01M | } |
204 | 62.6k | } |
205 | | |
206 | | static VOID ixheaace_extract_transient_candidates_4_1(FLOAT32 **ptr_energies, |
207 | | FLOAT32 *ptr_thresholds, |
208 | | FLOAT32 *ptr_transients, WORD32 num_cols, |
209 | | WORD32 start_band, WORD32 stop_band, |
210 | | WORD32 buf_len, WORD32 time_step) |
211 | | |
212 | 62.6k | { |
213 | 62.6k | WORD32 idx; |
214 | 62.6k | WORD32 buf_move = num_cols / 2; |
215 | 62.6k | WORD32 band = start_band; |
216 | | |
217 | 62.6k | memmove(ptr_transients, ptr_transients + num_cols, buf_move * sizeof(ptr_transients[0])); |
218 | 62.6k | memset(ptr_transients + buf_move, 0, num_cols * sizeof(ptr_transients[0])); |
219 | | |
220 | 4.07M | while (band < stop_band) { |
221 | 260M | for (idx = buf_move; idx < num_cols + buf_move; idx++) { |
222 | 256M | float l = 0, r = 0; |
223 | 1.02G | for (int d = 1; d < 4; d++) { |
224 | 770M | l = ptr_energies[(idx - d) / time_step][band]; |
225 | 770M | r = ptr_energies[(idx + d) / time_step][band]; |
226 | 770M | if (r - l > ptr_thresholds[band]) |
227 | 4.26M | ptr_transients[idx] += (r - l - ptr_thresholds[band]) / ptr_thresholds[band]; |
228 | 770M | } |
229 | 256M | } |
230 | 4.01M | band++; |
231 | 4.01M | } |
232 | 62.6k | } |
233 | | |
234 | | VOID ixheaace_detect_transient_4_1(FLOAT32 **ptr_energies, |
235 | | ixheaace_pstr_sbr_trans_detector pstr_sbr_trans_det, |
236 | | WORD32 *ptr_tran_vector, WORD32 time_step, |
237 | 62.6k | ixheaace_sbr_codec_type sbr_codec) { |
238 | 62.6k | WORD32 i; |
239 | 62.6k | WORD32 no_cols = pstr_sbr_trans_det->no_cols; |
240 | 62.6k | WORD32 qmf_start_sample = time_step * 4; |
241 | 62.6k | FLOAT32 int_thr = (FLOAT32)pstr_sbr_trans_det->tran_thr / (FLOAT32)pstr_sbr_trans_det->no_rows; |
242 | 62.6k | FLOAT32 *ptr_trans = &(pstr_sbr_trans_det->ptr_transients[qmf_start_sample]); |
243 | | |
244 | 62.6k | ptr_tran_vector[0] = 0; |
245 | 62.6k | ptr_tran_vector[1] = 0; |
246 | | |
247 | 62.6k | ixheaace_calc_thresholds_4_1(ptr_energies, pstr_sbr_trans_det->no_cols, |
248 | 62.6k | pstr_sbr_trans_det->no_rows, pstr_sbr_trans_det->ptr_thresholds, |
249 | 62.6k | sbr_codec, time_step); |
250 | | |
251 | 62.6k | ixheaace_extract_transient_candidates_4_1( |
252 | 62.6k | ptr_energies, pstr_sbr_trans_det->ptr_thresholds, pstr_sbr_trans_det->ptr_transients, |
253 | 62.6k | pstr_sbr_trans_det->no_cols, 0, pstr_sbr_trans_det->no_rows, |
254 | 62.6k | pstr_sbr_trans_det->buffer_length, time_step); |
255 | | |
256 | 3.98M | for (i = 0; i < no_cols; i++) { |
257 | 3.92M | if ((ptr_trans[i] < 0.9f * ptr_trans[i - 1]) && (ptr_trans[i - 1] > int_thr)) { |
258 | 3.91k | ptr_tran_vector[0] = (WORD32)floor(i / time_step); |
259 | 3.91k | ptr_tran_vector[1] = 1; |
260 | 3.91k | break; |
261 | 3.91k | } |
262 | 3.92M | } |
263 | 62.6k | } |
264 | | |
265 | | VOID ixheaace_detect_transient_eld(FLOAT32 **ptr_energies, |
266 | | ixheaace_pstr_sbr_trans_detector pstr_sbr_trans_det, |
267 | 143k | WORD32 *ptr_tran_vector) { |
268 | 143k | WORD32 i, band; |
269 | 143k | WORD32 max_idx = 0, is_transient = 0; |
270 | 143k | FLOAT32 delta_max = 0, tmp, min_energy; |
271 | 143k | WORD32 num_slots = pstr_sbr_trans_det->time_slots; |
272 | 143k | WORD32 look_ahead = pstr_sbr_trans_det->look_ahead; |
273 | 143k | WORD32 start_band = pstr_sbr_trans_det->start_band; |
274 | 143k | WORD32 stop_band = pstr_sbr_trans_det->stop_band; |
275 | 143k | FLOAT32 *ptr_energy = pstr_sbr_trans_det->energy; |
276 | 143k | FLOAT32 *ptr_delta_energy = pstr_sbr_trans_det->delta_energy; |
277 | 143k | FLOAT32 *ptr_transients = pstr_sbr_trans_det->ptr_transients; |
278 | 143k | WORD32 ts = look_ahead; |
279 | 143k | FLOAT32 weighted_energy; |
280 | | |
281 | 143k | ptr_tran_vector[0] = ptr_tran_vector[1] = 0; |
282 | 143k | ptr_tran_vector[2] = 0; |
283 | | |
284 | 143k | memset(ptr_transients + look_ahead, 0, num_slots * sizeof(ptr_transients[0])); |
285 | | |
286 | 2.35M | while (ts < num_slots + look_ahead) { |
287 | 2.21M | tmp = 0.0f; |
288 | 2.21M | max_idx = 0; |
289 | 2.21M | delta_max = 0; |
290 | 2.21M | is_transient = 0; |
291 | 2.21M | i = 0; |
292 | 2.21M | band = start_band; |
293 | | |
294 | 50.5M | while (band < stop_band) { |
295 | 48.3M | tmp += (ptr_energies[ts][band] * pstr_sbr_trans_det->coeff[i]); |
296 | 48.3M | band++; |
297 | 48.3M | i++; |
298 | 48.3M | } |
299 | | |
300 | 2.21M | ptr_energy[ts] = tmp; |
301 | 2.21M | min_energy = (ptr_energy[ts - 1]) + IXHEAACE_SMALL_ENERGY; |
302 | 2.21M | ptr_delta_energy[ts] = ptr_energy[ts] / min_energy; |
303 | | |
304 | 2.21M | weighted_energy = ptr_energy[ts] * (1.0f / 1.4f); |
305 | | |
306 | 2.21M | if ((ptr_delta_energy[ts] >= IXHEAACE_TRANSIENT_THRESHOLD) && |
307 | 2.21M | (((ptr_transients[ts - 2] == 0) && (ptr_transients[ts - 1] == 0)) || |
308 | 48.3k | (weighted_energy >= ptr_energy[ts - 1]) || (weighted_energy >= ptr_energy[ts - 2]))) { |
309 | 48.3k | ptr_transients[ts] = 1; |
310 | 48.3k | } |
311 | | |
312 | 2.21M | ts++; |
313 | 2.21M | } |
314 | | |
315 | 2.35M | for (ts = 0; ts < num_slots; ts++) { |
316 | 2.21M | if (ptr_transients[ts] && (ptr_delta_energy[ts] > delta_max)) { |
317 | 38.6k | delta_max = ptr_delta_energy[ts]; |
318 | 38.6k | max_idx = ts; |
319 | 38.6k | is_transient = 1; |
320 | 38.6k | } |
321 | 2.21M | } |
322 | | |
323 | 143k | if (is_transient) { |
324 | 36.4k | ptr_tran_vector[0] = max_idx; |
325 | 36.4k | ptr_tran_vector[1] = 1; |
326 | 36.4k | } |
327 | | |
328 | 429k | for (ts = 0; ts < look_ahead; ts++) { |
329 | 286k | if (ptr_transients[ts + num_slots]) { |
330 | 1.93k | ptr_tran_vector[2] = 1; |
331 | 1.93k | } |
332 | 286k | ptr_energy[ts] = ptr_energy[num_slots + ts]; |
333 | 286k | ptr_transients[ts] = ptr_transients[num_slots + ts]; |
334 | 286k | ptr_delta_energy[ts] = ptr_delta_energy[num_slots + ts]; |
335 | 286k | } |
336 | 143k | } |