Coverage Report

Created: 2025-08-03 06:57

/src/libxaac/encoder/iusace_fd_fac.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 "ixheaace_adjust_threshold_data.h"
25
#include "iusace_bitbuffer.h"
26
#include "ixheaace_mps_common_define.h"
27
/* DRC */
28
#include "impd_drc_common_enc.h"
29
#include "impd_drc_uni_drc.h"
30
#include "impd_drc_tables.h"
31
#include "impd_drc_api.h"
32
#include "impd_drc_uni_drc_eq.h"
33
#include "impd_drc_uni_drc_filter_bank.h"
34
#include "impd_drc_gain_enc.h"
35
#include "impd_drc_struct_def.h"
36
37
#include "iusace_cnst.h"
38
#include "iusace_tns_usac.h"
39
#include "iusace_psy_mod.h"
40
#include "iusace_ms.h"
41
#include "iusace_fd_qc_util.h"
42
#include "ixheaace_memory_standards.h"
43
#include "iusace_config.h"
44
#include "iusace_tcx_mdct.h"
45
#include "iusace_arith_enc.h"
46
#include "iusace_fd_quant.h"
47
#include "iusace_signal_classifier.h"
48
#include "iusace_block_switch_const.h"
49
#include "iusace_block_switch_struct_def.h"
50
#include "ixheaace_sbr_header.h"
51
#include "ixheaace_config.h"
52
#include "ixheaace_asc_write.h"
53
#include "iusace_main.h"
54
#include "iusace_func_prototypes.h"
55
#include "iusace_lpd_rom.h"
56
#include "iusace_lpd.h"
57
#include "iusace_avq_enc.h"
58
#include "ixheaac_error_standards.h"
59
#include "ixheaace_error_codes.h"
60
61
static VOID iusace_decode_fd_fac(WORD32 *ptr_fac_prms, WORD32 len_subfrm, WORD32 fac_len,
62
                                 FLOAT32 *ptr_lpc_coeffs, FLOAT32 *zir_sig, FLOAT32 *ptr_fac_dec,
63
3.89k
                                 iusace_scratch_mem *pstr_scratch) {
64
3.89k
  FLOAT32 *x = pstr_scratch->p_x;
65
3.89k
  FLOAT32 *xn2 = pstr_scratch->p_xn_2;
66
3.89k
  FLOAT32 fac_gain;
67
3.89k
  WORD32 i;
68
3.89k
  const FLOAT32 *sin_window;
69
3.89k
  FLOAT32 *fac_window = pstr_scratch->p_fac_window;
70
3.89k
  FLOAT32 ap[ORDER + 1];
71
72
3.89k
  if (fac_len == 64) {
73
0
    sin_window = iusace_sin_window_128;
74
3.89k
  } else {
75
3.89k
    sin_window = iusace_sin_window_256;
76
3.89k
  }
77
78
3.89k
  if (ptr_lpc_coeffs != NULL && ptr_fac_dec != NULL) {
79
3.89k
    fac_gain = (FLOAT32)pow(10.0f, ((FLOAT32)ptr_fac_prms[0]) / 28.0f);
80
469k
    for (i = 0; i < fac_len; i++) {
81
465k
      x[i] = (FLOAT32)ptr_fac_prms[i + 1] * fac_gain;
82
465k
    }
83
84
3.89k
    iusace_tcx_mdct(x, xn2, fac_len, pstr_scratch);
85
86
3.89k
    iusace_get_weighted_lpc(ptr_lpc_coeffs, ap);
87
88
3.89k
    memset(xn2 + fac_len, 0, fac_len * sizeof(FLOAT32));
89
3.89k
    iusace_synthesis_tool_float(ap, xn2, ptr_fac_dec, 2 * fac_len, xn2 + fac_len,
90
3.89k
                                pstr_scratch->p_buf_synthesis_tool);
91
92
3.89k
    if (zir_sig != NULL) {
93
0
      for (i = 0; i < fac_len; i++) {
94
0
        fac_window[i] = sin_window[i] * sin_window[(2 * fac_len) - 1 - i];
95
0
        fac_window[fac_len + i] = 1.0f - (sin_window[fac_len + i] * sin_window[fac_len + i]);
96
0
      }
97
0
      for (i = 0; i < fac_len; i++) {
98
0
        ptr_fac_dec[i] += zir_sig[1 + (len_subfrm / 2) + i] * fac_window[fac_len + i] +
99
0
                          zir_sig[1 + (len_subfrm / 2) - 1 - i] * fac_window[fac_len - 1 - i];
100
0
      }
101
0
    }
102
3.89k
  }
103
104
3.89k
  return;
105
3.89k
}
106
107
VOID iusace_fac_apply(FLOAT32 *orig, WORD32 len_subfrm, WORD32 fac_len, WORD32 low_pass_line,
108
                      WORD32 target_br, FLOAT32 *synth, FLOAT32 *ptr_lpc_coeffs,
109
                      WORD16 *fac_bits_word, WORD32 *num_fac_bits,
110
3.89k
                      iusace_scratch_mem *pstr_scratch) {
111
3.89k
  FLOAT32 *xn2 = pstr_scratch->p_xn2;
112
3.89k
  FLOAT32 *fac_dec = pstr_scratch->p_fac_dec;
113
3.89k
  FLOAT32 *right_fac_spec = pstr_scratch->p_right_fac_spec;
114
3.89k
  FLOAT32 *x2 = pstr_scratch->p_x2;
115
3.89k
  WORD32 *param = pstr_scratch->p_param;
116
3.89k
  FLOAT32 ap[ORDER + 1];
117
3.89k
  FLOAT32 fac_gain;
118
3.89k
  WORD32 i, index;
119
3.89k
  WORD32 num_enc_bits = 0;
120
3.89k
  WORD32 start_right = 2 * len_subfrm - fac_len;
121
122
3.89k
  *num_fac_bits = 0;
123
124
3.89k
  memset(xn2, 0, (FAC_LENGTH + ORDER) * sizeof(FLOAT32));
125
126
3.89k
  memcpy(xn2 + ORDER, &orig[start_right], fac_len * sizeof(FLOAT32));
127
469k
  for (i = 0; i < fac_len; i++) {
128
465k
    xn2[ORDER + i] -= synth[start_right + i];
129
465k
  }
130
131
3.89k
  iusace_get_weighted_lpc(ptr_lpc_coeffs, ap);
132
3.89k
  iusace_compute_lp_residual(ap, xn2 + ORDER, x2, fac_len);
133
469k
  for (i = 0; i < fac_len; i++) {
134
465k
    x2[i] = x2[i] * (2.0f / (FLOAT32)fac_len);
135
465k
  }
136
137
3.89k
  iusace_tcx_mdct(x2, right_fac_spec, fac_len, pstr_scratch);
138
139
3.89k
  memset(&right_fac_spec[low_pass_line], 0, (fac_len - low_pass_line) * sizeof(FLOAT32));
140
141
3.89k
  fac_gain = iusace_calc_sq_gain(right_fac_spec, target_br, fac_len, pstr_scratch->p_sq_gain_en);
142
3.89k
  index = (WORD32)floor(0.5f + (28.0f * (FLOAT32)log10(fac_gain)));
143
3.89k
  if (index < 0) index = 0;
144
3.89k
  if (index > 127) index = 127;
145
3.89k
  param[0] = index;
146
3.89k
  fac_gain = (FLOAT32)pow(10.0f, ((FLOAT32)index) / 28.0f);
147
469k
  for (i = 0; i < fac_len; i++) right_fac_spec[i] /= fac_gain;
148
149
62.1k
  for (i = 0; i < fac_len; i += 8) {
150
58.2k
    iusace_find_nearest_neighbor(&right_fac_spec[i], &param[i + 1]);
151
58.2k
  }
152
153
3.89k
  iusace_write_bits2buf(index, 7, fac_bits_word);
154
3.89k
  num_enc_bits += 7;
155
3.89k
  num_enc_bits += iusace_fd_encode_fac(&param[1], &fac_bits_word[7], fac_len);
156
3.89k
  iusace_decode_fd_fac(&param[0], len_subfrm, fac_len, ptr_lpc_coeffs, NULL, fac_dec,
157
3.89k
                       pstr_scratch);
158
3.89k
  *num_fac_bits = num_enc_bits;
159
160
469k
  for (i = 0; i < fac_len; i++) {
161
465k
    synth[start_right + i] += fac_dec[i];
162
465k
  }
163
3.89k
  return;
164
3.89k
}
165
166
IA_ERRORCODE iusace_fd_fac(WORD32 *sfb_offsets, WORD32 sfb_active, FLOAT64 *orig_sig_dbl,
167
                           WORD32 window_sequence, FLOAT64 *synth_time,
168
                           ia_usac_td_encoder_struct *pstr_acelp, WORD32 last_subfr_was_acelp,
169
                           WORD32 next_frm_lpd, WORD16 *fac_prm_out, WORD32 *num_fac_bits,
170
319k
                           iusace_scratch_mem *pstr_scratch) {
171
319k
  const FLOAT32 *sin_window = NULL;
172
319k
  LOOPIDX i;
173
319k
  FLOAT32 *zir_sig = NULL;
174
319k
  FLOAT32 *lpc_coeffs_q = NULL;
175
319k
  WORD32 index;
176
319k
  WORD32 low_pass_line = 0;
177
319k
  WORD32 fac_len;
178
319k
  FLOAT64 *left_fac_time_data = pstr_scratch->p_left_fac_time_data;
179
319k
  FLOAT32 *left_fac_timedata_flt = pstr_scratch->p_left_fac_timedata_flt;
180
319k
  FLOAT32 *left_fac_spec = pstr_scratch->p_left_fac_spec;
181
319k
  FLOAT64 *fac_win = pstr_scratch->p_fac_win;
182
319k
  WORD32 *fac_prm = pstr_scratch->p_fac_prm;
183
319k
  WORD16 *fac_bits_word = pstr_scratch->p_fac_bits_word;
184
319k
  FLOAT32 *acelp_folded = pstr_scratch->p_acelp_folded_scratch;
185
186
319k
  *num_fac_bits = 0;
187
188
319k
  if (last_subfr_was_acelp || next_frm_lpd)
189
4.41k
  {
190
4.41k
    if (window_sequence == EIGHT_SHORT_SEQUENCE)
191
1.05k
      fac_len = (pstr_acelp->len_frame / 16);
192
3.36k
    else
193
3.36k
      fac_len = (pstr_acelp->len_frame / 8);
194
195
4.41k
    low_pass_line = (WORD32)(sfb_offsets[sfb_active] * fac_len /
196
4.41k
      (FLOAT32)pstr_acelp->len_frame);
197
4.41k
  }
198
199
319k
  if (last_subfr_was_acelp) {
200
1.19k
    FLOAT32 *tmp_lp_res = pstr_scratch->ptr_tmp_lp_res;
201
1.19k
    FLOAT32 lpc_coeffs[ORDER + 1];
202
1.19k
    FLOAT32 ener, fac_gain;
203
1.19k
    WORD32 left_start;
204
205
1.19k
    switch (fac_len) {
206
56
      case 48:
207
56
        sin_window = iusace_sin_window_96;
208
56
        break;
209
523
      case 64:
210
523
        sin_window = iusace_sin_window_128;
211
523
        break;
212
149
      case 96:
213
149
        sin_window = iusace_sin_window_192;
214
149
        break;
215
468
      case 128:
216
468
        sin_window = iusace_sin_window_256;
217
468
        break;
218
0
      default:
219
0
        return IA_EXHEAACE_EXE_FATAL_USAC_INVALID_FAC_LEN;
220
1.19k
    }
221
222
111k
    for (i = 0; i < fac_len; i++) {
223
110k
      fac_win[i] = sin_window[i] * sin_window[(2 * fac_len) - 1 - i];
224
110k
      fac_win[fac_len + i] = 1.0f - (sin_window[fac_len + i] * sin_window[fac_len + i]);
225
110k
    }
226
227
1.19k
    left_start = (pstr_acelp->len_frame / 2) - fac_len - ORDER;
228
229
241k
    for (i = 0; i < 2 * fac_len + ORDER; i++) {
230
239k
      left_fac_time_data[i] = orig_sig_dbl[left_start + i];
231
239k
    }
232
233
111k
    for (i = 0; i < fac_len; i++) {
234
110k
      left_fac_time_data[fac_len + ORDER + i] =
235
110k
          left_fac_time_data[fac_len + ORDER + i] - synth_time[left_start + fac_len + ORDER + i];
236
110k
    }
237
238
1.19k
    zir_sig = pstr_acelp->lpd_state.tcx_quant;
239
240
20.3k
    for (i = 0; i < ORDER; i++) {
241
19.1k
      left_fac_time_data[fac_len + i] =
242
19.1k
          left_fac_time_data[fac_len + i] - zir_sig[1 + 128 - ORDER + i];
243
19.1k
    }
244
245
111k
    for (i = 0; i < fac_len; i++) {
246
110k
      acelp_folded[i] = zir_sig[1 + 128 + i] * (FLOAT32)fac_win[fac_len + i] +
247
110k
                        zir_sig[1 + 128 - 1 - i] * (FLOAT32)fac_win[fac_len - 1 - i];
248
110k
    }
249
250
1.19k
    {
251
1.19k
      FLOAT32 ener_tmp;
252
1.19k
      ener = 0.0f;
253
1.19k
      ener_tmp = 0.0f;
254
255
111k
      for (i = 0; i < fac_len; i++) {
256
110k
        ener += (FLOAT32)(left_fac_time_data[i + ORDER + fac_len] *
257
110k
                          left_fac_time_data[i + ORDER + fac_len]);
258
110k
      }
259
1.19k
      ener *= 2.0f;
260
261
111k
      for (i = 0; i < fac_len; i++) {
262
110k
        ener_tmp += acelp_folded[i] * acelp_folded[i];
263
110k
      }
264
265
1.19k
      if (ener_tmp > ener)
266
10
        fac_gain = (FLOAT32)sqrt(ener / ener_tmp);
267
1.18k
      else
268
1.18k
        fac_gain = 1.0f;
269
270
111k
      for (i = 0; i < fac_len; i++) {
271
110k
        left_fac_time_data[i + ORDER + fac_len] -= fac_gain * acelp_folded[i];
272
110k
      }
273
1.19k
    }
274
275
241k
    for (i = 0; i < 2 * fac_len + ORDER; i++) {
276
239k
      left_fac_timedata_flt[i] = (FLOAT32)left_fac_time_data[i];
277
239k
    }
278
279
1.19k
    lpc_coeffs_q = pstr_acelp->lpd_state.lpc_coeffs_quant;
280
1.19k
    lpc_coeffs_q += ORDER + 1;
281
1.19k
    iusace_get_weighted_lpc(lpc_coeffs_q, lpc_coeffs);
282
1.19k
    iusace_compute_lp_residual(lpc_coeffs, left_fac_timedata_flt + ORDER + fac_len, tmp_lp_res,
283
1.19k
                               fac_len);
284
1.19k
    FLOAT32 coeff = (2.0f / (FLOAT32)fac_len);
285
111k
    for (i = 0; i < fac_len; i++) {
286
110k
      tmp_lp_res[i] = tmp_lp_res[i] * coeff;
287
110k
    }
288
289
1.19k
    iusace_tcx_mdct(tmp_lp_res, left_fac_spec, fac_len, pstr_scratch);
290
1.19k
    memset(&left_fac_spec[low_pass_line], 0, (fac_len - low_pass_line) * sizeof(FLOAT32));
291
292
1.19k
    fac_gain = iusace_calc_sq_gain(left_fac_spec, 240, fac_len, pstr_scratch->p_sq_gain_en);
293
294
1.19k
    index = (WORD32)floor(0.5f + (28.0f * (FLOAT32)log10(fac_gain)));
295
1.19k
    if (index < 0) index = 0;
296
1.19k
    if (index > 127) index = 127;
297
1.19k
    iusace_write_bits2buf(index, 7, fac_bits_word);
298
1.19k
    *num_fac_bits += 7;
299
1.19k
    fac_gain = (FLOAT32)pow(10.0f, ((FLOAT32)index) / 28.0f);
300
301
111k
    for (i = 0; i < fac_len; i++) {
302
110k
      left_fac_spec[i] /= fac_gain;
303
110k
    }
304
305
14.9k
    for (i = 0; i < fac_len; i += 8) {
306
13.7k
      iusace_find_nearest_neighbor(&left_fac_spec[i], &fac_prm[i]);
307
13.7k
    }
308
309
1.19k
    *num_fac_bits += iusace_fd_encode_fac(fac_prm, &fac_bits_word[7], fac_len);
310
311
27.3k
    for (i = 0; i < (*num_fac_bits + 7) / 8; i++) {
312
26.1k
      fac_prm_out[i] =
313
26.1k
          (WORD16)((fac_bits_word[8 * i + 0] & 0x1) << 7 | (fac_bits_word[8 * i + 1] & 0x1) << 6 |
314
26.1k
                   (fac_bits_word[8 * i + 2] & 0x1) << 5 | (fac_bits_word[8 * i + 3] & 0x1) << 4 |
315
26.1k
                   (fac_bits_word[8 * i + 4] & 0x1) << 3 | (fac_bits_word[8 * i + 5] & 0x1) << 2 |
316
26.1k
                   (fac_bits_word[8 * i + 6] & 0x1) << 1 | (fac_bits_word[8 * i + 7] & 0x1) << 0);
317
26.1k
    }
318
317k
  } else {
319
317k
    *num_fac_bits = 0;
320
317k
  }
321
322
319k
  if (next_frm_lpd) {
323
1.91M
    for (i = 0; i < 1024 / 2 + 1 + ORDER; i++) {
324
1.91M
      pstr_acelp->fd_synth[i] = (FLOAT32)synth_time[pstr_acelp->len_frame - 1 + i - ORDER];
325
1.91M
      pstr_acelp->fd_orig[i] = (FLOAT32)orig_sig_dbl[pstr_acelp->len_frame + i - ORDER];
326
1.91M
    }
327
328
3.61k
    pstr_acelp->low_pass_line = low_pass_line;
329
3.61k
  }
330
331
319k
  return IA_NO_ERROR;
332
319k
}