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