diff --git a/include-gpl/audio/audiofifo.h b/include-gpl/audio/audiofifo.h index 98f35b886..8b99e3be5 100644 --- a/include-gpl/audio/audiofifo.h +++ b/include-gpl/audio/audiofifo.h @@ -18,11 +18,13 @@ #ifndef INCLUDE_AUDIOFIFO_H #define INCLUDE_AUDIOFIFO_H +#include #include #include #include "util/export.h" -class SDRANGELOVE_API AudioFifo { +class SDRANGELOVE_API AudioFifo : public QObject { + Q_OBJECT public: AudioFifo(); AudioFifo(uint sampleSize, uint numSamples); @@ -30,8 +32,8 @@ public: bool setSize(uint sampleSize, uint numSamples); - uint write(const quint8* data, uint numSamples, int timeout = INT_MAX); - uint read(quint8* data, uint numSamples, int timeout = INT_MAX); + uint write(const quint8* data, uint numSamples, int timeout_ms = INT_MAX); + uint read(quint8* data, uint numSamples, int timeout_ms = INT_MAX); uint drain(uint numSamples); void clear(); diff --git a/include-gpl/audio/audiooutput.h b/include-gpl/audio/audiooutput.h index 7523efffd..1260ebf17 100644 --- a/include-gpl/audio/audiooutput.h +++ b/include-gpl/audio/audiooutput.h @@ -20,6 +20,7 @@ #include #include +#include #include #include #include "util/export.h" @@ -39,6 +40,8 @@ public: void addFifo(AudioFifo* audioFifo); void removeFifo(AudioFifo* audioFifo); + uint getRate() const { return m_audioFormat.sampleRate(); } + private: QMutex m_mutex; QAudioOutput* m_audioOutput; @@ -47,6 +50,8 @@ private: AudioFifos m_audioFifos; std::vector m_mixBuffer; + QAudioFormat m_audioFormat; + //virtual bool open(OpenMode mode); virtual qint64 readData(char* data, qint64 maxLen); virtual qint64 writeData(const char* data, qint64 len); diff --git a/include-gpl/dsp/dspengine.h b/include-gpl/dsp/dspengine.h index d46607698..22fd44a93 100644 --- a/include-gpl/dsp/dspengine.h +++ b/include-gpl/dsp/dspengine.h @@ -55,6 +55,9 @@ public: MessageQueue* getInputMessageQueue() { return &m_inputMessageQueue; } MessageQueue* getOutputMessageQueue() { return &m_outputMessageQueue; } + uint getAudioSampleRate() const { return m_audioSampleRate; } + void setAudioSampleRate(uint rate); + void start(); //!< This thread start void stop(); //!< This thread stop @@ -102,6 +105,7 @@ private: uint m_sampleRate; quint64 m_centerFrequency; + uint m_audioSampleRate; bool m_dcOffsetCorrection; bool m_iqImbalanceCorrection; diff --git a/include-gpl/dsp/interpolator.h b/include-gpl/dsp/interpolator.h index 961db9123..326b911db 100644 --- a/include-gpl/dsp/interpolator.h +++ b/include-gpl/dsp/interpolator.h @@ -20,13 +20,18 @@ public: void free(); // Original code allowed for upsampling, but was never used that way - bool interpolate(Real* distance, const Complex& next, Complex* result) + bool interpolate(Real *distance, const Complex& next, Complex* result) { advanceFilter(next); *distance -= 1.0; + if (*distance >= 1.0) + { return false; - doInterpolate((int)floor(*distance * (Real)m_phaseSteps), result); + } + + doInterpolate((int) floor(*distance * (Real)m_phaseSteps), result); + return true; } diff --git a/include-gpl/mainwindow.h b/include-gpl/mainwindow.h index a1fba92c1..c177ee678 100644 --- a/include-gpl/mainwindow.h +++ b/include-gpl/mainwindow.h @@ -103,15 +103,15 @@ private: PluginManager* m_pluginManager; void loadSettings(); - void loadSettings(const Preset* preset); - void saveSettings(Preset* preset); + void loadPresetSettings(const Preset* preset); + void savePresetSettings(Preset* preset); void saveSettings(); void createStatusBar(); void closeEvent(QCloseEvent*); void updateCenterFreqDisplay(); void updateSampleRate(); - void updatePresets(); + void updatePresetControls(); QTreeWidgetItem* addPresetToTree(const Preset* preset); void applySettings(); diff --git a/include/dsp/threadedsamplesink.h b/include/dsp/threadedsamplesink.h index 38e12ccf7..38da91426 100644 --- a/include/dsp/threadedsamplesink.h +++ b/include/dsp/threadedsamplesink.h @@ -23,11 +23,29 @@ #include "dsp/samplefifo.h" #include "util/messagequeue.h" #include "util/export.h" -#include "util/syncmessenger.h" class SampleSink; class QThread; +/** + * Because Qt is a piece of shit this class cannot be a nested protected class of ThreadedSampleSink + * So let's make everything public + */ +class ThreadedSampleFifo : public QObject { + Q_OBJECT + +public: + ThreadedSampleFifo(SampleSink* sampleSink, std::size_t size = 1<<18); + ~ThreadedSampleFifo(); + void writeToFifo(SampleVector::const_iterator& begin, SampleVector::const_iterator& end); + + SampleSink* m_sampleSink; + SampleFifo m_sampleFifo; + +public slots: + void handleFifoData(); +}; + /** * This class is a wrapper for SampleSink that runs the SampleSink object in its own thread */ @@ -51,13 +69,10 @@ public: QString getSampleSinkObjectName() const; protected: - QThread *m_thread; //!< The thead object - SyncMessenger m_syncMessenger; //!< Used to process messages synchronously with the thread - SampleSink* m_sampleSink; - SampleFifo m_sampleFifo; -protected slots: - void handleData(); + QThread *m_thread; //!< The thead object + ThreadedSampleFifo *m_threadedSampleFifo; + SampleSink* m_sampleSink; }; #endif // INCLUDE_THREADEDSAMPLESINK_H diff --git a/plugins/channel/am/amdemod.cpp b/plugins/channel/am/amdemod.cpp index 6280c6f6d..1ec37fd26 100644 --- a/plugins/channel/am/amdemod.cpp +++ b/plugins/channel/am/amdemod.cpp @@ -21,14 +21,15 @@ #include #include #include "audio/audiooutput.h" +#include "dsp/dspengine.h" #include "dsp/channelizer.h" #include "dsp/pidcontroller.h" MESSAGE_CLASS_DEFINITION(AMDemod::MsgConfigureAMDemod, Message) -AMDemod::AMDemod(AudioFifo* audioFifo, SampleSink* sampleSink) : +AMDemod::AMDemod(SampleSink* sampleSink) : m_sampleSink(sampleSink), - m_audioFifo(audioFifo) + m_audioFifo(4, 48000) { setObjectName("AMDemod"); @@ -38,15 +39,17 @@ AMDemod::AMDemod(AudioFifo* audioFifo, SampleSink* sampleSink) : m_config.m_afBandwidth = 3000; m_config.m_squelch = -40.0; m_config.m_volume = 2.0; - m_config.m_audioSampleRate = 48000; + m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate(); apply(); - m_audioBuffer.resize(16384); + m_audioBuffer.resize(1<<14); m_audioBufferFill = 0; m_movingAverage.resize(16, 0); m_volumeAGC.resize(4096, 0.003, 0); + + DSPEngine::instance()->addAudioSink(&m_audioFifo); } AMDemod::~AMDemod() @@ -63,7 +66,7 @@ void AMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_itera { Complex ci; - if (m_audioFifo->size() == 0) + if (m_audioFifo.size() == 0) { return; } @@ -82,7 +85,7 @@ void AMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_itera if (m_movingAverage.average() >= m_squelchLevel) { - m_squelchState = m_running.m_audioSampleRate/ 20; + m_squelchState = m_running.m_audioSampleRate / 20; } qint16 sample; @@ -122,12 +125,11 @@ void AMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_itera if (m_audioBufferFill >= m_audioBuffer.size()) { - uint res = m_audioFifo->write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 1); + uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 10); - // FIXME: Not necessarily bad, There is a race between threads but generally it works i.e. samples are not lost if (res != m_audioBufferFill) { - qDebug("AMDemod::feed: %u/%u audio samples lost", m_audioBufferFill - res, m_audioBufferFill); + qDebug("AMDemod::feed: %u/%u audio samples written", res, m_audioBufferFill); } m_audioBufferFill = 0; @@ -139,14 +141,12 @@ void AMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_itera if (m_audioBufferFill > 0) { - uint res = m_audioFifo->write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 1); + uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 10); - // Same remark as above - /* if (res != m_audioBufferFill) { - qDebug("AMDemod::feed: %u samples written vs %u requested", res, m_audioBufferFill); - }*/ + qDebug("AMDemod::feed: %u/%u tail samples written", res, m_audioBufferFill); + } m_audioBufferFill = 0; } @@ -161,12 +161,11 @@ void AMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_itera void AMDemod::start() { + qDebug() << "AMDemod::start: m_inputSampleRate: " << m_config.m_inputSampleRate + << " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset; + m_squelchState = 0; - m_audioFifo->clear(); - m_interpolatorRegulation = 0.9999; - m_interpolatorDistance = 1.0; - m_interpolatorDistanceRemain = 0.0; - m_lastSample = 0; + m_audioFifo.clear(); } void AMDemod::stop() @@ -203,7 +202,7 @@ bool AMDemod::handleMessage(const Message& cmd) apply(); - qDebug() << " - MsgConfigureAMDemod:" + qDebug() << "AMDemod::handleMessage: MsgConfigureAMDemod:" << " m_rfBandwidth: " << m_config.m_rfBandwidth << " m_afBandwidth: " << m_config.m_afBandwidth << " m_volume: " << m_config.m_volume @@ -239,6 +238,8 @@ void AMDemod::apply() m_interpolator.create(16, m_config.m_inputSampleRate, m_config.m_rfBandwidth / 2.2); m_interpolatorDistanceRemain = 0; m_interpolatorDistance = (Real) m_config.m_inputSampleRate / (Real) m_config.m_audioSampleRate; + qDebug() << "AMDemod::apply: m_inputSampleRate: " << m_config.m_inputSampleRate + << " m_interpolatorDistance: " << m_interpolatorDistance; } if((m_config.m_afBandwidth != m_running.m_afBandwidth) || diff --git a/plugins/channel/am/amdemod.h b/plugins/channel/am/amdemod.h index 5279036e1..8dd64b749 100644 --- a/plugins/channel/am/amdemod.h +++ b/plugins/channel/am/amdemod.h @@ -30,8 +30,9 @@ class AudioFifo; class AMDemod : public SampleSink { + Q_OBJECT public: - AMDemod(AudioFifo* audioFifo, SampleSink* sampleSink); + AMDemod(SampleSink* sampleSink); ~AMDemod(); void configure(MessageQueue* messageQueue, Real rfBandwidth, Real afBandwidth, Real volume, Real squelch); @@ -106,7 +107,6 @@ private: Config m_running; NCO m_nco; - Real m_interpolatorRegulation; Interpolator m_interpolator; Real m_interpolatorDistance; Real m_interpolatorDistanceRemain; @@ -115,8 +115,6 @@ private: Real m_squelchLevel; int m_squelchState; - Real m_lastArgument; - Complex m_lastSample; MovingAverage m_movingAverage; SimpleAGC m_volumeAGC; @@ -124,7 +122,7 @@ private: uint m_audioBufferFill; SampleSink* m_sampleSink; - AudioFifo* m_audioFifo; + AudioFifo m_audioFifo; SampleVector m_sampleBuffer; void apply(); diff --git a/plugins/channel/am/amdemodgui.cpp b/plugins/channel/am/amdemodgui.cpp index de10d8921..f675661b4 100644 --- a/plugins/channel/am/amdemodgui.cpp +++ b/plugins/channel/am/amdemodgui.cpp @@ -201,11 +201,9 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, QWidget* parent) : connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool))); connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked())); - m_audioFifo = new AudioFifo(4, 48000); - m_amDemod = new AMDemod(m_audioFifo, 0); + m_amDemod = new AMDemod(0); m_channelizer = new Channelizer(m_amDemod); m_threadedChannelizer = new ThreadedSampleSink(m_channelizer, this); - DSPEngine::instance()->addAudioSink(m_audioFifo); DSPEngine::instance()->addThreadedSink(m_threadedChannelizer); m_channelMarker = new ChannelMarker(this); @@ -227,7 +225,6 @@ AMDemodGUI::~AMDemodGUI() delete m_threadedChannelizer; delete m_channelizer; delete m_amDemod; - delete m_audioFifo; delete m_channelMarker; delete ui; } diff --git a/sdrbase/audio/audiofifo.cpp b/sdrbase/audio/audiofifo.cpp index 97f65de46..0b6962b6a 100644 --- a/sdrbase/audio/audiofifo.cpp +++ b/sdrbase/audio/audiofifo.cpp @@ -62,7 +62,7 @@ bool AudioFifo::setSize(uint sampleSize, uint numSamples) return create(sampleSize, numSamples); } -uint AudioFifo::write(const quint8* data, uint numSamples, int timeout) +uint AudioFifo::write(const quint8* data, uint numSamples, int timeout_ms) { QTime time; uint total; @@ -77,7 +77,7 @@ uint AudioFifo::write(const quint8* data, uint numSamples, int timeout) time.start(); m_mutex.lock(); - if(timeout == 0) + if(timeout_ms == 0) { total = MIN(numSamples, m_size - m_fill); } @@ -92,11 +92,11 @@ uint AudioFifo::write(const quint8* data, uint numSamples, int timeout) { if (isFull()) { - if (time.elapsed() < timeout) + if (time.elapsed() < timeout_ms) { m_writeWaitLock.lock(); m_mutex.unlock(); - int ms = timeout - time.elapsed(); + int ms = timeout_ms - time.elapsed(); if(ms < 1) { @@ -141,7 +141,7 @@ uint AudioFifo::write(const quint8* data, uint numSamples, int timeout) return total; } -uint AudioFifo::read(quint8* data, uint numSamples, int timeout) +uint AudioFifo::read(quint8* data, uint numSamples, int timeout_ms) { QTime time; uint total; @@ -156,7 +156,7 @@ uint AudioFifo::read(quint8* data, uint numSamples, int timeout) time.start(); m_mutex.lock(); - if(timeout == 0) + if(timeout_ms == 0) { total = MIN(numSamples, m_fill); } @@ -171,11 +171,11 @@ uint AudioFifo::read(quint8* data, uint numSamples, int timeout) { if(isEmpty()) { - if(time.elapsed() < timeout) + if(time.elapsed() < timeout_ms) { m_readWaitLock.lock(); m_mutex.unlock(); - int ms = timeout - time.elapsed(); + int ms = timeout_ms - time.elapsed(); if(ms < 1) { diff --git a/sdrbase/audio/audiooutput.cpp b/sdrbase/audio/audiooutput.cpp index a74faf039..e45cc7705 100644 --- a/sdrbase/audio/audiooutput.cpp +++ b/sdrbase/audio/audiooutput.cpp @@ -50,7 +50,6 @@ bool AudioOutput::start(int device, int rate) //Q_UNUSED(device); //Q_UNUSED(rate); - QAudioFormat format; QAudioDeviceInfo devInfo; if (device < 0) @@ -76,31 +75,36 @@ bool AudioOutput::start(int device, int rate) //QAudioDeviceInfo devInfo(QAudioDeviceInfo::defaultOutputDevice()); - format.setSampleRate(rate); - format.setChannelCount(2); - format.setSampleSize(16); - format.setCodec("audio/pcm"); - format.setByteOrder(QAudioFormat::LittleEndian); - format.setSampleType(QAudioFormat::SignedInt); + m_audioFormat.setSampleRate(rate); + m_audioFormat.setChannelCount(2); + m_audioFormat.setSampleSize(16); + m_audioFormat.setCodec("audio/pcm"); + m_audioFormat.setByteOrder(QAudioFormat::LittleEndian); + m_audioFormat.setSampleType(QAudioFormat::SignedInt); - if (!devInfo.isFormatSupported(format)) + if (!devInfo.isFormatSupported(m_audioFormat)) { - qWarning("AudioOutput::start: %d Hz S16_LE audio format not supported", rate); - format = devInfo.nearestFormat(format); + m_audioFormat = devInfo.nearestFormat(m_audioFormat); + qWarning("AudioOutput::start: %d Hz S16_LE audio format not supported. New rate: %d", rate, m_audioFormat.sampleRate()); } - if (format.sampleSize() != 16) + if (m_audioFormat.sampleSize() != 16) { qWarning("AudioOutput::start: Audio device ( %s ) failed", qPrintable(devInfo.defaultOutputDevice().deviceName())); return false; } - m_audioOutput = new QAudioOutput(devInfo, format); + m_audioOutput = new QAudioOutput(devInfo, m_audioFormat); QIODevice::open(QIODevice::ReadOnly); m_audioOutput->start(this); + if (m_audioOutput->state() != QAudio::ActiveState) + { + qWarning("AudioOutput::start: cannot start"); + } + return true; } diff --git a/sdrbase/dsp/channelizer.cpp b/sdrbase/dsp/channelizer.cpp index 938b4bd34..5f36582e7 100644 --- a/sdrbase/dsp/channelizer.cpp +++ b/sdrbase/dsp/channelizer.cpp @@ -32,7 +32,7 @@ void Channelizer::configure(MessageQueue* messageQueue, int sampleRate, int cent void Channelizer::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly) { - if(m_sampleSink == NULL) { + if(m_sampleSink == 0) { m_sampleBuffer.clear(); return; } @@ -55,16 +55,19 @@ void Channelizer::feed(SampleVector::const_iterator begin, SampleVector::const_i void Channelizer::start() { - if(m_sampleSink != NULL) + if(m_sampleSink != 0) { - qDebug() << "Channelizer::start: thread: " << thread(); + qDebug() << "Channelizer::start: thread: " << thread() + << " m_inputSampleRate: " << m_inputSampleRate + << " m_requestedOutputSampleRate: " << m_requestedOutputSampleRate + << " m_requestedCenterFrequency: " << m_requestedCenterFrequency; m_sampleSink->start(); } } void Channelizer::stop() { - if(m_sampleSink != NULL) + if(m_sampleSink != 0) m_sampleSink->stop(); } @@ -79,7 +82,7 @@ bool Channelizer::handleMessage(const Message& cmd) qDebug() << "Channelizer::handleMessage: DSPSignalNotification: m_inputSampleRate: " << m_inputSampleRate; applyConfiguration(); - if (m_sampleSink != NULL) + if (m_sampleSink != 0) { m_sampleSink->handleMessage(notif); } @@ -99,17 +102,11 @@ bool Channelizer::handleMessage(const Message& cmd) applyConfiguration(); - if (m_sampleSink != NULL) - { - MsgChannelizerNotification notif(m_currentOutputSampleRate, m_currentCenterFrequency); - m_sampleSink->handleMessage(notif); - } - return true; } else { - if (m_sampleSink != NULL) + if (m_sampleSink != 0) { return m_sampleSink->handleMessage(cmd); } @@ -132,11 +129,17 @@ void Channelizer::applyConfiguration() << ", req=" << m_requestedOutputSampleRate << ", out=" << m_currentOutputSampleRate << ", fc=" << m_currentCenterFrequency; + + if (m_sampleSink != 0) + { + MsgChannelizerNotification notif(m_currentOutputSampleRate, m_currentCenterFrequency); + m_sampleSink->handleMessage(notif); + } } Channelizer::FilterStage::FilterStage(Mode mode) : m_filter(new IntHalfbandFilter), - m_workFunction(NULL) + m_workFunction(0) { switch(mode) { case ModeCenter: diff --git a/sdrbase/dsp/dspengine.cpp b/sdrbase/dsp/dspengine.cpp index e9624dbe6..36f165ae6 100644 --- a/sdrbase/dsp/dspengine.cpp +++ b/sdrbase/dsp/dspengine.cpp @@ -32,6 +32,7 @@ DSPEngine::DSPEngine(QObject* parent) : m_sampleSinks(), m_sampleRate(0), m_centerFrequency(0), + m_audioSampleRate(48000), m_dcOffsetCorrection(false), m_iqImbalanceCorrection(false), m_iOffset(0), @@ -411,13 +412,13 @@ DSPEngine::State DSPEngine::gotoInit() for (SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); ++it) { - qDebug() << " - initializing " << (*it)->objectName().toStdString().c_str(); + qDebug() << "DSPEngine::gotoInit: initializing " << (*it)->objectName().toStdString().c_str(); (*it)->handleMessage(notif); } for (ThreadedSampleSinks::const_iterator it = m_threadedSampleSinks.begin(); it != m_threadedSampleSinks.end(); ++it) { - qDebug() << " - initializing ThreadedSampleSink(" << (*it)->getSampleSinkObjectName().toStdString().c_str() << ")"; + qDebug() << "DSPEngine::gotoInit: initializing ThreadedSampleSink(" << (*it)->getSampleSinkObjectName().toStdString().c_str() << ")"; (*it)->handleSinkMessage(notif); } @@ -431,8 +432,8 @@ DSPEngine::State DSPEngine::gotoInit() DSPEngine::State DSPEngine::gotoRunning() { - qDebug() << "DSPEngine::gotoRunning"; - + qDebug() << "DSPEngine::gotoRunning"; + switch(m_state) { case StNotStarted: @@ -450,10 +451,10 @@ DSPEngine::State DSPEngine::gotoRunning() } if(m_sampleSource == NULL) { - return gotoError("No sample source configured"); + return gotoError("DSPEngine::gotoRunning: No sample source configured"); } - qDebug() << " - " << m_deviceDescription.toStdString().c_str() << " started"; + qDebug() << "DSPEngine::gotoRunning: " << m_deviceDescription.toStdString().c_str() << " started"; // Start everything @@ -463,20 +464,21 @@ DSPEngine::State DSPEngine::gotoRunning() } m_audioOutput.start(-1, 48000); // Use default output device at 48 kHz + m_audioSampleRate = m_audioOutput.getRate(); for(SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); it++) { - qDebug() << " - starting " << (*it)->objectName().toStdString().c_str(); + qDebug() << "DSPEngine::gotoRunning: starting " << (*it)->objectName().toStdString().c_str(); (*it)->start(); } for (ThreadedSampleSinks::const_iterator it = m_threadedSampleSinks.begin(); it != m_threadedSampleSinks.end(); ++it) { - qDebug() << " - starting ThreadedSampleSink(" << (*it)->getSampleSinkObjectName().toStdString().c_str() << ")"; + qDebug() << "DSPEngine::gotoRunning: starting ThreadedSampleSink(" << (*it)->getSampleSinkObjectName().toStdString().c_str() << ")"; (*it)->start(); } - qDebug() << " - input message queue pending: " << m_inputMessageQueue.size(); + qDebug() << "DSPEngine::gotoRunning:input message queue pending: " << m_inputMessageQueue.size(); return StRunning; } @@ -681,3 +683,8 @@ void DSPEngine::handleSourceMessages() delete message; } } + +void DSPEngine::setAudioSampleRate(uint rate) +{ + m_audioSampleRate = rate; +} diff --git a/sdrbase/dsp/filesink.cpp b/sdrbase/dsp/filesink.cpp index b2a5cd6d0..c5f66b689 100644 --- a/sdrbase/dsp/filesink.cpp +++ b/sdrbase/dsp/filesink.cpp @@ -90,7 +90,7 @@ bool FileSink::handleMessage(const Message& message) DSPSignalNotification& notif = (DSPSignalNotification&) message; m_sampleRate = notif.getSampleRate(); m_centerFrequency = notif.getCenterFrequency(); - qDebug() << " - DSPSignalNotification: m_inputSampleRate: " << m_sampleRate + qDebug() << "FileSink::handleMessage: DSPSignalNotification: m_inputSampleRate: " << m_sampleRate << " m_centerFrequency: " << m_centerFrequency; return true; } @@ -98,7 +98,7 @@ bool FileSink::handleMessage(const Message& message) { MsgConfigureFileSink& conf = (MsgConfigureFileSink&) message; handleConfigure(conf.getFileName()); - qDebug() << " - MsgConfigureFileSink: fileName: " << m_fileName.c_str(); + qDebug() << "FileSink::handleMessage: MsgConfigureFileSink: fileName: " << m_fileName.c_str(); return true; } else diff --git a/sdrbase/dsp/threadedsamplesink.cpp b/sdrbase/dsp/threadedsamplesink.cpp index 7d532dcf4..4dd86200b 100644 --- a/sdrbase/dsp/threadedsamplesink.cpp +++ b/sdrbase/dsp/threadedsamplesink.cpp @@ -1,10 +1,26 @@ #include #include -#include #include "dsp/threadedsamplesink.h" #include "dsp/dspcommands.h" #include "util/message.h" +ThreadedSampleFifo::ThreadedSampleFifo(SampleSink *sampleSink, std::size_t size) : + m_sampleSink(sampleSink) +{ + connect(&m_sampleFifo, SIGNAL(dataReady()), this, SLOT(handleFifoData())); + m_sampleFifo.setSize(size); +} + +ThreadedSampleFifo::~ThreadedSampleFifo() +{ + m_sampleFifo.readCommit(m_sampleFifo.fill()); +} + +void ThreadedSampleFifo::writeToFifo(SampleVector::const_iterator& begin, SampleVector::const_iterator& end) +{ + m_sampleFifo.write(begin, end); +} + ThreadedSampleSink::ThreadedSampleSink(SampleSink* sampleSink, QObject *parent) : m_sampleSink(sampleSink) { @@ -14,11 +30,13 @@ ThreadedSampleSink::ThreadedSampleSink(SampleSink* sampleSink, QObject *parent) qDebug() << "ThreadedSampleSink::ThreadedSampleSink: " << name; m_thread = new QThread(parent); - moveToThread(m_thread); // FIXME: the intermediate FIFO should be handled within the sink. Define a new type of sink that is compatible with threading + m_threadedSampleFifo = new ThreadedSampleFifo(m_sampleSink); + //moveToThread(m_thread); // FIXME: Fixed? the intermediate FIFO should be handled within the sink. Define a new type of sink that is compatible with threading m_sampleSink->moveToThread(m_thread); - m_sampleFifo.moveToThread(m_thread); - connect(&m_sampleFifo, SIGNAL(dataReady()), this, SLOT(handleData())); - m_sampleFifo.setSize(262144); + m_threadedSampleFifo->moveToThread(m_thread); + //m_sampleFifo.moveToThread(m_thread); + //connect(&m_sampleFifo, SIGNAL(dataReady()), this, SLOT(handleData())); + //m_sampleFifo.setSize(262144); qDebug() << "ThreadedSampleSink::ThreadedSampleSink: thread: " << thread() << " m_thread: " << m_thread; } @@ -41,14 +59,13 @@ void ThreadedSampleSink::stop() m_sampleSink->stop(); m_thread->exit(); m_thread->wait(); - m_sampleFifo.readCommit(m_sampleFifo.fill()); - } void ThreadedSampleSink::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly) { - // m_sampleSink->feed(begin, end, positiveOnly); - m_sampleFifo.write(begin, end); + //m_sampleSink->feed(begin, end, positiveOnly); + //m_sampleFifo.write(begin, end); + m_threadedSampleFifo->writeToFifo(begin, end); } bool ThreadedSampleSink::handleSinkMessage(Message& cmd) @@ -62,7 +79,7 @@ QString ThreadedSampleSink::getSampleSinkObjectName() const } -void ThreadedSampleSink::handleData() // FIXME: Move it to the new threadable sink class +void ThreadedSampleFifo::handleFifoData() // FIXME: Fixed? Move it to the new threadable sink class { bool positiveOnly = false; diff --git a/sdrbase/mainwindow.cpp b/sdrbase/mainwindow.cpp index 4037e1233..c8c07aafd 100644 --- a/sdrbase/mainwindow.cpp +++ b/sdrbase/mainwindow.cpp @@ -100,14 +100,13 @@ MainWindow::MainWindow(QWidget* parent) : ui->sampleSource->blockSignals(sampleSourceSignalsBlocked); m_spectrumVis = new SpectrumVis(ui->glSpectrum); + ui->glSpectrum->connectTimer(m_masterTimer); + ui->glSpectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum); m_dspEngine->addSink(m_spectrumVis); m_fileSink = new FileSink(); m_dspEngine->addSink(m_fileSink); - ui->glSpectrum->connectTimer(m_masterTimer); - ui->glSpectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum); - qDebug() << "MainWindow::MainWindow: loadSettings..."; loadSettings(); @@ -123,17 +122,17 @@ MainWindow::MainWindow(QWidget* parent) : ui->sampleSource->blockSignals(sampleSourceSignalsBlocked); } - qDebug() << "MainWindow::MainWindow: load current settings..."; + qDebug() << "MainWindow::MainWindow: load current preset settings..."; - loadSettings(m_settings.getCurrent()); + loadPresetSettings(m_settings.getCurrent()); qDebug() << "MainWindow::MainWindow: apply settings..."; applySettings(); - qDebug() << "MainWindow::MainWindow: update presets..."; + qDebug() << "MainWindow::MainWindow: update preset controls..."; - updatePresets(); + updatePresetControls(); qDebug() << "MainWindow::MainWindow: end"; } @@ -203,15 +202,11 @@ void MainWindow::loadSettings() { addPresetToTree(m_settings.getPreset(i)); } - - Preset* current = m_settings.getCurrent(); - - //loadSettings(current); } -void MainWindow::loadSettings(const Preset* preset) +void MainWindow::loadPresetSettings(const Preset* preset) { - qDebug() << "MainWindow::loadSettings(preset): " << preset->getSource().toStdString().c_str(); + qDebug() << "MainWindow::loadPresetSettings: preset: " << preset->getSource().toStdString().c_str(); ui->glSpectrumGUI->deserialize(preset->getSpectrumConfig()); ui->dcOffset->setChecked(preset->getDCOffsetCorrection()); @@ -227,14 +222,14 @@ void MainWindow::saveSettings() { qDebug() << "MainWindow::saveSettings"; - saveSettings(m_settings.getCurrent()); + savePresetSettings(m_settings.getCurrent()); m_settings.save(); } -void MainWindow::saveSettings(Preset* preset) +void MainWindow::savePresetSettings(Preset* preset) { - qDebug() << "MainWindow::saveSettings(preset): " << preset->getSource().toStdString().c_str(); + qDebug() << "MainWindow::savePresetSettings: preset: " << preset->getSource().toStdString().c_str(); preset->setSpectrumConfig(ui->glSpectrumGUI->serialize()); preset->clearChannels(); @@ -281,13 +276,17 @@ void MainWindow::updateSampleRate() m_sampleRateWidget->setText(tr("Rate: %1 kHz").arg((float)m_sampleRate / 1000)); } -void MainWindow::updatePresets() +void MainWindow::updatePresetControls() { ui->presetTree->resizeColumnToContents(0); - if(ui->presetTree->currentItem() != 0) { + + if(ui->presetTree->currentItem() != 0) + { ui->presetDelete->setEnabled(true); ui->presetLoad->setEnabled(true); - } else { + } + else + { ui->presetDelete->setEnabled(false); ui->presetLoad->setEnabled(false); } @@ -318,7 +317,7 @@ QTreeWidgetItem* MainWindow::addPresetToTree(const Preset* preset) item->setData(0, Qt::UserRole, qVariantFromValue(preset)); ui->presetTree->resizeColumnToContents(0); - updatePresets(); + updatePresetControls(); return item; } @@ -477,7 +476,7 @@ void MainWindow::on_presetSave_clicked() if(dlg.exec() == QDialog::Accepted) { Preset* preset = m_settings.newPreset(dlg.group(), dlg.description()); - saveSettings(preset); + savePresetSettings(preset); ui->presetTree->setCurrentItem(addPresetToTree(preset)); } @@ -492,7 +491,7 @@ void MainWindow::on_presetUpdate_clicked() const Preset* preset = qvariant_cast(item->data(0, Qt::UserRole)); if (preset != 0) { Preset* preset_mod = const_cast(preset); - saveSettings(preset_mod); + savePresetSettings(preset_mod); } } } @@ -504,7 +503,7 @@ void MainWindow::on_presetLoad_clicked() QTreeWidgetItem* item = ui->presetTree->currentItem(); if(item == 0) { - updatePresets(); + updatePresetControls(); return; } const Preset* preset = qvariant_cast(item->data(0, Qt::UserRole)); @@ -512,7 +511,7 @@ void MainWindow::on_presetLoad_clicked() return; } - loadSettings(preset); + loadPresetSettings(preset); applySettings(); } @@ -520,7 +519,7 @@ void MainWindow::on_presetDelete_clicked() { QTreeWidgetItem* item = ui->presetTree->currentItem(); if(item == 0) { - updatePresets(); + updatePresetControls(); return; } const Preset* preset = qvariant_cast(item->data(0, Qt::UserRole)); @@ -535,7 +534,7 @@ void MainWindow::on_presetDelete_clicked() void MainWindow::on_presetTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous) { - updatePresets(); + updatePresetControls(); } void MainWindow::on_presetTree_itemActivated(QTreeWidgetItem *item, int column)