btstack/3rd-party/liblc3codec/Decoder/ResidualSpectrum.cpp
2022-02-23 18:17:21 +01:00

260 lines
7.8 KiB
C++
Raw 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.

/*
* ResidualSpectrum.cpp
*
* Copyright 2019 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 "ResidualSpectrum.hpp"
#include "BitReader.hpp"
#include <cmath>
namespace Lc3Dec
{
ResidualSpectrum::ResidualSpectrum(uint16_t NE_)
:
NE(NE_),
X_hat_q_residual(nullptr),
nResBits(0)
{
X_hat_q_residual = new double[NE];
}
ResidualSpectrum::~ResidualSpectrum()
{
delete[] X_hat_q_residual;
}
void ResidualSpectrum::run(
const uint8_t* bytes,
uint16_t& bp_side,
uint8_t& mask_side,
const uint16_t lastnz,
const int16_t* const X_hat_q_ari,
uint16_t const nbits_residual, // the const is implementation dependent and thus not repeated in header declaration
uint8_t* save_lev,
const uint8_t& lsbMode,
uint16_t& nf_seed,
uint16_t& zeroFrame,
const int16_t gg_ind,
int16_t F_NF
)
{
// 3.4.2.6 Residual data and finalization (d09r02_F2F)
/* Decode residual bits */
for (uint16_t k = 0; k < lastnz; k++)
{
X_hat_q_residual [k] = X_hat_q_ari[k];
}
//for (k = lastnz; k < 𝑁𝐸; k++)
for (uint16_t k = lastnz; k < NE; k++)
{
//𝑋𝑞 ̂[k] = 0;
X_hat_q_residual [k] = 0;
}
uint8_t resBits[nbits_residual];
uint16_t remaining_nbits_residual = nbits_residual; // changed relative to specification to ensure const input into array allocation
nResBits = 0;
if (lsbMode == 0)
{
//for (k = 0; k < 𝑁𝐸; k++)
for (uint16_t k = 0; k < NE; k++)
{
//if (𝑋𝑞 ̂[k] != 0)
if (X_hat_q_residual[k] != 0)
{
if (nResBits == remaining_nbits_residual)
{
break;
}
resBits[nResBits++] = read_bit(bytes, &bp_side, &mask_side);
}
}
}
else
{
for (uint16_t k = 0; k < lastnz; k+=2)
{
if (save_lev[k] > 0)
{
if (remaining_nbits_residual == 0)
{
break;
}
uint8_t bit = read_bit(bytes, &bp_side, &mask_side);
remaining_nbits_residual--;
if (bit == 1)
{
//if (𝑋𝑞 ̂[k] > 0)
if (X_hat_q_residual[k] > 0)
{
//𝑋𝑞 ̂[k] += 1;
X_hat_q_residual[k] += 1;
}
//else if (𝑋𝑞 ̂[k] < 0)
else if (X_hat_q_residual[k] < 0)
{
//𝑋𝑞 ̂[k] -= 1;
X_hat_q_residual[k] -= 1;
}
else
{
if (remaining_nbits_residual == 0)
{
break;
}
bit = read_bit(bytes, &bp_side, &mask_side);
remaining_nbits_residual--;
if (bit == 0)
{
//𝑋𝑞 ̂[k] = 1;
X_hat_q_residual[k] = 1;
}
else
{
//𝑋𝑞 ̂[k] = -1;
X_hat_q_residual[k] = -1;
}
}
}
if (remaining_nbits_residual == 0)
{
break;
}
bit = read_bit(bytes, &bp_side, &mask_side);
remaining_nbits_residual--;
if (bit == 1)
{
//if (𝑋𝑞 ̂[k+1] > 0)
if (X_hat_q_residual[k+1] > 0)
{
//𝑋𝑞 ̂[k+1] += 1;
X_hat_q_residual[k+1] += 1;
}
//else if (𝑋𝑞 ̂[k+1] < 0)
else if (X_hat_q_residual[k+1] < 0)
{
//𝑋𝑞 ̂[k+1] -= 1;
X_hat_q_residual[k+1] -= 1;
}
else
{
if (remaining_nbits_residual == 0)
{
break;
}
bit = read_bit(bytes, &bp_side, &mask_side);
remaining_nbits_residual--;
if (bit == 0)
{
//𝑋𝑞 ̂[k+1] = 1;
X_hat_q_residual[k+1] = 1;
}
else
{
//𝑋𝑞 ̂[k+1] = -1;
X_hat_q_residual[k+1] = -1;
}
}
}
}
}
}
/* Noise Filling Seed */
int16_t tmp = 0;
//for (k = 0; k < 𝑁𝐸; k++)
for (uint16_t k = 0; k < NE; k++)
{
//tmp += abs(𝑋𝑞 ̂[k]) * k;
tmp += abs(X_hat_q_residual[k]) * k;
}
nf_seed = tmp & 0xFFFF; /* Note that both tmp and nf_seed are 32-bit int*/
/* Zero frame flag */
//if (lastnz == 2 && 𝑋𝑞 ̂[0] == 0 && 𝑋𝑞 ̂[1] == 0 && 𝑔𝑔𝑖𝑛𝑑 == 0 && 𝐹𝑁𝐹 == 7)
if (
(lastnz == 2) && (X_hat_q_residual[0] == 0.0) &&
(X_hat_q_residual[1] == 0.0) &&
(gg_ind == 0) &&
(F_NF == 7)
)
{
zeroFrame = 1;
}
else
{
zeroFrame = 0;
}
//3.4.3 Residual decoding (d09r02_F2F)
//Residual decoding is performed only when lsbMode is 0.
if (lsbMode == 0)
{
uint16_t k, n;
k = n = 0;
//while (k < 𝑁𝐸 && n < nResBits)
while (k < NE && n < nResBits)
{
//if (𝑋𝑞 ̂[k] != 0)
if (X_hat_q_residual[k] != 0)
{
if (resBits[n++] == 0)
{
//if (𝑋𝑞 ̂[k] > 0)
if (X_hat_q_residual[k] > 0)
{
//𝑋𝑞 ̂[k] -= 0.1875;
X_hat_q_residual[k] -= 0.1875;
}
else
{
//𝑋𝑞 ̂[k] -= 0.3125;
X_hat_q_residual[k] -= 0.3125;
}
}
else
{
//if (𝑋𝑞 ̂[k] > 0)
if (X_hat_q_residual[k] > 0)
{
//𝑋𝑞 ̂[k] += 0.3125;
X_hat_q_residual[k] += 0.3125;
}
else
{
//𝑋𝑞 ̂[k] += 0.1875;
X_hat_q_residual[k] += 0.1875;
}
}
}
k++;
}
}
}
void ResidualSpectrum::registerDatapoints(DatapointContainer* datapoints)
{
if (nullptr != datapoints)
{
datapoints->addDatapoint( "X_hat_q_residual", &X_hat_q_residual[0], sizeof(double)*NE );
}
}
}//namespace Lc3Dec