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