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