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
ixheaace_calc_thresholds(FLOAT32 ** ptr_energies,WORD32 num_cols,WORD32 num_rows,FLOAT32 * ptr_thresholds,ixheaace_sbr_codec_type sbr_codec)40 static VOID ixheaace_calc_thresholds(FLOAT32 **ptr_energies, WORD32 num_cols, WORD32 num_rows,
41 FLOAT32 *ptr_thresholds, ixheaace_sbr_codec_type sbr_codec) {
42 FLOAT32 mean_val, std_val, thr;
43 FLOAT32 *ptr_energy;
44 FLOAT32 inv_num_cols = 1.0f / (FLOAT32)(num_cols + num_cols / 2);
45 FLOAT32 inv_num_cols_1 = 1.0f / (FLOAT32)(num_cols + num_cols / 2 - 1);
46
47 WORD32 i = 0;
48 WORD32 j;
49
50 while (i < num_rows) {
51 mean_val = std_val = 0;
52
53 j = num_cols >> 2;
54 while (j < num_cols) {
55 ptr_energy = &ptr_energies[j][i];
56 mean_val += (*ptr_energy);
57 ptr_energy += 64;
58 mean_val += (*ptr_energy);
59 j += 2;
60 }
61
62 mean_val *= inv_num_cols * 2.0f;
63
64 j = num_cols >> 2;
65 while (j < num_cols) {
66 FLOAT32 tmp_var;
67 tmp_var = (sbr_codec == HEAAC_SBR) ? mean_val - ptr_energies[j][i] : ptr_energies[j][i];
68 std_val += tmp_var * tmp_var;
69 j++;
70 }
71
72 std_val = (FLOAT32)((sbr_codec == HEAAC_SBR)
73 ? sqrt(std_val * inv_num_cols_1)
74 : sqrt(fabs((mean_val * mean_val) - std_val * inv_num_cols * 2.0f)));
75
76 thr = 0.66f * ptr_thresholds[i] + 0.34f * IXHEAACE_SBR_TRAN_STD_FAC * std_val;
77 ptr_thresholds[i] = MAX(thr, IXHEAACE_SBR_TRAN_ABS_THR);
78
79 i++;
80 }
81 }
82
ixheaace_extract_transient_candidates(FLOAT32 ** ptr_energies,FLOAT32 * ptr_thresholds,FLOAT32 * ptr_transients,WORD32 num_cols,WORD32 start_band,WORD32 stop_band,WORD32 buf_len)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 {
89 WORD32 idx;
90 WORD32 buf_move = buf_len >> 1;
91 FLOAT32 dt_1, dt_2, dt_3, inv_thr;
92 WORD32 len = num_cols + (num_cols >> 1) - 3;
93 WORD32 band = start_band;
94
95 memmove(ptr_transients, ptr_transients + num_cols, buf_move * sizeof(ptr_transients[0]));
96 memset(ptr_transients + buf_move, 0, (buf_len - buf_move) * sizeof(ptr_transients[0]));
97
98 while (band < stop_band) {
99 inv_thr = (FLOAT32)1.0f / ptr_thresholds[band];
100 FLOAT32 temp_energy_1 = ptr_energies[((num_cols >> 1) - 2) / 2][band];
101 FLOAT32 temp_energy_2 = ptr_energies[((num_cols >> 1)) / 2][band];
102 FLOAT32 temp_energy_3 = ptr_energies[((num_cols >> 1) + 2) / 2][band];
103 for (idx = 0; idx < len; idx++) {
104 if (!idx) {
105 dt_1 = temp_energy_2 - temp_energy_1;
106 dt_2 = temp_energy_3 - temp_energy_1;
107 dt_3 = temp_energy_3 - ptr_energies[((num_cols >> 1) - 4) / 2][band];
108 } else {
109 FLOAT32 temp_energy_4 = ptr_energies[(idx + (num_cols >> 1) + 3) / 2][band];
110 dt_1 = temp_energy_3 - temp_energy_2;
111 dt_2 = temp_energy_3 - temp_energy_1 + dt_1;
112 dt_3 = temp_energy_4 - temp_energy_1 + dt_2;
113 temp_energy_1 = temp_energy_2;
114 temp_energy_2 = temp_energy_3;
115 temp_energy_3 = temp_energy_4;
116 }
117 if (dt_1 > ptr_thresholds[band]) {
118 ptr_transients[idx + buf_move] += dt_1 * inv_thr - 1.0f;
119 }
120 if (dt_2 > ptr_thresholds[band]) {
121 ptr_transients[idx + buf_move] += dt_2 * inv_thr - 1.0f;
122 }
123 if (dt_3 > ptr_thresholds[band]) {
124 ptr_transients[idx + buf_move] += dt_3 * inv_thr - 1.0f;
125 }
126 }
127 for (idx = 1; idx < len; idx += 2) {
128 ptr_transients[idx + buf_move + 1] = ptr_transients[idx + buf_move];
129 }
130 band++;
131 }
132 }
133
ixheaace_detect_transient(FLOAT32 ** ptr_energies,ixheaace_pstr_sbr_trans_detector pstr_sbr_trans_det,WORD32 * ptr_tran_vector,WORD32 time_step,ixheaace_sbr_codec_type sbr_codec)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 ixheaace_sbr_codec_type sbr_codec) {
138 WORD32 i;
139 WORD32 no_cols = pstr_sbr_trans_det->no_cols;
140 WORD32 qmf_start_sample = no_cols + time_step * 4;
141 FLOAT32 int_thr = (FLOAT32)pstr_sbr_trans_det->tran_thr / (FLOAT32)pstr_sbr_trans_det->no_rows;
142 FLOAT32 *ptr_trans = &(pstr_sbr_trans_det->ptr_transients[qmf_start_sample]);
143
144 ptr_tran_vector[0] = 0;
145 ptr_tran_vector[1] = 0;
146
147 ixheaace_calc_thresholds(ptr_energies, pstr_sbr_trans_det->no_cols, pstr_sbr_trans_det->no_rows,
148 pstr_sbr_trans_det->ptr_thresholds, sbr_codec);
149
150 ixheaace_extract_transient_candidates(
151 ptr_energies, pstr_sbr_trans_det->ptr_thresholds, pstr_sbr_trans_det->ptr_transients,
152 pstr_sbr_trans_det->no_cols, 0, pstr_sbr_trans_det->no_rows,
153 pstr_sbr_trans_det->buffer_length);
154
155 for (i = 0; i < no_cols; i++) {
156 if ((ptr_trans[i] < 0.9f * ptr_trans[i - 1]) && (ptr_trans[i - 1] > int_thr)) {
157 ptr_tran_vector[0] = (WORD32)floor(i / time_step);
158 ptr_tran_vector[1] = 1;
159 break;
160 }
161 }
162 }
163
ixheaace_detect_transient_eld(FLOAT32 ** ptr_energies,ixheaace_pstr_sbr_trans_detector pstr_sbr_trans_det,WORD32 * ptr_tran_vector)164 VOID ixheaace_detect_transient_eld(FLOAT32 **ptr_energies,
165 ixheaace_pstr_sbr_trans_detector pstr_sbr_trans_det,
166 WORD32 *ptr_tran_vector) {
167 WORD32 i, band;
168 WORD32 max_idx = 0, is_transient = 0;
169 FLOAT32 delta_max = 0, tmp, min_energy;
170 WORD32 num_slots = pstr_sbr_trans_det->time_slots;
171 WORD32 look_ahead = pstr_sbr_trans_det->look_ahead;
172 WORD32 start_band = pstr_sbr_trans_det->start_band;
173 WORD32 stop_band = pstr_sbr_trans_det->stop_band;
174 FLOAT32 *ptr_energy = pstr_sbr_trans_det->energy;
175 FLOAT32 *ptr_delta_energy = pstr_sbr_trans_det->delta_energy;
176 FLOAT32 *ptr_transients = pstr_sbr_trans_det->ptr_transients;
177 WORD32 ts = look_ahead;
178 FLOAT32 weighted_energy;
179
180 ptr_tran_vector[0] = ptr_tran_vector[1] = 0;
181 ptr_tran_vector[2] = 0;
182
183 memset(ptr_transients + look_ahead, 0, num_slots * sizeof(ptr_transients[0]));
184
185 while (ts < num_slots + look_ahead) {
186 tmp = 0.0f;
187 max_idx = 0;
188 delta_max = 0;
189 is_transient = 0;
190 i = 0;
191 band = start_band;
192
193 while (band < stop_band) {
194 tmp += (ptr_energies[ts][band] * pstr_sbr_trans_det->coeff[i]);
195 band++;
196 i++;
197 }
198
199 ptr_energy[ts] = tmp;
200 min_energy = (ptr_energy[ts - 1]) + IXHEAACE_SMALL_ENERGY;
201 ptr_delta_energy[ts] = ptr_energy[ts] / min_energy;
202
203 weighted_energy = ptr_energy[ts] * (1.0f / 1.4f);
204
205 if ((ptr_delta_energy[ts] >= IXHEAACE_TRANSIENT_THRESHOLD) &&
206 (((ptr_transients[ts - 2] == 0) && (ptr_transients[ts - 1] == 0)) ||
207 (weighted_energy >= ptr_energy[ts - 1]) || (weighted_energy >= ptr_energy[ts - 2]))) {
208 ptr_transients[ts] = 1;
209 }
210
211 ts++;
212 }
213
214 for (ts = 0; ts < num_slots; ts++) {
215 if (ptr_transients[ts] && (ptr_delta_energy[ts] > delta_max)) {
216 delta_max = ptr_delta_energy[ts];
217 max_idx = ts;
218 is_transient = 1;
219 }
220 }
221
222 if (is_transient) {
223 ptr_tran_vector[0] = max_idx;
224 ptr_tran_vector[1] = 1;
225 }
226
227 for (ts = 0; ts < look_ahead; ts++) {
228 if (ptr_transients[ts + num_slots]) {
229 ptr_tran_vector[2] = 1;
230 }
231 ptr_energy[ts] = ptr_energy[num_slots + ts];
232 ptr_transients[ts] = ptr_transients[num_slots + ts];
233 ptr_delta_energy[ts] = ptr_delta_energy[num_slots + ts];
234 }
235 }
236