Multiple modulators support: works with two modulators

This commit is contained in:
f4exb 2016-12-26 12:11:51 +01:00
parent 2a8a3bf457
commit 5598265e66
7 changed files with 103 additions and 9 deletions

View File

@ -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);
}
}

View File

@ -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_ */

View File

@ -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);
}

View File

@ -23,6 +23,7 @@
#include <QMutex>
#include <QWaitCondition>
#include <list>
#include <map>
#include "dsp/dsptypes.h"
#include "dsp/fftwindow.h"
#include "util/messagequeue.h"
@ -99,6 +100,14 @@ private:
typedef std::list<ThreadedBasebandSampleSource*> ThreadedBasebandSampleSources;
ThreadedBasebandSampleSources m_threadedBasebandSampleSources; //!< baseband sample sources on their own threads (usually channels)
typedef std::map<BasebandSampleSource*, SampleVector::iterator> BasebandSampleSourcesIteratorMap;
typedef std::pair<BasebandSampleSource*, SampleVector::iterator> BasebandSampleSourcesIteratorMapKV;
BasebandSampleSourcesIteratorMap m_basebandSampleSourcesIteratorMap;
typedef std::map<ThreadedBasebandSampleSource*, SampleVector::iterator> ThreadedBasebandSampleSourcesIteratorMap;
typedef std::pair<ThreadedBasebandSampleSource*, SampleVector::iterator> ThreadedBasebandSampleSourcesIteratorMapKV;
ThreadedBasebandSampleSourcesIteratorMap m_threadedBasebandSampleSourcesIteratorMap;
BasebandSampleSink *m_spectrumSink;
uint m_sampleRate;

View File

@ -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;

View File

@ -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);

View File

@ -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: