• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 }