|
|
|
@ -16,301 +16,328 @@
|
|
|
|
#include "MBEDecoder.h"
|
|
|
|
#include "MBEDecoder.h"
|
|
|
|
|
|
|
|
|
|
|
|
using namespace edac;
|
|
|
|
using namespace edac;
|
|
|
|
using namespace vocoder;
|
|
|
|
|
|
|
|
|
|
|
|
namespace vocoder {
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Constants
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// Constants
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
const int MBEDecoder::dW[72] = { 0,0,3,2,1,1,0,0,1,1,0,0,3,2,1,1,3,2,1,1,0,0,3,2,0,0,3,2,1,1,0,0,1,1,0,0,3,2,1,1,3,2,1,1,0,0,3,2,0,0,3,2,1,1,0,0,1,1,0,0,3,2,1,1,3,3,2,1,0,0,3,3, };
|
|
|
|
|
|
|
|
|
|
|
|
const int MBEDecoder::dW[72] = { 0,0,3,2,1,1,0,0,1,1,0,0,3,2,1,1,3,2,1,1,0,0,3,2,0,0,3,2,1,1,0,0,1,1,0,0,3,2,1,1,3,2,1,1,0,0,3,2,0,0,3,2,1,1,0,0,1,1,0,0,3,2,1,1,3,3,2,1,0,0,3,3, };
|
|
|
|
const int MBEDecoder::dX[72] = { 10,22,11,9,10,22,11,23,8,20,9,21,10,8,9,21,8,6,7,19,8,20,9,7,6,18,7,5,6,18,7,19,4,16,5,17,6,4,5,17,4,2,3,15,4,16,5,3,2,14,3,1,2,14,3,15,0,12,1,13,2,0,1,13,0,12,10,11,0,12,1,13, };
|
|
|
|
|
|
|
|
|
|
|
|
const int MBEDecoder::dX[72] = { 10,22,11,9,10,22,11,23,8,20,9,21,10,8,9,21,8,6,7,19,8,20,9,7,6,18,7,5,6,18,7,19,4,16,5,17,6,4,5,17,4,2,3,15,4,16,5,3,2,14,3,1,2,14,3,15,0,12,1,13,2,0,1,13,0,12,10,11,0,12,1,13, };
|
|
|
|
const int MBEDecoder::rW[36] = {
|
|
|
|
|
|
|
|
0, 1, 0, 1, 0, 1,
|
|
|
|
const int MBEDecoder::rW[36] = {
|
|
|
|
0, 1, 0, 1, 0, 1,
|
|
|
|
0, 1, 0, 1, 0, 1,
|
|
|
|
0, 1, 0, 1, 0, 1,
|
|
|
|
0, 1, 0, 1, 0, 1,
|
|
|
|
0, 1, 0, 1, 0, 2,
|
|
|
|
0, 1, 0, 1, 0, 1,
|
|
|
|
0, 2, 0, 2, 0, 2,
|
|
|
|
0, 1, 0, 1, 0, 2,
|
|
|
|
0, 2, 0, 2, 0, 2
|
|
|
|
0, 2, 0, 2, 0, 2,
|
|
|
|
};
|
|
|
|
0, 2, 0, 2, 0, 2
|
|
|
|
|
|
|
|
};
|
|
|
|
const int MBEDecoder::rX[36] = {
|
|
|
|
|
|
|
|
23, 10, 22, 9, 21, 8,
|
|
|
|
const int MBEDecoder::rX[36] = {
|
|
|
|
20, 7, 19, 6, 18, 5,
|
|
|
|
23, 10, 22, 9, 21, 8,
|
|
|
|
17, 4, 16, 3, 15, 2,
|
|
|
|
20, 7, 19, 6, 18, 5,
|
|
|
|
14, 1, 13, 0, 12, 10,
|
|
|
|
17, 4, 16, 3, 15, 2,
|
|
|
|
11, 9, 10, 8, 9, 7,
|
|
|
|
14, 1, 13, 0, 12, 10,
|
|
|
|
8, 6, 7, 5, 6, 4
|
|
|
|
11, 9, 10, 8, 9, 7,
|
|
|
|
};
|
|
|
|
8, 6, 7, 5, 6, 4
|
|
|
|
|
|
|
|
};
|
|
|
|
// bit 0
|
|
|
|
|
|
|
|
const int MBEDecoder::rY[36] = {
|
|
|
|
// bit 0
|
|
|
|
0, 2, 0, 2, 0, 2,
|
|
|
|
const int MBEDecoder::rY[36] = {
|
|
|
|
0, 2, 0, 3, 0, 3,
|
|
|
|
0, 2, 0, 2, 0, 2,
|
|
|
|
1, 3, 1, 3, 1, 3,
|
|
|
|
0, 2, 0, 3, 0, 3,
|
|
|
|
1, 3, 1, 3, 1, 3,
|
|
|
|
1, 3, 1, 3, 1, 3,
|
|
|
|
1, 3, 1, 3, 1, 3,
|
|
|
|
1, 3, 1, 3, 1, 3,
|
|
|
|
1, 3, 1, 3, 1, 3
|
|
|
|
1, 3, 1, 3, 1, 3,
|
|
|
|
};
|
|
|
|
1, 3, 1, 3, 1, 3
|
|
|
|
|
|
|
|
};
|
|
|
|
const int MBEDecoder::rZ[36] = {
|
|
|
|
|
|
|
|
5, 3, 4, 2, 3, 1,
|
|
|
|
const int MBEDecoder::rZ[36] = {
|
|
|
|
2, 0, 1, 13, 0, 12,
|
|
|
|
5, 3, 4, 2, 3, 1,
|
|
|
|
22, 11, 21, 10, 20, 9,
|
|
|
|
2, 0, 1, 13, 0, 12,
|
|
|
|
19, 8, 18, 7, 17, 6,
|
|
|
|
22, 11, 21, 10, 20, 9,
|
|
|
|
16, 5, 15, 4, 14, 3,
|
|
|
|
19, 8, 18, 7, 17, 6,
|
|
|
|
13, 2, 12, 1, 11, 0
|
|
|
|
16, 5, 15, 4, 14, 3,
|
|
|
|
};
|
|
|
|
13, 2, 12, 1, 11, 0
|
|
|
|
|
|
|
|
};
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// Public Class Members
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
// Public Class Members
|
|
|
|
|
|
|
|
// ---------------------------------------------------------------------------
|
|
|
|
/* Initializes a new instance of the MBEDecoder class. */
|
|
|
|
|
|
|
|
|
|
|
|
/* Initializes a new instance of the MBEDecoder class. */
|
|
|
|
MBEDecoder::MBEDecoder(MBE_DECODER_MODE mode) :
|
|
|
|
|
|
|
|
m_mbelibParms(NULL),
|
|
|
|
MBEDecoder::MBEDecoder(MBE_DECODER_MODE mode) :
|
|
|
|
m_mbeMode(mode),
|
|
|
|
m_mbelibParms(NULL),
|
|
|
|
m_gainAdjust(1.0f)
|
|
|
|
m_mbeMode(mode),
|
|
|
|
{
|
|
|
|
m_gainAdjust(1.0f)
|
|
|
|
m_mbelibParms = new mbelibParms();
|
|
|
|
|
|
|
|
mbe_initMbeParms(m_mbelibParms->m_cur_mp, m_mbelibParms->m_prev_mp, m_mbelibParms->m_prev_mp_enhanced);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
::memset(gainMaxBuf, 0, sizeof(float) * 200);
|
|
|
|
|
|
|
|
gainMaxBufPtr = gainMaxBuf;
|
|
|
|
|
|
|
|
gainMaxIdx = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Finalizes a instance of the MBEDecoder class. */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
MBEDecoder::~MBEDecoder()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
delete m_mbelibParms;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Decodes the given MBE codewords to deinterleaved MBE bits using the decoder mode. */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int32_t MBEDecoder::decodeBits(uint8_t* codeword, char* mbeBits)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
int32_t errs = 0;
|
|
|
|
|
|
|
|
float samples[160U];
|
|
|
|
|
|
|
|
::memset(samples, 0x00U, 160U * sizeof(float));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (m_mbeMode)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
case DECODE_DMR_AMBE:
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
char ambe_d[49U];
|
|
|
|
m_mbelibParms = new mbelibParms();
|
|
|
|
char ambe_fr[4][24];
|
|
|
|
mbe_initMbeParms(m_mbelibParms->m_cur_mp, m_mbelibParms->m_prev_mp, m_mbelibParms->m_prev_mp_enhanced);
|
|
|
|
::memset(ambe_d, 0x00U, 49U);
|
|
|
|
|
|
|
|
::memset(ambe_fr, 0x00U, 96U);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const int* w, *x, *y, *z;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
w = rW;
|
|
|
|
|
|
|
|
x = rX;
|
|
|
|
|
|
|
|
y = rY;
|
|
|
|
|
|
|
|
z = rZ;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 9; ++i) {
|
|
|
|
|
|
|
|
for (int j = 0; j < 8; j += 2) {
|
|
|
|
|
|
|
|
ambe_fr[*y][*z] = (1 & (codeword[i] >> (7 - (j + 1))));
|
|
|
|
|
|
|
|
ambe_fr[*w][*x] = (1 & (codeword[i] >> (7 - j)));
|
|
|
|
|
|
|
|
w++;
|
|
|
|
|
|
|
|
x++;
|
|
|
|
|
|
|
|
y++;
|
|
|
|
|
|
|
|
z++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
errs = mbe_eccAmbe3600x2450C0(ambe_fr);
|
|
|
|
::memset(gainMaxBuf, 0, sizeof(float) * 200);
|
|
|
|
mbe_demodulateAmbe3600x2450Data(ambe_fr);
|
|
|
|
gainMaxBufPtr = gainMaxBuf;
|
|
|
|
|
|
|
|
gainMaxIdx = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
errs += mbe_eccAmbe3600x2450Data(ambe_fr, ambe_d);
|
|
|
|
/* Finalizes a instance of the MBEDecoder class. */
|
|
|
|
|
|
|
|
|
|
|
|
::memcpy(mbeBits, ambe_d, 49U);
|
|
|
|
MBEDecoder::~MBEDecoder()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
delete m_mbelibParms;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case DECODE_88BIT_IMBE:
|
|
|
|
/* Decodes the given MBE codewords to deinterleaved MBE bits using the decoder mode. */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int32_t MBEDecoder::decodeBits(uint8_t* codeword, char* mbeBits)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
char imbe_d[88U];
|
|
|
|
int32_t errs = 0;
|
|
|
|
::memset(imbe_d, 0x00U, 88U);
|
|
|
|
float samples[160U];
|
|
|
|
|
|
|
|
::memset(samples, 0x00U, 160U * sizeof(float));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (m_mbeMode)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
case DECODE_DMR_AMBE:
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
char ambe_d[49U];
|
|
|
|
|
|
|
|
char ambe_fr[4][24];
|
|
|
|
|
|
|
|
::memset(ambe_d, 0x00U, 49U);
|
|
|
|
|
|
|
|
::memset(ambe_fr, 0x00U, 96U);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const int* w, *x, *y, *z;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
w = rW;
|
|
|
|
|
|
|
|
x = rX;
|
|
|
|
|
|
|
|
y = rY;
|
|
|
|
|
|
|
|
z = rZ;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 9; ++i) {
|
|
|
|
|
|
|
|
for (int j = 0; j < 8; j += 2) {
|
|
|
|
|
|
|
|
ambe_fr[*y][*z] = (1 & (codeword[i] >> (7 - (j + 1))));
|
|
|
|
|
|
|
|
ambe_fr[*w][*x] = (1 & (codeword[i] >> (7 - j)));
|
|
|
|
|
|
|
|
w++;
|
|
|
|
|
|
|
|
x++;
|
|
|
|
|
|
|
|
y++;
|
|
|
|
|
|
|
|
z++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 11; ++i) {
|
|
|
|
errs = mbe_eccAmbe3600x2450C0(ambe_fr);
|
|
|
|
for (int j = 0; j < 8; j++) {
|
|
|
|
mbe_demodulateAmbe3600x2450Data(ambe_fr);
|
|
|
|
imbe_d[j + (8 * i)] = (1 & (codeword[i] >> (7 - j)));
|
|
|
|
|
|
|
|
|
|
|
|
errs += mbe_eccAmbe3600x2450Data(ambe_fr, ambe_d);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
::memcpy(mbeBits, ambe_d, 49U);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
case DECODE_88BIT_IMBE:
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
char imbe_d[88U];
|
|
|
|
|
|
|
|
::memset(imbe_d, 0x00U, 88U);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 11; ++i) {
|
|
|
|
|
|
|
|
for (int j = 0; j < 8; j++) {
|
|
|
|
|
|
|
|
imbe_d[j + (8 * i)] = (1 & (codeword[i] >> (7 - j)));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
::memcpy(mbeBits, imbe_d, 88U);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
::memcpy(mbeBits, imbe_d, 88U);
|
|
|
|
return errs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return errs;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Decodes the given MBE codewords to PCM samples using the decoder mode. */
|
|
|
|
/* Decodes the given MBE codewords to PCM samples using the decoder mode. */
|
|
|
|
|
|
|
|
|
|
|
|
int32_t MBEDecoder::decodeF(uint8_t* codeword, float samples[])
|
|
|
|
int32_t MBEDecoder::decodeF(uint8_t* codeword, float samples[])
|
|
|
|
{
|
|
|
|
|
|
|
|
int32_t errs = 0;
|
|
|
|
|
|
|
|
switch (m_mbeMode)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
case DECODE_DMR_AMBE:
|
|
|
|
int32_t errs = 0;
|
|
|
|
{
|
|
|
|
switch (m_mbeMode)
|
|
|
|
char ambe_d[49U];
|
|
|
|
{
|
|
|
|
char ambe_fr[4][24];
|
|
|
|
case DECODE_DMR_AMBE:
|
|
|
|
::memset(ambe_d, 0x00U, 49U);
|
|
|
|
{
|
|
|
|
::memset(ambe_fr, 0x00U, 96U);
|
|
|
|
char ambe_d[49U];
|
|
|
|
|
|
|
|
char ambe_fr[4][24];
|
|
|
|
const int* w, *x, *y, *z;
|
|
|
|
::memset(ambe_d, 0x00U, 49U);
|
|
|
|
|
|
|
|
::memset(ambe_fr, 0x00U, 96U);
|
|
|
|
w = rW;
|
|
|
|
|
|
|
|
x = rX;
|
|
|
|
const int* w, *x, *y, *z;
|
|
|
|
y = rY;
|
|
|
|
|
|
|
|
z = rZ;
|
|
|
|
w = rW;
|
|
|
|
|
|
|
|
x = rX;
|
|
|
|
for (int i = 0; i < 9; ++i) {
|
|
|
|
y = rY;
|
|
|
|
for (int j = 0; j < 8; j += 2) {
|
|
|
|
z = rZ;
|
|
|
|
ambe_fr[*y][*z] = (1 & (codeword[i] >> (7 - (j + 1))));
|
|
|
|
|
|
|
|
ambe_fr[*w][*x] = (1 & (codeword[i] >> (7 - j)));
|
|
|
|
for (int i = 0; i < 9; ++i) {
|
|
|
|
w++;
|
|
|
|
for (int j = 0; j < 8; j += 2) {
|
|
|
|
x++;
|
|
|
|
ambe_fr[*y][*z] = (1 & (codeword[i] >> (7 - (j + 1))));
|
|
|
|
y++;
|
|
|
|
ambe_fr[*w][*x] = (1 & (codeword[i] >> (7 - j)));
|
|
|
|
z++;
|
|
|
|
w++;
|
|
|
|
|
|
|
|
x++;
|
|
|
|
|
|
|
|
y++;
|
|
|
|
|
|
|
|
z++;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int ambeErrs;
|
|
|
|
int ambeErrs;
|
|
|
|
char ambeErrStr[64U];
|
|
|
|
char ambeErrStr[64U];
|
|
|
|
::memset(ambeErrStr, 0x20U, 64U);
|
|
|
|
::memset(ambeErrStr, 0x20U, 64U);
|
|
|
|
|
|
|
|
|
|
|
|
mbe_processAmbe3600x2450FrameF(samples, &ambeErrs, &errs, ambeErrStr, ambe_fr, ambe_d, m_mbelibParms->m_cur_mp, m_mbelibParms->m_prev_mp, m_mbelibParms->m_prev_mp_enhanced, 3);
|
|
|
|
mbe_processAmbe3600x2450FrameF(samples, &ambeErrs, &errs, ambeErrStr, ambe_fr, ambe_d, m_mbelibParms->m_cur_mp, m_mbelibParms->m_prev_mp, m_mbelibParms->m_prev_mp_enhanced, 3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
|
|
case DECODE_88BIT_IMBE:
|
|
|
|
case DECODE_88BIT_IMBE:
|
|
|
|
{
|
|
|
|
{
|
|
|
|
char imbe_d[88U];
|
|
|
|
char imbe_d[88U];
|
|
|
|
::memset(imbe_d, 0x00U, 88U);
|
|
|
|
::memset(imbe_d, 0x00U, 88U);
|
|
|
|
|
|
|
|
|
|
|
|
for (int i = 0; i < 11; ++i) {
|
|
|
|
for (int i = 0; i < 11; ++i) {
|
|
|
|
for (int j = 0; j < 8; j++) {
|
|
|
|
for (int j = 0; j < 8; j++) {
|
|
|
|
imbe_d[j + (8 * i)] = (1 & (codeword[i] >> (7 - j)));
|
|
|
|
imbe_d[j + (8 * i)] = (1 & (codeword[i] >> (7 - j)));
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int ambeErrs;
|
|
|
|
int ambeErrs;
|
|
|
|
char ambeErrStr[64U];
|
|
|
|
char ambeErrStr[64U];
|
|
|
|
::memset(ambeErrStr, 0x20U, 64U);
|
|
|
|
::memset(ambeErrStr, 0x20U, 64U);
|
|
|
|
|
|
|
|
|
|
|
|
mbe_processImbe4400DataF(samples, &ambeErrs, &errs, ambeErrStr, imbe_d, m_mbelibParms->m_cur_mp, m_mbelibParms->m_prev_mp, m_mbelibParms->m_prev_mp_enhanced, 3);
|
|
|
|
mbe_processImbe4400DataF(samples, &ambeErrs, &errs, ambeErrStr, imbe_d, m_mbelibParms->m_cur_mp, m_mbelibParms->m_prev_mp, m_mbelibParms->m_prev_mp_enhanced, 3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
break;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return errs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return errs;
|
|
|
|
/* Decodes the given MBE codewords to PCM samples using the decoder mode. */
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Decodes the given MBE codewords to PCM samples using the decoder mode. */
|
|
|
|
int32_t MBEDecoder::decode(uint8_t* codeword, int16_t samples[])
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
float samplesF[160U];
|
|
|
|
|
|
|
|
::memset(samplesF, 0x00U, 160U * sizeof(float));
|
|
|
|
|
|
|
|
int32_t errs = decodeF(codeword, samplesF);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float* sampleFPtr = samplesF;
|
|
|
|
|
|
|
|
if (m_autoGain) {
|
|
|
|
|
|
|
|
// detect max level
|
|
|
|
|
|
|
|
float max = 0.0f;
|
|
|
|
|
|
|
|
for (int n = 0; n < 160; n++) {
|
|
|
|
|
|
|
|
float out = fabsf(*sampleFPtr);
|
|
|
|
|
|
|
|
if (out > max) {
|
|
|
|
|
|
|
|
max = out;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
sampleFPtr++;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int32_t MBEDecoder::decode(uint8_t* codeword, int16_t samples[])
|
|
|
|
*gainMaxBufPtr = max;
|
|
|
|
{
|
|
|
|
gainMaxBufPtr++;
|
|
|
|
float samplesF[160U];
|
|
|
|
gainMaxIdx++;
|
|
|
|
::memset(samplesF, 0x00U, 160U * sizeof(float));
|
|
|
|
|
|
|
|
int32_t errs = decodeF(codeword, samplesF);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
float* sampleFPtr = samplesF;
|
|
|
|
if (gainMaxIdx > 24) {
|
|
|
|
if (m_autoGain) {
|
|
|
|
gainMaxIdx = 0;
|
|
|
|
// detect max level
|
|
|
|
gainMaxBufPtr = gainMaxBuf;
|
|
|
|
float max = 0.0f;
|
|
|
|
|
|
|
|
for (int n = 0; n < 160; n++) {
|
|
|
|
|
|
|
|
float out = fabsf(*sampleFPtr);
|
|
|
|
|
|
|
|
if (out > max) {
|
|
|
|
|
|
|
|
max = out;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
sampleFPtr++;
|
|
|
|
// lookup max history
|
|
|
|
}
|
|
|
|
for (int i = 0; i < 25; i++) {
|
|
|
|
|
|
|
|
float a = gainMaxBuf[i];
|
|
|
|
*gainMaxBufPtr = max;
|
|
|
|
if (a > max) {
|
|
|
|
gainMaxBufPtr++;
|
|
|
|
max = a;
|
|
|
|
gainMaxIdx++;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (gainMaxIdx > 24) {
|
|
|
|
// determine optimal gain level
|
|
|
|
gainMaxIdx = 0;
|
|
|
|
float gainFactor = 0.0f, gainDelta = 0.0f;
|
|
|
|
gainMaxBufPtr = gainMaxBuf;
|
|
|
|
if (max > static_cast<float>(0)) {
|
|
|
|
}
|
|
|
|
gainFactor = (static_cast<float>(30000) / max);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
gainFactor = static_cast<float>(50);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// lookup max history
|
|
|
|
if (gainFactor < m_gainAdjust) {
|
|
|
|
for (int i = 0; i < 25; i++) {
|
|
|
|
m_gainAdjust = gainFactor;
|
|
|
|
float a = gainMaxBuf[i];
|
|
|
|
gainDelta = static_cast<float>(0);
|
|
|
|
if (a > max) {
|
|
|
|
|
|
|
|
max = a;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
if (gainFactor > static_cast<float>(50)) {
|
|
|
|
|
|
|
|
gainFactor = static_cast<float>(50);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// determine optimal gain level
|
|
|
|
gainDelta = gainFactor - m_gainAdjust;
|
|
|
|
float gainFactor = 0.0f, gainDelta = 0.0f;
|
|
|
|
|
|
|
|
if (max > static_cast<float>(0)) {
|
|
|
|
|
|
|
|
gainFactor = (static_cast<float>(30000) / max);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
gainFactor = static_cast<float>(50);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (gainFactor < m_gainAdjust) {
|
|
|
|
if (gainDelta > (static_cast<float>(0.05) * m_gainAdjust)) {
|
|
|
|
m_gainAdjust = gainFactor;
|
|
|
|
gainDelta = (static_cast<float>(0.05) * m_gainAdjust);
|
|
|
|
gainDelta = static_cast<float>(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
else {
|
|
|
|
|
|
|
|
if (gainFactor > static_cast<float>(50)) {
|
|
|
|
|
|
|
|
gainFactor = static_cast<float>(50);
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
gainDelta = gainFactor - m_gainAdjust;
|
|
|
|
gainDelta /= static_cast<float>(160);
|
|
|
|
|
|
|
|
|
|
|
|
if (gainDelta > (static_cast<float>(0.05) * m_gainAdjust)) {
|
|
|
|
// adjust output gain
|
|
|
|
gainDelta = (static_cast<float>(0.05) * m_gainAdjust);
|
|
|
|
sampleFPtr = samplesF;
|
|
|
|
|
|
|
|
for (int n = 0; n < 160; n++) {
|
|
|
|
|
|
|
|
*sampleFPtr = (m_gainAdjust + (static_cast<float>(n) * gainDelta)) * (*sampleFPtr);
|
|
|
|
|
|
|
|
sampleFPtr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gainDelta /= static_cast<float>(160);
|
|
|
|
m_gainAdjust += (static_cast<float>(160) * gainDelta);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// adjust output gain
|
|
|
|
int16_t* samplePtr = samples;
|
|
|
|
sampleFPtr = samplesF;
|
|
|
|
sampleFPtr = samplesF;
|
|
|
|
for (int n = 0; n < 160; n++) {
|
|
|
|
for (int n = 0; n < 160; n++) {
|
|
|
|
*sampleFPtr = (m_gainAdjust + (static_cast<float>(n) * gainDelta)) * (*sampleFPtr);
|
|
|
|
float smp = *sampleFPtr;
|
|
|
|
|
|
|
|
if (!m_autoGain) {
|
|
|
|
|
|
|
|
smp *= m_gainAdjust;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// audio clipping
|
|
|
|
|
|
|
|
if (smp > 32760) {
|
|
|
|
|
|
|
|
smp = 32760;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (smp < -32760) {
|
|
|
|
|
|
|
|
smp = -32760;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*samplePtr = (int16_t)(smp);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
samplePtr++;
|
|
|
|
sampleFPtr++;
|
|
|
|
sampleFPtr++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_gainAdjust += (static_cast<float>(160) * gainDelta);
|
|
|
|
return errs;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int16_t* samplePtr = samples;
|
|
|
|
// Extern methods for C#/C++ interop
|
|
|
|
sampleFPtr = samplesF;
|
|
|
|
MBEDecoder* MBEDecoder_Create(MBE_DECODER_MODE mode)
|
|
|
|
for (int n = 0; n < 160; n++) {
|
|
|
|
{
|
|
|
|
float smp = *sampleFPtr;
|
|
|
|
return new MBEDecoder(mode);
|
|
|
|
if (!m_autoGain) {
|
|
|
|
}
|
|
|
|
smp *= m_gainAdjust;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// audio clipping
|
|
|
|
int32_t MBEDecoder_Decode(MBEDecoder* pDecoder, uint8_t* codeword, int16_t* samples)
|
|
|
|
if (smp > 32760) {
|
|
|
|
{
|
|
|
|
smp = 32760;
|
|
|
|
if (pDecoder != NULL)
|
|
|
|
}
|
|
|
|
{
|
|
|
|
else if (smp < -32760) {
|
|
|
|
return pDecoder->decode(codeword, samples);
|
|
|
|
smp = -32760;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
*samplePtr = (int16_t)(smp);
|
|
|
|
void MBEDecoder_Delete(MBEDecoder* pDecoder)
|
|
|
|
|
|
|
|
{
|
|
|
|
samplePtr++;
|
|
|
|
if (pDecoder != NULL)
|
|
|
|
sampleFPtr++;
|
|
|
|
{
|
|
|
|
|
|
|
|
delete pDecoder;
|
|
|
|
|
|
|
|
pDecoder = NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return errs;
|
|
|
|
} // namespace vocoder
|
|
|
|
}
|
|
|
|
|