unplugged-vendor/system/bt/embdrv/lc3/Decoder/ArithmeticDec.cpp

301 lines
9.1 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* ArithmeticDec.cpp
*
* Copyright 2019 HIMSA II K/S - www.himsa.dk. Represented by EHIMA - www.ehima.com
*
* 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.
*/
#include "ArithmeticDec.hpp"
#include "TemporalNoiseShapingTables.hpp"
#include "SpectralDataTables.hpp"
#include "BitReader.hpp"
#include <cstring>
#include <cmath>
#include <algorithm> // std::min
namespace Lc3Dec
{
ArithmeticDec::ArithmeticDec(uint16_t NF_, uint16_t NE_, uint16_t rateFlag_, uint8_t tns_lpc_weighting_)
:
NF(NF_),
NE(NE_),
rateFlag(rateFlag_),
tns_lpc_weighting(tns_lpc_weighting_),
X_hat_q_ari(nullptr),
save_lev(nullptr),
nf_seed(0),
nbits_residual(0)
{
X_hat_q_ari = new int16_t[NE];
save_lev = new uint8_t[NE];
}
ArithmeticDec::~ArithmeticDec()
{
delete[] X_hat_q_ari;
delete[] save_lev;
}
void ac_dec_init(const uint8_t bytes[], uint16_t* bp, struct ac_dec_state* st)
{
st->low = 0;
st->range = 0x00ffffff;
for (uint8_t i = 0; i < 3; i++)
{
st->low <<= 8;
st->low += bytes[(*bp)++];
}
}
uint8_t ac_decode(
const uint8_t bytes[],
uint16_t* bp,
struct ac_dec_state* st,
int16_t cum_freq[],
int16_t sym_freq[],
uint8_t numsym,
uint8_t& BEC_detect
)
{
uint32_t tmp = st->range >> 10;
if (st->low >= (tmp<<10))
{
BEC_detect = 1;
return 0;
}
uint8_t val = numsym-1;
while (st->low < tmp * cum_freq[val])
{
val--;
}
st->low -= tmp * cum_freq[val];
st->range = tmp * sym_freq[val];
while (st->range < 0x10000)
{
st->low <<= 8;
st->low &= 0x00ffffff;
st->low += bytes[(*bp)++];
st->range <<= 8;
}
return val;
}
double ArithmeticDec::rc_q(uint8_t k, uint8_t f)
{
// with Δ =π/17
const double pi = std::acos(-1);
double quantizer_stepsize = pi / 17.0;
return sin( quantizer_stepsize * ( rc_i[k + 8*f] -8 ) );
}
void ArithmeticDec::run(
const uint8_t* bytes,
uint16_t& bp,
uint16_t& bp_side,
uint8_t& mask_side,
int16_t& num_tns_filters,
int16_t rc_order[],
const uint8_t& lsbMode,
const int16_t& lastnz,
uint16_t nbits,
uint8_t& BEC_detect
)
{
int16_t c = 0;
// make local copy of rc_order (is this really what we want)
rc_order_ari[0] = rc_order[0];
rc_order_ari[1] = rc_order[1];
/* Arithmetic Decoder Initialization */
ac_dec_init(bytes, &bp, &st);
/* TNS data */
// Note: some initialization code like that below can be found in d09r02,
// but there has been none in d09r01. However, the complete initialization
// has been added here, in order to get a proper match to the reference output data
for (uint8_t f = 0; f < 2; f++)
{
for (uint8_t k = 0; k < 8; k++)
{
rc_i[k + 8*f] = 8;
}
}
for (uint8_t f = 0; f < num_tns_filters; f++)
{
//if (𝑟𝑐𝑜𝑟𝑑𝑒𝑟(𝑓) > 0)
if (rc_order[f] > 0)
{
//𝑟𝑐𝑜𝑟𝑑𝑒𝑟(𝑓) = ac_decode(bytes, &bp, &st,
rc_order_ari[f] = ac_decode(bytes, &bp, &st,
ac_tns_order_cumfreq[tns_lpc_weighting],
ac_tns_order_freq[tns_lpc_weighting], 8,
BEC_detect);
if (BEC_detect)
{
// early exit to avoid unpredictable side-effects
return;
}
rc_order_ari[f] = rc_order_ari[f] + 1;
// specification (d09r02_F2F) proposes initialization
// of rc_i at this place; here implemented above in order
// to be performed independet from num_tns_filters
for (uint8_t k = 0; k < rc_order_ari[f]; k++)
{
//𝑟𝑐𝑖(𝑘,𝑓) = ac_decode(bytes, &bp, &st, ac_tns_coef_cumfreq[k],
//rc_i[k][f] = ac_decode(bytes, &bp, &st, ac_tns_coef_cumfreq[k],
rc_i[k + 8*f] = ac_decode(bytes, &bp, &st, ac_tns_coef_cumfreq[k],
ac_tns_coef_freq[k], 17,
BEC_detect);
if (BEC_detect)
{
// early exit to avoid unpredictable side-effects
return;
}
}
}
}
/* Spectral data */
for (uint16_t k = 0; k < lastnz; k += 2)
{
uint16_t t = c + rateFlag;
//if (k > 𝑁𝐸/2)
if (k > NE/2)
{
t += 256;
}
//𝑋𝑞̂[k] = 𝑋𝑞̂[k+1] = 0;
X_hat_q_ari[k] = X_hat_q_ari[k+1] = 0;
uint8_t lev;
uint8_t sym;
for (lev = 0; lev < 14; lev++)
{
uint8_t pki = ac_spec_lookup[t+std::min(lev,static_cast<uint8_t>(3U))*1024];
sym = ac_decode(bytes, &bp, &st, ac_spec_cumfreq[pki],
ac_spec_freq[pki], 17,
BEC_detect);
if (BEC_detect)
{
// early exit to avoid unpredictable side-effects
return;
}
if (sym < 16)
{
break;
}
if (lsbMode == 0 || lev > 0)
{
uint8_t bit = read_bit(bytes, &bp_side, &mask_side);
//𝑋𝑞̂[k] += bit << lev;
X_hat_q_ari[k] += bit << lev;
bit = read_bit(bytes, &bp_side, &mask_side);
//𝑋𝑞̂[k+1] += bit << lev;
X_hat_q_ari[k+1] += bit << lev;
}
}
if (lev == 14)
{
BEC_detect = 1;
return;
}
if (lsbMode == 1)
{
save_lev[k] = lev;
}
uint8_t a = sym & 0x3;
uint8_t b = sym >> 2;
//𝑋𝑞̂[k] += a << lev;
//𝑋𝑞̂[k+1] += b << lev;
//if (𝑋𝑞̂[k] > 0)
X_hat_q_ari[k] += a << lev;
X_hat_q_ari[k+1] += b << lev;
if (X_hat_q_ari[k] > 0)
{
uint8_t bit = read_bit(bytes, &bp_side, &mask_side);
if (bit == 1)
{
//𝑋𝑞̂[k] = -𝑋𝑞̂[k];
X_hat_q_ari[k] = -X_hat_q_ari[k];
}
}
//if (𝑋𝑞̂[k+1] > 0)
if (X_hat_q_ari[k+1] > 0)
{
uint8_t bit = read_bit(bytes, &bp_side, &mask_side);
if (bit == 1)
{
//𝑋𝑞̂[k+1] = -𝑋𝑞̂[k+1];
X_hat_q_ari[k+1] = -X_hat_q_ari[k+1];
}
}
lev = std::min(lev,static_cast<uint8_t>(3));
if (lev <= 1)
{
t = 1 + (a+b)*(lev+1);
}
else
{
t = 12 + lev;
}
c = (c&15)*16 + t;
// Note: specification of the following line hase been changed from d09r01 to d09r02_F2F
if (bp - bp_side > 3)
{
BEC_detect = 1;
return;
}
}
// reset remaining fields in array X_hat_q_ari to simplify testing
for (int16_t k = lastnz; k < NE; k++)
{
X_hat_q_ari [k] = 0;
}
// 3.4.2.6 Residual data and finalization (d09r02_F2F)
/* Number of residual bits */
int16_t nbits_side = nbits - (8 * bp_side + 8 - log2(mask_side));
int16_t nbits_ari = (bp - 3) * 8;
nbits_ari += 25 - floor(log2(st.range));
int16_t nbits_residual_tmp = nbits - (nbits_side + nbits_ari);
if (nbits_residual_tmp < 0)
{
BEC_detect = 1;
return;
}
nbits_residual = nbits_residual_tmp;
}
void ArithmeticDec::registerDatapoints(DatapointContainer* datapoints)
{
if (nullptr != datapoints)
{
datapoints->addDatapoint( "rateFlag", &rateFlag, sizeof(rateFlag) );
datapoints->addDatapoint( "tns_lpc_weighting", &tns_lpc_weighting, sizeof(tns_lpc_weighting) );
datapoints->addDatapoint( "rc_order_ari", &rc_order_ari[0], sizeof(rc_order_ari) );
datapoints->addDatapoint( "rc_i", &rc_i[0], sizeof(rc_i) );
datapoints->addDatapoint( "X_hat_q_ari", &X_hat_q_ari[0], sizeof(int16_t)*NE );
datapoints->addDatapoint( "nbits_residual", &nbits_residual, sizeof(nbits_residual) );
}
}
}//namespace Lc3Dec