xref: /aosp_15_r20/external/libxaac/encoder/ixheaace_sbr_tran_det_hp.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_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