/src/libxaac/decoder/ixheaacd_avq_dec.c
Line | Count | Source (jump to first uncovered line) |
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 | 205k | WORD32 *rem) { |
44 | 205k | WORD32 i, j, sum; |
45 | 205k | WORD32 s, e[8], em; |
46 | 205k | WORD32 rem_temp[8]; |
47 | | |
48 | 205k | memcpy(rem_temp, rem, 8 * sizeof(WORD32)); |
49 | | |
50 | 205k | sum = 0; |
51 | 1.85M | for (i = 0; i < 8; i++) { |
52 | 1.64M | if (x[i] < 0) { |
53 | 177k | y[i] = ixheaac_negate32_sat( |
54 | 177k | ixheaac_shl32_sat((ixheaac_sub32_sat(1, x[i]) >> 1), 1)); |
55 | 1.46M | } else { |
56 | 1.46M | y[i] = ixheaac_shl32_sat((ixheaac_add32_sat(1, x[i]) >> 1), 1); |
57 | 1.46M | } |
58 | 1.64M | sum = ixheaac_add32_sat(sum, y[i]); |
59 | | |
60 | 1.64M | if (x[i] % 2 != 0) { |
61 | 563k | if (x[i] < 0) { |
62 | 172k | rem_temp[i] = ixheaac_negate32_sat( |
63 | 172k | ixheaac_sub32_sat(rem_temp[i], (1 << count))); |
64 | 390k | } else { |
65 | 390k | rem_temp[i] = ixheaac_sub32_sat(rem_temp[i], (1 << count)); |
66 | 390k | } |
67 | 563k | } |
68 | 1.64M | } |
69 | | |
70 | 205k | if (sum % 4) { |
71 | 101k | em = 0; |
72 | 101k | j = 0; |
73 | 912k | for (i = 0; i < 8; i++) { |
74 | 810k | e[i] = rem_temp[i]; |
75 | 810k | } |
76 | 912k | for (i = 0; i < 8; i++) { |
77 | 810k | if (e[i] < 0) { |
78 | 338k | s = -e[i]; |
79 | 472k | } else { |
80 | 472k | s = e[i]; |
81 | 472k | } |
82 | | |
83 | 810k | if (em < s) { |
84 | 132k | em = s; |
85 | 132k | j = i; |
86 | 132k | } |
87 | 810k | } |
88 | | |
89 | 101k | if (e[j] < 0) { |
90 | 57.5k | y[j] -= 2; |
91 | 57.5k | rem_temp[j] = ixheaac_add32_sat(rem_temp[j], (2 << count)); |
92 | 57.5k | } else { |
93 | 43.7k | y[j] = ixheaac_add32_sat(y[j], 2); |
94 | 43.7k | rem_temp[j] = ixheaac_sub32_sat(rem_temp[j], (2 << count)); |
95 | 43.7k | } |
96 | 101k | } |
97 | | |
98 | 205k | memcpy(rem, rem_temp, 8 * sizeof(WORD32)); |
99 | 205k | return; |
100 | 205k | } |
101 | | |
102 | | VOID ixheaacd_voronoi_search(WORD32 x[], WORD32 y[], WORD32 count, WORD32 *rem1, |
103 | 102k | WORD32 *rem2) { |
104 | 102k | WORD32 i, y0[8], y1[8]; |
105 | 102k | WORD32 x1[8], tmp; |
106 | 102k | WORD32 e0, e1; |
107 | | |
108 | 102k | ixheaacd_nearest_neighbor_2d(x, y0, count, rem1); |
109 | 926k | for (i = 0; i < 8; i++) { |
110 | 823k | if (x[i] == 0) { |
111 | 427k | if (rem2[i] == 0) { |
112 | 168k | x1[i] = x[i] - 1; |
113 | 259k | } else { |
114 | 259k | x1[i] = 0; |
115 | 259k | rem2[i] = ixheaac_sub32_sat(rem2[i], (1 << count)); |
116 | 259k | } |
117 | 427k | } else { |
118 | 395k | x1[i] = ixheaac_sub32_sat(x[i], 1); |
119 | 395k | } |
120 | 823k | } |
121 | | |
122 | 102k | ixheaacd_nearest_neighbor_2d(x1, y1, count, rem2); |
123 | | |
124 | 926k | for (i = 0; i < 8; i++) { |
125 | 823k | y1[i] = ixheaac_add32_sat(y1[i], 1); |
126 | 823k | } |
127 | | |
128 | 102k | e0 = e1 = 0; |
129 | 926k | for (i = 0; i < 8; i++) { |
130 | 823k | tmp = rem1[i]; |
131 | 823k | e0 = ixheaac_add32_sat(ixheaac_sat64_32((WORD64)tmp * (WORD64)tmp), e0); |
132 | 823k | tmp = rem2[i]; |
133 | 823k | e1 = ixheaac_add32_sat(ixheaac_sat64_32((WORD64)tmp * (WORD64)tmp), e1); |
134 | 823k | } |
135 | | |
136 | 102k | if (e0 < e1) { |
137 | 607k | for (i = 0; i < 8; i++) { |
138 | 539k | y[i] = y0[i]; |
139 | 539k | } |
140 | 67.4k | } else { |
141 | 318k | for (i = 0; i < 8; i++) { |
142 | 283k | y[i] = y1[i]; |
143 | 283k | } |
144 | 35.4k | } |
145 | 102k | return; |
146 | 102k | } |
147 | | |
148 | 102k | VOID ixheaacd_voronoi_idx_dec(WORD32 *kv, WORD32 m, WORD32 *y, WORD32 count) { |
149 | 102k | WORD32 i, v[8], tmp, sum, *ptr1, *ptr2; |
150 | 102k | WORD32 z[8]; |
151 | 102k | WORD32 rem1[8], rem2[8]; |
152 | | |
153 | 926k | for (i = 0; i < 8; i++) y[i] = kv[7]; |
154 | | |
155 | 102k | z[7] = y[7] >> count; |
156 | 102k | rem1[7] = y[7] & (m - 1); |
157 | 102k | sum = 0; |
158 | 720k | for (i = 6; i >= 1; i--) { |
159 | 617k | tmp = ixheaac_shl32_sat(kv[i], 1); |
160 | 617k | sum = ixheaac_add32_sat(sum, tmp); |
161 | 617k | y[i] = ixheaac_add32_sat(y[i], tmp); |
162 | 617k | z[i] = y[i] >> count; |
163 | 617k | rem1[i] = y[i] & (m - 1); |
164 | 617k | } |
165 | 102k | y[0] = ixheaac_add32_sat( |
166 | 102k | y[0], |
167 | 102k | ixheaac_add32_sat(ixheaac_sat64_32((WORD64)4 * (WORD64)kv[0]), sum)); |
168 | 102k | z[0] = (ixheaac_sub32_sat(y[0], 2)) >> count; |
169 | 102k | if (m != 0) |
170 | 102k | rem1[0] = (ixheaac_sub32_sat(y[0], 2)) % m; |
171 | 0 | else |
172 | 0 | rem1[0] = ixheaac_sub32_sat(y[0], 2); |
173 | | |
174 | 102k | memcpy(rem2, rem1, 8 * sizeof(WORD32)); |
175 | | |
176 | 102k | ixheaacd_voronoi_search(z, v, count, rem1, rem2); |
177 | | |
178 | 102k | ptr1 = y; |
179 | 102k | ptr2 = v; |
180 | 926k | for (i = 0; i < 8; i++) { |
181 | 823k | *ptr1 = ixheaac_sub32_sat(*ptr1, |
182 | 823k | ixheaac_sat64_32((WORD64)m * (WORD64)*ptr2++)); |
183 | 823k | ptr1++; |
184 | 823k | } |
185 | 102k | } |
186 | | |
187 | 1.43M | static VOID ixheaacd_gosset_rank_of_permutation(WORD32 rank, WORD32 *xs) { |
188 | 1.43M | WORD32 i, j, a[8], w[8], base, fac, fac_b, target; |
189 | | |
190 | 1.43M | j = 0; |
191 | 1.43M | w[j] = 1; |
192 | 1.43M | a[j] = xs[0]; |
193 | 1.43M | base = 1; |
194 | 11.4M | for (i = 1; i < 8; i++) { |
195 | 10.0M | if (xs[i] != xs[i - 1]) { |
196 | 2.33M | j++; |
197 | 2.33M | w[j] = 1; |
198 | 2.33M | a[j] = xs[i]; |
199 | 7.72M | } else { |
200 | 7.72M | w[j]++; |
201 | 7.72M | base *= w[j]; |
202 | 7.72M | } |
203 | 10.0M | } |
204 | | |
205 | 1.43M | if (w[0] == 8) { |
206 | 552k | for (i = 0; i < 8; i++) xs[i] = a[0]; |
207 | 1.37M | } else { |
208 | 1.37M | target = rank * base; |
209 | 1.37M | fac_b = 1; |
210 | | |
211 | 12.3M | for (i = 0; i < 8; i++) { |
212 | 11.0M | fac = fac_b * ixheaacd_factorial_7[i]; |
213 | 11.0M | j = -1; |
214 | 22.6M | do { |
215 | 22.6M | target -= w[++j] * fac; |
216 | 22.6M | } while (target >= 0); |
217 | 11.0M | xs[i] = a[j]; |
218 | | |
219 | 11.0M | target += w[j] * fac; |
220 | 11.0M | fac_b *= w[j]; |
221 | 11.0M | w[j]--; |
222 | 11.0M | } |
223 | 1.37M | } |
224 | | |
225 | 1.43M | return; |
226 | 1.43M | } |
227 | | |
228 | | static WORD32 ixheaacd_get_abs_leader_tbl(const UWORD32 *table, |
229 | 2.87M | UWORD32 code_book_ind, WORD32 size) { |
230 | 2.87M | WORD32 i; |
231 | | |
232 | 3.67M | for (i = 4; i < size; i += 4) { |
233 | 3.30M | if (code_book_ind < table[i]) break; |
234 | 3.30M | } |
235 | 2.87M | if (i > size) i = size; |
236 | | |
237 | 2.87M | if (code_book_ind < table[i - 2]) i -= 2; |
238 | 2.87M | if (code_book_ind < table[i - 1]) i--; |
239 | 2.87M | i--; |
240 | | |
241 | 2.87M | return (i); |
242 | 2.87M | } |
243 | | |
244 | | static VOID ixheaacd_gosset_decode_base_index(WORD32 n, UWORD32 code_book_ind, |
245 | 3.15M | WORD32 *ya) { |
246 | 3.15M | WORD32 i, im, t, sign_code, idx = 0, ks, rank; |
247 | | |
248 | 3.15M | if (n < 2) { |
249 | 15.4M | for (i = 0; i < 8; i++) ya[i] = 0; |
250 | 1.72M | } else { |
251 | 1.43M | switch (n) { |
252 | 648k | case 2: |
253 | 1.23M | case 3: |
254 | 1.23M | i = ixheaacd_get_abs_leader_tbl(ixheaacd_cardinality_offset_table_i3, |
255 | 1.23M | code_book_ind, LEN_I3); |
256 | 1.23M | idx = ixheaacd_pos_abs_leaders_a3[i]; |
257 | 1.23M | break; |
258 | 204k | case 4: |
259 | 204k | i = ixheaacd_get_abs_leader_tbl(ixheaacd_cardinality_offset_tab_i4, |
260 | 204k | code_book_ind, LEN_I4); |
261 | 204k | idx = ixheaacd_pos_abs_leaders_a4[i]; |
262 | 204k | break; |
263 | 1.43M | } |
264 | | |
265 | 12.9M | for (i = 0; i < 8; i++) ya[i] = ixheaacd_absolute_leader_tab_da[idx][i]; |
266 | | |
267 | 1.43M | t = ixheaacd_iso_code_index_table[idx]; |
268 | 1.43M | im = ixheaacd_iso_code_num_table[idx]; |
269 | 1.43M | ks = ixheaacd_get_abs_leader_tbl(ixheaacd_signed_leader_is + t, |
270 | 1.43M | code_book_ind, im); |
271 | | |
272 | 1.43M | sign_code = 2 * ixheaacd_iso_code_data_table[t + ks]; |
273 | 12.9M | for (i = 7; i >= 0; i--) { |
274 | 11.4M | ya[i] *= (1 - (sign_code & 2)); |
275 | 11.4M | sign_code >>= 1; |
276 | 11.4M | } |
277 | | |
278 | 1.43M | rank = code_book_ind - ixheaacd_signed_leader_is[t + ks]; |
279 | | |
280 | 1.43M | ixheaacd_gosset_rank_of_permutation(rank, ya); |
281 | 1.43M | } |
282 | 3.15M | return; |
283 | 3.15M | } |
284 | | |
285 | | VOID ixheaacd_rotated_gosset_mtx_dec(WORD32 qn, WORD32 code_book_idx, |
286 | 3.15M | WORD32 *kv, WORD32 *b) { |
287 | 3.15M | if (qn <= 4) { |
288 | 3.05M | ixheaacd_gosset_decode_base_index(qn, code_book_idx, b); |
289 | 3.05M | } else { |
290 | 102k | WORD32 i, m, c[8]; |
291 | 102k | WORD32 count = 0; |
292 | 316k | while (qn > 4) { |
293 | 213k | count++; |
294 | 213k | qn -= 2; |
295 | 213k | } |
296 | | |
297 | 102k | if (count >= 31) |
298 | 0 | m = MAX_32; |
299 | 102k | else |
300 | 102k | m = 1 << count; |
301 | | |
302 | 102k | ixheaacd_gosset_decode_base_index(qn, code_book_idx, b); |
303 | | |
304 | 102k | ixheaacd_voronoi_idx_dec(kv, m, c, count); |
305 | | |
306 | 926k | for (i = 0; i < 8; i++) { |
307 | 823k | b[i] = |
308 | 823k | ixheaac_add32_sat(ixheaac_sat64_32((WORD64)m * (WORD64)b[i]), c[i]); |
309 | 823k | } |
310 | 102k | } |
311 | 3.15M | return; |
312 | 3.15M | } |