You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
312 lines
8.1 KiB
312 lines
8.1 KiB
/******************************************************************************
|
|
* *
|
|
* Copyright (C) 2018 The Android Open Source Project
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at:
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*
|
|
*****************************************************************************
|
|
* Originally developed and contributed by Ittiam Systems Pvt. Ltd, Bangalore
|
|
*/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <float.h>
|
|
#include <math.h>
|
|
#include <assert.h>
|
|
#include <string.h>
|
|
#include "ixheaacd_type_def.h"
|
|
#include "ixheaacd_constants.h"
|
|
#include "ixheaacd_basic_ops32.h"
|
|
#include "ixheaacd_basic_ops40.h"
|
|
#include "ixheaacd_acelp_com.h"
|
|
|
|
extern const WORD32 ixheaacd_factorial_7[8];
|
|
extern const WORD32 ixheaacd_iso_code_index_table[LEN_ABS_LEADER];
|
|
extern const UWORD8 ixheaacd_iso_code_data_table[LEN_SIGN_LEADER];
|
|
extern const UWORD32 ixheaacd_signed_leader_is[LEN_SIGN_LEADER];
|
|
extern const WORD32 ixheaacd_iso_code_num_table[],
|
|
ixheaacd_pos_abs_leaders_a3[], ixheaacd_pos_abs_leaders_a4[];
|
|
extern const UWORD8 ixheaacd_absolute_leader_tab_da[][8];
|
|
extern const UWORD32 ixheaacd_cardinality_offset_table_i3[],
|
|
ixheaacd_cardinality_offset_tab_i4[];
|
|
|
|
static VOID ixheaacd_nearest_neighbor_2d(WORD32 x[], WORD32 y[], WORD32 count,
|
|
WORD32 *rem) {
|
|
WORD32 i, j, sum;
|
|
WORD32 s, e[8], em;
|
|
WORD32 rem_temp[8];
|
|
|
|
memcpy(rem_temp, rem, 8 * sizeof(WORD32));
|
|
|
|
sum = 0;
|
|
for (i = 0; i < 8; i++) {
|
|
if (x[i] < 0) {
|
|
y[i] = ixheaacd_negate32_sat(
|
|
ixheaacd_shl32_sat((ixheaacd_sub32_sat(1, x[i]) >> 1), 1));
|
|
} else {
|
|
y[i] = ixheaacd_shl32_sat((ixheaacd_add32_sat(1, x[i]) >> 1), 1);
|
|
}
|
|
sum = ixheaacd_add32_sat(sum, y[i]);
|
|
|
|
if (x[i] % 2 != 0) {
|
|
if (x[i] < 0) {
|
|
rem_temp[i] = ixheaacd_negate32_sat(
|
|
ixheaacd_sub32_sat(rem_temp[i], (1 << count)));
|
|
} else {
|
|
rem_temp[i] = ixheaacd_sub32_sat(rem_temp[i], (1 << count));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (sum % 4) {
|
|
em = 0;
|
|
j = 0;
|
|
for (i = 0; i < 8; i++) {
|
|
e[i] = rem_temp[i];
|
|
}
|
|
for (i = 0; i < 8; i++) {
|
|
if (e[i] < 0) {
|
|
s = -e[i];
|
|
} else {
|
|
s = e[i];
|
|
}
|
|
|
|
if (em < s) {
|
|
em = s;
|
|
j = i;
|
|
}
|
|
}
|
|
|
|
if (e[j] < 0) {
|
|
y[j] -= 2;
|
|
rem_temp[j] = ixheaacd_add32_sat(rem_temp[j], (2 << count));
|
|
} else {
|
|
y[j] = ixheaacd_add32_sat(y[j], 2);
|
|
rem_temp[j] = ixheaacd_sub32_sat(rem_temp[j], (2 << count));
|
|
}
|
|
}
|
|
|
|
memcpy(rem, rem_temp, 8 * sizeof(WORD32));
|
|
return;
|
|
}
|
|
|
|
VOID ixheaacd_voronoi_search(WORD32 x[], WORD32 y[], WORD32 count, WORD32 *rem1,
|
|
WORD32 *rem2) {
|
|
WORD32 i, y0[8], y1[8];
|
|
WORD32 x1[8], tmp;
|
|
WORD32 e0, e1;
|
|
|
|
ixheaacd_nearest_neighbor_2d(x, y0, count, rem1);
|
|
for (i = 0; i < 8; i++) {
|
|
if (x[i] == 0) {
|
|
if (rem2[i] == 0) {
|
|
x1[i] = x[i] - 1;
|
|
} else {
|
|
x1[i] = 0;
|
|
rem2[i] = ixheaacd_sub32_sat(rem2[i], (1 << count));
|
|
}
|
|
} else {
|
|
x1[i] = ixheaacd_sub32_sat(x[i], 1);
|
|
}
|
|
}
|
|
|
|
ixheaacd_nearest_neighbor_2d(x1, y1, count, rem2);
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
y1[i] = ixheaacd_add32_sat(y1[i], 1);
|
|
}
|
|
|
|
e0 = e1 = 0;
|
|
for (i = 0; i < 8; i++) {
|
|
tmp = rem1[i];
|
|
e0 = ixheaacd_add32_sat(ixheaacd_sat64_32((WORD64)tmp * (WORD64)tmp), e0);
|
|
tmp = rem2[i];
|
|
e1 = ixheaacd_add32_sat(ixheaacd_sat64_32((WORD64)tmp * (WORD64)tmp), e1);
|
|
}
|
|
|
|
if (e0 < e1) {
|
|
for (i = 0; i < 8; i++) {
|
|
y[i] = y0[i];
|
|
}
|
|
} else {
|
|
for (i = 0; i < 8; i++) {
|
|
y[i] = y1[i];
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
VOID ixheaacd_voronoi_idx_dec(WORD32 *kv, WORD32 m, WORD32 *y, WORD32 count) {
|
|
WORD32 i, v[8], tmp, sum, *ptr1, *ptr2;
|
|
WORD32 z[8];
|
|
WORD32 rem1[8], rem2[8];
|
|
|
|
for (i = 0; i < 8; i++) y[i] = kv[7];
|
|
|
|
z[7] = y[7] >> count;
|
|
rem1[7] = y[7] & (m - 1);
|
|
sum = 0;
|
|
for (i = 6; i >= 1; i--) {
|
|
tmp = ixheaacd_shl32_sat(kv[i], 1);
|
|
sum = ixheaacd_add32_sat(sum, tmp);
|
|
y[i] = ixheaacd_add32_sat(y[i], tmp);
|
|
z[i] = y[i] >> count;
|
|
rem1[i] = y[i] & (m - 1);
|
|
}
|
|
y[0] = ixheaacd_add32_sat(
|
|
y[0],
|
|
ixheaacd_add32_sat(ixheaacd_sat64_32((WORD64)4 * (WORD64)kv[0]), sum));
|
|
z[0] = (ixheaacd_sub32_sat(y[0], 2)) >> count;
|
|
if (m != 0)
|
|
rem1[0] = (ixheaacd_sub32_sat(y[0], 2)) % m;
|
|
else
|
|
rem1[0] = ixheaacd_sub32_sat(y[0], 2);
|
|
|
|
memcpy(rem2, rem1, 8 * sizeof(WORD32));
|
|
|
|
ixheaacd_voronoi_search(z, v, count, rem1, rem2);
|
|
|
|
ptr1 = y;
|
|
ptr2 = v;
|
|
for (i = 0; i < 8; i++) {
|
|
*ptr1 = ixheaacd_sub32_sat(*ptr1,
|
|
ixheaacd_sat64_32((WORD64)m * (WORD64)*ptr2++));
|
|
ptr1++;
|
|
}
|
|
}
|
|
|
|
static VOID ixheaacd_gosset_rank_of_permutation(WORD32 rank, WORD32 *xs) {
|
|
WORD32 i, j, a[8], w[8], base, fac, fac_b, target;
|
|
|
|
j = 0;
|
|
w[j] = 1;
|
|
a[j] = xs[0];
|
|
base = 1;
|
|
for (i = 1; i < 8; i++) {
|
|
if (xs[i] != xs[i - 1]) {
|
|
j++;
|
|
w[j] = 1;
|
|
a[j] = xs[i];
|
|
} else {
|
|
w[j]++;
|
|
base *= w[j];
|
|
}
|
|
}
|
|
|
|
if (w[0] == 8) {
|
|
for (i = 0; i < 8; i++) xs[i] = a[0];
|
|
} else {
|
|
target = rank * base;
|
|
fac_b = 1;
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
fac = fac_b * ixheaacd_factorial_7[i];
|
|
j = -1;
|
|
do {
|
|
target -= w[++j] * fac;
|
|
} while (target >= 0);
|
|
xs[i] = a[j];
|
|
|
|
target += w[j] * fac;
|
|
fac_b *= w[j];
|
|
w[j]--;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static WORD32 ixheaacd_get_abs_leader_tbl(const UWORD32 *table,
|
|
UWORD32 code_book_ind, WORD32 size) {
|
|
WORD32 i;
|
|
|
|
for (i = 4; i < size; i += 4) {
|
|
if (code_book_ind < table[i]) break;
|
|
}
|
|
if (i > size) i = size;
|
|
|
|
if (code_book_ind < table[i - 2]) i -= 2;
|
|
if (code_book_ind < table[i - 1]) i--;
|
|
i--;
|
|
|
|
return (i);
|
|
}
|
|
|
|
static VOID ixheaacd_gosset_decode_base_index(WORD32 n, UWORD32 code_book_ind,
|
|
WORD32 *ya) {
|
|
WORD32 i, im, t, sign_code, idx = 0, ks, rank;
|
|
|
|
if (n < 2) {
|
|
for (i = 0; i < 8; i++) ya[i] = 0;
|
|
} else {
|
|
switch (n) {
|
|
case 2:
|
|
case 3:
|
|
i = ixheaacd_get_abs_leader_tbl(ixheaacd_cardinality_offset_table_i3,
|
|
code_book_ind, LEN_I3);
|
|
idx = ixheaacd_pos_abs_leaders_a3[i];
|
|
break;
|
|
case 4:
|
|
i = ixheaacd_get_abs_leader_tbl(ixheaacd_cardinality_offset_tab_i4,
|
|
code_book_ind, LEN_I4);
|
|
idx = ixheaacd_pos_abs_leaders_a4[i];
|
|
break;
|
|
}
|
|
|
|
for (i = 0; i < 8; i++) ya[i] = ixheaacd_absolute_leader_tab_da[idx][i];
|
|
|
|
t = ixheaacd_iso_code_index_table[idx];
|
|
im = ixheaacd_iso_code_num_table[idx];
|
|
ks = ixheaacd_get_abs_leader_tbl(ixheaacd_signed_leader_is + t,
|
|
code_book_ind, im);
|
|
|
|
sign_code = 2 * ixheaacd_iso_code_data_table[t + ks];
|
|
for (i = 7; i >= 0; i--) {
|
|
ya[i] *= (1 - (sign_code & 2));
|
|
sign_code >>= 1;
|
|
}
|
|
|
|
rank = code_book_ind - ixheaacd_signed_leader_is[t + ks];
|
|
|
|
ixheaacd_gosset_rank_of_permutation(rank, ya);
|
|
}
|
|
return;
|
|
}
|
|
|
|
VOID ixheaacd_rotated_gosset_mtx_dec(WORD32 qn, WORD32 code_book_idx,
|
|
WORD32 *kv, WORD32 *b) {
|
|
if (qn <= 4) {
|
|
ixheaacd_gosset_decode_base_index(qn, code_book_idx, b);
|
|
} else {
|
|
WORD32 i, m, c[8];
|
|
WORD32 count = 0;
|
|
while (qn > 4) {
|
|
count++;
|
|
qn -= 2;
|
|
}
|
|
|
|
if (count >= 31)
|
|
m = MAX_32;
|
|
else
|
|
m = 1 << count;
|
|
|
|
ixheaacd_gosset_decode_base_index(qn, code_book_idx, b);
|
|
|
|
ixheaacd_voronoi_idx_dec(kv, m, c, count);
|
|
|
|
for (i = 0; i < 8; i++) {
|
|
b[i] =
|
|
ixheaacd_add32_sat(ixheaacd_sat64_32((WORD64)m * (WORD64)b[i]), c[i]);
|
|
}
|
|
}
|
|
return;
|
|
} |