Coverage Report

Created: 2025-09-17 07:02

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