• 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] = -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