diff --git a/dsdplus/dmr_data.cpp b/dsdplus/dmr_data.cpp
new file mode 100644
index 000000000..170e83ba9
--- /dev/null
+++ b/dsdplus/dmr_data.cpp
@@ -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 . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#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
diff --git a/dsdplus/dmr_data.h b/dsdplus/dmr_data.h
new file mode 100644
index 000000000..d832dc278
--- /dev/null
+++ b/dsdplus/dmr_data.h
@@ -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 . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#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_ */
diff --git a/dsdplus/dsd_decoder.cpp b/dsdplus/dsd_decoder.cpp
index 27807b034..03d7cdd99 100644
--- a/dsdplus/dsd_decoder.cpp
+++ b/dsdplus/dsd_decoder.cpp
@@ -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;
}
}
diff --git a/dsdplus/dsd_decoder.h b/dsdplus/dsd_decoder.h
index b26a762a2..e3728b663 100644
--- a/dsdplus/dsd_decoder.h
+++ b/dsdplus/dsd_decoder.h
@@ -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
diff --git a/dsdplus/dsd_mbe.cpp b/dsdplus/dsd_mbe.cpp
new file mode 100644
index 000000000..08d8639b2
--- /dev/null
+++ b/dsdplus/dsd_mbe.cpp
@@ -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 . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#include
+#include
+#include
+#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;
+ }
+ }
+}
+
+
+}
diff --git a/dsdplus/dsd_mbe.h b/dsdplus/dsd_mbe.h
new file mode 100644
index 000000000..c35c7aa32
--- /dev/null
+++ b/dsdplus/dsd_mbe.h
@@ -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 . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#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_ */