1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2026-06-05 15:34:57 -04:00

Merge branch 'dev'

This commit is contained in:
f4exb
2018-01-28 09:28:25 +01:00
137 changed files with 3685 additions and 973 deletions
+5 -1
View File
@@ -55,7 +55,11 @@ private:
int m_fcPos;
static AirspyThread *m_this;
Decimators<qint16, SDR_SAMP_SZ, 12> m_decimators;
#ifdef SDR_RX_SAMPLE_24BIT
Decimators<qint64, qint16, SDR_RX_SAMP_SZ, 12> m_decimators;
#else
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12> m_decimators;
#endif
void run();
void callback(const qint16* buf, qint32 len);
@@ -53,7 +53,11 @@ private:
unsigned int m_log2Decim;
static AirspyHFThread *m_this;
Decimators<qint16, SDR_SAMP_SZ, 16> m_decimators;
#ifdef SDR_RX_SAMPLE_24BIT
Decimators<qint64, qint16, SDR_RX_SAMP_SZ, 16> m_decimators;
#else
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 16> m_decimators;
#endif
void run();
void callback(const qint16* buf, qint32 len);
@@ -51,7 +51,11 @@ private:
unsigned int m_log2Decim;
int m_fcPos;
Decimators<qint16, SDR_SAMP_SZ, 12> m_decimators;
#ifdef SDR_RX_SAMPLE_24BIT
Decimators<qint64, qint16, SDR_RX_SAMP_SZ, 12> m_decimators;
#else
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12> m_decimators;
#endif
void run();
void callback(const qint16* buf, qint32 len);
@@ -175,6 +175,7 @@ bool FileSourceGui::handleMessage(const Message& message)
else if (FileSourceInput::MsgReportFileSourceStreamData::match(message))
{
m_sampleRate = ((FileSourceInput::MsgReportFileSourceStreamData&)message).getSampleRate();
m_sampleSize = ((FileSourceInput::MsgReportFileSourceStreamData&)message).getSampleSize();
m_centerFrequency = ((FileSourceInput::MsgReportFileSourceStreamData&)message).getCenterFrequency();
m_startingTimeStamp = ((FileSourceInput::MsgReportFileSourceStreamData&)message).getStartingTimeStamp();
m_recordLength = ((FileSourceInput::MsgReportFileSourceStreamData&)message).getRecordLength();
@@ -312,6 +313,7 @@ void FileSourceGui::updateWithStreamData()
{
ui->centerFrequency->setValue(m_centerFrequency/1000);
ui->sampleRateText->setText(tr("%1k").arg((float)m_sampleRate / 1000));
ui->sampleSizeText->setText(tr("%1b").arg(m_sampleSize));
ui->play->setEnabled(m_acquisition);
QTime recordLength(0, 0, 0, 0);
recordLength = recordLength.addSecs(m_recordLength);
@@ -63,6 +63,7 @@ private:
bool m_acquisition;
QString m_fileName;
int m_sampleRate;
quint32 m_sampleSize;
quint64 m_centerFrequency;
quint32 m_recordLength;
std::time_t m_startingTimeStamp;
@@ -6,7 +6,7 @@
<rect>
<x>0</x>
<y>0</y>
<width>246</width>
<width>300</width>
<height>190</height>
</rect>
</property>
@@ -231,16 +231,56 @@
<layout class="QHBoxLayout" name="rateTimeLayout">
<item>
<widget class="QLabel" name="sampleRateText">
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="toolTip">
<string>Record sample rate</string>
<string>Record sample rate (kS/s)</string>
</property>
<property name="text">
<string>0k</string>
<string>00000k</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="sampleSizeText">
<property name="minimumSize">
<size>
<width>22</width>
<height>0</height>
</size>
</property>
<property name="font">
<font>
<pointsize>8</pointsize>
</font>
</property>
<property name="toolTip">
<string>Record sample size (bits)</string>
</property>
<property name="text">
<string>00b</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
@@ -48,6 +48,7 @@ FileSourceInput::FileSourceInput(DeviceSourceAPI *deviceAPI) :
m_deviceDescription(),
m_fileName("..."),
m_sampleRate(0),
m_sampleSize(0),
m_centerFrequency(0),
m_recordLength(0),
m_startingTimeStamp(0),
@@ -85,6 +86,7 @@ void FileSourceInput::openFileStream()
m_sampleRate = header.sampleRate;
m_centerFrequency = header.centerFrequency;
m_startingTimeStamp = header.startTimeStamp;
m_sampleSize = header.sampleSize;
if (fileSize > sizeof(FileRecord::Header)) {
m_recordLength = (fileSize - sizeof(FileRecord::Header)) / (4 * m_sampleRate);
@@ -97,6 +99,7 @@ void FileSourceInput::openFileStream()
<< " length: " << m_recordLength << " seconds";
MsgReportFileSourceStreamData *report = MsgReportFileSourceStreamData::create(m_sampleRate,
m_sampleSize,
m_centerFrequency,
m_startingTimeStamp,
m_recordLength); // file stream data
@@ -136,7 +139,7 @@ bool FileSourceInput::start()
m_ifstream.seekg(sizeof(FileRecord::Header), std::ios::beg);
}
if(!m_sampleFifo.setSize(m_sampleRate * 4)) {
if(!m_sampleFifo.setSize(m_sampleRate * sizeof(Sample))) {
qCritical("Could not allocate SampleFifo");
return false;
}
@@ -149,7 +152,7 @@ bool FileSourceInput::start()
return false;
}
m_fileSourceThread->setSamplerate(m_sampleRate);
m_fileSourceThread->setSampleRateAndSize(m_sampleRate, m_sampleSize);
m_fileSourceThread->connectTimer(m_masterTimer);
m_fileSourceThread->startWork();
m_deviceDescription = "FileSource";
@@ -173,30 +173,35 @@ public:
public:
int getSampleRate() const { return m_sampleRate; }
quint32 getSampleSize() const { return m_sampleSize; }
quint64 getCenterFrequency() const { return m_centerFrequency; }
std::time_t getStartingTimeStamp() const { return m_startingTimeStamp; }
quint32 getRecordLength() const { return m_recordLength; }
static MsgReportFileSourceStreamData* create(int sampleRate,
quint32 sampleSize,
quint64 centerFrequency,
std::time_t startingTimeStamp,
quint32 recordLength)
{
return new MsgReportFileSourceStreamData(sampleRate, centerFrequency, startingTimeStamp, recordLength);
return new MsgReportFileSourceStreamData(sampleRate, sampleSize, centerFrequency, startingTimeStamp, recordLength);
}
protected:
int m_sampleRate;
quint32 m_sampleSize;
quint64 m_centerFrequency;
std::time_t m_startingTimeStamp;
quint32 m_recordLength;
MsgReportFileSourceStreamData(int sampleRate,
quint32 sampleSize,
quint64 centerFrequency,
std::time_t startingTimeStamp,
quint32 recordLength) :
Message(),
m_sampleRate(sampleRate),
m_sampleSize(sampleSize),
m_centerFrequency(centerFrequency),
m_startingTimeStamp(startingTimeStamp),
m_recordLength(recordLength)
@@ -265,6 +270,7 @@ public:
QString m_deviceDescription;
QString m_fileName;
int m_sampleRate;
quint32 m_sampleSize;
quint64 m_centerFrequency;
quint32 m_recordLength; //!< record length in seconds computed from file size
std::time_t m_startingTimeStamp;
@@ -29,7 +29,7 @@
const PluginDescriptor FileSourcePlugin::m_pluginDescriptor = {
QString("File source input"),
QString("3.10.1"),
QString("3.11.1"),
QString("(c) Edouard Griffiths, F4EXB"),
QString("https://github.com/f4exb/sdrangel"),
true,
@@ -27,12 +27,15 @@ FileSourceThread::FileSourceThread(std::ifstream *samplesStream, SampleSinkFifo*
QThread(parent),
m_running(false),
m_ifstream(samplesStream),
m_buf(0),
m_fileBuf(0),
m_convertBuf(0),
m_bufsize(0),
m_chunksize(0),
m_sampleFifo(sampleFifo),
m_samplesCount(0),
m_samplerate(0),
m_samplesize(0),
m_samplebytes(0),
m_throttlems(FILESOURCE_THROTTLE_MS),
m_throttleToggle(false)
{
@@ -45,8 +48,12 @@ FileSourceThread::~FileSourceThread()
stopWork();
}
if (m_buf != 0) {
free(m_buf);
if (m_fileBuf != 0) {
free(m_fileBuf);
}
if (m_convertBuf != 0) {
free(m_convertBuf);
}
}
@@ -77,49 +84,67 @@ void FileSourceThread::stopWork()
wait();
}
void FileSourceThread::setSamplerate(int samplerate)
void FileSourceThread::setSampleRateAndSize(int samplerate, quint32 samplesize)
{
qDebug() << "FileSourceThread::setSamplerate:"
<< " new:" << samplerate
<< " old:" << m_samplerate;
qDebug() << "FileSourceThread::setSampleRateAndSize:"
<< " new rate:" << samplerate
<< " new size:" << samplesize
<< " old rate:" << m_samplerate
<< " old size:" << m_samplesize;
if (samplerate != m_samplerate)
if ((samplerate != m_samplerate) || (samplesize != m_samplesize))
{
if (m_running) {
stopWork();
}
m_samplerate = samplerate;
// TODO: implement FF and slow motion here. 4 corresponds to live. 2 is half speed, 8 is doulbe speed
m_chunksize = (m_samplerate * 4 * m_throttlems) / 1000;
m_samplesize = samplesize;
m_samplebytes = m_samplesize > 16 ? sizeof(int32_t) : sizeof(int16_t);
// TODO: implement FF and slow motion here. 2 corresponds to live. 1 is half speed, 4 is double speed
m_chunksize = (m_samplerate * 2 * m_samplebytes * m_throttlems) / 1000;
setBuffer(m_chunksize);
setBuffers(m_chunksize);
}
//m_samplerate = samplerate;
}
void FileSourceThread::setBuffer(std::size_t chunksize)
void FileSourceThread::setBuffers(std::size_t chunksize)
{
if (chunksize > m_bufsize)
{
m_bufsize = chunksize;
int nbSamples = m_bufsize/(2 * m_samplebytes);
if (m_buf == 0)
if (m_fileBuf == 0)
{
qDebug() << "FileSourceThread::setBuffer: Allocate buffer";
m_buf = (quint8*) malloc(m_bufsize);
qDebug() << "FileSourceThread::setBuffers: Allocate file buffer";
m_fileBuf = (quint8*) malloc(m_bufsize);
}
else
{
qDebug() << "FileSourceThread::setBuffer: Re-allocate buffer";
quint8 *buf = m_buf;
m_buf = (quint8*) realloc((void*) m_buf, m_bufsize);
if (!m_buf) free(buf);
qDebug() << "FileSourceThread::setBuffers: Re-allocate file buffer";
quint8 *buf = m_fileBuf;
m_fileBuf = (quint8*) realloc((void*) m_fileBuf, m_bufsize);
if (!m_fileBuf) free(buf);
}
qDebug() << "FileSourceThread::setBuffer: size: " << m_bufsize
<< " #samples: " << (m_bufsize/4);
if (m_convertBuf == 0)
{
qDebug() << "FileSourceThread::setBuffers: Allocate conversion buffer";
m_convertBuf = (quint8*) malloc(nbSamples*sizeof(Sample));
}
else
{
qDebug() << "FileSourceThread::setBuffers: Re-allocate conversion buffer";
quint8 *buf = m_convertBuf;
m_convertBuf = (quint8*) realloc((void*) m_convertBuf, nbSamples*sizeof(Sample));
if (!m_convertBuf) free(buf);
}
qDebug() << "FileSourceThread::setBuffers: size: " << m_bufsize
<< " #samples: " << nbSamples;
}
}
@@ -151,17 +176,18 @@ void FileSourceThread::tick()
if (throttlems != m_throttlems)
{
m_throttlems = throttlems;
m_chunksize = 4 * ((m_samplerate * (m_throttlems+(m_throttleToggle ? 1 : 0))) / 1000);
m_chunksize = 2 * m_samplebytes * ((m_samplerate * (m_throttlems+(m_throttleToggle ? 1 : 0))) / 1000);
m_throttleToggle = !m_throttleToggle;
setBuffer(m_chunksize);
setBuffers(m_chunksize);
}
// read samples directly feeding the SampleFifo (no callback)
m_ifstream->read(reinterpret_cast<char*>(m_buf), m_chunksize);
m_ifstream->read(reinterpret_cast<char*>(m_fileBuf), m_chunksize);
if (m_ifstream->eof())
{
m_sampleFifo->write(m_buf, m_ifstream->gcount());
writeToSampleFifo(m_fileBuf, (qint32) m_ifstream->gcount());
//m_sampleFifo->write(m_buf, m_ifstream->gcount());
// TODO: handle loop playback situation
m_ifstream->clear();
m_ifstream->seekg(sizeof(FileRecord::Header), std::ios::beg);
@@ -171,8 +197,55 @@ void FileSourceThread::tick()
}
else
{
m_sampleFifo->write(m_buf, m_chunksize);
m_samplesCount += m_chunksize / 4;
writeToSampleFifo(m_fileBuf, (qint32) m_chunksize);
//m_sampleFifo->write(m_buf, m_chunksize);
m_samplesCount += m_chunksize / (2 * m_samplebytes);
}
}
}
void FileSourceThread::writeToSampleFifo(const quint8* buf, qint32 nbBytes)
{
if (m_samplesize == 16)
{
if (SDR_RX_SAMP_SZ == 16)
{
m_sampleFifo->write(buf, nbBytes);
}
else if (SDR_RX_SAMP_SZ == 24)
{
FixReal *convertBuf = (FixReal *) m_convertBuf;
const int16_t *fileBuf = (int16_t *) buf;
int nbSamples = nbBytes / (2 * m_samplebytes);
for (int is = 0; is < nbSamples; is++)
{
convertBuf[2*is] = fileBuf[2*is] << 8;
convertBuf[2*is+1] = fileBuf[2*is+1] << 8;
}
m_sampleFifo->write((quint8*) convertBuf, nbSamples*sizeof(Sample));
}
}
else if (m_samplesize == 24)
{
if (SDR_RX_SAMP_SZ == 24)
{
m_sampleFifo->write(buf, nbBytes);
}
else if (SDR_RX_SAMP_SZ == 16)
{
FixReal *convertBuf = (FixReal *) m_convertBuf;
const int32_t *fileBuf = (int32_t *) buf;
int nbSamples = nbBytes / (2 * m_samplebytes);
for (int is = 0; is < nbSamples; is++)
{
convertBuf[2*is] = fileBuf[2*is] >> 8;
convertBuf[2*is+1] = fileBuf[2*is+1] >> 8;
}
m_sampleFifo->write((quint8*) convertBuf, nbSamples*sizeof(Sample));
}
}
}
@@ -41,8 +41,8 @@ public:
void startWork();
void stopWork();
void setSamplerate(int samplerate);
void setBuffer(std::size_t chunksize);
void setSampleRateAndSize(int samplerate, quint32 samplesize);
void setBuffers(std::size_t chunksize);
bool isRunning() const { return m_running; }
std::size_t getSamplesCount() const { return m_samplesCount; }
void setSamplesCount(int samplesCount) { m_samplesCount = samplesCount; }
@@ -55,20 +55,23 @@ private:
bool m_running;
std::ifstream* m_ifstream;
quint8 *m_buf;
quint8 *m_fileBuf;
quint8 *m_convertBuf;
std::size_t m_bufsize;
std::size_t m_chunksize;
SampleSinkFifo* m_sampleFifo;
std::size_t m_samplesCount;
int m_samplerate;
int m_samplerate; //!< File I/Q stream original sample rate
quint32 m_samplesize; //!< File effective sample size in bits (I or Q). Ex: 16, 24.
quint32 m_samplebytes; //!< Number of bytes used to store a I or Q sample. Ex: 2. 4.
int m_throttlems;
QElapsedTimer m_elapsedTimer;
bool m_throttleToggle;
void run();
//void decimate1(SampleVector::iterator* it, const qint16* buf, qint32 len);
//void callback(const qint16* buf, qint32 len);
void writeToSampleFifo(const quint8* buf, qint32 nbBytes);
private slots:
void tick();
};
@@ -54,7 +54,11 @@ private:
unsigned int m_log2Decim;
int m_fcPos;
Decimators<qint8, SDR_SAMP_SZ, 8> m_decimators;
#ifdef SDR_RX_SAMPLE_24BIT
Decimators<qint64, qint8, SDR_RX_SAMP_SZ, 8> m_decimators;
#else
Decimators<qint32, qint8, SDR_RX_SAMP_SZ, 8> m_decimators;
#endif
void run();
void callback(const qint8* buf, qint32 len);
@@ -55,7 +55,11 @@ private:
unsigned int m_log2Decim; // soft decimation
Decimators<qint16, SDR_SAMP_SZ, 12> m_decimators;
#ifdef SDR_RX_SAMPLE_24BIT
Decimators<qint64, qint16, SDR_RX_SAMP_SZ, 12> m_decimators;
#else
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12> m_decimators;
#endif
void run();
void callback(const qint16* buf, qint32 len);
@@ -59,7 +59,11 @@ private:
int m_fcPos;
float m_phasor;
Decimators<qint16, SDR_SAMP_SZ, 12> m_decimators;
#ifdef SDR_RX_SAMPLE_24BIT
Decimators<qint64, qint16, SDR_RX_SAMP_SZ, 12> m_decimators;
#else
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12> m_decimators;
#endif
void run();
void convert(const qint16* buf, qint32 len);
+5 -1
View File
@@ -52,7 +52,11 @@ private:
unsigned int m_log2Decim;
int m_fcPos;
DecimatorsU<quint8, SDR_SAMP_SZ, 8, 127> m_decimators;
#ifdef SDR_RX_SAMPLE_24BIT
DecimatorsU<qint64, quint8, SDR_RX_SAMP_SZ, 8, 127> m_decimators;
#else
DecimatorsU<qint32, quint8, SDR_RX_SAMP_SZ, 8, 127> m_decimators;
#endif
void run();
void callback(const quint8* buf, qint32 len);
@@ -174,7 +174,7 @@ void SDRdaemonSourceBuffer::checkSlotData(int slotIndex)
if (sampleRate > 0)
{
int64_t ts = m_currentMeta.m_tv_sec * 1000000LL + m_currentMeta.m_tv_usec;
ts -= (rwDelayBytes * 1000000LL) / (sampleRate * sizeof(Sample));
ts -= (rwDelayBytes * 1000000LL) / (sampleRate * sizeof(SDRdaemonSample));
m_tvOut_sec = ts / 1000000LL;
m_tvOut_usec = ts - (m_tvOut_sec * 1000000LL);
}
@@ -55,7 +55,7 @@ public:
}
};
struct Sample
struct SDRdaemonSample
{
int16_t i;
int16_t q;
@@ -68,12 +68,12 @@ public:
uint8_t filler;
};
static const int samplesPerBlock = (SDRDAEMONSOURCE_UDPSIZE - sizeof(Header)) / sizeof(Sample);
static const int samplesPerBlock = (SDRDAEMONSOURCE_UDPSIZE - sizeof(Header)) / sizeof(SDRdaemonSample);
static const int framesSize = SDRDAEMONSOURCE_NBDECODERSLOTS * (SDRDAEMONSOURCE_NBORIGINALBLOCKS - 1) * (SDRDAEMONSOURCE_UDPSIZE - sizeof(Header));
struct ProtectedBlock
{
Sample samples[samplesPerBlock];
SDRdaemonSample samples[samplesPerBlock];
};
struct SuperBlock
@@ -26,7 +26,7 @@
const PluginDescriptor SDRdaemonSourcePlugin::m_pluginDescriptor = {
QString("SDRdaemon source input"),
QString("3.9.0"),
QString("3.11.1"),
QString("(c) Edouard Griffiths, F4EXB"),
QString("https://github.com/f4exb/sdrangel"),
true,
@@ -51,6 +51,8 @@ SDRdaemonSourceUDPHandler::SDRdaemonSourceUDPHandler(SampleSinkFifo *sampleFifo,
m_throttlems(SDRDAEMONSOURCE_THROTTLE_MS),
m_readLengthSamples(0),
m_readLength(0),
m_converterBuffer(0),
m_converterBufferNbSamples(0),
m_throttleToggle(false),
m_rateDivider(1000/SDRDAEMONSOURCE_THROTTLE_MS),
m_autoCorrBuffer(true)
@@ -72,6 +74,7 @@ SDRdaemonSourceUDPHandler::~SDRdaemonSourceUDPHandler()
{
stop();
delete[] m_udpBuf;
if (m_converterBuffer) { delete[] m_converterBuffer; }
#ifdef USE_INTERNAL_TIMER
if (m_timer) {
delete m_timer;
@@ -263,9 +266,32 @@ void SDRdaemonSourceUDPHandler::tick()
m_readLength = m_readLengthSamples * SDRdaemonSourceBuffer::m_iqSampleSize;
// read samples directly feeding the SampleFifo (no callback)
m_sampleFifo->write(reinterpret_cast<quint8*>(m_sdrDaemonBuffer.readData(m_readLength)), m_readLength);
m_samplesCount += m_readLengthSamples;
if (SDR_RX_SAMP_SZ == 16)
{
// read samples directly feeding the SampleFifo (no callback)
m_sampleFifo->write(reinterpret_cast<quint8*>(m_sdrDaemonBuffer.readData(m_readLength)), m_readLength);
m_samplesCount += m_readLengthSamples;
}
else if (SDR_RX_SAMP_SZ == 24)
{
if (m_readLengthSamples > m_converterBufferNbSamples)
{
if (m_converterBuffer) { delete[] m_converterBuffer; }
m_converterBuffer = new int32_t[m_readLengthSamples*2];
}
uint8_t *buf = m_sdrDaemonBuffer.readData(m_readLength);
for (unsigned int is = 0; is < m_readLengthSamples; is++)
{
m_converterBuffer[2*is] = ((int16_t*)buf)[2*is];
m_converterBuffer[2*is]<<=8;
m_converterBuffer[2*is+1] = ((int16_t*)buf)[2*is+1];
m_converterBuffer[2*is+1]<<=8;
}
m_sampleFifo->write(reinterpret_cast<quint8*>(m_converterBuffer), m_readLengthSamples*sizeof(Sample));
}
if (m_tickCount < m_rateDivider)
{
@@ -77,6 +77,8 @@ private:
int m_throttlems;
uint32_t m_readLengthSamples;
uint32_t m_readLength;
int32_t *m_converterBuffer;
uint32_t m_converterBufferNbSamples;
bool m_throttleToggle;
uint32_t m_rateDivider;
bool m_autoCorrBuffer;
+5 -1
View File
@@ -52,7 +52,11 @@ private:
unsigned int m_log2Decim;
int m_fcPos;
Decimators<qint16, SDR_SAMP_SZ, 12> m_decimators;
#ifdef SDR_RX_SAMPLE_24BIT
Decimators<qint64, qint16, SDR_RX_SAMP_SZ, 12> m_decimators;
#else
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12> m_decimators;
#endif
void run();
void callback(const qint16* buf, qint32 len);
@@ -85,9 +85,15 @@ private:
bool m_throttleToggle;
QMutex m_mutex;
Decimators<qint16, SDR_SAMP_SZ, 8> m_decimators_8;
Decimators<qint16, SDR_SAMP_SZ, 12> m_decimators_12;
Decimators<qint16, SDR_SAMP_SZ, 16> m_decimators_16;
#ifdef SDR_RX_SAMPLE_24BIT
Decimators<qint64, qint16, SDR_RX_SAMP_SZ, 8> m_decimators_8;
Decimators<qint64, qint16, SDR_RX_SAMP_SZ, 12> m_decimators_12;
Decimators<qint64, qint16, SDR_RX_SAMP_SZ, 16> m_decimators_16;
#else
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 8> m_decimators_8;
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 12> m_decimators_12;
Decimators<qint32, qint16, SDR_RX_SAMP_SZ, 16> m_decimators_16;
#endif
void run();
void callback(const qint16* buf, qint32 len);