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