mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-12-24 19:00:36 -05:00
DSDplus library: interim state #3
This commit is contained in:
parent
e7906225b2
commit
a448a8e462
231
dsdplus/dmr_data.cpp
Normal file
231
dsdplus/dmr_data.cpp
Normal 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
49
dsdplus/dmr_data.h
Normal 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_ */
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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
290
dsdplus/dsd_mbe.cpp
Normal 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
45
dsdplus/dsd_mbe.h
Normal 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_ */
|
Loading…
Reference in New Issue
Block a user