Coverage Report

Created: 2026-07-16 06:11

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libxaac/decoder/ixheaacd_avq_dec.c
Line
Count
Source
1
/******************************************************************************
2
 *                                                                            *
3
 * Copyright (C) 2018 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
#include <stdio.h>
21
#include <stdlib.h>
22
#include <float.h>
23
#include <math.h>
24
#include <assert.h>
25
#include <string.h>
26
#include "ixheaac_type_def.h"
27
#include "ixheaac_constants.h"
28
#include "ixheaac_basic_ops32.h"
29
#include "ixheaac_basic_ops40.h"
30
#include "ixheaacd_acelp_com.h"
31
32
extern const WORD32 ixheaacd_factorial_7[8];
33
extern const WORD32 ixheaacd_iso_code_index_table[LEN_ABS_LEADER];
34
extern const UWORD8 ixheaacd_iso_code_data_table[LEN_SIGN_LEADER];
35
extern const UWORD32 ixheaacd_signed_leader_is[LEN_SIGN_LEADER];
36
extern const WORD32 ixheaacd_iso_code_num_table[],
37
    ixheaacd_pos_abs_leaders_a3[], ixheaacd_pos_abs_leaders_a4[];
38
extern const UWORD8 ixheaacd_absolute_leader_tab_da[][8];
39
extern const UWORD32 ixheaacd_cardinality_offset_table_i3[],
40
    ixheaacd_cardinality_offset_tab_i4[];
41
42
static VOID ixheaacd_nearest_neighbor_2d(WORD32 x[], WORD32 y[], WORD32 count,
43
261k
                                         WORD32 *rem) {
44
261k
  WORD32 i, j, sum;
45
261k
  WORD32 s, e[8], em;
46
261k
  WORD32 rem_temp[8];
47
48
261k
  memcpy(rem_temp, rem, 8 * sizeof(WORD32));
49
50
261k
  sum = 0;
51
2.35M
  for (i = 0; i < 8; i++) {
52
2.09M
    if (x[i] < 0) {
53
227k
      y[i] = ixheaac_negate32_sat(
54
227k
          ixheaac_shl32_sat((ixheaac_sub32_sat(1, x[i]) >> 1), 1));
55
1.86M
    } else {
56
1.86M
      y[i] = ixheaac_shl32_sat((ixheaac_add32_sat(1, x[i]) >> 1), 1);
57
1.86M
    }
58
2.09M
    sum = ixheaac_add32_sat(sum, y[i]);
59
60
2.09M
    if (x[i] % 2 != 0) {
61
709k
      if (x[i] < 0) {
62
221k
        rem_temp[i] = ixheaac_negate32_sat(
63
221k
            ixheaac_sub32_sat(rem_temp[i], (1 << count)));
64
488k
      } else {
65
488k
        rem_temp[i] = ixheaac_sub32_sat(rem_temp[i], (1 << count));
66
488k
      }
67
709k
    }
68
2.09M
  }
69
70
261k
  if (sum % 4) {
71
127k
    em = 0;
72
127k
    j = 0;
73
1.14M
    for (i = 0; i < 8; i++) {
74
1.02M
      e[i] = rem_temp[i];
75
1.02M
    }
76
1.14M
    for (i = 0; i < 8; i++) {
77
1.02M
      if (e[i] < 0) {
78
428k
        s = -e[i];
79
592k
      } else {
80
592k
        s = e[i];
81
592k
      }
82
83
1.02M
      if (em < s) {
84
171k
        em = s;
85
171k
        j = i;
86
171k
      }
87
1.02M
    }
88
89
127k
    if (e[j] < 0) {
90
68.4k
      y[j] -= 2;
91
68.4k
      rem_temp[j] = ixheaac_add32_sat(rem_temp[j], (2 << count));
92
68.4k
    } else {
93
59.1k
      y[j] = ixheaac_add32_sat(y[j], 2);
94
59.1k
      rem_temp[j] = ixheaac_sub32_sat(rem_temp[j], (2 << count));
95
59.1k
    }
96
127k
  }
97
98
261k
  memcpy(rem, rem_temp, 8 * sizeof(WORD32));
99
261k
  return;
100
261k
}
101
102
VOID ixheaacd_voronoi_search(WORD32 x[], WORD32 y[], WORD32 count, WORD32 *rem1,
103
130k
                             WORD32 *rem2) {
104
130k
  WORD32 i, y0[8], y1[8];
105
130k
  WORD32 x1[8], tmp;
106
130k
  WORD32 e0, e1;
107
108
130k
  ixheaacd_nearest_neighbor_2d(x, y0, count, rem1);
109
1.17M
  for (i = 0; i < 8; i++) {
110
1.04M
    if (x[i] == 0) {
111
552k
      if (rem2[i] == 0) {
112
215k
        x1[i] = x[i] - 1;
113
336k
      } else {
114
336k
        x1[i] = 0;
115
336k
        rem2[i] = ixheaac_sub32_sat(rem2[i], (1 << count));
116
336k
      }
117
552k
    } else {
118
494k
      x1[i] = ixheaac_sub32_sat(x[i], 1);
119
494k
    }
120
1.04M
  }
121
122
130k
  ixheaacd_nearest_neighbor_2d(x1, y1, count, rem2);
123
124
1.17M
  for (i = 0; i < 8; i++) {
125
1.04M
    y1[i] = ixheaac_add32_sat(y1[i], 1);
126
1.04M
  }
127
128
130k
  e0 = e1 = 0;
129
1.17M
  for (i = 0; i < 8; i++) {
130
1.04M
    tmp = rem1[i];
131
1.04M
    e0 = ixheaac_add32_sat(ixheaac_sat64_32((WORD64)tmp * (WORD64)tmp), e0);
132
1.04M
    tmp = rem2[i];
133
1.04M
    e1 = ixheaac_add32_sat(ixheaac_sat64_32((WORD64)tmp * (WORD64)tmp), e1);
134
1.04M
  }
135
136
130k
  if (e0 < e1) {
137
839k
    for (i = 0; i < 8; i++) {
138
746k
      y[i] = y0[i];
139
746k
    }
140
93.2k
  } else {
141
338k
    for (i = 0; i < 8; i++) {
142
300k
      y[i] = y1[i];
143
300k
    }
144
37.5k
  }
145
130k
  return;
146
130k
}
147
148
130k
VOID ixheaacd_voronoi_idx_dec(WORD32 *kv, WORD32 m, WORD32 *y, WORD32 count) {
149
130k
  WORD32 i, v[8], tmp, sum, *ptr1, *ptr2;
150
130k
  WORD32 z[8];
151
130k
  WORD32 rem1[8], rem2[8];
152
153
1.17M
  for (i = 0; i < 8; i++) y[i] = kv[7];
154
155
130k
  z[7] = y[7] >> count;
156
130k
  rem1[7] = y[7] & (m - 1);
157
130k
  sum = 0;
158
915k
  for (i = 6; i >= 1; i--) {
159
785k
    tmp = ixheaac_shl32_sat(kv[i], 1);
160
785k
    sum = ixheaac_add32_sat(sum, tmp);
161
785k
    y[i] = ixheaac_add32_sat(y[i], tmp);
162
785k
    z[i] = y[i] >> count;
163
785k
    rem1[i] = y[i] & (m - 1);
164
785k
  }
165
130k
  y[0] = ixheaac_add32_sat(
166
130k
      y[0],
167
130k
      ixheaac_add32_sat(ixheaac_sat64_32((WORD64)4 * (WORD64)kv[0]), sum));
168
130k
  z[0] = (ixheaac_sub32_sat(y[0], 2)) >> count;
169
130k
  if (m != 0)
170
130k
    rem1[0] = (ixheaac_sub32_sat(y[0], 2)) % m;
171
0
  else
172
0
    rem1[0] = ixheaac_sub32_sat(y[0], 2);
173
174
130k
  memcpy(rem2, rem1, 8 * sizeof(WORD32));
175
176
130k
  ixheaacd_voronoi_search(z, v, count, rem1, rem2);
177
178
130k
  ptr1 = y;
179
130k
  ptr2 = v;
180
1.17M
  for (i = 0; i < 8; i++) {
181
1.04M
    *ptr1 = ixheaac_sub32_sat(*ptr1,
182
1.04M
                               ixheaac_sat64_32((WORD64)m * (WORD64)*ptr2++));
183
1.04M
    ptr1++;
184
1.04M
  }
185
130k
}
186
187
1.76M
static VOID ixheaacd_gosset_rank_of_permutation(WORD32 rank, WORD32 *xs) {
188
1.76M
  WORD32 i, j, a[8], w[8], base, fac, fac_b, target;
189
190
1.76M
  j = 0;
191
1.76M
  w[j] = 1;
192
1.76M
  a[j] = xs[0];
193
1.76M
  base = 1;
194
14.1M
  for (i = 1; i < 8; i++) {
195
12.3M
    if (xs[i] != xs[i - 1]) {
196
2.98M
      j++;
197
2.98M
      w[j] = 1;
198
2.98M
      a[j] = xs[i];
199
9.37M
    } else {
200
9.37M
      w[j]++;
201
9.37M
      base *= w[j];
202
9.37M
    }
203
12.3M
  }
204
205
1.76M
  if (w[0] == 8) {
206
510k
    for (i = 0; i < 8; i++) xs[i] = a[0];
207
1.71M
  } else {
208
1.71M
    target = rank * base;
209
1.71M
    fac_b = 1;
210
211
15.3M
    for (i = 0; i < 8; i++) {
212
13.6M
      fac = fac_b * ixheaacd_factorial_7[i];
213
13.6M
      j = -1;
214
28.8M
      do {
215
28.8M
        target -= w[++j] * fac;
216
28.8M
      } while (target >= 0);
217
13.6M
      xs[i] = a[j];
218
219
13.6M
      target += w[j] * fac;
220
13.6M
      fac_b *= w[j];
221
13.6M
      w[j]--;
222
13.6M
    }
223
1.71M
  }
224
225
1.76M
  return;
226
1.76M
}
227
228
static WORD32 ixheaacd_get_abs_leader_tbl(const UWORD32 *table,
229
3.53M
                                          UWORD32 code_book_ind, WORD32 size) {
230
3.53M
  WORD32 i;
231
232
4.55M
  for (i = 4; i < size; i += 4) {
233
4.08M
    if (code_book_ind < table[i]) break;
234
4.08M
  }
235
3.53M
  if (i > size) i = size;
236
237
3.53M
  if (code_book_ind < table[i - 2]) i -= 2;
238
3.53M
  if (code_book_ind < table[i - 1]) i--;
239
3.53M
  i--;
240
241
3.53M
  return (i);
242
3.53M
}
243
244
static VOID ixheaacd_gosset_decode_base_index(WORD32 n, UWORD32 code_book_ind,
245
3.78M
                                              WORD32 *ya) {
246
3.78M
  WORD32 i, im, t, sign_code, idx = 0, ks, rank;
247
248
3.78M
  if (n < 2) {
249
18.1M
    for (i = 0; i < 8; i++) ya[i] = 0;
250
2.01M
  } else {
251
1.76M
    switch (n) {
252
751k
      case 2:
253
1.50M
      case 3:
254
1.50M
        i = ixheaacd_get_abs_leader_tbl(ixheaacd_cardinality_offset_table_i3,
255
1.50M
                                        code_book_ind, LEN_I3);
256
1.50M
        idx = ixheaacd_pos_abs_leaders_a3[i];
257
1.50M
        break;
258
263k
      case 4:
259
263k
        i = ixheaacd_get_abs_leader_tbl(ixheaacd_cardinality_offset_tab_i4,
260
263k
                                        code_book_ind, LEN_I4);
261
263k
        idx = ixheaacd_pos_abs_leaders_a4[i];
262
263k
        break;
263
1.76M
    }
264
265
15.9M
    for (i = 0; i < 8; i++) ya[i] = ixheaacd_absolute_leader_tab_da[idx][i];
266
267
1.76M
    t = ixheaacd_iso_code_index_table[idx];
268
1.76M
    im = ixheaacd_iso_code_num_table[idx];
269
1.76M
    ks = ixheaacd_get_abs_leader_tbl(ixheaacd_signed_leader_is + t,
270
1.76M
                                     code_book_ind, im);
271
272
1.76M
    sign_code = 2 * ixheaacd_iso_code_data_table[t + ks];
273
15.9M
    for (i = 7; i >= 0; i--) {
274
14.1M
      ya[i] *= (1 - (sign_code & 2));
275
14.1M
      sign_code >>= 1;
276
14.1M
    }
277
278
1.76M
    rank = code_book_ind - ixheaacd_signed_leader_is[t + ks];
279
280
1.76M
    ixheaacd_gosset_rank_of_permutation(rank, ya);
281
1.76M
  }
282
3.78M
  return;
283
3.78M
}
284
285
VOID ixheaacd_rotated_gosset_mtx_dec(WORD32 qn, WORD32 code_book_idx,
286
3.78M
                                     WORD32 *kv, WORD32 *b) {
287
3.78M
  if (qn <= 4) {
288
3.64M
    ixheaacd_gosset_decode_base_index(qn, code_book_idx, b);
289
3.64M
  } else {
290
130k
    WORD32 i, m, c[8];
291
130k
    WORD32 count = 0;
292
414k
    while (qn > 4) {
293
283k
      count++;
294
283k
      qn -= 2;
295
283k
    }
296
297
130k
    if (count >= 31)
298
0
      m = MAX_32;
299
130k
    else
300
130k
      m = 1 << count;
301
302
130k
    ixheaacd_gosset_decode_base_index(qn, code_book_idx, b);
303
304
130k
    ixheaacd_voronoi_idx_dec(kv, m, c, count);
305
306
1.17M
    for (i = 0; i < 8; i++) {
307
1.04M
      b[i] =
308
1.04M
          ixheaac_add32_sat(ixheaac_sat64_32((WORD64)m * (WORD64)b[i]), c[i]);
309
1.04M
    }
310
130k
  }
311
3.78M
  return;
312
3.78M
}