Coverage Report

Created: 2025-08-26 06:53

/src/libxaac/encoder/iusace_lpc.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 "ixheaac_type_def.h"
23
#include "iusace_bitbuffer.h"
24
#include "iusace_cnst.h"
25
#include "iusace_tns_usac.h"
26
#include "iusace_psy_mod.h"
27
#include "iusace_block_switch_const.h"
28
#include "iusace_rom.h"
29
30
156M
static FLOAT32 iusace_lpc_eval_chebyshev_polyn(FLOAT32 x, FLOAT32 *coefs, WORD32 order) {
31
156M
  WORD32 i;
32
156M
  FLOAT32 b0, b1, b2, x2;
33
156M
  x2 = 2.0f * x;
34
156M
  b2 = 1.0f;
35
156M
  b1 = x2 + coefs[1];
36
1.09G
  for (i = 2; i < order; i++) {
37
937M
    b0 = x2 * b1 - b2 + coefs[i];
38
937M
    b2 = b1;
39
937M
    b1 = b0;
40
937M
  }
41
156M
  return (x * b1 - b2 + 0.5f * coefs[order]);
42
156M
}
43
44
811k
VOID iusace_lpc_2_lsp_conversion(FLOAT32 *lpc, FLOAT32 *lsp, FLOAT32 *prev_lsp) {
45
811k
  FLOAT32 sum_polyn[(ORDER_BY_2) + 1], diff_polyn[(ORDER_BY_2) + 1];
46
811k
  FLOAT32 *p1_lpc, *p2_lpc, *p_sum_polyn, *p_diff_polyn;
47
811k
  WORD32 i, j = 0, num_found_freeq = 0, is_first_polyn = 0;
48
811k
  FLOAT32 x_low, y_low, x_high, y_high, x_mid, y_mid, x_lin_interp;
49
50
811k
  p_sum_polyn = sum_polyn;
51
811k
  p_diff_polyn = diff_polyn;
52
811k
  *p_sum_polyn++ = 1.0f;
53
811k
  *p_diff_polyn++ = 1.0f;
54
811k
  sum_polyn[0] = 1.0f;
55
811k
  diff_polyn[0] = 1.0f;
56
811k
  p1_lpc = lpc + 1;
57
811k
  p2_lpc = lpc + ORDER;
58
7.29M
  for (i = 0; i <= ORDER_BY_2 - 1; i++) {
59
6.48M
    *p_sum_polyn = *p1_lpc + *p2_lpc - *(p_sum_polyn - 1);
60
6.48M
    p_sum_polyn++;
61
6.48M
    *p_diff_polyn = *p1_lpc++ - *p2_lpc-- + *(p_diff_polyn - 1);
62
6.48M
    p_diff_polyn++;
63
6.48M
  }
64
811k
  p_sum_polyn = sum_polyn;
65
811k
  x_low = iusace_chebyshev_polyn_grid[0];
66
811k
  y_low = iusace_lpc_eval_chebyshev_polyn(x_low, p_sum_polyn, ORDER_BY_2);
67
68
91.4M
  while ((num_found_freeq < ORDER) && (j < CHEBYSHEV_NUM_POINTS)) {
69
90.6M
    j++;
70
90.6M
    x_high = x_low;
71
90.6M
    y_high = y_low;
72
90.6M
    x_low = iusace_chebyshev_polyn_grid[j];
73
90.6M
    y_low = iusace_lpc_eval_chebyshev_polyn(x_low, p_sum_polyn, ORDER_BY_2);
74
75
90.6M
    if (y_low * y_high <= 0.0) /* if sign change new root exists */
76
12.9M
    {
77
12.9M
      j--;
78
64.8M
      for (i = 0; i < CHEBYSHEV_NUM_ITER; i++) {
79
51.9M
        x_mid = 0.5f * (x_low + x_high);
80
51.9M
        y_mid = iusace_lpc_eval_chebyshev_polyn(x_mid, p_sum_polyn, ORDER_BY_2);
81
51.9M
        if (y_low * y_mid <= 0.0) {
82
26.4M
          y_high = y_mid;
83
26.4M
          x_high = x_mid;
84
26.4M
        } else {
85
25.4M
          y_low = y_mid;
86
25.4M
          x_low = x_mid;
87
25.4M
        }
88
51.9M
      }
89
90
      /* linear interpolation for evaluating the root */
91
12.9M
      x_lin_interp = x_low - y_low * (x_high - x_low) / (y_high - y_low);
92
93
12.9M
      lsp[num_found_freeq] = x_lin_interp;
94
12.9M
      num_found_freeq++;
95
96
12.9M
      is_first_polyn = 1 - is_first_polyn;
97
12.9M
      p_sum_polyn = is_first_polyn ? diff_polyn : sum_polyn;
98
99
12.9M
      x_low = x_lin_interp;
100
12.9M
      y_low = iusace_lpc_eval_chebyshev_polyn(x_low, p_sum_polyn, ORDER_BY_2);
101
12.9M
    }
102
90.6M
  }
103
104
  /* Check if ORDER roots found */
105
  /* if not use the LSPs from previous frame */
106
811k
  if (num_found_freeq < ORDER) {
107
0
    for (i = 0; i < ORDER; i++) lsp[i] = prev_lsp[i];
108
0
  }
109
811k
}
110
111
11.0M
static VOID iusace_compute_coeff_poly_f(FLOAT32 *lsp, FLOAT32 *poly1, FLOAT32 *poly2) {
112
11.0M
  FLOAT32 b1, b2;
113
11.0M
  FLOAT32 *ptr_lsp;
114
11.0M
  WORD32 i, j;
115
116
11.0M
  ptr_lsp = lsp;
117
11.0M
  poly1[0] = poly2[0] = 1.0f;
118
119
99.6M
  for (i = 1; i <= ORDER_BY_2; i++) {
120
88.6M
    b1 = -2.0f * (*ptr_lsp++);
121
88.6M
    b2 = -2.0f * (*ptr_lsp++);
122
88.6M
    poly1[i] = (b1 * poly1[i - 1]) + (2.0f * poly1[i - 2]);
123
88.6M
    poly2[i] = (b2 * poly2[i - 1]) + (2.0f * poly2[i - 2]);
124
398M
    for (j = i - 1; j > 0; j--) {
125
310M
      poly1[j] += (b1 * poly1[j - 1]) + poly1[j - 2];
126
310M
      poly2[j] += (b2 * poly2[j - 1]) + poly2[j - 2];
127
310M
    }
128
88.6M
  }
129
11.0M
}
130
131
11.0M
VOID iusace_lsp_to_lp_conversion(FLOAT32 *lsp, FLOAT32 *lp_flt_coff_a) {
132
11.0M
  WORD32 i;
133
11.0M
  FLOAT32 *ppoly_f1, *ppoly_f2;
134
11.0M
  FLOAT32 *plp_flt_coff_a_bott, *plp_flt_coff_a_top;
135
11.0M
  FLOAT32 poly1[ORDER_BY_2 + 2], poly2[ORDER_BY_2 + 2];
136
137
11.0M
  poly1[0] = 0.0f;
138
11.0M
  poly2[0] = 0.0f;
139
140
11.0M
  iusace_compute_coeff_poly_f(lsp, &poly1[1], &poly2[1]);
141
142
11.0M
  ppoly_f1 = poly1 + ORDER_BY_2 + 1;
143
11.0M
  ppoly_f2 = poly2 + ORDER_BY_2 + 1;
144
145
99.6M
  for (i = 0; i < ORDER_BY_2; i++) {
146
88.6M
    ppoly_f1[0] += ppoly_f1[-1];
147
88.6M
    ppoly_f2[0] -= ppoly_f2[-1];
148
88.6M
    ppoly_f1--;
149
88.6M
    ppoly_f2--;
150
88.6M
  }
151
152
11.0M
  plp_flt_coff_a_bott = lp_flt_coff_a;
153
11.0M
  *plp_flt_coff_a_bott++ = 1.0f;
154
11.0M
  plp_flt_coff_a_top = lp_flt_coff_a + ORDER;
155
11.0M
  ppoly_f1 = poly1 + 2;
156
11.0M
  ppoly_f2 = poly2 + 2;
157
99.6M
  for (i = 0; i < ORDER_BY_2; i++) {
158
88.6M
    *plp_flt_coff_a_bott++ = 0.5f * (*ppoly_f1 + *ppoly_f2);
159
88.6M
    *plp_flt_coff_a_top-- = 0.5f * (*ppoly_f1++ - *ppoly_f2++);
160
88.6M
  }
161
11.0M
}
162
163
811k
VOID iusace_levinson_durbin_algo(FLOAT32 *auto_corr_input, FLOAT32 *lpc) {
164
811k
  WORD32 i, j;
165
811k
  FLOAT32 lpc_val, sum, sigma;
166
811k
  FLOAT32 reflection_coeffs[LEV_DUR_MAX_ORDER];
167
168
811k
  lpc[0] = 1.0f;
169
170
811k
  reflection_coeffs[0] = -auto_corr_input[1] / auto_corr_input[0];
171
811k
  lpc[1] = reflection_coeffs[0];
172
811k
  sigma = auto_corr_input[0] + auto_corr_input[1] * reflection_coeffs[0];
173
174
12.9M
  for (i = 2; i <= ORDER; i++) {
175
12.1M
    sum = 0.0f;
176
121M
    for (j = 0; j < i; j++) sum += auto_corr_input[i - j] * lpc[j];
177
12.1M
    reflection_coeffs[i - 1] = -sum / sigma;
178
179
12.1M
    sigma = sigma * (1.0f - reflection_coeffs[i - 1] * reflection_coeffs[i - 1]);
180
181
12.1M
    if (sigma <= 1.0E-09f) {
182
0
      for (j = i; j <= ORDER; j++) {
183
0
        reflection_coeffs[j - 1] = 0.0f;
184
0
        lpc[j] = 0.0f;
185
0
      }
186
0
      break;
187
0
    }
188
189
64.0M
    for (j = 1; j <= (i / 2); j++) {
190
51.9M
      lpc_val = lpc[j] + reflection_coeffs[i - 1] * lpc[i - j];
191
51.9M
      lpc[i - j] += reflection_coeffs[i - 1] * lpc[j];
192
51.9M
      lpc[j] = lpc_val;
193
51.9M
    }
194
195
12.1M
    lpc[i] = reflection_coeffs[i - 1];
196
12.1M
  }
197
811k
}
198
199
42.9M
VOID iusace_get_weighted_lpc(FLOAT32 *lpc, FLOAT32 *weighted_lpc) {
200
42.9M
  WORD32 i;
201
773M
  for (i = 0; i <= ORDER; i++) {
202
730M
    weighted_lpc[i] = iusace_gamma_table[i] * lpc[i];
203
730M
  }
204
42.9M
}
205
206
1.00M
VOID iusace_lsp_2_lsf_conversion(FLOAT32 *lsp, FLOAT32 *lsf) {
207
1.00M
  WORD32 i;
208
17.1M
  for (i = 0; i < ORDER; i++) {
209
16.1M
    lsf[i] = (FLOAT32)(acos(lsp[i]) * LSP_2_LSF_SCALE);
210
16.1M
  }
211
1.00M
}
212
213
811k
VOID iusace_lsf_2_lsp_conversion(FLOAT32 *lsf, FLOAT32 *lsp) {
214
811k
  WORD32 i;
215
13.7M
  for (i = 0; i < ORDER; i++) lsp[i] = (FLOAT32)cos((FLOAT64)lsf[i] * (FLOAT64)PI_BY_6400);
216
811k
}