Coverage Report

Created: 2025-07-12 07:02

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