Coverage Report

Created: 2026-01-17 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libxaac/encoder/iusace_avq_enc.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 <stdlib.h>
23
#include "ixheaac_type_def.h"
24
#include "iusace_avq_enc.h"
25
26
2.98M
static VOID iusace_gosset_compute_rank_and_sign(WORD32 *x, WORD32 *rank, WORD32 *sign_code) {
27
2.98M
  WORD32 xs[8], a[8], q, d[8], w[8], A, B, idx, tmp, abs_i, abs_j;
28
2.98M
  WORD32 i, j, k;
29
26.8M
  for (i = 0; i < 8; i++) {
30
23.8M
    xs[i] = x[i];
31
23.8M
  }
32
23.8M
  for (k = 0; k < 7; k++) {
33
20.8M
    j = k;
34
104M
    for (i = k + 1; i < 8; i++) {
35
83.5M
      abs_j = abs(xs[j]);
36
83.5M
      abs_i = abs(xs[i]);
37
83.5M
      if (abs_i >= abs_j) {
38
63.3M
        if (abs_i > xs[j]) {
39
22.5M
          j = i;
40
22.5M
        }
41
63.3M
      }
42
83.5M
    }
43
20.8M
    if (j > k) {
44
11.7M
      tmp = xs[k];
45
11.7M
      xs[k] = xs[j];
46
11.7M
      xs[j] = tmp;
47
11.7M
    }
48
20.8M
  }
49
2.98M
  *sign_code = 0;
50
26.8M
  for (i = 0; i < 8; i++) {
51
23.8M
    if (xs[i] < 0) {
52
7.76M
      *sign_code += iusace_pow2_table[i];
53
7.76M
    }
54
23.8M
  }
55
2.98M
  a[0] = xs[0];
56
2.98M
  q = 1;
57
23.8M
  for (i = 1; i < 8; i++) {
58
20.8M
    if (xs[i] != xs[i - 1]) {
59
4.89M
      a[q] = xs[i];
60
4.89M
      q++;
61
4.89M
    }
62
20.8M
  }
63
26.8M
  for (i = 0; i < 8; i++) {
64
48.0M
    for (j = 0; j < q; j++) {
65
48.0M
      if (x[i] == a[j]) {
66
23.8M
        d[i] = j;
67
23.8M
        break;
68
23.8M
      }
69
48.0M
    }
70
23.8M
  }
71
2.98M
  *rank = 0;
72
10.8M
  for (j = 0; j < q; j++) {
73
7.87M
    w[j] = 0;
74
7.87M
  }
75
2.98M
  B = 1;
76
26.8M
  for (i = 7; i >= 0; i--) {
77
23.8M
    idx = d[i];
78
23.8M
    w[idx]++;
79
23.8M
    B *= w[idx];
80
23.8M
    A = 0;
81
48.0M
    for (j = 0; j < idx; j++) {
82
24.1M
      A += w[j];
83
24.1M
    }
84
23.8M
    if (A > 0) {
85
9.14M
      *rank += A * iusace_factorial_table[i] / B;
86
9.14M
    }
87
23.8M
  }
88
2.98M
}
89
90
2.98M
static VOID iusace_gosset_compute_base_idx(WORD32 *x, WORD32 ka, WORD32 *idx) {
91
2.98M
  WORD32 rank, offset, code, i, ks;
92
2.98M
  iusace_gosset_compute_rank_and_sign(x, &rank, &code);
93
2.98M
  ks = -1;
94
11.6M
  for (i = iusace_iso_code_index_table[ka]; i < LEN_SIGN_LEADER; i++) {
95
11.6M
    if (code == iusace_iso_code_data_table[i]) {
96
2.98M
      ks = i;
97
2.98M
      break;
98
2.98M
    }
99
11.6M
  }
100
2.98M
  if (ks == -1) {
101
0
    ks = 0;
102
0
  }
103
2.98M
  offset = iusace_signed_leader_is[ks];
104
2.98M
  *idx = offset + rank;
105
2.98M
  return;
106
2.98M
}
107
108
6.47M
static WORD32 iusace_find_absolute_leader(WORD32 *y) {
109
6.47M
  WORD32 i, nb, pos, ka;
110
6.47M
  WORD64 s, C[8], id;
111
58.2M
  for (i = 0; i < 8; i++) {
112
51.8M
    C[i] = (WORD64)y[i] * y[i];
113
51.8M
  }
114
6.47M
  s = 0;
115
58.2M
  for (i = 0; i < 8; i++) {
116
51.8M
    s += C[i];
117
51.8M
  }
118
6.47M
  s >>= 3;
119
6.47M
  ka = LEN_ABS_LEADER + 1;
120
6.47M
  if (s == 0) {
121
974k
    ka = LEN_ABS_LEADER;
122
5.50M
  } else {
123
5.50M
    if (s <= NB_SPHERE) {
124
5.16M
      id = 0;
125
46.4M
      for (i = 0; i < 8; i++) {
126
41.3M
        id += C[i] * C[i];
127
41.3M
      }
128
5.16M
      id = id >> 3;
129
5.16M
      nb = iusace_da_num_bits[s - 1];
130
5.16M
      pos = iusace_da_pos[s - 1];
131
9.77M
      for (i = 0; i < nb; i++) {
132
7.59M
        if (id == (long)iusace_da_id[pos]) {
133
2.99M
          ka = pos;
134
2.99M
          break;
135
2.99M
        }
136
4.60M
        pos++;
137
4.60M
      }
138
5.16M
    }
139
5.50M
  }
140
6.47M
  return (ka);
141
6.47M
}
142
143
67.8M
static VOID iusace_nearest_neighbor_2d(FLOAT32 *x, WORD32 *y) {
144
67.8M
  WORD32 i, j;
145
67.8M
  WORD64 sum;
146
67.8M
  FLOAT32 diff[8], em;
147
67.8M
  sum = 0;
148
610M
  for (i = 0; i < 8; i++) {
149
542M
    if (x[i] < 0) {
150
358M
      y[i] = -2 * (((WORD32)(1.0 - x[i])) >> 1);
151
358M
    } else {
152
184M
      y[i] = 2 * (((WORD32)(1.0 + x[i])) >> 1);
153
184M
    }
154
542M
    sum += y[i];
155
542M
  }
156
67.8M
  if (sum % 4) {
157
23.0M
    FLOAT32 s;
158
23.0M
    em = 0;
159
23.0M
    j = 0;
160
207M
    for (i = 0; i < 8; i++) {
161
184M
      diff[i] = x[i] - y[i];
162
184M
      s = (FLOAT32)fabs(diff[i]);
163
184M
      if (em < s) {
164
57.4M
        em = s;
165
57.4M
        j = i;
166
57.4M
      }
167
184M
    }
168
23.0M
    if (diff[j] < 0) {
169
10.9M
      y[j] -= 2;
170
12.0M
    } else {
171
12.0M
      y[j] += 2;
172
12.0M
    }
173
23.0M
  }
174
67.8M
  return;
175
67.8M
}
176
177
33.9M
VOID iusace_find_nearest_neighbor(FLOAT32 *bk, WORD32 *ck) {
178
33.9M
  WORD32 i, y1[8], y2[8];
179
33.9M
  FLOAT32 e1k, e2k, x1[8], tmp;
180
181
33.9M
  iusace_nearest_neighbor_2d(bk, y1);
182
183
305M
  for (i = 0; i < 8; i++) {
184
271M
    x1[i] = bk[i] - 1.0f;
185
271M
  }
186
33.9M
  iusace_nearest_neighbor_2d(x1, y2);
187
305M
  for (i = 0; i < 8; i++) {
188
271M
    y2[i] += 1;
189
271M
  }
190
  /* Compute e1k = (Bk - y1k)^2 and e2k = (Bk – y2k)^2 */
191
33.9M
  e1k = e2k = 0.0;
192
305M
  for (i = 0; i < 8; i++) {
193
271M
    tmp = bk[i] - y1[i];
194
271M
    e1k += tmp * tmp;
195
271M
    tmp = bk[i] - y2[i];
196
271M
    e2k += tmp * tmp;
197
271M
  }
198
199
  /* Select best lattice point */
200
33.9M
  if (e1k < e2k) {
201
220M
    for (i = 0; i < 8; i++) {
202
196M
      ck[i] = y1[i];
203
196M
    }
204
24.5M
  } else {
205
84.4M
    for (i = 0; i < 8; i++) {
206
75.0M
      ck[i] = y2[i];
207
75.0M
    }
208
9.38M
  }
209
33.9M
  return;
210
33.9M
}
211
212
2.51M
static VOID iusace_vononoi_idx(WORD32 *kv, WORD32 m, WORD32 *y) {
213
2.51M
  WORD32 i, v[8], tmp, sum, *ptr1, *ptr2;
214
2.51M
  FLOAT32 z[8];
215
22.6M
  for (i = 0; i < 8; i++) {
216
20.1M
    y[i] = kv[7];
217
20.1M
  }
218
2.51M
  z[7] = (FLOAT32)y[7] / m;
219
2.51M
  sum = 0;
220
17.6M
  for (i = 6; i >= 1; i--) {
221
15.0M
    tmp = kv[i] << 1;
222
15.0M
    sum += tmp;
223
15.0M
    y[i] += tmp;
224
15.0M
    z[i] = (FLOAT32)y[i] / m;
225
15.0M
  }
226
2.51M
  y[0] += (4 * kv[0] + sum);
227
2.51M
  z[0] = (FLOAT32)(y[0] - 2) / m;
228
2.51M
  iusace_find_nearest_neighbor(z, v);
229
2.51M
  ptr1 = y;
230
2.51M
  ptr2 = v;
231
22.6M
  for (i = 0; i < 8; i++) {
232
20.1M
    *ptr1++ -= m * *ptr2++;
233
20.1M
  }
234
2.51M
}
235
236
1.25M
static VOID iusace_compute_coord(WORD32 *y, WORD32 *k) {
237
1.25M
  WORD32 i, tmp, sum;
238
1.25M
  k[7] = y[7];
239
1.25M
  tmp = y[7];
240
1.25M
  sum = 5 * y[7];
241
8.80M
  for (i = 6; i >= 1; i--) {
242
7.54M
    k[i] = (y[i] - tmp) >> 1;
243
7.54M
    sum -= y[i];
244
7.54M
  }
245
1.25M
  k[0] = (y[0] + sum) >> 2;
246
1.25M
}
247
248
3.95M
VOID iusace_apply_voronoi_ext(WORD32 *x, WORD32 *n, WORD32 *idx, WORD32 *k) {
249
3.95M
  WORD32 ka, c[8];
250
3.95M
  WORD32 i, r, m, v[8], c_tmp[8], k_mod[8], k_tmp[8], iter, ka_tmp, n_tmp, mask;
251
3.95M
  FLOAT32 sphere;
252
3.95M
  ka = iusace_find_absolute_leader(x);
253
3.95M
  *n = iusace_da_nq[ka];
254
3.95M
  if (*n <= 4) {
255
24.3M
    for (i = 0; i < 8; i++) {
256
21.6M
      c[i] = x[i];
257
21.6M
    }
258
2.70M
  } else {
259
1.25M
    sphere = 0.0;
260
11.3M
    for (i = 0; i < 8; i++) {
261
10.0M
      sphere += (FLOAT32)x[i] * (FLOAT32)x[i];
262
10.0M
    }
263
1.25M
    sphere *= 0.125;
264
1.25M
    r = 1;
265
1.25M
    sphere *= 0.25;
266
1.62M
    while (sphere > 11.0) {
267
367k
      r++;
268
367k
      sphere *= 0.25;
269
367k
    }
270
1.25M
    iusace_compute_coord(x, k_mod);
271
1.25M
    m = 1 << r;
272
1.25M
    mask = m - 1;
273
3.77M
    for (iter = 0; iter < 2; iter++) {
274
22.6M
      for (i = 0; i < 8; i++) {
275
20.1M
        k_tmp[i] = k_mod[i] & mask;
276
20.1M
      }
277
2.51M
      iusace_vononoi_idx(k_tmp, m, v);
278
22.6M
      for (i = 0; i < 8; i++) {
279
20.1M
        c_tmp[i] = (x[i] - v[i]) / m;
280
20.1M
      }
281
2.51M
      ka_tmp = iusace_find_absolute_leader(c_tmp);
282
2.51M
      n_tmp = iusace_da_nq[ka_tmp];
283
2.51M
      if (n_tmp > 4) {
284
1.25M
        r++;
285
1.25M
        m = m << 1;
286
1.25M
        mask = ((mask << 1) + 1);
287
1.26M
      } else {
288
1.26M
        if (n_tmp < 3) {
289
91.2k
          n_tmp = 3;
290
91.2k
        }
291
1.26M
        ka = ka_tmp;
292
1.26M
        *n = n_tmp + 2 * r;
293
11.3M
        for (i = 0; i < 8; i++) {
294
10.1M
          k[i] = k_tmp[i];
295
10.1M
        }
296
11.3M
        for (i = 0; i < 8; i++) {
297
10.1M
          c[i] = c_tmp[i];
298
10.1M
        }
299
1.26M
        r--;
300
1.26M
        m = m >> 1;
301
1.26M
        mask = mask >> 1;
302
1.26M
      }
303
2.51M
    }
304
1.25M
  }
305
306
3.95M
  if (*n > 0) {
307
2.98M
    iusace_gosset_compute_base_idx(c, ka, idx);
308
2.98M
  }
309
3.95M
  return;
310
3.95M
}
311
312
1.14M
VOID iusace_alg_vec_quant(FLOAT32 *ptr_input, WORD32 *ptr_out, WORD32 *ptr_lpc_idx) {
313
1.14M
  WORD32 i, l, nq, pos, c[8], kv[8];
314
1.14M
  FLOAT32 x1[8];
315
1.14M
  WORD32 lpc_index;
316
317
1.14M
  pos = 2;
318
3.43M
  for (l = 0; l < 2; l++) {
319
20.5M
    for (i = 0; i < 8; i++) {
320
18.3M
      x1[i] = ptr_input[l * 8 + i];
321
18.3M
      kv[i] = 0;
322
18.3M
    }
323
324
2.28M
    iusace_find_nearest_neighbor(x1, c);
325
326
2.28M
    iusace_apply_voronoi_ext(c, &nq, &lpc_index, kv);
327
328
20.5M
    for (i = 0; i < 8; i++) {
329
18.3M
      ptr_out[l * 8 + i] = c[i];
330
18.3M
    }
331
332
2.28M
    ptr_lpc_idx[l] = nq;
333
334
2.28M
    if (nq > 0) {
335
2.08M
      ptr_lpc_idx[pos++] = lpc_index;
336
18.7M
      for (i = 0; i < 8; i++) {
337
16.6M
        ptr_lpc_idx[pos++] = kv[i];
338
16.6M
      }
339
2.08M
    }
340
2.28M
  }
341
342
1.14M
  return;
343
1.14M
}