From 5598265e66770a322aa430ee8e0809dbedb28427 Mon Sep 17 00:00:00 2001 From: f4exb Date: Mon, 26 Dec 2016 12:11:51 +0100 Subject: [PATCH] Multiple modulators support: works with two modulators --- sdrbase/dsp/basebandsamplesource.cpp | 14 +++- sdrbase/dsp/basebandsamplesource.h | 3 + sdrbase/dsp/dspdevicesinkengine.cpp | 80 ++++++++++++++++++++-- sdrbase/dsp/dspdevicesinkengine.h | 9 +++ sdrbase/dsp/samplesourcefifo.cpp | 2 +- sdrbase/dsp/samplesourcefifo.h | 1 + sdrbase/dsp/threadedbasebandsamplesource.h | 3 + 7 files changed, 103 insertions(+), 9 deletions(-) diff --git a/sdrbase/dsp/basebandsamplesource.cpp b/sdrbase/dsp/basebandsamplesource.cpp index 14c023e48..63c2d9853 100644 --- a/sdrbase/dsp/basebandsamplesource.cpp +++ b/sdrbase/dsp/basebandsamplesource.cpp @@ -22,6 +22,7 @@ BasebandSampleSource::BasebandSampleSource() : m_sampleFifo(48000) // arbitrary, will be adjusted to match device sink FIFO size { connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages())); + connect(&m_sampleFifo, SIGNAL(dataWrite(int)), this, SLOT(handleWriteToFifo(int))); } BasebandSampleSource::~BasebandSampleSource() @@ -41,6 +42,17 @@ void BasebandSampleSource::handleInputMessages() } } - +void BasebandSampleSource::handleWriteToFifo(int nbSamples) +{ + SampleVector::iterator writeAt; + m_sampleFifo.getWriteIterator(writeAt); + pullAudio(nbSamples); // Pre-fetch input audio samples this is mandatory to keep things running smoothly + + for (int i = 0; i < nbSamples; i++) + { + pull((*writeAt)); + m_sampleFifo.bumpIndex(writeAt); + } +} diff --git a/sdrbase/dsp/basebandsamplesource.h b/sdrbase/dsp/basebandsamplesource.h index 3564c06f4..f2adf201b 100644 --- a/sdrbase/dsp/basebandsamplesource.h +++ b/sdrbase/dsp/basebandsamplesource.h @@ -51,6 +51,8 @@ public: } } + SampleSourceFifo& getSampleSourceFifo() { return m_sampleFifo; } + virtual bool handleMessage(const Message& cmd) = 0; //!< Processing of a message. Returns true if message has actually been processed MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication @@ -63,6 +65,7 @@ protected: protected slots: void handleInputMessages(); + void handleWriteToFifo(int nbSamples); }; #endif /* SDRBASE_DSP_BASEBANDSAMPLESOURCE_H_ */ diff --git a/sdrbase/dsp/dspdevicesinkengine.cpp b/sdrbase/dsp/dspdevicesinkengine.cpp index c9000a1df..698a2c04a 100644 --- a/sdrbase/dsp/dspdevicesinkengine.cpp +++ b/sdrbase/dsp/dspdevicesinkengine.cpp @@ -176,7 +176,7 @@ void DSPDeviceSinkEngine::work(int nbWriteSamples) // single channel source handling if ((m_threadedBasebandSampleSources.size() + m_basebandSampleSources.size()) == 1) { - qDebug("DSPDeviceSinkEngine::work: single channel source handling"); +// qDebug("DSPDeviceSinkEngine::work: single channel source handling"); for (ThreadedBasebandSampleSources::iterator it = m_threadedBasebandSampleSources.begin(); it != m_threadedBasebandSampleSources.end(); ++it) { @@ -190,12 +190,68 @@ void DSPDeviceSinkEngine::work(int nbWriteSamples) // multiple channel sources handling else if ((m_threadedBasebandSampleSources.size() + m_basebandSampleSources.size()) > 1) { - qDebug("DSPDeviceSinkEngine::work: multiple channel sources handling"); - // TODO properly - if (m_threadedBasebandSampleSources.size() > 0) +// qDebug("DSPDeviceSinkEngine::work: multiple channel sources handling"); + + SampleVector::iterator writeBegin; + sampleFifo->getWriteIterator(writeBegin); + SampleVector::iterator writeAt = writeBegin; + Sample s; + int sourceOccurence = 0; + + // Read a chunk of data from the sources + + for (ThreadedBasebandSampleSources::iterator it = m_threadedBasebandSampleSources.begin(); it != m_threadedBasebandSampleSources.end(); ++it) { - (*m_threadedBasebandSampleSources.begin())->feed(sampleFifo, nbWriteSamples); + ((*it)->getSampleSourceFifo()).readAdvance(m_threadedBasebandSampleSourcesIteratorMap[*it], nbWriteSamples); + m_threadedBasebandSampleSourcesIteratorMap[*it] -= nbWriteSamples; } + + for (BasebandSampleSources::iterator it = m_basebandSampleSources.begin(); it != m_basebandSampleSources.end(); ++it) + { + ((*it)->getSampleSourceFifo()).readAdvance(m_basebandSampleSourcesIteratorMap[*it], nbWriteSamples); + m_basebandSampleSourcesIteratorMap[*it] -= nbWriteSamples; + } + + // Process sample by sample + + for (int is = 0; is < nbWriteSamples; is++) + { + // pull data from threaded sources and merge them in the device sample FIFO + for (ThreadedBasebandSampleSources::iterator it = m_threadedBasebandSampleSources.begin(); it != m_threadedBasebandSampleSources.end(); ++it) + { + s = *m_threadedBasebandSampleSourcesIteratorMap[*it]; + s /= (m_threadedBasebandSampleSources.size() + m_basebandSampleSources.size()); + + if (sourceOccurence == 0) { + (*writeAt) = s; + } else { + (*writeAt) += s; + } + + sourceOccurence++; + m_threadedBasebandSampleSourcesIteratorMap[*it]++; + } + + // pull data from direct sources and merge them in the device sample FIFO + for (BasebandSampleSources::iterator it = m_basebandSampleSources.begin(); it != m_basebandSampleSources.end(); ++it) + { + s = *m_basebandSampleSourcesIteratorMap[*it]; + s /= (m_threadedBasebandSampleSources.size() + m_basebandSampleSources.size()); + + if (sourceOccurence == 0) { + (*writeAt) = s; + } else { + (*writeAt) += s; + } + + sourceOccurence++; + m_basebandSampleSourcesIteratorMap[*it]++; + } + + sampleFifo->bumpIndex(writeAt); + sourceOccurence = 0; + } + // SampleVector::iterator writeBegin; // sampleFifo->getWriteIterator(writeBegin); // SampleVector::iterator writeAt = writeBegin; @@ -390,14 +446,14 @@ DSPDeviceSinkEngine::State DSPDeviceSinkEngine::gotoRunning() for(BasebandSampleSources::const_iterator it = m_basebandSampleSources.begin(); it != m_basebandSampleSources.end(); it++) { qDebug() << "DSPDeviceSinkEngine::gotoRunning: starting " << (*it)->objectName().toStdString().c_str(); - // TODO: equalize channel source FIFO size with device sink FIFO size + (*it)->getSampleSourceFifo().resize(2*m_deviceSampleSink->getSampleFifo()->size()); // Equalize channel source FIFO size with device sink FIFO size (*it)->start(); } for (ThreadedBasebandSampleSources::const_iterator it = m_threadedBasebandSampleSources.begin(); it != m_threadedBasebandSampleSources.end(); ++it) { qDebug() << "DSPDeviceSinkEngine::gotoRunning: starting ThreadedSampleSource(" << (*it)->getSampleSourceObjectName().toStdString().c_str() << ")"; - // TODO: equalize channel source FIFO size with device sink FIFO size + (*it)->getSampleSourceFifo().resize(2*m_deviceSampleSink->getSampleFifo()->size()); // Equalize channel source FIFO size with device sink FIFO size (*it)->start(); } @@ -507,6 +563,10 @@ void DSPDeviceSinkEngine::handleSynchronousMessages() { BasebandSampleSource* source = ((DSPAddSource*) message)->getSampleSource(); m_basebandSampleSources.push_back(source); + BasebandSampleSourcesIteratorMapKV kv; + kv.first = source; + (source->getSampleSourceFifo()).getReadIterator(kv.second); + m_basebandSampleSourcesIteratorMap.insert(kv); } else if (DSPRemoveSource::match(*message)) { @@ -516,18 +576,24 @@ void DSPDeviceSinkEngine::handleSynchronousMessages() source->stop(); } + m_basebandSampleSourcesIteratorMap.erase(source); m_basebandSampleSources.remove(source); } else if (DSPAddThreadedSampleSource::match(*message)) { ThreadedBasebandSampleSource *threadedSource = ((DSPAddThreadedSampleSource*) message)->getThreadedSampleSource(); m_threadedBasebandSampleSources.push_back(threadedSource); + ThreadedBasebandSampleSourcesIteratorMapKV kv; + kv.first = threadedSource; + (threadedSource->getSampleSourceFifo()).getReadIterator(kv.second); + m_threadedBasebandSampleSourcesIteratorMap.insert(kv); threadedSource->start(); } else if (DSPRemoveThreadedSampleSource::match(*message)) { ThreadedBasebandSampleSource* threadedSource = ((DSPRemoveThreadedSampleSource*) message)->getThreadedSampleSource(); threadedSource->stop(); + m_threadedBasebandSampleSourcesIteratorMap.erase(threadedSource); m_threadedBasebandSampleSources.remove(threadedSource); } diff --git a/sdrbase/dsp/dspdevicesinkengine.h b/sdrbase/dsp/dspdevicesinkengine.h index 5d4b72945..66e08bd62 100644 --- a/sdrbase/dsp/dspdevicesinkengine.h +++ b/sdrbase/dsp/dspdevicesinkengine.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "dsp/dsptypes.h" #include "dsp/fftwindow.h" #include "util/messagequeue.h" @@ -99,6 +100,14 @@ private: typedef std::list ThreadedBasebandSampleSources; ThreadedBasebandSampleSources m_threadedBasebandSampleSources; //!< baseband sample sources on their own threads (usually channels) + typedef std::map BasebandSampleSourcesIteratorMap; + typedef std::pair BasebandSampleSourcesIteratorMapKV; + BasebandSampleSourcesIteratorMap m_basebandSampleSourcesIteratorMap; + + typedef std::map ThreadedBasebandSampleSourcesIteratorMap; + typedef std::pair ThreadedBasebandSampleSourcesIteratorMapKV; + ThreadedBasebandSampleSourcesIteratorMap m_threadedBasebandSampleSourcesIteratorMap; + BasebandSampleSink *m_spectrumSink; uint m_sampleRate; diff --git a/sdrbase/dsp/samplesourcefifo.cpp b/sdrbase/dsp/samplesourcefifo.cpp index e6264b588..b7ce9ec57 100644 --- a/sdrbase/dsp/samplesourcefifo.cpp +++ b/sdrbase/dsp/samplesourcefifo.cpp @@ -49,7 +49,7 @@ void SampleSourceFifo::init() void SampleSourceFifo::readAdvance(SampleVector::iterator& readUntil, unsigned int nbSamples) { // QMutexLocker mutexLocker(&m_mutex); - assert(nbSamples < m_size/4); + assert(nbSamples <= m_size/2); m_ir = (m_ir + nbSamples) % m_size; readUntil = m_data.begin() + m_size + m_ir; diff --git a/sdrbase/dsp/samplesourcefifo.h b/sdrbase/dsp/samplesourcefifo.h index 16953aabd..f42f9c6b5 100644 --- a/sdrbase/dsp/samplesourcefifo.h +++ b/sdrbase/dsp/samplesourcefifo.h @@ -32,6 +32,7 @@ public: ~SampleSourceFifo(); void resize(uint32_t size); + uint32_t size() const { return m_size; } void init(); /** advance read pointer for the given length and activate R/W signals */ void readAdvance(SampleVector::iterator& readUntil, unsigned int nbSamples); diff --git a/sdrbase/dsp/threadedbasebandsamplesource.h b/sdrbase/dsp/threadedbasebandsamplesource.h index 66c2bf67c..35fd47bdc 100644 --- a/sdrbase/dsp/threadedbasebandsamplesource.h +++ b/sdrbase/dsp/threadedbasebandsamplesource.h @@ -46,11 +46,14 @@ public: bool handleSourceMessage(const Message& cmd); //!< Send message to source synchronously void pull(Sample& sample); //!< Pull one sample from source + void pullAudio(int nbSamples) { if (m_basebandSampleSource) m_basebandSampleSource->pullAudio(nbSamples); } /** direct feeding of sample source FIFO */ void feed(SampleSourceFifo* sampleFifo, int nbSamples); + SampleSourceFifo& getSampleSourceFifo() { return m_basebandSampleSource->getSampleSourceFifo(); } + QString getSampleSourceObjectName() const; protected: