/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 | 437k | FLOAT32 *ptr_thresholds, ixheaace_sbr_codec_type sbr_codec) { |
42 | 437k | FLOAT32 mean_val, std_val, thr; |
43 | 437k | FLOAT32 *ptr_energy; |
44 | 437k | FLOAT32 inv_num_cols = 1.0f / (FLOAT32)(num_cols + num_cols / 2); |
45 | 437k | FLOAT32 inv_num_cols_1 = 1.0f / (FLOAT32)(num_cols + num_cols / 2 - 1); |
46 | | |
47 | 437k | WORD32 i = 0; |
48 | 437k | WORD32 j; |
49 | | |
50 | 28.4M | while (i < num_rows) { |
51 | 27.9M | mean_val = std_val = 0; |
52 | | |
53 | 27.9M | j = num_cols >> 2; |
54 | 363M | while (j < num_cols) { |
55 | 335M | ptr_energy = &ptr_energies[j][i]; |
56 | 335M | mean_val += (*ptr_energy); |
57 | 335M | ptr_energy += 64; |
58 | 335M | mean_val += (*ptr_energy); |
59 | 335M | j += 2; |
60 | 335M | } |
61 | | |
62 | 27.9M | mean_val *= inv_num_cols * 2.0f; |
63 | | |
64 | 27.9M | j = num_cols >> 2; |
65 | 699M | while (j < num_cols) { |
66 | 671M | FLOAT32 tmp_var; |
67 | 671M | tmp_var = (sbr_codec == HEAAC_SBR) ? mean_val - ptr_energies[j][i] : ptr_energies[j][i]; |
68 | 671M | std_val += tmp_var * tmp_var; |
69 | 671M | j++; |
70 | 671M | } |
71 | | |
72 | 27.9M | std_val = (FLOAT32)((sbr_codec == HEAAC_SBR) |
73 | 27.9M | ? sqrt(std_val * inv_num_cols_1) |
74 | 27.9M | : sqrt(fabs((mean_val * mean_val) - std_val * inv_num_cols * 2.0f))); |
75 | | |
76 | 27.9M | thr = 0.66f * ptr_thresholds[i] + 0.34f * IXHEAACE_SBR_TRAN_STD_FAC * std_val; |
77 | 27.9M | ptr_thresholds[i] = MAX(thr, IXHEAACE_SBR_TRAN_ABS_THR); |
78 | | |
79 | 27.9M | i++; |
80 | 27.9M | } |
81 | 437k | } |
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 | 437k | { |
89 | 437k | WORD32 idx; |
90 | 437k | WORD32 buf_move = buf_len >> 1; |
91 | 437k | FLOAT32 dt_1, dt_2, dt_3, inv_thr; |
92 | 437k | WORD32 len = num_cols + (num_cols >> 1) - 3; |
93 | 437k | WORD32 band = start_band; |
94 | | |
95 | 437k | memmove(ptr_transients, ptr_transients + num_cols, buf_move * sizeof(ptr_transients[0])); |
96 | 437k | memset(ptr_transients + buf_move, 0, (buf_len - buf_move) * sizeof(ptr_transients[0])); |
97 | | |
98 | 28.4M | while (band < stop_band) { |
99 | 27.9M | inv_thr = (FLOAT32)1.0f / ptr_thresholds[band]; |
100 | 27.9M | FLOAT32 temp_energy_1 = ptr_energies[((num_cols >> 1) - 2) / 2][band]; |
101 | 27.9M | FLOAT32 temp_energy_2 = ptr_energies[((num_cols >> 1)) / 2][band]; |
102 | 27.9M | FLOAT32 temp_energy_3 = ptr_energies[((num_cols >> 1) + 2) / 2][band]; |
103 | 1.28G | for (idx = 0; idx < len; idx++) { |
104 | 1.25G | if (!idx) { |
105 | 27.9M | dt_1 = temp_energy_2 - temp_energy_1; |
106 | 27.9M | dt_2 = temp_energy_3 - temp_energy_1; |
107 | 27.9M | dt_3 = temp_energy_3 - ptr_energies[((num_cols >> 1) - 4) / 2][band]; |
108 | 1.23G | } else { |
109 | 1.23G | FLOAT32 temp_energy_4 = ptr_energies[(idx + (num_cols >> 1) + 3) / 2][band]; |
110 | 1.23G | dt_1 = temp_energy_3 - temp_energy_2; |
111 | 1.23G | dt_2 = temp_energy_3 - temp_energy_1 + dt_1; |
112 | 1.23G | dt_3 = temp_energy_4 - temp_energy_1 + dt_2; |
113 | 1.23G | temp_energy_1 = temp_energy_2; |
114 | 1.23G | temp_energy_2 = temp_energy_3; |
115 | 1.23G | temp_energy_3 = temp_energy_4; |
116 | 1.23G | } |
117 | 1.25G | if (dt_1 > ptr_thresholds[band]) { |
118 | 17.8M | ptr_transients[idx + buf_move] += dt_1 * inv_thr - 1.0f; |
119 | 17.8M | } |
120 | 1.25G | if (dt_2 > ptr_thresholds[band]) { |
121 | 41.3M | ptr_transients[idx + buf_move] += dt_2 * inv_thr - 1.0f; |
122 | 41.3M | } |
123 | 1.25G | if (dt_3 > ptr_thresholds[band]) { |
124 | 58.3M | ptr_transients[idx + buf_move] += dt_3 * inv_thr - 1.0f; |
125 | 58.3M | } |
126 | 1.25G | } |
127 | 643M | for (idx = 1; idx < len; idx += 2) { |
128 | 615M | ptr_transients[idx + buf_move + 1] = ptr_transients[idx + buf_move]; |
129 | 615M | } |
130 | 27.9M | band++; |
131 | 27.9M | } |
132 | 437k | } |
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 | 437k | ixheaace_sbr_codec_type sbr_codec) { |
138 | 437k | WORD32 i; |
139 | 437k | WORD32 no_cols = pstr_sbr_trans_det->no_cols; |
140 | 437k | WORD32 qmf_start_sample = no_cols + time_step * 4; |
141 | 437k | FLOAT32 int_thr = (FLOAT32)pstr_sbr_trans_det->tran_thr / (FLOAT32)pstr_sbr_trans_det->no_rows; |
142 | 437k | FLOAT32 *ptr_trans = &(pstr_sbr_trans_det->ptr_transients[qmf_start_sample]); |
143 | | |
144 | 437k | ptr_tran_vector[0] = 0; |
145 | 437k | ptr_tran_vector[1] = 0; |
146 | | |
147 | 437k | ixheaace_calc_thresholds(ptr_energies, pstr_sbr_trans_det->no_cols, pstr_sbr_trans_det->no_rows, |
148 | 437k | pstr_sbr_trans_det->ptr_thresholds, sbr_codec); |
149 | | |
150 | 437k | ixheaace_extract_transient_candidates( |
151 | 437k | ptr_energies, pstr_sbr_trans_det->ptr_thresholds, pstr_sbr_trans_det->ptr_transients, |
152 | 437k | pstr_sbr_trans_det->no_cols, 0, pstr_sbr_trans_det->no_rows, |
153 | 437k | pstr_sbr_trans_det->buffer_length); |
154 | | |
155 | 13.2M | for (i = 0; i < no_cols; i++) { |
156 | 12.9M | if ((ptr_trans[i] < 0.9f * ptr_trans[i - 1]) && (ptr_trans[i - 1] > int_thr)) { |
157 | 84.9k | ptr_tran_vector[0] = (WORD32)floor(i / time_step); |
158 | 84.9k | ptr_tran_vector[1] = 1; |
159 | 84.9k | break; |
160 | 84.9k | } |
161 | 12.9M | } |
162 | 437k | } |
163 | | |
164 | | static VOID ixheaace_calc_thresholds_4_1(FLOAT32 **ptr_energies, WORD32 num_cols, WORD32 num_rows, |
165 | 64.3k | FLOAT32 *ptr_thresholds, WORD32 time_step) { |
166 | 64.3k | FLOAT32 mean_val, std_val, thr; |
167 | 64.3k | FLOAT32 *ptr_energy; |
168 | 64.3k | FLOAT32 inv_num_cols = 1.0f / (FLOAT32)((num_cols + num_cols / 2) / time_step); |
169 | 64.3k | FLOAT32 inv_num_cols_1 = 1.0f / (FLOAT32)((num_cols + num_cols / 2 - 1) / time_step); |
170 | | |
171 | 64.3k | WORD32 i = 0; |
172 | 64.3k | WORD32 j; |
173 | 64.3k | WORD32 start_band = 8; |
174 | 64.3k | WORD32 end_band = 32; |
175 | | |
176 | 4.18M | while (i < num_rows) { |
177 | 4.11M | mean_val = std_val = 0; |
178 | | |
179 | 4.11M | j = start_band; |
180 | 102M | while (j < end_band) { |
181 | 98.8M | ptr_energy = &ptr_energies[j][i]; |
182 | 98.8M | mean_val += (*ptr_energy); |
183 | 98.8M | j++; |
184 | 98.8M | } |
185 | | |
186 | 4.11M | mean_val *= inv_num_cols; |
187 | | |
188 | 4.11M | j = start_band; |
189 | 102M | while (j < end_band) { |
190 | 98.8M | FLOAT32 tmp_var; |
191 | 98.8M | tmp_var = mean_val - ptr_energies[j][i]; |
192 | 98.8M | std_val += tmp_var * tmp_var; |
193 | 98.8M | j++; |
194 | 98.8M | } |
195 | | |
196 | 4.11M | std_val = (FLOAT32)sqrt(std_val * inv_num_cols_1); |
197 | | |
198 | 4.11M | thr = 0.66f * ptr_thresholds[i] + 0.34f * IXHEAACE_SBR_TRAN_STD_FAC * std_val; |
199 | 4.11M | ptr_thresholds[i] = MAX(thr, IXHEAACE_SBR_TRAN_ABS_THR); |
200 | | |
201 | 4.11M | i++; |
202 | 4.11M | } |
203 | 64.3k | } |
204 | | |
205 | | static VOID ixheaace_extract_transient_candidates_4_1(FLOAT32 **ptr_energies, |
206 | | FLOAT32 *ptr_thresholds, |
207 | | FLOAT32 *ptr_transients, WORD32 num_cols, |
208 | | WORD32 start_band, WORD32 stop_band, |
209 | | WORD32 time_step) |
210 | | |
211 | 64.3k | { |
212 | 64.3k | WORD32 idx; |
213 | 64.3k | WORD32 buf_move = num_cols / 2; |
214 | 64.3k | WORD32 band = start_band; |
215 | | |
216 | 64.3k | memmove(ptr_transients, ptr_transients + num_cols, buf_move * sizeof(ptr_transients[0])); |
217 | 64.3k | memset(ptr_transients + buf_move, 0, num_cols * sizeof(ptr_transients[0])); |
218 | | |
219 | 4.18M | while (band < stop_band) { |
220 | 267M | for (idx = buf_move; idx < num_cols + buf_move; idx++) { |
221 | 263M | float l = 0, r = 0; |
222 | 1.05G | for (int d = 1; d < 4; d++) { |
223 | 790M | l = ptr_energies[(idx - d) / time_step][band]; |
224 | 790M | r = ptr_energies[(idx + d) / time_step][band]; |
225 | 790M | if (r - l > ptr_thresholds[band]) |
226 | 6.15M | ptr_transients[idx] += (r - l - ptr_thresholds[band]) / ptr_thresholds[band]; |
227 | 790M | } |
228 | 263M | } |
229 | 4.11M | band++; |
230 | 4.11M | } |
231 | 64.3k | } |
232 | | |
233 | | VOID ixheaace_detect_transient_4_1(FLOAT32 **ptr_energies, |
234 | | ixheaace_pstr_sbr_trans_detector pstr_sbr_trans_det, |
235 | 64.3k | WORD32 *ptr_tran_vector, WORD32 time_step) { |
236 | 64.3k | WORD32 i; |
237 | 64.3k | WORD32 no_cols = pstr_sbr_trans_det->no_cols; |
238 | 64.3k | WORD32 qmf_start_sample = time_step * 4; |
239 | 64.3k | FLOAT32 int_thr = (FLOAT32)pstr_sbr_trans_det->tran_thr / (FLOAT32)pstr_sbr_trans_det->no_rows; |
240 | 64.3k | FLOAT32 *ptr_trans = &(pstr_sbr_trans_det->ptr_transients[qmf_start_sample]); |
241 | | |
242 | 64.3k | ptr_tran_vector[0] = 0; |
243 | 64.3k | ptr_tran_vector[1] = 0; |
244 | | |
245 | 64.3k | ixheaace_calc_thresholds_4_1(ptr_energies, pstr_sbr_trans_det->no_cols, |
246 | 64.3k | pstr_sbr_trans_det->no_rows, pstr_sbr_trans_det->ptr_thresholds, |
247 | 64.3k | time_step); |
248 | | |
249 | 64.3k | ixheaace_extract_transient_candidates_4_1( |
250 | 64.3k | ptr_energies, pstr_sbr_trans_det->ptr_thresholds, pstr_sbr_trans_det->ptr_transients, |
251 | 64.3k | pstr_sbr_trans_det->no_cols, 0, pstr_sbr_trans_det->no_rows, time_step); |
252 | | |
253 | 3.99M | for (i = 0; i < no_cols; i++) { |
254 | 3.93M | if ((ptr_trans[i] < 0.9f * ptr_trans[i - 1]) && (ptr_trans[i - 1] > int_thr)) { |
255 | 6.43k | ptr_tran_vector[0] = (WORD32)floor(i / time_step); |
256 | 6.43k | ptr_tran_vector[1] = 1; |
257 | 6.43k | break; |
258 | 6.43k | } |
259 | 3.93M | } |
260 | 64.3k | } |
261 | | |
262 | | VOID ixheaace_detect_transient_eld(FLOAT32 **ptr_energies, |
263 | | ixheaace_pstr_sbr_trans_detector pstr_sbr_trans_det, |
264 | 173k | WORD32 *ptr_tran_vector) { |
265 | 173k | WORD32 i, band; |
266 | 173k | WORD32 max_idx = 0, is_transient = 0; |
267 | 173k | FLOAT32 delta_max = 0, tmp, min_energy; |
268 | 173k | WORD32 num_slots = pstr_sbr_trans_det->time_slots; |
269 | 173k | WORD32 look_ahead = pstr_sbr_trans_det->look_ahead; |
270 | 173k | WORD32 start_band = pstr_sbr_trans_det->start_band; |
271 | 173k | WORD32 stop_band = pstr_sbr_trans_det->stop_band; |
272 | 173k | FLOAT32 *ptr_energy = pstr_sbr_trans_det->energy; |
273 | 173k | FLOAT32 *ptr_delta_energy = pstr_sbr_trans_det->delta_energy; |
274 | 173k | FLOAT32 *ptr_transients = pstr_sbr_trans_det->ptr_transients; |
275 | 173k | WORD32 ts = look_ahead; |
276 | 173k | FLOAT32 weighted_energy; |
277 | | |
278 | 173k | ptr_tran_vector[0] = ptr_tran_vector[1] = 0; |
279 | 173k | ptr_tran_vector[2] = 0; |
280 | | |
281 | 173k | memset(ptr_transients + look_ahead, 0, num_slots * sizeof(ptr_transients[0])); |
282 | | |
283 | 2.86M | while (ts < num_slots + look_ahead) { |
284 | 2.69M | tmp = 0.0f; |
285 | 2.69M | max_idx = 0; |
286 | 2.69M | delta_max = 0; |
287 | 2.69M | is_transient = 0; |
288 | 2.69M | i = 0; |
289 | 2.69M | band = start_band; |
290 | | |
291 | 61.9M | while (band < stop_band) { |
292 | 59.2M | tmp += (ptr_energies[ts][band] * pstr_sbr_trans_det->coeff[i]); |
293 | 59.2M | band++; |
294 | 59.2M | i++; |
295 | 59.2M | } |
296 | | |
297 | 2.69M | ptr_energy[ts] = tmp; |
298 | 2.69M | min_energy = (ptr_energy[ts - 1]) + IXHEAACE_SMALL_ENERGY; |
299 | 2.69M | ptr_delta_energy[ts] = ptr_energy[ts] / min_energy; |
300 | | |
301 | 2.69M | weighted_energy = ptr_energy[ts] * (1.0f / 1.4f); |
302 | | |
303 | 2.69M | if ((ptr_delta_energy[ts] >= IXHEAACE_TRANSIENT_THRESHOLD) && |
304 | 2.69M | (((ptr_transients[ts - 2] == 0) && (ptr_transients[ts - 1] == 0)) || |
305 | 70.6k | (weighted_energy >= ptr_energy[ts - 1]) || (weighted_energy >= ptr_energy[ts - 2]))) { |
306 | 70.6k | ptr_transients[ts] = 1; |
307 | 70.6k | } |
308 | | |
309 | 2.69M | ts++; |
310 | 2.69M | } |
311 | | |
312 | 2.86M | for (ts = 0; ts < num_slots; ts++) { |
313 | 2.69M | if (ptr_transients[ts] && (ptr_delta_energy[ts] > delta_max)) { |
314 | 56.5k | delta_max = ptr_delta_energy[ts]; |
315 | 56.5k | max_idx = ts; |
316 | 56.5k | is_transient = 1; |
317 | 56.5k | } |
318 | 2.69M | } |
319 | | |
320 | 173k | if (is_transient) { |
321 | 54.0k | ptr_tran_vector[0] = max_idx; |
322 | 54.0k | ptr_tran_vector[1] = 1; |
323 | 54.0k | } |
324 | | |
325 | 520k | for (ts = 0; ts < look_ahead; ts++) { |
326 | 346k | if (ptr_transients[ts + num_slots]) { |
327 | 2.43k | ptr_tran_vector[2] = 1; |
328 | 2.43k | } |
329 | 346k | ptr_energy[ts] = ptr_energy[num_slots + ts]; |
330 | 346k | ptr_transients[ts] = ptr_transients[num_slots + ts]; |
331 | 346k | ptr_delta_energy[ts] = ptr_delta_energy[num_slots + ts]; |
332 | 346k | } |
333 | 173k | } |