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