Coverage Report

Created: 2025-08-03 06:57

/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
102M
static FLOAT32 iusace_lpc_eval_chebyshev_polyn(FLOAT32 x, FLOAT32 *coefs, WORD32 order) {
31
102M
  WORD32 i;
32
102M
  FLOAT32 b0, b1, b2, x2;
33
102M
  x2 = 2.0f * x;
34
102M
  b2 = 1.0f;
35
102M
  b1 = x2 + coefs[1];
36
720M
  for (i = 2; i < order; i++) {
37
617M
    b0 = x2 * b1 - b2 + coefs[i];
38
617M
    b2 = b1;
39
617M
    b1 = b0;
40
617M
  }
41
102M
  return (x * b1 - b2 + 0.5f * coefs[order]);
42
102M
}
43
44
537k
VOID iusace_lpc_2_lsp_conversion(FLOAT32 *lpc, FLOAT32 *lsp, FLOAT32 *prev_lsp) {
45
537k
  FLOAT32 sum_polyn[(ORDER_BY_2) + 1], diff_polyn[(ORDER_BY_2) + 1];
46
537k
  FLOAT32 *p1_lpc, *p2_lpc, *p_sum_polyn, *p_diff_polyn;
47
537k
  WORD32 i, j = 0, num_found_freeq = 0, is_first_polyn = 0;
48
537k
  FLOAT32 x_low, y_low, x_high, y_high, x_mid, y_mid, x_lin_interp;
49
50
537k
  p_sum_polyn = sum_polyn;
51
537k
  p_diff_polyn = diff_polyn;
52
537k
  *p_sum_polyn++ = 1.0f;
53
537k
  *p_diff_polyn++ = 1.0f;
54
537k
  sum_polyn[0] = 1.0f;
55
537k
  diff_polyn[0] = 1.0f;
56
537k
  p1_lpc = lpc + 1;
57
537k
  p2_lpc = lpc + ORDER;
58
4.83M
  for (i = 0; i <= ORDER_BY_2 - 1; i++) {
59
4.29M
    *p_sum_polyn = *p1_lpc + *p2_lpc - *(p_sum_polyn - 1);
60
4.29M
    p_sum_polyn++;
61
4.29M
    *p_diff_polyn = *p1_lpc++ - *p2_lpc-- + *(p_diff_polyn - 1);
62
4.29M
    p_diff_polyn++;
63
4.29M
  }
64
537k
  p_sum_polyn = sum_polyn;
65
537k
  x_low = iusace_chebyshev_polyn_grid[0];
66
537k
  y_low = iusace_lpc_eval_chebyshev_polyn(x_low, p_sum_polyn, ORDER_BY_2);
67
68
59.9M
  while ((num_found_freeq < ORDER) && (j < CHEBYSHEV_NUM_POINTS)) {
69
59.4M
    j++;
70
59.4M
    x_high = x_low;
71
59.4M
    y_high = y_low;
72
59.4M
    x_low = iusace_chebyshev_polyn_grid[j];
73
59.4M
    y_low = iusace_lpc_eval_chebyshev_polyn(x_low, p_sum_polyn, ORDER_BY_2);
74
75
59.4M
    if (y_low * y_high <= 0.0) /* if sign change new root exists */
76
8.59M
    {
77
8.59M
      j--;
78
42.9M
      for (i = 0; i < CHEBYSHEV_NUM_ITER; i++) {
79
34.3M
        x_mid = 0.5f * (x_low + x_high);
80
34.3M
        y_mid = iusace_lpc_eval_chebyshev_polyn(x_mid, p_sum_polyn, ORDER_BY_2);
81
34.3M
        if (y_low * y_mid <= 0.0) {
82
17.2M
          y_high = y_mid;
83
17.2M
          x_high = x_mid;
84
17.2M
        } else {
85
17.1M
          y_low = y_mid;
86
17.1M
          x_low = x_mid;
87
17.1M
        }
88
34.3M
      }
89
90
      /* linear interpolation for evaluating the root */
91
8.59M
      x_lin_interp = x_low - y_low * (x_high - x_low) / (y_high - y_low);
92
93
8.59M
      lsp[num_found_freeq] = x_lin_interp;
94
8.59M
      num_found_freeq++;
95
96
8.59M
      is_first_polyn = 1 - is_first_polyn;
97
8.59M
      p_sum_polyn = is_first_polyn ? diff_polyn : sum_polyn;
98
99
8.59M
      x_low = x_lin_interp;
100
8.59M
      y_low = iusace_lpc_eval_chebyshev_polyn(x_low, p_sum_polyn, ORDER_BY_2);
101
8.59M
    }
102
59.4M
  }
103
104
  /* Check if ORDER roots found */
105
  /* if not use the LSPs from previous frame */
106
537k
  if (num_found_freeq < ORDER) {
107
0
    for (i = 0; i < ORDER; i++) lsp[i] = prev_lsp[i];
108
0
  }
109
537k
}
110
111
7.27M
static VOID iusace_compute_coeff_poly_f(FLOAT32 *lsp, FLOAT32 *poly1, FLOAT32 *poly2) {
112
7.27M
  FLOAT32 b1, b2;
113
7.27M
  FLOAT32 *ptr_lsp;
114
7.27M
  WORD32 i, j;
115
116
7.27M
  ptr_lsp = lsp;
117
7.27M
  poly1[0] = poly2[0] = 1.0f;
118
119
65.4M
  for (i = 1; i <= ORDER_BY_2; i++) {
120
58.1M
    b1 = -2.0f * (*ptr_lsp++);
121
58.1M
    b2 = -2.0f * (*ptr_lsp++);
122
58.1M
    poly1[i] = (b1 * poly1[i - 1]) + (2.0f * poly1[i - 2]);
123
58.1M
    poly2[i] = (b2 * poly2[i - 1]) + (2.0f * poly2[i - 2]);
124
261M
    for (j = i - 1; j > 0; j--) {
125
203M
      poly1[j] += (b1 * poly1[j - 1]) + poly1[j - 2];
126
203M
      poly2[j] += (b2 * poly2[j - 1]) + poly2[j - 2];
127
203M
    }
128
58.1M
  }
129
7.27M
}
130
131
7.27M
VOID iusace_lsp_to_lp_conversion(FLOAT32 *lsp, FLOAT32 *lp_flt_coff_a) {
132
7.27M
  WORD32 i;
133
7.27M
  FLOAT32 *ppoly_f1, *ppoly_f2;
134
7.27M
  FLOAT32 *plp_flt_coff_a_bott, *plp_flt_coff_a_top;
135
7.27M
  FLOAT32 poly1[ORDER_BY_2 + 2], poly2[ORDER_BY_2 + 2];
136
137
7.27M
  poly1[0] = 0.0f;
138
7.27M
  poly2[0] = 0.0f;
139
140
7.27M
  iusace_compute_coeff_poly_f(lsp, &poly1[1], &poly2[1]);
141
142
7.27M
  ppoly_f1 = poly1 + ORDER_BY_2 + 1;
143
7.27M
  ppoly_f2 = poly2 + ORDER_BY_2 + 1;
144
145
65.4M
  for (i = 0; i < ORDER_BY_2; i++) {
146
58.1M
    ppoly_f1[0] += ppoly_f1[-1];
147
58.1M
    ppoly_f2[0] -= ppoly_f2[-1];
148
58.1M
    ppoly_f1--;
149
58.1M
    ppoly_f2--;
150
58.1M
  }
151
152
7.27M
  plp_flt_coff_a_bott = lp_flt_coff_a;
153
7.27M
  *plp_flt_coff_a_bott++ = 1.0f;
154
7.27M
  plp_flt_coff_a_top = lp_flt_coff_a + ORDER;
155
7.27M
  ppoly_f1 = poly1 + 2;
156
7.27M
  ppoly_f2 = poly2 + 2;
157
65.4M
  for (i = 0; i < ORDER_BY_2; i++) {
158
58.1M
    *plp_flt_coff_a_bott++ = 0.5f * (*ppoly_f1 + *ppoly_f2);
159
58.1M
    *plp_flt_coff_a_top-- = 0.5f * (*ppoly_f1++ - *ppoly_f2++);
160
58.1M
  }
161
7.27M
}
162
163
537k
VOID iusace_levinson_durbin_algo(FLOAT32 *auto_corr_input, FLOAT32 *lpc) {
164
537k
  WORD32 i, j;
165
537k
  FLOAT32 lpc_val, sum, sigma;
166
537k
  FLOAT32 reflection_coeffs[LEV_DUR_MAX_ORDER];
167
168
537k
  lpc[0] = 1.0f;
169
170
537k
  reflection_coeffs[0] = -auto_corr_input[1] / auto_corr_input[0];
171
537k
  lpc[1] = reflection_coeffs[0];
172
537k
  sigma = auto_corr_input[0] + auto_corr_input[1] * reflection_coeffs[0];
173
174
8.59M
  for (i = 2; i <= ORDER; i++) {
175
8.05M
    sum = 0.0f;
176
80.5M
    for (j = 0; j < i; j++) sum += auto_corr_input[i - j] * lpc[j];
177
8.05M
    reflection_coeffs[i - 1] = -sum / sigma;
178
179
8.05M
    sigma = sigma * (1.0f - reflection_coeffs[i - 1] * reflection_coeffs[i - 1]);
180
181
8.05M
    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
42.4M
    for (j = 1; j <= (i / 2); j++) {
190
34.3M
      lpc_val = lpc[j] + reflection_coeffs[i - 1] * lpc[i - j];
191
34.3M
      lpc[i - j] += reflection_coeffs[i - 1] * lpc[j];
192
34.3M
      lpc[j] = lpc_val;
193
34.3M
    }
194
195
8.05M
    lpc[i] = reflection_coeffs[i - 1];
196
8.05M
  }
197
537k
}
198
199
27.4M
VOID iusace_get_weighted_lpc(FLOAT32 *lpc, FLOAT32 *weighted_lpc) {
200
27.4M
  WORD32 i;
201
494M
  for (i = 0; i <= ORDER; i++) {
202
467M
    weighted_lpc[i] = iusace_gamma_table[i] * lpc[i];
203
467M
  }
204
27.4M
}
205
206
666k
VOID iusace_lsp_2_lsf_conversion(FLOAT32 *lsp, FLOAT32 *lsf) {
207
666k
  WORD32 i;
208
11.3M
  for (i = 0; i < ORDER; i++) {
209
10.6M
    lsf[i] = (FLOAT32)(acos(lsp[i]) * LSP_2_LSF_SCALE);
210
10.6M
  }
211
666k
}
212
213
537k
VOID iusace_lsf_2_lsp_conversion(FLOAT32 *lsf, FLOAT32 *lsp) {
214
537k
  WORD32 i;
215
9.13M
  for (i = 0; i < ORDER; i++) lsp[i] = (FLOAT32)cos((FLOAT64)lsf[i] * (FLOAT64)PI_BY_6400);
216
537k
}