433 lines
12 KiB
C
433 lines
12 KiB
C
/******************************************************************************
|
|
* *
|
|
* Copyright (C) 2023 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 <string.h>
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
#include "ixheaac_type_def.h"
|
|
#include "ixheaace_adjust_threshold_data.h"
|
|
#include "iusace_bitbuffer.h"
|
|
#include "ixheaace_mps_common_define.h"
|
|
|
|
/* DRC */
|
|
#include "impd_drc_common_enc.h"
|
|
#include "impd_drc_uni_drc.h"
|
|
#include "impd_drc_tables.h"
|
|
#include "impd_drc_api.h"
|
|
#include "impd_drc_uni_drc_eq.h"
|
|
#include "impd_drc_uni_drc_filter_bank.h"
|
|
#include "impd_drc_gain_enc.h"
|
|
#include "impd_drc_struct_def.h"
|
|
|
|
#include "iusace_cnst.h"
|
|
#include "iusace_tns_usac.h"
|
|
#include "iusace_psy_mod.h"
|
|
#include "iusace_config.h"
|
|
#include "iusace_arith_enc.h"
|
|
#include "iusace_block_switch_const.h"
|
|
#include "iusace_rom.h"
|
|
|
|
#define ARITH_ESCAPE (16)
|
|
|
|
static VOID iusace_arith_map_context(WORD32 pres_n, WORD32 prev_n, WORD32 *ptr_c_prev,
|
|
WORD32 *ptr_c_pres, WORD32 arith_reset_flag) {
|
|
WORD32 i, k;
|
|
FLOAT32 ratio;
|
|
WORD32 c_prev[516];
|
|
WORD32 c_pres[516];
|
|
|
|
if (arith_reset_flag) {
|
|
memset(ptr_c_pres, 0, 516 * sizeof(WORD32));
|
|
memset(ptr_c_prev, 0, 516 * sizeof(WORD32));
|
|
} else {
|
|
memcpy(&c_prev[2], &ptr_c_prev[2], (prev_n / 2 + 2) * sizeof(WORD32));
|
|
memcpy(&c_pres[2], &ptr_c_pres[2], (prev_n / 2 + 2) * sizeof(WORD32));
|
|
|
|
ratio = (FLOAT32)(prev_n) / (FLOAT32)(pres_n);
|
|
for (i = 0; i < (pres_n / 2); i++) {
|
|
k = (WORD32)((FLOAT32)(i)*ratio);
|
|
ptr_c_pres[2 + i] = c_pres[2 + k];
|
|
ptr_c_prev[2 + i] = c_prev[2 + k];
|
|
}
|
|
|
|
ptr_c_pres[(pres_n / 2) + 2] = c_pres[(prev_n / 2) + 2];
|
|
ptr_c_pres[(pres_n / 2) + 3] = c_pres[(prev_n / 2) + 3];
|
|
ptr_c_prev[(pres_n / 2) + 2] = c_prev[(prev_n / 2) + 2];
|
|
ptr_c_prev[(pres_n / 2) + 3] = c_prev[(prev_n / 2) + 3];
|
|
}
|
|
return;
|
|
}
|
|
|
|
static WORD32 iusace_arith_get_state(WORD32 *c_pres, WORD32 *c_prev, WORD32 *s, WORD32 idx) {
|
|
WORD32 s_tmp = *s;
|
|
|
|
s_tmp = s_tmp >> 4;
|
|
s_tmp = s_tmp + (c_prev[idx + 1] << 12);
|
|
s_tmp = (s_tmp & 0xFFF0) + c_pres[idx - 1];
|
|
|
|
*s = s_tmp;
|
|
|
|
if (idx > 3) {
|
|
if ((c_pres[idx - 1] + c_pres[idx - 2] + c_pres[idx - 3]) < 5) {
|
|
return (s_tmp + 0x10000);
|
|
}
|
|
}
|
|
|
|
return (s_tmp);
|
|
}
|
|
|
|
static UWORD16 iusace_arith_get_pk(WORD32 c) {
|
|
WORD32 j;
|
|
WORD32 i, i_min, i_max;
|
|
|
|
i_min = -1;
|
|
i_max = (sizeof(iusace_ari_lookup_m) / sizeof(iusace_ari_lookup_m[0])) - 1;
|
|
while ((i_max - i_min) > 1) {
|
|
i = i_min + ((i_max - i_min) / 2);
|
|
j = iusace_ari_hash_m[i];
|
|
if (c < j)
|
|
i_max = i;
|
|
else if (c > j)
|
|
i_min = i;
|
|
else
|
|
return (iusace_ari_hash_m_lsb[i]);
|
|
}
|
|
|
|
return (iusace_ari_lookup_m[i_max]);
|
|
}
|
|
|
|
static VOID iusace_copy_bit_buf(ia_bit_buf_struct *it_bit_buff_dest,
|
|
ia_bit_buf_struct *it_bit_buff_src) {
|
|
if (it_bit_buff_src != NULL && it_bit_buff_dest != NULL) {
|
|
it_bit_buff_dest->cnt_bits = it_bit_buff_src->cnt_bits;
|
|
it_bit_buff_dest->ptr_write_next = it_bit_buff_src->ptr_write_next;
|
|
it_bit_buff_dest->write_position = it_bit_buff_src->write_position;
|
|
}
|
|
return;
|
|
}
|
|
|
|
static WORD32 iusace_arith_encode_level2(ia_bit_buf_struct *pstr_it_bit_buff, WORD32 bp,
|
|
WORD32 *ptr_c_pres, WORD32 *ptr_c_prev, WORD32 *quant,
|
|
WORD32 n, WORD32 nt, WORD32 use_stop) {
|
|
WORD32 qs[32];
|
|
iusace_state_arith as, as_stop;
|
|
|
|
WORD32 a, b, a1, b1, m;
|
|
WORD32 s, t, i, l, lev, esc_nb;
|
|
UWORD16 pki;
|
|
WORD32 bp_start = bp;
|
|
WORD32 bp_stop = bp;
|
|
WORD32 stop = 0;
|
|
WORD32 sopt;
|
|
WORD32 a2, b2;
|
|
ia_bit_buf_struct it_bit_buff_temp;
|
|
memset(&it_bit_buff_temp, 0, sizeof(it_bit_buff_temp));
|
|
iusace_copy_bit_buf(&it_bit_buff_temp, pstr_it_bit_buff);
|
|
|
|
as.low = 0;
|
|
as.high = 65535;
|
|
as.value = 0;
|
|
|
|
sopt = ptr_c_prev[0] << 12;
|
|
|
|
for (i = 0; i < n; i++) {
|
|
if ((use_stop == 1 || use_stop == 2) && (stop == 0)) {
|
|
WORD32 j;
|
|
|
|
stop = 1;
|
|
for (j = i; j < n; j++) {
|
|
if (quant[2 * j] != 0 || quant[2 * j + 1] != 0) {
|
|
stop = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (stop) {
|
|
s = iusace_arith_get_state(ptr_c_pres, ptr_c_prev, &sopt, i);
|
|
t = s & 0xFFFFF;
|
|
|
|
pki = iusace_arith_get_pk(t);
|
|
|
|
if (use_stop == 1) {
|
|
bp = iusace_arith_encode(pstr_it_bit_buff, bp, &as, ARITH_ESCAPE, iusace_ari_cf_m[pki]);
|
|
pki = iusace_arith_get_pk(t + (1 << 17));
|
|
bp = iusace_arith_encode(pstr_it_bit_buff, bp, &as, 0, iusace_ari_cf_m[pki]);
|
|
|
|
break;
|
|
} else {
|
|
bp_stop = bp;
|
|
as_stop.low = as.low;
|
|
as_stop.high = as.high;
|
|
as_stop.value = as.value;
|
|
|
|
bp_stop =
|
|
iusace_arith_encode(NULL, bp_stop, &as_stop, ARITH_ESCAPE, iusace_ari_cf_m[pki]);
|
|
|
|
pki = iusace_arith_get_pk(t + (1 << 17));
|
|
bp_stop = iusace_arith_encode(NULL, bp_stop, &as_stop, (0), iusace_ari_cf_m[pki]);
|
|
}
|
|
}
|
|
}
|
|
s = iusace_arith_get_state(ptr_c_pres, ptr_c_prev, &sopt, i);
|
|
t = s & 0xFFFFF;
|
|
|
|
a = quant[2 * i];
|
|
b = quant[2 * i + 1];
|
|
a1 = abs(a);
|
|
b1 = abs(b);
|
|
|
|
ptr_c_pres[i] = a1 + b1 + 1;
|
|
if (ptr_c_pres[i] > 0xF) {
|
|
ptr_c_pres[i] = 0xF;
|
|
}
|
|
|
|
lev = 0;
|
|
esc_nb = 0;
|
|
|
|
while ((a1) > 3 || (b1) > 3) {
|
|
pki = iusace_arith_get_pk(t + (esc_nb << 17));
|
|
|
|
bp = iusace_arith_encode(pstr_it_bit_buff, bp, &as, ARITH_ESCAPE, iusace_ari_cf_m[pki]);
|
|
|
|
qs[lev++] = (a1 & 1) | ((b1 & 1) << 1);
|
|
a1 >>= 1;
|
|
b1 >>= 1;
|
|
esc_nb++;
|
|
|
|
if (esc_nb > 7) {
|
|
esc_nb = 7;
|
|
}
|
|
}
|
|
m = a1 + (b1 << 2);
|
|
pki = iusace_arith_get_pk(t + (esc_nb << 17));
|
|
bp = iusace_arith_encode(pstr_it_bit_buff, bp, &as, m, iusace_ari_cf_m[pki]);
|
|
|
|
a2 = a1;
|
|
b2 = b1;
|
|
|
|
for (l = lev - 1; l >= 0; l--) {
|
|
WORD32 lsbidx = (a2 == 0) ? 1 : ((b2 == 0) ? 0 : 2);
|
|
bp = iusace_arith_encode(pstr_it_bit_buff, bp, &as, qs[l], iusace_ari_cf_r[lsbidx]);
|
|
|
|
a2 = (a2 << 1) | (qs[l] & 1);
|
|
b2 = (b2 << 1) | ((qs[l] >> 1) & 1);
|
|
}
|
|
}
|
|
|
|
if (use_stop == 2) {
|
|
bp = iusace_arith_done(pstr_it_bit_buff, bp, &as);
|
|
if (stop) {
|
|
bp_stop = iusace_arith_done(NULL, bp_stop, &as_stop);
|
|
|
|
if (bp_stop < bp) {
|
|
iusace_copy_bit_buf(pstr_it_bit_buff, &it_bit_buff_temp);
|
|
bp = iusace_arith_encode_level2(pstr_it_bit_buff, bp_start, ptr_c_pres, ptr_c_prev, quant,
|
|
n, nt, 1);
|
|
} else {
|
|
iusace_copy_bit_buf(pstr_it_bit_buff, &it_bit_buff_temp);
|
|
bp = iusace_arith_encode_level2(pstr_it_bit_buff, bp_start, ptr_c_pres, ptr_c_prev, quant,
|
|
n, nt, 0);
|
|
}
|
|
} else {
|
|
iusace_copy_bit_buf(pstr_it_bit_buff, &it_bit_buff_temp);
|
|
bp = iusace_arith_encode_level2(pstr_it_bit_buff, bp_start, ptr_c_pres, ptr_c_prev, quant,
|
|
n, nt, 0);
|
|
}
|
|
} else {
|
|
bp = iusace_arith_done(pstr_it_bit_buff, bp, &as);
|
|
|
|
for (; i < nt; i++) {
|
|
ptr_c_pres[i] = 1;
|
|
}
|
|
|
|
for (i = 0; i < n; i++) {
|
|
if (quant[2 * i] != 0) {
|
|
if (quant[2 * i] > 0) {
|
|
iusace_write_bits_buf(pstr_it_bit_buff, 1, 1);
|
|
bp++;
|
|
} else {
|
|
iusace_write_bits_buf(pstr_it_bit_buff, 0, 1);
|
|
bp++;
|
|
}
|
|
}
|
|
|
|
if (quant[2 * i + 1] != 0) {
|
|
if (quant[2 * i + 1] > 0) {
|
|
iusace_write_bits_buf(pstr_it_bit_buff, 1, 1);
|
|
bp++;
|
|
} else {
|
|
iusace_write_bits_buf(pstr_it_bit_buff, 0, 1);
|
|
bp++;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (i = 0; i < nt; i++) {
|
|
ptr_c_prev[i] = ptr_c_pres[i];
|
|
ptr_c_pres[i] = 1;
|
|
}
|
|
}
|
|
|
|
return bp;
|
|
}
|
|
|
|
WORD32 iusace_arith_enc_spec(ia_bit_buf_struct *it_bit_buf, WORD32 window_sequence,
|
|
WORD32 *ptr_x_ac_enc, WORD32 max_spec_coefficients,
|
|
WORD32 *ptr_c_pres, WORD32 *ptr_c_prev, WORD32 *ptr_size_prev,
|
|
WORD32 arith_reset_flag, WORD32 ccfl) {
|
|
LOOPIDX i;
|
|
WORD32 write_flag = (it_bit_buf != NULL);
|
|
WORD32 size;
|
|
WORD32 num_wins = (window_sequence == EIGHT_SHORT_SEQUENCE) ? MAX_SHORT_WINDOWS : 1;
|
|
WORD32 bits_data_written = 0;
|
|
|
|
switch (window_sequence) {
|
|
case ONLY_LONG_SEQUENCE:
|
|
case LONG_START_SEQUENCE:
|
|
case STOP_START_SEQUENCE:
|
|
case LONG_STOP_SEQUENCE:
|
|
size = ccfl;
|
|
break;
|
|
case EIGHT_SHORT_SEQUENCE:
|
|
size = ccfl >> 3;
|
|
break;
|
|
default:
|
|
size = ccfl >> 3;
|
|
break;
|
|
}
|
|
|
|
iusace_arith_map_context(size, *ptr_size_prev, ptr_c_pres, ptr_c_prev, arith_reset_flag);
|
|
|
|
if (max_spec_coefficients > 0) {
|
|
for (i = 0; i < num_wins; i++) {
|
|
bits_data_written = iusace_arith_encode_level2(
|
|
it_bit_buf, bits_data_written, ptr_c_pres + 2, ptr_c_prev + 2, &ptr_x_ac_enc[i * size],
|
|
max_spec_coefficients / 2, size / 2, 2);
|
|
}
|
|
}
|
|
|
|
if (write_flag) {
|
|
*ptr_size_prev = size;
|
|
}
|
|
|
|
return bits_data_written;
|
|
}
|
|
|
|
WORD32 iusace_tcx_coding(ia_bit_buf_struct *pstr_it_bit_buff, WORD32 tcx_size,
|
|
WORD32 max_tcx_size, WORD32 *ptr_quant, WORD32 *c_pres, WORD32 *c_prev) {
|
|
WORD32 bits_written = 0;
|
|
|
|
iusace_arith_map_context(tcx_size, max_tcx_size, c_pres, c_prev, 0);
|
|
|
|
bits_written =
|
|
iusace_arith_encode_level2(pstr_it_bit_buff, bits_written, c_pres + 2, c_prev + 2,
|
|
&ptr_quant[0], tcx_size / 2, tcx_size / 2, 2);
|
|
|
|
iusace_arith_map_context(max_tcx_size, tcx_size, c_pres, c_prev, 0);
|
|
|
|
return bits_written;
|
|
}
|
|
|
|
WORD32 iusace_arith_done(ia_bit_buf_struct *pstr_it_bit_buff, WORD32 bp, iusace_state_arith *s) {
|
|
WORD32 low, high;
|
|
WORD32 bits_to_follow;
|
|
|
|
low = s->low;
|
|
high = s->high;
|
|
bits_to_follow = s->value + 1;
|
|
|
|
if (low < 16384) {
|
|
iusace_write_bits_buf(pstr_it_bit_buff, 0, 1);
|
|
bp++;
|
|
while (bits_to_follow) {
|
|
iusace_write_bits_buf(pstr_it_bit_buff, 1, 1);
|
|
bp++;
|
|
bits_to_follow--;
|
|
}
|
|
} else {
|
|
iusace_write_bits_buf(pstr_it_bit_buff, 1, 1);
|
|
bp++;
|
|
while (bits_to_follow) {
|
|
iusace_write_bits_buf(pstr_it_bit_buff, 0, 1);
|
|
bp++;
|
|
bits_to_follow--;
|
|
}
|
|
}
|
|
|
|
s->low = low;
|
|
s->high = high;
|
|
s->value = bits_to_follow;
|
|
|
|
return bp;
|
|
}
|
|
|
|
WORD32 iusace_arith_encode(ia_bit_buf_struct *pstr_it_bit_buff, WORD32 bp, iusace_state_arith *s,
|
|
WORD32 symbol, UWORD16 const *cum_freq) {
|
|
WORD32 low, high, range;
|
|
WORD32 bits_to_follow;
|
|
|
|
high = s->high;
|
|
low = s->low;
|
|
range = high - low + 1;
|
|
|
|
if (symbol > 0) {
|
|
high = low + ((range * cum_freq[symbol - 1]) >> 14) - 1;
|
|
}
|
|
|
|
low = low + ((range * cum_freq[symbol]) >> 14);
|
|
|
|
bits_to_follow = s->value;
|
|
|
|
for (;;) {
|
|
if (high < 32768) {
|
|
iusace_write_bits_buf(pstr_it_bit_buff, 0, 1);
|
|
bp++;
|
|
while (bits_to_follow) {
|
|
iusace_write_bits_buf(pstr_it_bit_buff, 1, 1);
|
|
bp++;
|
|
bits_to_follow--;
|
|
}
|
|
} else if (low >= 32768) {
|
|
iusace_write_bits_buf(pstr_it_bit_buff, 1, 1);
|
|
bp++;
|
|
while (bits_to_follow) {
|
|
iusace_write_bits_buf(pstr_it_bit_buff, 0, 1);
|
|
bp++;
|
|
bits_to_follow--;
|
|
}
|
|
low -= 32768;
|
|
high -= 32768;
|
|
} else if (low >= 16384 && high < 49152) {
|
|
bits_to_follow += 1;
|
|
low -= 16384;
|
|
high -= 16384;
|
|
} else
|
|
break;
|
|
|
|
low += low;
|
|
high += high + 1;
|
|
}
|
|
|
|
s->low = low;
|
|
s->high = high;
|
|
s->value = bits_to_follow;
|
|
|
|
return bp;
|
|
}
|