Coverage Report

Created: 2025-08-24 07:17

/src/libxaac/encoder/ixheaace_tns.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 <stdlib.h>
22
#include <math.h>
23
#include <string.h>
24
#include "ixheaac_type_def.h"
25
#include "ixheaac_constants.h"
26
#include "ixheaace_aac_constants.h"
27
28
#include "ixheaac_basic_ops32.h"
29
#include "ixheaac_basic_ops16.h"
30
#include "ixheaac_basic_ops40.h"
31
#include "ixheaac_basic_ops.h"
32
#include "ixheaac_error_standards.h"
33
34
#include "ixheaace_common_rom.h"
35
#include "ixheaace_psy_const.h"
36
#include "ixheaace_tns.h"
37
#include "ixheaace_tns_params.h"
38
#include "ixheaace_rom.h"
39
#include "ixheaace_bitbuffer.h"
40
#include "ixheaace_psy_configuration.h"
41
#include "ixheaace_tns_func.h"
42
#include "ixheaace_error_codes.h"
43
#include "ixheaace_common_utils.h"
44
45
static VOID ia_enhaacplus_enc_auto_to_parcor(const FLOAT32 *ptr_input, FLOAT32 *ptr_refl_coeff,
46
                                             WORD32 num_coeff, FLOAT32 *ptr_work_buffer,
47
888k
                                             FLOAT32 *prediction_gain) {
48
888k
  WORD32 i, j;
49
888k
  FLOAT32 *ptr_work_buf_tmp, tmp_var;
50
51
888k
  memset(ptr_refl_coeff, 0, num_coeff * sizeof(*ptr_refl_coeff));
52
53
888k
  if (ptr_input[0] == 0) {
54
59.6k
    return;
55
59.6k
  }
56
57
829k
  ptr_work_buffer[0] = ptr_input[0];
58
5.92M
  for (i = 1; i < num_coeff; i++) {
59
5.09M
    tmp_var = ptr_input[i];
60
5.09M
    ptr_work_buffer[i] = tmp_var;
61
5.09M
    ptr_work_buffer[i + num_coeff - 1] = tmp_var;
62
5.09M
  }
63
829k
  ptr_work_buffer[i + num_coeff - 1] = ptr_input[i];
64
65
6.75M
  for (i = 0; i < num_coeff; i++) {
66
5.92M
    FLOAT32 refc, tmp;
67
68
5.92M
    tmp = ptr_work_buffer[num_coeff + i];
69
70
5.92M
    if (tmp < 0.f) {
71
3.21M
      tmp = -tmp;
72
3.21M
    }
73
74
5.92M
    if ((ptr_work_buffer[0]) < tmp) {
75
0
      break;
76
0
    }
77
78
5.92M
    if (ptr_work_buffer[0] == 0.f) {
79
0
      refc = 0;
80
5.92M
    } else {
81
5.92M
      refc = (tmp / ptr_work_buffer[0]);
82
5.92M
    }
83
84
5.92M
    if (ptr_work_buffer[num_coeff + i] > 0.f) {
85
2.67M
      refc = -refc;
86
2.67M
    }
87
88
5.92M
    ptr_refl_coeff[i] = refc;
89
90
5.92M
    ptr_work_buf_tmp = &(ptr_work_buffer[num_coeff]);
91
92
34.3M
    for (j = i; j < num_coeff; j++) {
93
28.4M
      FLOAT32 accu1, accu2;
94
95
28.4M
      accu1 = (refc * ptr_work_buffer[j - i]);
96
28.4M
      accu1 = (accu1) + ptr_work_buf_tmp[j];
97
98
28.4M
      accu2 = (refc * ptr_work_buf_tmp[j]);
99
28.4M
      accu2 = accu2 + ptr_work_buffer[j - i];
100
101
28.4M
      ptr_work_buf_tmp[j] = accu1;
102
28.4M
      ptr_work_buffer[j - i] = accu2;
103
28.4M
    }
104
5.92M
  }
105
106
829k
  *prediction_gain = (ptr_input[0] / ptr_work_buffer[0]);
107
829k
}
108
109
static IA_ERRORCODE ia_enhaacplus_enc_calc_tns_filter(const FLOAT32 *ptr_signal,
110
                                                      const FLOAT32 *ptr_window, WORD32 num_lines,
111
                                                      WORD32 tns_order, FLOAT32 *ptr_parcor,
112
888k
                                                      FLOAT32 *prediction_gain) {
113
888k
  FLOAT32 auto_corr_buf[TEMPORAL_NOISE_SHAPING_MAX_ORDER + 1];
114
888k
  FLOAT32 par_cor_buf[2 * TEMPORAL_NOISE_SHAPING_MAX_ORDER];
115
888k
  WORD32 i;
116
117
888k
  if (tns_order > TEMPORAL_NOISE_SHAPING_MAX_ORDER) {
118
0
    return IA_EXHEAACE_EXE_FATAL_INVALID_TNS_FILT_ORDER;
119
0
  }
120
121
888k
  memset(&auto_corr_buf[0], 0, (tns_order + 1) * sizeof(auto_corr_buf[0]));
122
123
888k
  ia_enhaacplus_enc_auto_correlation(ptr_signal, auto_corr_buf, num_lines, tns_order + 1);
124
125
888k
  if (ptr_window) {
126
8.26M
    for (i = 0; i < tns_order + 1; i++) {
127
7.37M
      auto_corr_buf[i] = (auto_corr_buf[i] * ptr_window[i]);
128
7.37M
    }
129
888k
  }
130
131
888k
  ia_enhaacplus_enc_auto_to_parcor(auto_corr_buf, ptr_parcor, tns_order, par_cor_buf,
132
888k
                                   prediction_gain);
133
134
888k
  return IA_NO_ERROR;
135
888k
}
136
137
IA_ERRORCODE ia_enhaacplus_enc_tns_detect(ixheaace_temporal_noise_shaping_data *pstr_tns_data,
138
                                          ixheaace_temporal_noise_shaping_config tns_config,
139
                                          FLOAT32 *ptr_scratch_tns, const WORD32 *ptr_sfb_offset,
140
                                          FLOAT32 *ptr_spectrum, WORD32 sub_blk_num,
141
                                          WORD32 block_type, WORD32 aot, FLOAT32 *ptr_sfb_energy,
142
                                          FLOAT32 *ptr_shared_buffer1, WORD32 long_frame_len)
