Coverage Report

Created: 2025-07-18 06:38

/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
}