blob: 5ce8ff8377907d6213ac6ef59cc6b3a6fd0fa157 [file] [log] [blame]
/*
* DecoderFrame.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 "DecoderFrame.hpp"
#include <cmath>
#include <cstring>
#include "BitReader.hpp"
namespace Lc3Dec {
DecoderFrame::DecoderFrame(ResidualSpectrum& residualSpectrum_,
SpectralNoiseShaping& spectralNoiseShaping_,
PacketLossConcealment& packetLossConcealment_,
MdctDec& mdctDec_, const Lc3Config& lc3Config_,
uint16_t nbytes_)
: nbytes(nbytes_),
nbits(nbytes_ * 8),
lc3Config(lc3Config_),
tns_lpc_weighting(
(nbits <
((lc3Config.N_ms == Lc3Config::FrameDuration::d10ms) ? 480 : 360))
? 1
: 0),
sideInformation(lc3Config.NF, lc3Config.NE, lc3Config.Fs_ind),
arithmeticDec(lc3Config.NF, lc3Config.NE,
(nbits > (160 + lc3Config.Fs_ind * 160)) ? 512 : 0,
tns_lpc_weighting),
residualSpectrum(residualSpectrum_),
spectralNoiseShaping(spectralNoiseShaping_),
packetLossConcealment(packetLossConcealment_),
mdctDec(mdctDec_),
longTermPostfilter(lc3Config, nbits),
datapoints(nullptr),
frameN(0),
lastnz(0),
P_BW(0),
lsbMode(0),
gg_ind(0),
num_tns_filters(0),
pitch_present(0),
pitch_index(0),
ltpf_active(0),
F_NF(0),
ind_LF(0),
ind_HF(0),
Gind(0),
LS_indA(0),
LS_indB(0),
idxA(0),
idxB(0),
nf_seed(0),
zeroFrame(0),
gg_off(0),
X_hat_q_nf(nullptr),
X_hat_f(nullptr),
X_s_tns(nullptr),
X_hat_ss(nullptr),
x_hat_clip(nullptr) {
rc_order[0] = 0;
rc_order[1] = 0;
X_hat_q_nf = new double[lc3Config.NE];
X_hat_f = new double[lc3Config.NE];
X_s_tns = new double[lc3Config.NE];
X_hat_ss = new double[lc3Config.NE];
}
DecoderFrame::~DecoderFrame() {
if (nullptr != X_hat_q_nf) {
delete[] X_hat_q_nf;
}
if (nullptr != X_hat_f) {
delete[] X_hat_f;
}
if (nullptr != X_s_tns) {
delete[] X_s_tns;
}
if (nullptr != X_hat_ss) {
delete[] X_hat_ss;
}
if (nullptr != x_hat_clip) {
delete[] x_hat_clip;
}
}
void DecoderFrame::linkPreviousFrame(DecoderFrame* previousFrame) {
if (nullptr != previousFrame) {
longTermPostfilter = previousFrame->longTermPostfilter;
frameN = previousFrame->frameN;
}
}
void DecoderFrame::noiseFilling() {
// 3.4.4 Noise filling (d09r02_F2F)
// including extensions according to:
// section 3.4.4. Noise filling (d09r04)
// Noise filling is performed only when zeroFrame is 0.
for (int16_t k = 0; k < lc3Config.NE; k++) {
X_hat_q_nf[k] = residualSpectrum.X_hat_q_residual[k];
}
if (0 == zeroFrame) {
// bandwidth(𝑃𝑏𝑀)
// NB WB SSWB SWB FB
//𝑏𝑀_π‘ π‘‘π‘œπ‘ 80 160 240 320 400
uint16_t bw_stop_table[5] = {80, 160, 240, 320, 400};
uint16_t bw_stop = bw_stop_table[P_BW];
if (lc3Config.N_ms == Lc3Config::FrameDuration::d7p5ms) {
bw_stop *= 3;
bw_stop /= 4;
}
uint16_t NFstart =
(lc3Config.N_ms == Lc3Config::FrameDuration::d10ms) ? 24 : 18;
uint16_t NFwidth =
(lc3Config.N_ms == Lc3Config::FrameDuration::d10ms) ? 3 : 2;
/*
𝐿𝑁𝐹 Μ‚ = (8-𝐹𝑁𝐹)/16;
for k=0..bw_stop-1
if 𝐼𝑁𝐹(k)==1
nf_seed = (13849+nf_seed*31821) & 0xFFFF;
if nf_seed<0x8000
π‘‹π‘ž Μ‚(π‘˜) = 𝐿𝑁𝐹 Μ‚ ;
else
π‘‹π‘ž Μ‚(π‘˜) = βˆ’πΏπ‘πΉ Μ‚ ;
*/
uint16_t nf_state = nf_seed;
double L_NF_hat = (8 - F_NF) / 16.0;
for (uint16_t k = 0; k < bw_stop; k++) {
/*
The indices for the relevant spectral coefficients are given by:
𝐼𝑁𝐹 (π‘˜) = {
1 if 24 ≀ π‘˜ < 𝑏𝑀_π‘ π‘‘π‘œπ‘ π‘Žπ‘›π‘‘ π‘‹π‘ž Μ‚(𝑖) == 0 π‘“π‘œπ‘Ÿ π‘Žπ‘™π‘™ 𝑖 = π‘˜ βˆ’ 3. . min(π‘π‘€π‘ π‘‘π‘œπ‘
βˆ’ 1, π‘˜ + 3) 0 otherwise # (109) where 𝑏𝑀_π‘ π‘‘π‘œπ‘ depends on the bandwidth
information (see Section 3.4.2.4) as defined in Table 3.17.
*/
uint8_t I_NF_k = 0;
if ((NFstart <= k) && (k < bw_stop)) {
uint16_t limit =
((bw_stop - 1) < (k + NFwidth)) ? (bw_stop - 1) : (k + NFwidth);
I_NF_k = 1;
for (uint16_t i = k - NFwidth; i <= limit; i++) {
if (0 != residualSpectrum.X_hat_q_residual[i]) {
I_NF_k = 0;
break;
}
}
}
if (1 == I_NF_k) {
nf_state = (13849 + nf_state * 31821) & 0xFFFF;
if (nf_state < 0x8000) {
X_hat_q_nf[k] = L_NF_hat;
} else {
X_hat_q_nf[k] = -L_NF_hat;
}
}
}
}
}
void DecoderFrame::applyGlobalGain() {
// 3.4.5 Global gain (d09r02_F2F)
// The global gain is applied to the spectrum after noise filling has been
// applied using the following formula (110) & (111)
int16_t v1 = nbits / (10 * (lc3Config.Fs_ind + 1));
if (v1 > 115) {
gg_off = -115;
} else {
gg_off = -v1;
}
gg_off -= 105;
gg_off -= 5 * (lc3Config.Fs_ind + 1);
double exponent = (gg_ind + gg_off) / 28.0;
double gg = pow(10.0, exponent);
for (int16_t k = 0; k < lc3Config.NE; k++) {
X_hat_f[k] = gg * X_hat_q_nf[k];
}
}
void DecoderFrame::temporalNoiseShaping() {
// 3.4.6 TNS DecoderFrame (d09r02_F2F)
/*
for π‘˜ = 0 to 𝑁𝐸 βˆ’ 1 do {
𝑋𝑠 Μ‚(𝑛) = 𝑋𝑓 Μ‚(𝑛)
}
s0 = s1 = s2 = s3 = s4 = s5 = s6 = s7 = 0
for 𝑓 = 0 to num_tns_filters-1 do {
if (π‘Ÿπ‘π‘œπ‘Ÿπ‘‘π‘’π‘Ÿ (𝑓) > 0)
{
for 𝑛 = start_freq(𝑓) to stop_freq(f) βˆ’ 1 do {
t = 𝑋𝑓 Μ‚ (𝑛) βˆ’ π‘Ÿπ‘π‘ž (π‘Ÿπ‘π‘œπ‘Ÿπ‘‘π‘’π‘Ÿ (𝑓) βˆ’ 1 , 𝑓) βˆ™ π‘ π‘Ÿπ‘π‘œπ‘Ÿπ‘‘π‘’π‘Ÿ(𝑓)βˆ’1
for π‘˜ = π‘Ÿπ‘π‘œπ‘Ÿπ‘‘π‘’π‘Ÿ (𝑓) βˆ’ 2 to 0 do {
𝑑 = 𝑑 βˆ’ π‘Ÿπ‘π‘ž (π‘˜, 𝑓) βˆ™ π‘ π‘˜
π‘ π‘˜+1 = π‘Ÿπ‘π‘ž (π‘˜, 𝑓) βˆ™ 𝑑 + π‘ π‘˜
}
𝑋𝑆 Μ‚(𝑛) = 𝑑
𝑠0 = 𝑑
}
}
}
*/
uint16_t start_freq[2] = {12, 160};
uint16_t stop_freq[2];
if (lc3Config.N_ms == Lc3Config::FrameDuration::d10ms) {
if (4 == P_BW) start_freq[1] = 200;
switch (P_BW) {
case 0:
stop_freq[0] = 80;
break;
case 1:
stop_freq[0] = 160;
break;
case 2:
stop_freq[0] = 240;
break;
case 3:
stop_freq[0] = 160;
stop_freq[1] = 320;
break;
case 4:
stop_freq[0] = 200;
stop_freq[1] = 400;
break;
}
} else {
start_freq[0] = 9;
if (3 == P_BW) start_freq[1] = 120; // Errata 15098 implemented
if (4 == P_BW) start_freq[1] = 150;
switch (P_BW) {
case 0:
stop_freq[0] = 60;
break;
case 1:
stop_freq[0] = 120;
break;
case 2:
stop_freq[0] = 180;
break;
case 3:
// stop_freq[0] = 119; // this value is specified in Table 3.19
// (d09r06_KLG_AY_NH_FhG, 2019-12-20), but gives poor match to 32kHz
// decoder tests compared to reference decoder
stop_freq[0] = 120; // this value gives good match to reference decoder
// and is more consistent to 10ms case
stop_freq[1] = 240;
break;
case 4:
stop_freq[0] = 150;
stop_freq[1] = 300;
break;
}
}
for (int16_t k = 0; k < lc3Config.NE; k++) {
X_s_tns[k] = X_hat_f[k];
}
double s[8];
for (uint8_t k = 0; k < 8; k++) {
s[k] = 0.0;
}
for (uint8_t f = 0; f < num_tns_filters; f++) {
if (arithmeticDec.rc_order_ari[f] > 0) {
for (uint16_t n = start_freq[f]; n < stop_freq[f]; n++) {
double t = X_hat_f[n] -
arithmeticDec.rc_q(arithmeticDec.rc_order_ari[f] - 1, f) *
s[arithmeticDec.rc_order_ari[f] - 1];
for (int8_t k = arithmeticDec.rc_order_ari[f] - 2; k >= 0; k--) {
t = t - arithmeticDec.rc_q(k, f) * s[k];
s[k + 1] = arithmeticDec.rc_q(k, f) * t + s[k];
}
X_s_tns[n] = t;
s[0] = t;
}
}
}
}
void DecoderFrame::runFloat(const uint8_t* bytes, uint8_t BFI,
uint8_t& BEC_detect) {
// increment frame counter
frameN++;
// 5.4.2.2 Initialization
uint16_t bp = 0;
uint16_t bp_side = nbytes - 1;
uint8_t mask_side = 1;
BEC_detect = BFI; // Note: the base specification initializes BEC_detect with
// zero, but initialization with BFI is more meaningful
// 5.4.2.3 Side information
if (!BEC_detect) {
sideInformation.run(bytes, bp_side, mask_side, P_BW, lastnz, lsbMode,
gg_ind, num_tns_filters, rc_order, pitch_present,
pitch_index, ltpf_active, F_NF, ind_LF, ind_HF, Gind,
LS_indA, LS_indB, idxA, idxB, BEC_detect);
}
// 3.4.2.4 Bandwidth interpretation (d09r02_F2F)
// ...included somewhere else?
// 3.4.2.5 Arithmetic decoding (d09r02_F2F)
if (!BEC_detect) {
arithmeticDec.run(bytes, bp, bp_side, mask_side, num_tns_filters, rc_order,
lsbMode, lastnz, nbits, BEC_detect);
}
if (!BEC_detect) {
/* Decode residual bits */
// and 3.4.3 Residual decoding (d09r02_F2F)
residualSpectrum.run(bytes, bp_side, mask_side, lastnz,
arithmeticDec.X_hat_q_ari,
arithmeticDec.nbits_residual, arithmeticDec.save_lev,
lsbMode, nf_seed, zeroFrame, gg_ind, F_NF);
// 3.4.4 Noise filling (d09r02_F2F)
noiseFilling();
// 3.4.5 Global gain (d09r02_F2F)
applyGlobalGain();
// 3.4.6 TNS decoder (d09r02_F2F)
temporalNoiseShaping();
// 3.4.7 SNS decoder (d09r02_F2F)
spectralNoiseShaping.run(
X_s_tns, X_hat_ss, ind_LF, ind_HF, sideInformation.submodeMSB,
sideInformation.submodeLSB, Gind, LS_indA, LS_indB, idxA, idxB);
}
// Appendix B. Packet Loss Concealment (d09r02_F2F)
packetLossConcealment.run(BEC_detect, X_hat_ss, ltpf_active);
// 3.4.8 Low delay MDCT synthesis (d09r02_F2F)
mdctDec.run(X_hat_ss);
// 3.4.9 Long Term Postfilter (d09r02_F2F)
if (0 == pitch_present) {
pitch_index = 0;
ltpf_active = 0;
}
longTermPostfilter.setInputX(mdctDec.x_hat_mdct);
longTermPostfilter.run(ltpf_active, pitch_index);
}
void DecoderFrame::registerDatapoints(DatapointContainer* datapoints_) {
datapoints = datapoints_;
if (nullptr != datapoints) {
datapoints->addDatapoint("fs_idx", &lc3Config.Fs_ind,
sizeof(lc3Config.Fs_ind));
datapoints->addDatapoint("frameN", &frameN, sizeof(frameN));
datapoints->addDatapoint("lastnz", &lastnz, sizeof(lastnz));
datapoints->addDatapoint("P_BW", &P_BW, sizeof(P_BW));
datapoints->addDatapoint("lsbMode", &lsbMode, sizeof(lsbMode));
datapoints->addDatapoint("gg_ind", &gg_ind, sizeof(gg_ind));
datapoints->addDatapoint("num_tns_filters", &num_tns_filters,
sizeof(num_tns_filters));
datapoints->addDatapoint("rc_order", &rc_order[0], sizeof(rc_order));
datapoints->addDatapoint("pitch_index", &pitch_index, sizeof(pitch_index));
datapoints->addDatapoint("pitch_present", &pitch_present,
sizeof(pitch_present));
datapoints->addDatapoint("ltpf_active", &ltpf_active, sizeof(ltpf_active));
datapoints->addDatapoint("F_NF", &F_NF, sizeof(F_NF));
datapoints->addDatapoint("ind_LF", &ind_LF, sizeof(ind_LF));
datapoints->addDatapoint("ind_HF", &ind_HF, sizeof(ind_HF));
datapoints->addDatapoint("Gind", &Gind, sizeof(Gind));
datapoints->addDatapoint("LS_indA", &LS_indA, sizeof(LS_indA));
datapoints->addDatapoint("idxA", &idxA, sizeof(idxA));
datapoints->addDatapoint("idxB", &idxB, sizeof(idxB));
datapoints->addDatapoint("nf_seed", &nf_seed, sizeof(nf_seed));
datapoints->addDatapoint("zeroFrame", &zeroFrame, sizeof(zeroFrame));
datapoints->addDatapoint("gg_off", &gg_off, sizeof(gg_off));
datapoints->addDatapoint("rc_i_tns", &arithmeticDec.rc_i[0],
sizeof(arithmeticDec.rc_i[0]) * 8);
datapoints->addDatapoint("X_hat_q_nf", &X_hat_q_nf[0],
sizeof(double) * lc3Config.NE);
datapoints->addDatapoint("X_s_tns", &X_s_tns[0],
sizeof(double) * lc3Config.NE);
datapoints->addDatapoint("X_hat_ss", &X_hat_ss[0],
sizeof(double) * lc3Config.NE);
if (nullptr == x_hat_clip) {
x_hat_clip = new double[lc3Config.NF];
}
datapoints->addDatapoint("x_hat_clip", &x_hat_clip[0],
sizeof(double) * lc3Config.NF);
sideInformation.registerDatapoints(datapoints);
arithmeticDec.registerDatapoints(datapoints);
longTermPostfilter.registerDatapoints(datapoints);
}
}
} // namespace Lc3Dec