Home | History | Annotate | Download | only in decoder
      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