1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-27 10:19:15 -05:00

DSDplus library: interim state #3

This commit is contained in:
f4exb 2016-04-10 18:58:40 +02:00
parent e7906225b2
commit a448a8e462
6 changed files with 621 additions and 1 deletions

231
dsdplus/dmr_data.cpp Normal file
View File

@ -0,0 +1,231 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB. //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include "dmr_data.h"
#include "dsd_decoder.h"
namespace DSDplus
{
DSDDMRData::DSDDMRData(DSDDecoder *dsdDecoder) :
m_dsdDecoder(dsdDecoder)
{
}
DSDDMRData::~DSDDMRData()
{
}
void DSDDMRData::init()
{
cc[4] = 0;
bursttype[4] = 0;
dibit_p = m_dsdDecoder->m_state.dibit_buf_p - 90;
preProcess();
m_symbolIndex = 0; // reset
}
void DSDDMRData::preProcess()
{
int dibit;
// CACH
for (int i = 0; i < 12; i++)
{
dibit = *dibit_p;
dibit_p++;
if (m_dsdDecoder->m_opts.inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
cachdata[i] = dibit;
if (i == 2)
{
m_dsdDecoder->m_state.currentslot = (1 & (dibit >> 1)); // bit 1
if (m_dsdDecoder->m_state.currentslot == 0)
{
m_dsdDecoder->m_state.slot0light[0] = '[';
m_dsdDecoder->m_state.slot0light[6] = ']';
m_dsdDecoder->m_state.slot1light[0] = ' ';
m_dsdDecoder->m_state.slot1light[6] = ' ';
}
else
{
m_dsdDecoder->m_state.slot1light[0] = '[';
m_dsdDecoder->m_state.slot1light[6] = ']';
m_dsdDecoder->m_state.slot0light[0] = ' ';
m_dsdDecoder->m_state.slot0light[6] = ' ';
}
}
}
cachdata[12] = 0;
// current slot
dibit_p += 49;
// slot type
dibit = *dibit_p;
dibit_p++;
if (m_dsdDecoder->m_opts.inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
cc[0] = (1 & (dibit >> 1)) + 48; // bit 1
cc[1] = (1 & dibit) + 48; // bit 0
dibit = *dibit_p;
dibit_p++;
if (m_dsdDecoder->m_opts.inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
cc[2] = (1 & (dibit >> 1)) + 48; // bit 1
cc[3] = (1 & dibit) + 48; // bit 0
dibit = *dibit_p;
dibit_p++;
if (m_dsdDecoder->m_opts.inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
bursttype[0] = (1 & (dibit >> 1)) + 48; // bit 1
bursttype[1] = (1 & dibit) + 48; // bit 0
dibit = *dibit_p;
dibit_p++;
if (m_dsdDecoder->m_opts.inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
bursttype[2] = (1 & (dibit >> 1)) + 48; // bit 1
bursttype[3] = (1 & dibit) + 48; // bit 0
// parity bit
dibit_p++;
if (strcmp(bursttype, "0000") == 0)
{
sprintf(m_dsdDecoder->m_state.fsubtype, " PI Header ");
}
else if (strcmp(bursttype, "0001") == 0)
{
sprintf(m_dsdDecoder->m_state.fsubtype, " VOICE Header ");
}
else if (strcmp(bursttype, "0010") == 0)
{
sprintf(m_dsdDecoder->m_state.fsubtype, " TLC ");
}
else if (strcmp(bursttype, "0011") == 0)
{
sprintf(m_dsdDecoder->m_state.fsubtype, " CSBK ");
}
else if (strcmp(bursttype, "0100") == 0)
{
sprintf(m_dsdDecoder->m_state.fsubtype, " MBC Header ");
}
else if (strcmp(bursttype, "0101") == 0)
{
sprintf(m_dsdDecoder->m_state.fsubtype, " MBC ");
}
else if (strcmp(bursttype, "0110") == 0)
{
sprintf(m_dsdDecoder->m_state.fsubtype, " DATA Header ");
}
else if (strcmp(bursttype, "0111") == 0)
{
sprintf(m_dsdDecoder->m_state.fsubtype, " RATE 1/2 DATA");
}
else if (strcmp(bursttype, "1000") == 0)
{
sprintf(m_dsdDecoder->m_state.fsubtype, " RATE 3/4 DATA");
}
else if (strcmp(bursttype, "1001") == 0)
{
sprintf(m_dsdDecoder->m_state.fsubtype, " Slot idle ");
}
else if (strcmp(bursttype, "1010") == 0)
{
sprintf(m_dsdDecoder->m_state.fsubtype, " Rate 1 DATA ");
}
else
{
sprintf(m_dsdDecoder->m_state.fsubtype, " ");
}
// signaling data or sync
for (int i = 0; i < 24; i++)
{
dibit = *dibit_p;
dibit_p++;
if (m_dsdDecoder->m_opts.inverted_dmr == 1)
{
dibit = (dibit ^ 2);
}
syncdata[i] = dibit;
sync[i] = (dibit | 1) + 48;
}
sync[24] = 0;
syncdata[24] = 0;
if ((strcmp(sync, DMR_BS_DATA_SYNC) == 0)
|| (strcmp(sync, DMR_MS_DATA_SYNC) == 0))
{
if (m_dsdDecoder->m_state.currentslot == 0)
{
sprintf(m_dsdDecoder->m_state.slot0light, "[slot0]");
}
else
{
sprintf(m_dsdDecoder->m_state.slot1light, "[slot1]");
}
}
if (m_dsdDecoder->m_opts.errorbars == 1)
{
printf("%s %s ", m_dsdDecoder->m_state.slot0light, m_dsdDecoder->m_state.slot1light);
}
}
void DSDDMRData::process()
{
m_dsdDecoder->getDibit(); // get dibit from symbol but do nothing with it
if (m_symbolIndex == 120 -1) // last dibit to skip
{
m_dsdDecoder->m_fsmState = DSDDecoder::DSDLookForSync; // go back to search sync state
}
m_symbolIndex++;
}
} // namespace DSDplus

49
dsdplus/dmr_data.h Normal file
View File

@ -0,0 +1,49 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB. //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef DSDPLUS_DMR_DATA_H_
#define DSDPLUS_DMR_DATA_H_
namespace DSDplus
{
class DSDDecoder;
class DSDDMRData
{
public:
DSDDMRData(DSDDecoder *dsdDecoder);
~DSDDMRData();
void init();
void process();
private:
void preProcess(); //!< process the 90 in memory dibits in initial phase
DSDDecoder *m_dsdDecoder;
int m_symbolIndex; //!< Current absolute symbol index
int *dibit_p;
char sync[25];
char syncdata[25];
char cachdata[13];
char cc[5];
char bursttype[5];
};
}
#endif /* DSDPLUS_DMR_DATA_H_ */

View File

@ -25,7 +25,8 @@ DSDDecoder::DSDDecoder() :
m_fsmState(DSDLookForSync),
m_hasSync(0),
m_mbeDecoder(this),
m_dsdDMRVoice(this)
m_dsdDMRVoice(this),
m_dsdDMRData(this)
{
resetSymbol();
resetFrameSync();
@ -1624,6 +1625,7 @@ void DSDDecoder::processFrame()
else
{
m_state.err_str[0] = 0;
m_dsdDMRData.init();
m_fsmState = DSDprocessDMRdata;
}
}

View File

@ -22,6 +22,7 @@
#include "dsd_filters.h"
#include "dsd_mbe.h"
#include "dmr_voice.h"
#include "dmr_data.h"
/*
* Frame sync patterns
@ -65,6 +66,7 @@ class DSDDecoder
{
friend class DSDMBEDecoder;
friend class DSDDMRVoice;
friend class DSDDMRData;
public:
typedef enum
{
@ -129,6 +131,7 @@ private:
DSDMBEDecoder m_mbeDecoder;
// Frame decoders
DSDDMRVoice m_dsdDMRVoice;
DSDDMRData m_dsdDMRData;
};
} // namespace dsdplus

290
dsdplus/dsd_mbe.cpp Normal file
View File

@ -0,0 +1,290 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB. //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#include <string.h>
#include <math.h>
#include <mbelib.h>
#include "dsd_mbe.h"
#include "dsd_decoder.h"
namespace DSDplus
{
DSDMBEDecoder::DSDMBEDecoder(DSDDecoder *dsdDecoder) :
m_dsdDecoder(dsdDecoder)
{
}
DSDMBEDecoder::~DSDMBEDecoder()
{
}
void DSDMBEDecoder::processFrame(char imbe_fr[8][23], char ambe_fr[4][24], char imbe7100_fr[7][24])
{
// for (int i = 0; i < 88; i++)
// {
// imbe_d[i] = 0;
// }
memset((void *) imbe_d, 0, 88);
if ((m_dsdDecoder->m_state.synctype == 0) || (m_dsdDecoder->m_state.synctype == 1))
{
mbe_processImbe7200x4400Framef(m_dsdDecoder->m_state.audio_out_temp_buf, &m_dsdDecoder->m_state.errs,
&m_dsdDecoder->m_state.errs2, m_dsdDecoder->m_state.err_str, imbe_fr, imbe_d, m_dsdDecoder->m_state.cur_mp,
m_dsdDecoder->m_state.prev_mp, m_dsdDecoder->m_state.prev_mp_enhanced, m_dsdDecoder->m_opts.uvquality);
}
else if ((m_dsdDecoder->m_state.synctype == 14) || (m_dsdDecoder->m_state.synctype == 15))
{
mbe_processImbe7100x4400Framef(m_dsdDecoder->m_state.audio_out_temp_buf, &m_dsdDecoder->m_state.errs,
&m_dsdDecoder->m_state.errs2, m_dsdDecoder->m_state.err_str, imbe7100_fr, imbe_d,
m_dsdDecoder->m_state.cur_mp, m_dsdDecoder->m_state.prev_mp, m_dsdDecoder->m_state.prev_mp_enhanced,
m_dsdDecoder->m_opts.uvquality);
}
else if ((m_dsdDecoder->m_state.synctype == 6) || (m_dsdDecoder->m_state.synctype == 7))
{
mbe_processAmbe3600x2400Framef(m_dsdDecoder->m_state.audio_out_temp_buf, &m_dsdDecoder->m_state.errs,
&m_dsdDecoder->m_state.errs2, m_dsdDecoder->m_state.err_str, ambe_fr, ambe_d, m_dsdDecoder->m_state.cur_mp,
m_dsdDecoder->m_state.prev_mp, m_dsdDecoder->m_state.prev_mp_enhanced, m_dsdDecoder->m_opts.uvquality);
}
else
{
mbe_processAmbe3600x2450Framef(m_dsdDecoder->m_state.audio_out_temp_buf, &m_dsdDecoder->m_state.errs,
&m_dsdDecoder->m_state.errs2, m_dsdDecoder->m_state.err_str, ambe_fr, ambe_d, m_dsdDecoder->m_state.cur_mp,
m_dsdDecoder->m_state.prev_mp, m_dsdDecoder->m_state.prev_mp_enhanced, m_dsdDecoder->m_opts.uvquality);
}
if (m_dsdDecoder->m_opts.errorbars == 1)
{
fprintf(m_dsdDecoder->m_state.logfile, "%s", m_dsdDecoder->m_state.err_str);
}
processAudio();
// if (m_dsdDecoder->m_opts.wav_out_f != NULL)
// {
// writeSynthesizedVoice(opts, state);
// }
//
// if (m_dsdDecoder->m_opts.audio_out == 1)
// {
// playSynthesizedVoice(opts, state);
// }
}
void DSDMBEDecoder::processAudio()
{
int i, n;
float aout_abs, max, gainfactor, gaindelta, maxbuf;
if (m_dsdDecoder->m_opts.audio_gain == (float) 0)
{
// detect max level
max = 0;
m_dsdDecoder->m_state.audio_out_temp_buf_p = m_dsdDecoder->m_state.audio_out_temp_buf;
for (n = 0; n < 160; n++)
{
aout_abs = fabsf(*m_dsdDecoder->m_state.audio_out_temp_buf_p);
if (aout_abs > max)
{
max = aout_abs;
}
m_dsdDecoder->m_state.audio_out_temp_buf_p++;
}
*m_dsdDecoder->m_state.aout_max_buf_p = max;
m_dsdDecoder->m_state.aout_max_buf_p++;
m_dsdDecoder->m_state.aout_max_buf_idx++;
if (m_dsdDecoder->m_state.aout_max_buf_idx > 24)
{
m_dsdDecoder->m_state.aout_max_buf_idx = 0;
m_dsdDecoder->m_state.aout_max_buf_p = m_dsdDecoder->m_state.aout_max_buf;
}
// lookup max history
for (i = 0; i < 25; i++)
{
maxbuf = m_dsdDecoder->m_state.aout_max_buf[i];
if (maxbuf > max)
{
max = maxbuf;
}
}
// determine optimal gain level
if (max > (float) 0)
{
gainfactor = ((float) 30000 / max);
}
else
{
gainfactor = (float) 50;
}
if (gainfactor < m_dsdDecoder->m_state.aout_gain)
{
m_dsdDecoder->m_state.aout_gain = gainfactor;
gaindelta = (float) 0;
}
else
{
if (gainfactor > (float) 50)
{
gainfactor = (float) 50;
}
gaindelta = gainfactor - m_dsdDecoder->m_state.aout_gain;
if (gaindelta > ((float) 0.05 * m_dsdDecoder->m_state.aout_gain))
{
gaindelta = ((float) 0.05 * m_dsdDecoder->m_state.aout_gain);
}
}
gaindelta /= (float) 160;
}
else
{
gaindelta = (float) 0;
}
if (m_dsdDecoder->m_opts.audio_gain >= 0)
{
// adjust output gain
m_dsdDecoder->m_state.audio_out_temp_buf_p = m_dsdDecoder->m_state.audio_out_temp_buf;
for (n = 0; n < 160; n++)
{
*m_dsdDecoder->m_state.audio_out_temp_buf_p = (m_dsdDecoder->m_state.aout_gain
+ ((float) n * gaindelta)) * (*m_dsdDecoder->m_state.audio_out_temp_buf_p);
m_dsdDecoder->m_state.audio_out_temp_buf_p++;
}
m_dsdDecoder->m_state.aout_gain += ((float) 160 * gaindelta);
}
// copy audio datat to output buffer and upsample if necessary
m_dsdDecoder->m_state.audio_out_temp_buf_p = m_dsdDecoder->m_state.audio_out_temp_buf;
if (m_dsdDecoder->m_opts.split == 0)
{
for (n = 0; n < 160; n++)
{
upsample(*m_dsdDecoder->m_state.audio_out_temp_buf_p);
m_dsdDecoder->m_state.audio_out_temp_buf_p++;
m_dsdDecoder->m_state.audio_out_float_buf_p += 6;
m_dsdDecoder->m_state.audio_out_idx += 6;
m_dsdDecoder->m_state.audio_out_idx2 += 6;
}
m_dsdDecoder->m_state.audio_out_float_buf_p -= (960 + m_dsdDecoder->m_opts.playoffset);
// copy to output (short) buffer
for (n = 0; n < 960; n++)
{
if (*m_dsdDecoder->m_state.audio_out_float_buf_p > (float) 32760)
{
*m_dsdDecoder->m_state.audio_out_float_buf_p = (float) 32760;
}
else if (*m_dsdDecoder->m_state.audio_out_float_buf_p < (float) -32760)
{
*m_dsdDecoder->m_state.audio_out_float_buf_p = (float) -32760;
}
*m_dsdDecoder->m_state.audio_out_buf_p = (short) *m_dsdDecoder->m_state.audio_out_float_buf_p;
m_dsdDecoder->m_state.audio_out_buf_p++;
m_dsdDecoder->m_state.audio_out_float_buf_p++;
}
m_dsdDecoder->m_state.audio_out_float_buf_p += m_dsdDecoder->m_opts.playoffset;
}
else
{
for (n = 0; n < 160; n++)
{
if (*m_dsdDecoder->m_state.audio_out_temp_buf_p > (float) 32760)
{
*m_dsdDecoder->m_state.audio_out_temp_buf_p = (float) 32760;
}
else if (*m_dsdDecoder->m_state.audio_out_temp_buf_p < (float) -32760)
{
*m_dsdDecoder->m_state.audio_out_temp_buf_p = (float) -32760;
}
*m_dsdDecoder->m_state.audio_out_buf_p = (short) *m_dsdDecoder->m_state.audio_out_temp_buf_p;
m_dsdDecoder->m_state.audio_out_buf_p++;
m_dsdDecoder->m_state.audio_out_temp_buf_p++;
m_dsdDecoder->m_state.audio_out_idx++;
m_dsdDecoder->m_state.audio_out_idx2++;
}
}
// TODO: flag audio is uvailable
}
void DSDMBEDecoder::upsample(float invalue)
{
int i, j, sum;
float *outbuf1, c, d;
outbuf1 = m_dsdDecoder->m_state.audio_out_float_buf_p;
outbuf1--;
c = *outbuf1;
d = invalue;
// basic triangle interpolation
outbuf1++;
*outbuf1 = ((invalue * (float) 0.166) + (c * (float) 0.834));
outbuf1++;
*outbuf1 = ((invalue * (float) 0.332) + (c * (float) 0.668));
outbuf1++;
*outbuf1 = ((invalue * (float) 0.5) + (c * (float) 0.5));
outbuf1++;
*outbuf1 = ((invalue * (float) 0.668) + (c * (float) 0.332));
outbuf1++;
*outbuf1 = ((invalue * (float) 0.834) + (c * (float) 0.166));
outbuf1++;
*outbuf1 = d;
outbuf1++;
if (m_dsdDecoder->m_state.audio_out_idx2 > 24)
{
// smoothing
outbuf1 -= 16;
for (j = 0; j < 4; j++)
{
for (i = 0; i < 6; i++)
{
sum = 0;
outbuf1 -= 2;
sum += *outbuf1;
outbuf1 += 2;
sum += *outbuf1;
outbuf1 += 2;
sum += *outbuf1;
outbuf1 -= 2;
*outbuf1 = (sum / (float) 3);
outbuf1++;
}
outbuf1 -= 8;
}
}
}
}

45
dsdplus/dsd_mbe.h Normal file
View File

@ -0,0 +1,45 @@
///////////////////////////////////////////////////////////////////////////////////
// Copyright (C) 2016 Edouard Griffiths, F4EXB. //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
// the Free Software Foundation as version 3 of the License, or //
// //
// This program is distributed in the hope that it will be useful, //
// but WITHOUT ANY WARRANTY; without even the implied warranty of //
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
// GNU General Public License V3 for more details. //
// //
// You should have received a copy of the GNU General Public License //
// along with this program. If not, see <http://www.gnu.org/licenses/>. //
///////////////////////////////////////////////////////////////////////////////////
#ifndef DSDPLUS_DSD_MBE_H_
#define DSDPLUS_DSD_MBE_H_
namespace DSDplus
{
class DSDDecoder;
class DSDMBEDecoder
{
public:
DSDMBEDecoder(DSDDecoder *dsdDecoder);
~DSDMBEDecoder();
void processFrame(char imbe_fr[8][23], char ambe_fr[4][24], char imbe7100_fr[7][24]);
private:
void processAudio();
void upsample(float invalue);
DSDDecoder *m_dsdDecoder;
char imbe_d[88];
char ambe_d[49];
};
}
#endif /* DSDPLUS_DSD_MBE_H_ */