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