diff --git a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsource.cpp b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsource.cpp index 5f73a963b..a0eb1b295 100644 --- a/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsource.cpp +++ b/plugins/channelmimo/beamsteeringcwmod/beamsteeringcwmodsource.cpp @@ -33,7 +33,7 @@ BeamSteeringCWModSource::BeamSteeringCWModSource() : m_steeringDegrees(90), m_mutex(QMutex::Recursive) { - m_sampleMOFifo.init(2, 96000 * 8); + m_sampleMOFifo.init(2, 4096*64); m_vbegin.resize(2); for (int i = 0; i < 2; i++) diff --git a/plugins/samplemimo/testmosync/testmosync.cpp b/plugins/samplemimo/testmosync/testmosync.cpp index 8a3458655..c8482e58b 100644 --- a/plugins/samplemimo/testmosync/testmosync.cpp +++ b/plugins/samplemimo/testmosync/testmosync.cpp @@ -42,10 +42,13 @@ TestMOSync::TestMOSync(DeviceAPI *deviceAPI) : m_settings(), m_sinkThread(nullptr), m_deviceDescription("TestMOSync"), - m_runningTx(false) + m_runningTx(false), + m_masterTimer(deviceAPI->getMasterTimer()), + m_spectrumSink(nullptr), + m_feedSpectrumIndex(0) { m_mimoType = MIMOHalfSynchronous; - m_sampleMOFifo.init(2, 96000 * 4); + m_sampleMOFifo.init(2, 4096*64); m_deviceAPI->setNbSourceStreams(0); m_deviceAPI->setNbSinkStreams(2); } @@ -76,7 +79,11 @@ bool TestMOSync::startTx() m_sampleMOFifo.reset(); m_sinkThread->setFifo(&m_sampleMOFifo); m_sinkThread->setFcPos(m_settings.m_fcPosTx); + m_sinkThread->setSamplerate(m_settings.m_sampleRate); m_sinkThread->setLog2Interpolation(m_settings.m_log2Interp); + m_sinkThread->setSpectrumSink(m_spectrumSink); + m_sinkThread->setFeedSpectrumIndex(m_feedSpectrumIndex); + m_sinkThread->connectTimer(m_masterTimer); m_sinkThread->startWork(); mutexLocker.unlock(); m_runningTx = true; @@ -221,6 +228,15 @@ bool TestMOSync::handleMessage(const Message& message) } } +void TestMOSync::setFeedSpectrumIndex(unsigned int feedSpectrumIndex) +{ + m_feedSpectrumIndex = feedSpectrumIndex > 1 ? 1 : feedSpectrumIndex; + + if (m_sinkThread) { + m_sinkThread->setFeedSpectrumIndex(m_feedSpectrumIndex); + } +} + bool TestMOSync::applySettings(const TestMOSyncSettings& settings, bool force) { QList reverseAPIKeys; diff --git a/plugins/samplemimo/testmosync/testmosync.h b/plugins/samplemimo/testmosync/testmosync.h index 321289298..2e0e87f25 100644 --- a/plugins/samplemimo/testmosync/testmosync.h +++ b/plugins/samplemimo/testmosync/testmosync.h @@ -22,12 +22,14 @@ #include #include +#include #include "dsp/devicesamplemimo.h" #include "testmosyncsettings.h" class DeviceAPI; class TestMOSyncThread; +class BasebandSampleSink; class TestMOSync : public DeviceSampleMIMO { Q_OBJECT @@ -119,6 +121,8 @@ public: bool getRxRunning() const { return false; } bool getTxRunning() const { return m_runningTx; } + void setSpectrumSink(BasebandSampleSink* spectrumSink) { m_spectrumSink = spectrumSink; } + void setFeedSpectrumIndex(unsigned int feedSpectrumIndex); private: DeviceAPI *m_deviceAPI; @@ -127,6 +131,9 @@ private: TestMOSyncThread* m_sinkThread; QString m_deviceDescription; bool m_runningTx; + const QTimer& m_masterTimer; + BasebandSampleSink* m_spectrumSink; + unsigned int m_feedSpectrumIndex; bool applySettings(const TestMOSyncSettings& settings, bool force); }; diff --git a/plugins/samplemimo/testmosync/testmosyncgui.cpp b/plugins/samplemimo/testmosync/testmosyncgui.cpp index 684d2692f..4c0054484 100644 --- a/plugins/samplemimo/testmosync/testmosyncgui.cpp +++ b/plugins/samplemimo/testmosync/testmosyncgui.cpp @@ -26,6 +26,7 @@ #include "gui/glspectrum.h" #include "dsp/dspengine.h" #include "dsp/dspcommands.h" +#include "dsp/spectrumvis.h" #include "mainwindow.h" #include "device/deviceapi.h" #include "device/deviceuiset.h" @@ -49,6 +50,7 @@ TestMOSyncGui::TestMOSyncGui(DeviceUISet *deviceUISet, QWidget* parent) : m_lastEngineState(DeviceAPI::StNotStarted) { ui->setupUi(this); + m_sampleMIMO = (TestMOSync*) m_deviceUISet->m_deviceAPI->getSampleMIMO(); ui->centerFrequency->setColorMapper(ColorMapper(ColorMapper::GrayGold)); ui->centerFrequency->setValueRange(7, 0, pow(10,7)); @@ -56,6 +58,13 @@ TestMOSyncGui::TestMOSyncGui(DeviceUISet *deviceUISet, QWidget* parent) : ui->sampleRate->setColorMapper(ColorMapper(ColorMapper::GrayGreenYellow)); ui->sampleRate->setValueRange(7, 32000U, 9000000U); + m_spectrumVis = new SpectrumVis(SDR_TX_SCALEF, ui->glSpectrum); + m_sampleMIMO->setSpectrumSink(m_spectrumVis); + ui->glSpectrum->setCenterFrequency(m_settings.m_centerFrequency); + ui->glSpectrum->setSampleRate(m_settings.m_sampleRate*(1<glSpectrum->connectTimer(MainWindow::getInstance()->getMasterTimer()); + ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum); + connect(&(m_deviceUISet->m_deviceAPI->getMasterTimer()), SIGNAL(timeout()), this, SLOT(tick())); connect(&m_updateTimer, SIGNAL(timeout()), this, SLOT(updateHardware())); connect(&m_statusTimer, SIGNAL(timeout()), this, SLOT(updateStatus())); @@ -63,9 +72,12 @@ TestMOSyncGui::TestMOSyncGui(DeviceUISet *deviceUISet, QWidget* parent) : displaySettings(); - m_sampleMIMO = (TestMOSync*) m_deviceUISet->m_deviceAPI->getSampleMIMO(); m_sampleMIMO->setMessageQueueToGUI(&m_inputMessageQueue); connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()), Qt::QueuedConnection); + + m_deviceUISet->m_spectrum->setDisplayedStream(false, 0); + m_deviceUISet->m_deviceAPI->setSpectrumSinkInput(false, 0); + m_deviceUISet->setSpectrumScalingFactor(SDR_TX_SCALEF); } TestMOSyncGui::~TestMOSyncGui() @@ -114,12 +126,15 @@ QByteArray TestMOSyncGui::serialize() const bool TestMOSyncGui::deserialize(const QByteArray& data) { - if(m_settings.deserialize(data)) { + if (m_settings.deserialize(data)) + { displaySettings(); m_forceSettings = true; sendSettings(); return true; - } else { + } + else + { resetToDefaults(); return false; } @@ -127,7 +142,28 @@ bool TestMOSyncGui::deserialize(const QByteArray& data) bool TestMOSyncGui::handleMessage(const Message& message) { - if (TestMOSync::MsgConfigureTestMOSync::match(message)) + if (DSPMIMOSignalNotification::match(message)) + { + const DSPMIMOSignalNotification& cfg = (DSPMIMOSignalNotification&) message; + int istream = cfg.getIndex(); + bool sourceOrSink = cfg.getSourceOrSink(); + qDebug("TestMOSyncGui::handleMessage: DSPMIMOSignalNotification: %s:%d SampleRate:%d, CenterFrequency:%llu", + sourceOrSink ? "Rx" : "Tx", + istream, + cfg.getSampleRate(), + cfg.getCenterFrequency() + ); + + if (!sourceOrSink) + { + m_sampleRate = cfg.getSampleRate(); + m_deviceCenterFrequency = cfg.getCenterFrequency(); + updateSampleRateAndFrequency(); + } + + return true; + } + else if (TestMOSync::MsgConfigureTestMOSync::match(message)) { qDebug("TestMOSyncGui::handleMessage: message: MsgConfigureTestMOSync"); const TestMOSync::MsgConfigureTestMOSync& cfg = (TestMOSync::MsgConfigureTestMOSync&) message; @@ -158,24 +194,9 @@ void TestMOSyncGui::handleInputMessages() while ((message = m_inputMessageQueue.pop()) != 0) { - - if (DSPSignalNotification::match(*message)) - { - DSPSignalNotification* notif = (DSPSignalNotification*) message; - qDebug("TestMOSyncGui::handleInputMessages: DSPSignalNotification: SampleRate:%d, CenterFrequency:%llu", notif->getSampleRate(), notif->getCenterFrequency()); - m_sampleRate = notif->getSampleRate(); - m_deviceCenterFrequency = notif->getCenterFrequency(); - updateSampleRateAndFrequency(); - + if (handleMessage(*message)) { delete message; } - else - { - if (handleMessage(*message)) - { - delete message; - } - } } } @@ -201,20 +222,23 @@ void TestMOSyncGui::sendSettings() void TestMOSyncGui::updateHardware() { - qDebug() << "TestMOSyncGui::updateHardware"; - TestMOSync::MsgConfigureTestMOSync* message = TestMOSync::MsgConfigureTestMOSync::create(m_settings, m_forceSettings); - m_sampleMIMO->getInputMessageQueue()->push(message); - m_forceSettings = false; - m_updateTimer.stop(); + if (m_doApplySettings) + { + qDebug() << "TestMOSyncGui::updateHardware"; + TestMOSync::MsgConfigureTestMOSync* message = TestMOSync::MsgConfigureTestMOSync::create(m_settings, m_forceSettings); + m_sampleMIMO->getInputMessageQueue()->push(message); + m_forceSettings = false; + m_updateTimer.stop(); + } } void TestMOSyncGui::updateStatus() { - int state = m_deviceUISet->m_deviceAPI->state(); + int state = m_deviceUISet->m_deviceAPI->state(1); - if(m_lastEngineState != state) + if (m_lastEngineState != state) { - switch(state) + switch (state) { case DeviceAPI::StNotStarted: ui->startStop->setStyleSheet("QToolButton { background:rgb(79,79,79); }"); @@ -240,12 +264,14 @@ void TestMOSyncGui::updateStatus() void TestMOSyncGui::on_centerFrequency_changed(quint64 value) { m_settings.m_centerFrequency = value * 1000; + ui->glSpectrum->setCenterFrequency(m_settings.m_centerFrequency); sendSettings(); } void TestMOSyncGui::on_sampleRate_changed(quint64 value) { m_settings.m_sampleRate = value; + ui->glSpectrum->setSampleRate(m_settings.m_sampleRate*(1<glSpectrum->setSampleRate(m_settings.m_sampleRate*(1<m_spectrum->setDisplayedStream(false, index); + m_deviceUISet->m_deviceAPI->setSpectrumSinkInput(false, index); + m_sampleMIMO->setFeedSpectrumIndex(index); +} + void TestMOSyncGui::tick() { } diff --git a/plugins/samplemimo/testmosync/testmosyncgui.h b/plugins/samplemimo/testmosync/testmosyncgui.h index 7d38b7083..d0006afd2 100644 --- a/plugins/samplemimo/testmosync/testmosyncgui.h +++ b/plugins/samplemimo/testmosync/testmosyncgui.h @@ -29,6 +29,7 @@ class DeviceUISet; class TestMOSync; +class SpectrumVis; namespace Ui { class TestMOSyncGui; @@ -70,6 +71,7 @@ private: std::size_t m_tickCount; int m_lastEngineState; MessageQueue m_inputMessageQueue; + SpectrumVis* m_spectrumVis; void blockApplySettings(bool block) { m_doApplySettings = !block; } void displaySettings(); @@ -82,6 +84,7 @@ private slots: void on_sampleRate_changed(quint64 value); void on_startStop_toggled(bool checked); void on_interp_currentIndexChanged(int index); + void on_spectrumIndex_currentIndexChanged(int index); void updateHardware(); void updateStatus(); void tick(); diff --git a/plugins/samplemimo/testmosync/testmosyncgui.ui b/plugins/samplemimo/testmosync/testmosyncgui.ui index ecc7611b4..159663ced 100644 --- a/plugins/samplemimo/testmosync/testmosyncgui.ui +++ b/plugins/samplemimo/testmosync/testmosyncgui.ui @@ -7,7 +7,7 @@ 0 0 350 - 190 + 400 @@ -19,7 +19,7 @@ 350 - 190 + 400 @@ -182,6 +182,39 @@ 4 + + + + + + + :/dsb.png + + + + + + + + 35 + 16777215 + + + + Select which stream index to display spectrum + + + + 0 + + + + + 1 + + + + @@ -292,6 +325,29 @@ + + + + + + + 200 + 200 + + + + + Liberation Mono + 8 + + + + + + + + + @@ -323,6 +379,18 @@ QToolButton
gui/buttonswitch.h
+ + GLSpectrum + QWidget +
gui/glspectrum.h
+ 1 +
+ + GLSpectrumGUI + QWidget +
gui/glspectrumgui.h
+ 1 +
diff --git a/plugins/samplemimo/testmosync/testmosyncthread.cpp b/plugins/samplemimo/testmosync/testmosyncthread.cpp index 9920264bc..91441b49b 100644 --- a/plugins/samplemimo/testmosync/testmosyncthread.cpp +++ b/plugins/samplemimo/testmosync/testmosyncthread.cpp @@ -19,6 +19,7 @@ #include #include "dsp/samplemofifo.h" +#include "dsp/basebandsamplesink.h" #include "testmosyncsettings.h" #include "testmosyncthread.h" @@ -29,10 +30,13 @@ TestMOSyncThread::TestMOSyncThread(QObject* parent) : m_log2Interp(0), m_throttlems(TestMOSyncSettings::m_msThrottle), m_throttleToggle(false), - m_samplesRemainder(0) + m_blockSize(TestMOSyncSettings::m_blockSize), + m_samplesRemainder(0), + m_feedSpectrumIndex(0), + m_spectrumSink(nullptr) { qDebug("TestMOSyncThread::TestMOSyncThread"); - m_buf = new qint16[2*TestMOSyncSettings::m_blockSize*2]; + m_buf = new qint16[2*m_blockSize*2]; } TestMOSyncThread::~TestMOSyncThread() @@ -102,6 +106,9 @@ void TestMOSyncThread::setSamplerate(int samplerate) m_samplerate = samplerate; m_samplesChunkSize = (m_samplerate * m_throttlems) / 1000; + m_blockSize = (m_samplerate * 50) / 1000; + delete[] m_buf; + m_buf = new qint16[2*m_blockSize*2]; if (wasRunning) { startWork(); @@ -159,18 +166,18 @@ void TestMOSyncThread::callback(qint16* buf, qint32 samplesPerChannel) if (iPart1Begin != iPart1End) { - callbackPart(buf, samplesPerChannel, iPart1Begin, iPart1End - iPart1Begin); + callbackPart(buf, (iPart1End - iPart1Begin)*(1< decim=16). len is a number of samples (not a number of I or Q) -void TestMOSyncThread::callbackPart(qint16* buf, qint32 samplesPerChannel, int iBegin, qint32 nSamples) +void TestMOSyncThread::callbackPart(qint16* buf, qint32 nSamples, int iBegin) { for (unsigned int channel = 0; channel < 2; channel++) { @@ -178,7 +185,7 @@ void TestMOSyncThread::callbackPart(qint16* buf, qint32 samplesPerChannel, int i if (m_log2Interp == 0) { - m_interpolators[channel].interpolate1(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate1(&begin, &buf[channel*2*nSamples], 2*nSamples); } else { @@ -187,22 +194,22 @@ void TestMOSyncThread::callbackPart(qint16* buf, qint32 samplesPerChannel, int i switch (m_log2Interp) { case 1: - m_interpolators[channel].interpolate2_inf(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate2_inf(&begin, &buf[channel*2*nSamples], 2*nSamples); break; case 2: - m_interpolators[channel].interpolate4_inf(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate4_inf(&begin, &buf[channel*2*nSamples], 2*nSamples); break; case 3: - m_interpolators[channel].interpolate8_inf(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate8_inf(&begin, &buf[channel*2*nSamples], 2*nSamples); break; case 4: - m_interpolators[channel].interpolate16_inf(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate16_inf(&begin, &buf[channel*2*nSamples], 2*nSamples); break; case 5: - m_interpolators[channel].interpolate32_inf(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate32_inf(&begin, &buf[channel*2*nSamples], 2*nSamples); break; case 6: - m_interpolators[channel].interpolate64_inf(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate64_inf(&begin, &buf[channel*2*nSamples], 2*nSamples); break; default: break; @@ -213,22 +220,22 @@ void TestMOSyncThread::callbackPart(qint16* buf, qint32 samplesPerChannel, int i switch (m_log2Interp) { case 1: - m_interpolators[channel].interpolate2_sup(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate2_sup(&begin, &buf[channel*2*nSamples], 2*nSamples); break; case 2: - m_interpolators[channel].interpolate4_sup(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate4_sup(&begin, &buf[channel*2*nSamples], 2*nSamples); break; case 3: - m_interpolators[channel].interpolate8_sup(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate8_sup(&begin, &buf[channel*2*nSamples], 2*nSamples); break; case 4: - m_interpolators[channel].interpolate16_sup(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate16_sup(&begin, &buf[channel*2*nSamples], 2*nSamples); break; case 5: - m_interpolators[channel].interpolate32_sup(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate32_sup(&begin, &buf[channel*2*nSamples], 2*nSamples); break; case 6: - m_interpolators[channel].interpolate64_sup(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate64_sup(&begin, &buf[channel*2*nSamples], 2*nSamples); break; default: break; @@ -239,28 +246,32 @@ void TestMOSyncThread::callbackPart(qint16* buf, qint32 samplesPerChannel, int i switch (m_log2Interp) { case 1: - m_interpolators[channel].interpolate2_cen(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate2_cen(&begin, &buf[channel*2*nSamples], 2*nSamples); break; case 2: - m_interpolators[channel].interpolate4_cen(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate4_cen(&begin, &buf[channel*2*nSamples], 2*nSamples); break; case 3: - m_interpolators[channel].interpolate8_cen(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate8_cen(&begin, &buf[channel*2*nSamples], 2*nSamples); break; case 4: - m_interpolators[channel].interpolate16_cen(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate16_cen(&begin, &buf[channel*2*nSamples], 2*nSamples); break; case 5: - m_interpolators[channel].interpolate32_cen(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate32_cen(&begin, &buf[channel*2*nSamples], 2*nSamples); break; case 6: - m_interpolators[channel].interpolate64_cen(&begin, &buf[channel*2*samplesPerChannel], nSamples*2); + m_interpolators[channel].interpolate64_cen(&begin, &buf[channel*2*nSamples], 2*nSamples); break; default: break; } } } + + if (channel == m_feedSpectrumIndex) { + feedSpectrum(&buf[channel*2*nSamples], nSamples*2); + } } } @@ -279,12 +290,33 @@ void TestMOSyncThread::tick() int chunkSize = std::min((int) m_samplesChunkSize, m_samplerate) + m_samplesRemainder; - while (chunkSize >= TestMOSyncSettings::m_blockSize) + while (chunkSize >= m_blockSize) { - callback(m_buf, TestMOSyncSettings::m_blockSize); - chunkSize -= TestMOSyncSettings::m_blockSize; + callback(m_buf, m_blockSize); + chunkSize -= m_blockSize; } m_samplesRemainder = chunkSize; } } + +void TestMOSyncThread::feedSpectrum(int16_t *buf, unsigned int bufSize) +{ + if (!m_spectrumSink) { + return; + } + + m_samplesVector.allocate(bufSize/2); + Sample16 *s16Buf = (Sample16*) buf; + + std::transform( + s16Buf, + s16Buf + (bufSize/2), + m_samplesVector.m_vector.begin(), + [](Sample16 s) -> Sample { + return Sample{s.m_real, s.m_imag}; + } + ); + + m_spectrumSink->feed(m_samplesVector.m_vector.begin(), m_samplesVector.m_vector.begin() + (bufSize/2), false); +} diff --git a/plugins/samplemimo/testmosync/testmosyncthread.h b/plugins/samplemimo/testmosync/testmosyncthread.h index 552b9ae52..65967468a 100644 --- a/plugins/samplemimo/testmosync/testmosyncthread.h +++ b/plugins/samplemimo/testmosync/testmosyncthread.h @@ -26,11 +26,13 @@ #include #include "dsp/interpolators.h" +#include "util/incrementalvector.h" #define TESTMOSYNC_THROTTLE_MS 50 class QTimer; class SampleMOFifo; +class BasebandSampleSink; class TestMOSyncThread : public QThread { Q_OBJECT @@ -50,15 +52,24 @@ public: void setFifo(SampleMOFifo *sampleFifo) { m_sampleFifo = sampleFifo; } SampleMOFifo *getFifo() { return m_sampleFifo; } void connectTimer(const QTimer& timer); + void setSpectrumSink(BasebandSampleSink *spectrumSink) { m_spectrumSink = spectrumSink; } + void setFeedSpectrumIndex(unsigned int feedSpectrumIndex) { m_feedSpectrumIndex = feedSpectrumIndex > 1 ? 1 : feedSpectrumIndex; } private: +#pragma pack(push, 1) + struct Sample16 + { + int16_t m_real; + int16_t m_imag; + }; +#pragma pack(pop) QMutex m_startWaitMutex; QWaitCondition m_startWaiter; bool m_running; qint16 *m_buf; //!< Full buffer for SISO or MIMO operation SampleMOFifo* m_sampleFifo; - Interpolators m_interpolators[2]; + Interpolators m_interpolators[2]; unsigned int m_log2Interp; int m_fcPos; @@ -66,13 +77,19 @@ private: QElapsedTimer m_elapsedTimer; bool m_throttleToggle; unsigned int m_samplesChunkSize; + unsigned int m_blockSize; unsigned int m_samplesRemainder; int m_samplerate; + unsigned int m_feedSpectrumIndex; + BasebandSampleSink* m_spectrumSink; + IncrementalVector m_samplesVector; + void run(); unsigned int getNbFifos(); - void callbackPart(qint16* buf, qint32 samplesPerChannel, int iBegin, qint32 nSamples); + void callbackPart(qint16* buf, qint32 nSamples, int iBegin); void callback(qint16* buf, qint32 samplesPerChannel); + void feedSpectrum(int16_t *buf, unsigned int bufSize); private slots: void tick();