143
144
1.23M
{
145
1.23M
  FLOAT32 prediction_gain = 0;
146
1.23M
  FLOAT32 *ptr_weighted_spec = ptr_scratch_tns + sub_blk_num * long_frame_len;
147
1.23M
  WORD i;
148
1.23M
  FLOAT32 *ptr_weighted_spec_new = ptr_weighted_spec;
149
1.23M
  IA_ERRORCODE error_code = IA_NO_ERROR;
150
151
1.23M
  if (tns_config.tns_active) {
152
888k
    ia_enhaacplus_enc_calc_weighted_spectrum(ptr_spectrum, ptr_weighted_spec, ptr_sfb_energy,
153
888k
                                             ptr_sfb_offset, tns_config.lpc_start_line,
154
888k
                                             tns_config.lpc_stop_line, tns_config.lpc_start_band,
155
888k
                                             tns_config.lpc_stop_band, ptr_shared_buffer1, aot);
156
157
11.5M
    for (i = tns_config.lpc_stop_line; i < (tns_config.lpc_stop_line + 12); i++) {
158
10.6M
      ptr_weighted_spec_new[i] = 0;
159
10.6M
    }
160
161
888k
    if (block_type != SHORT_WINDOW) {
162
291k
      error_code = ia_enhaacplus_enc_calc_tns_filter(
163
291k
          &ptr_weighted_spec_new[tns_config.lpc_start_line], tns_config.acf_window_float,
164
291k
          tns_config.lpc_stop_line - tns_config.lpc_start_line, tns_config.max_order,
165
291k
          pstr_tns_data->data_raw.tns_data_long.sub_block_info.parcor, &prediction_gain);
166
167
291k
      if (error_code != IA_NO_ERROR) {
168
0
        return error_code;
169
0
      }
170
291k
      pstr_tns_data->data_raw.tns_data_long.sub_block_info.tns_active =
171
291k
          ((prediction_gain) > tns_config.threshold) ? 1 : 0;
172
173
291k
      pstr_tns_data->data_raw.tns_data_long.sub_block_info.prediction_gain = prediction_gain;
174
597k
    } else {
175
597k
      error_code = ia_enhaacplus_enc_calc_tns_filter(
176
597k
          &ptr_weighted_spec_new[tns_config.lpc_start_line], tns_config.acf_window_float,
177
597k
          tns_config.lpc_stop_line - tns_config.lpc_start_line, tns_config.max_order,
178
597k
          pstr_tns_data->data_raw.tns_data_short.sub_block_info[sub_blk_num].parcor,
179
597k
          &prediction_gain);
180
181
597k
      if (error_code != IA_NO_ERROR) {
182
0
        return error_code;
183
0
      }
184
185
597k
      pstr_tns_data->data_raw.tns_data_short.sub_block_info[sub_blk_num].tns_active =
186
597k
          ((prediction_gain) > tns_config.threshold) ? 1 : 0;
187
188
597k
      pstr_tns_data->data_raw.tns_data_short.sub_block_info[sub_blk_num].prediction_gain =
189
597k
          prediction_gain;
190
597k
    }
191
888k
  } else {
192
345k
    if (block_type != SHORT_WINDOW) {
193
157k
      pstr_tns_data->data_raw.tns_data_long.sub_block_info.tns_active = 0;
194
157k
      pstr_tns_data->data_raw.tns_data_long.sub_block_info.prediction_gain = 0.f;
195
188k
    } else {
196
188k
      pstr_tns_data->data_raw.tns_data_short.sub_block_info[sub_blk_num].tns_active = 0;
197
188k
      pstr_tns_data->data_raw.tns_data_short.sub_block_info[sub_blk_num].prediction_gain = 0.f;
198
188k
    }
199
345k
  }
200
1.23M
  return error_code;
201
1.23M
}
202
203
VOID ia_enhaacplus_enc_tns_sync(ixheaace_temporal_noise_shaping_data *pstr_tns_data_dst,
204
                                const ixheaace_temporal_noise_shaping_data *pstr_tns_data_src,
205
                                const ixheaace_temporal_noise_shaping_config tns_config,
206
445k
                                const WORD32 sub_blk_num, const WORD32 block_type) {
207
445k
  if (block_type != SHORT_WINDOW) {
208
128k
    ixheaace_temporal_noise_shaping_subblock_info_long *pstr_sfb_info_dst;
209
128k
    const ixheaace_temporal_noise_shaping_subblock_info_long *pstr_sfb_info_src;
210
211
128k
    pstr_sfb_info_dst = &pstr_tns_data_dst->data_raw.tns_data_long.sub_block_info;
212
128k
    pstr_sfb_info_src = &pstr_tns_data_src->data_raw.tns_data_long.sub_block_info;
213
128k
    FLOAT32 tmp_var = pstr_sfb_info_dst->prediction_gain;
214
128k
    if (fabs(tmp_var - pstr_sfb_info_src->prediction_gain) < (tmp_var * 0.03f)) {
215
61.0k
      pstr_sfb_info_dst->tns_active = pstr_sfb_info_src->tns_active;
216
217
61.0k
      memcpy(pstr_sfb_info_dst->parcor, pstr_sfb_info_src->parcor,
218
61.0k
             tns_config.max_order * sizeof(pstr_sfb_info_dst->parcor[0]));
219
61.0k
    }
220
317k
  } else {
221
317k
    ixheaace_temporal_noise_shaping_subblock_info_short *pstr_sfb_info_dst;
222
317k
    const ixheaace_temporal_noise_shaping_subblock_info_short *pstr_sfb_info_src;
223
317k
    pstr_sfb_info_dst = &pstr_tns_data_dst->data_raw.tns_data_short.sub_block_info[sub_blk_num];
224
317k
    pstr_sfb_info_src = &pstr_tns_data_src->data_raw.tns_data_short.sub_block_info[sub_blk_num];
225
226
317k
    FLOAT32 tmp_var = pstr_sfb_info_dst->prediction_gain;
227
317k
    if (fabs(tmp_var - pstr_sfb_info_src->prediction_gain) < (tmp_var * 0.03f)) {
228
203k
      pstr_sfb_info_dst->tns_active = pstr_sfb_info_src->tns_active;
229
230
203k
      memcpy(pstr_sfb_info_dst->parcor, pstr_sfb_info_src->parcor,
231
203k
             tns_config.max_order * sizeof(pstr_sfb_info_dst->parcor[0]));
232
203k
    }
233
317k
  }
234
445k
}
235
236
static WORD32 ia_enhaacplus_enc_index_search3(
237
1.08M
    FLOAT32 parcor, ixheaace_temporal_noise_shaping_tables *pstr_tns_tab) {
238
1.08M
  WORD32 index = 0;
239
1.08M
  WORD32 i;
240
241
9.73M
  for (i = 0; i < 8; i++) {
242
8.65M
    if (parcor > pstr_tns_tab->tns_coeff_3_borders[i]) {
243
5.54M
      index = i;
244
5.54M
    }
245
8.65M
  }
246
247
1.08M
  return (index - 4);
248
1.08M
}
249
static WORD32 ia_enhaacplus_enc_index_search4(
250
2.65M
    FLOAT32 parcor, ixheaace_temporal_noise_shaping_tables *pstr_tns_tab) {
251
2.65M
  WORD32 index = 0;
252
2.65M
  WORD32 i;
253
45.1M
  for (i = 0; i < 16; i++) {
254
42.5M
    if (parcor > pstr_tns_tab->tns_coeff_4_borders[i]) {
255
25.1M
      index = i;
256
25.1M
    }
257
42.5M
  }
258
259
2.65M
  return (index - 8);
260
2.65M
}
261
262
static VOID ia_enhaacplus_enc_parcor_to_index(
263
    const FLOAT32 *ptr_parcor, WORD32 *ptr_index, WORD32 order, WORD32 bits_per_coeff,
264
437k
    ixheaace_temporal_noise_shaping_tables *pstr_tns_tab) {
265
437k
  WORD32 i;
266
267
437k
  if (bits_per_coeff == 3) {
268
1.29M
    for (i = order - 1; i >= 0; i--) {
269
1.08M
      ptr_index[i] = ia_enhaacplus_enc_index_search3(ptr_parcor[i], pstr_tns_tab);
270
1.08M
    }
271
221k
  } else {
272
2.87M
    for (i = order - 1; i >= 0; i--) {
273
2.65M
      ptr_index[i] = ia_enhaacplus_enc_index_search4(ptr_parcor[i], pstr_tns_tab);
274
2.65M
    }
275
221k
  }
276
437k
}
277
278
static VOID ia_enhaacplus_enc_index_to_parcor(
279
    const WORD32 *ptr_index, FLOAT32 *ptr_parcor, WORD32 order, WORD32 bits_per_coeff,
280
437k
    ixheaace_temporal_noise_shaping_tables *pstr_tns_tab) {
281
437k
  WORD32 i;
282
283
437k
  if (bits_per_coeff == 4) {
284
2.87M
    for (i = order - 1; i >= 0; i--) {
285
2.65M
      ptr_parcor[i] = pstr_tns_tab->tns_coeff_4[ptr_index[i] + 8];
286
2.65M
    }
287
221k
  } else {
288
1.29M
    for (i = order - 1; i >= 0; i--) {
289
1.08M
      ptr_parcor[i] = pstr_tns_tab->tns_coeff_3[ptr_index[i] + 4];
290
1.08M
    }
291
216k
  }
292
437k
}
293
294
VOID ia_enhaacplus_enc_tns_encode(ixheaace_temporal_noise_shaping_params *pstr_tns_info,
295
                                    ixheaace_temporal_noise_shaping_data *pstr_tns_data,
296
                                    WORD32 num_sfb,
297
                                    ixheaace_temporal_noise_shaping_config tns_config,
298
                                    WORD32 lowpass_line, FLOAT32 *ptr_spectrum,
299
                                    WORD32 sub_blk_num, WORD32 block_type,
300
1.23M
                                    ixheaace_temporal_noise_shaping_tables *pstr_tns_tab) {
301
1.23M
  WORD32 i;
302
1.23M
  FLOAT32 *ptr_parcor;
303
304
1.23M
  if (block_type != SHORT_WINDOW) {
305
449k
    if (pstr_tns_data->data_raw.tns_data_long.sub_block_info.tns_active == 0) {
306
227k
      pstr_tns_info->tns_active[sub_blk_num] = 0;
307
227k
      return;
308
227k
    } else {
309
221k
      ia_enhaacplus_enc_parcor_to_index(
310
221k
          pstr_tns_data->data_raw.tns_data_long.sub_block_info.parcor, &pstr_tns_info->coef[0],
311
221k
          tns_config.max_order, tns_config.coef_res, pstr_tns_tab);
312
313
221k
      ia_enhaacplus_enc_index_to_parcor(
314
221k
          &pstr_tns_info->coef[0], pstr_tns_data->data_raw.tns_data_long.sub_block_info.parcor,
315
221k
          tns_config.max_order, tns_config.coef_res, pstr_tns_tab);
316
317
221k
      ptr_parcor =
318
221k
          &pstr_tns_data->data_raw.tns_data_long.sub_block_info.parcor[tns_config.max_order - 1];
319
320
1.05M
      for (i = tns_config.max_order - 1; i >= 0; i--) {
321
1.05M
        FLOAT32 tmp_var = *ptr_parcor--;
322
323
1.05M
        if (tmp_var > 0.1f || tmp_var < -0.1f) {
324
221k
          break;
325
221k
        }
326
1.05M
      }
327
221k
      pstr_tns_info->order[sub_blk_num] = i + 1;
328
329
221k
      pstr_tns_info->tns_active[sub_blk_num] = 1;
330
331
1.77M
      for (i = sub_blk_num + 1; i < TRANS_FAC; i++) {
332
1.55M
        pstr_tns_info->tns_active[i] = 0;
333
1.55M
      }
334
335
221k
      pstr_tns_info->coef_res[sub_blk_num] = (WORD8)tns_config.coef_res;
336
337
221k
      pstr_tns_info->length[sub_blk_num] = num_sfb - tns_config.tns_start_band;
338
339
221k
      ia_enhaacplus_enc_analysis_filter_lattice(
340
221k
          &(ptr_spectrum[tns_config.tns_start_line]),
341
221k
          MIN(tns_config.tns_stop_line, lowpass_line) - tns_config.tns_start_line,
342
221k
          pstr_tns_data->data_raw.tns_data_long.sub_block_info.parcor,
343
221k
          pstr_tns_info->order[sub_blk_num], &(ptr_spectrum[tns_config.tns_start_line]));
344
221k
    }
345
449k
  } else /*short block*/
346
785k
  {
347
785k
    if (pstr_tns_data->data_raw.tns_data_short.sub_block_info[sub_blk_num].tns_active == 0) {
348
569k
      pstr_tns_info->tns_active[sub_blk_num] = 0;
349
350
569k
      return;
351
569k
    } else {
352
216k
      ia_enhaacplus_enc_parcor_to_index(
353
216k
          pstr_tns_data->data_raw.tns_data_short.sub_block_info[sub_blk_num].parcor,
354
216k
          &pstr_tns_info->coef[sub_blk_num * TEMPORAL_NOISE_SHAPING_MAX_ORDER_SHORT],
355
216k
          tns_config.max_order, tns_config.coef_res, pstr_tns_tab);
356
357
216k
      ia_enhaacplus_enc_index_to_parcor(
358
216k
          &pstr_tns_info->coef[sub_blk_num * TEMPORAL_NOISE_SHAPING_MAX_ORDER_SHORT],
359
216k
          pstr_tns_data->data_raw.tns_data_short.sub_block_info[sub_blk_num].parcor,
360
216k
          tns_config.max_order, tns_config.coef_res, pstr_tns_tab);
361
362
216k
      ptr_parcor = &pstr_tns_data->data_raw.tns_data_short.sub_block_info[sub_blk_num]
363
216k
                        .parcor[tns_config.max_order - 1];
364
727k
      for (i = tns_config.max_order - 1; i >= 0; i--) {
365
727k
        FLOAT32 tmp_var = *ptr_parcor--;
366
727k
        if (tmp_var > 0.1f || tmp_var < -0.1f) {
367
216k
          break;
368
216k
        }
369
727k
      }
370
371
216k
      pstr_tns_info->order[sub_blk_num] = i + 1;
372
373
216k
      pstr_tns_info->tns_active[sub_blk_num] = 1;
374
375
216k
      pstr_tns_info->coef_res[sub_blk_num] = (WORD8)tns_config.coef_res;
376
377
216k
      pstr_tns_info->length[sub_blk_num] = num_sfb - tns_config.tns_start_band;
378
379
216k
      ia_enhaacplus_enc_analysis_filter_lattice(
380
216k
          &(ptr_spectrum[tns_config.tns_start_line]),
381
216k
          tns_config.tns_stop_line - tns_config.tns_start_line,
382
216k
          pstr_tns_data->data_raw.tns_data_short.sub_block_info[sub_blk_num].parcor,
383
216k
          pstr_tns_info->order[sub_blk_num], &(ptr_spectrum[tns_config.tns_start_line]));
384
216k
    }
385
785k
  }
386
387
437k
  return;
388
1.23M
}
389
390
VOID ia_enhaacplus_enc_apply_tns_mult_table_to_ratios(WORD32 start_cb, WORD32 stop_cb,
391
437k
                                                      FLOAT32 *ptr_thresholds) {
392
437k
  WORD32 i;
393
394
3.91M
  for (i = start_cb; i < stop_cb; i++) {
395
3.47M
    ptr_thresholds[i] = (FLOAT32)(ptr_thresholds[i] * 0.25f);
396
3.47M
  }
397
437k
}