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 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 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 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 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 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 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 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