| /* |
| * ArithmeticDec.cpp |
| * |
| * Copyright 2021 HIMSA II K/S - www.himsa.com. 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 <algorithm> // std::min |
| #include <cmath> |
| #include <cstring> |
| |
| #include "BitReader.hpp" |
| #include "SpectralDataTables.hpp" |
| #include "TemporalNoiseShapingTables.hpp" |
| |
| 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 |