mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-10-01 01:06:35 -04:00
Multiple modulators support: works with two modulators
This commit is contained in:
parent
2a8a3bf457
commit
5598265e66
@ -22,6 +22,7 @@ BasebandSampleSource::BasebandSampleSource() :
|
|||||||
m_sampleFifo(48000) // arbitrary, will be adjusted to match device sink FIFO size
|
m_sampleFifo(48000) // arbitrary, will be adjusted to match device sink FIFO size
|
||||||
{
|
{
|
||||||
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
connect(&m_inputMessageQueue, SIGNAL(messageEnqueued()), this, SLOT(handleInputMessages()));
|
||||||
|
connect(&m_sampleFifo, SIGNAL(dataWrite(int)), this, SLOT(handleWriteToFifo(int)));
|
||||||
}
|
}
|
||||||
|
|
||||||
BasebandSampleSource::~BasebandSampleSource()
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -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
|
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
|
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; } //!< Get the queue for asynchronous inbound communication
|
||||||
@ -63,6 +65,7 @@ protected:
|
|||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void handleInputMessages();
|
void handleInputMessages();
|
||||||
|
void handleWriteToFifo(int nbSamples);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SDRBASE_DSP_BASEBANDSAMPLESOURCE_H_ */
|
#endif /* SDRBASE_DSP_BASEBANDSAMPLESOURCE_H_ */
|
||||||
|
@ -176,7 +176,7 @@ void DSPDeviceSinkEngine::work(int nbWriteSamples)
|
|||||||
// single channel source handling
|
// single channel source handling
|
||||||
if ((m_threadedBasebandSampleSources.size() + m_basebandSampleSources.size()) == 1)
|
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)
|
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
|
// multiple channel sources handling
|
||||||
else if ((m_threadedBasebandSampleSources.size() + m_basebandSampleSources.size()) > 1)
|
else if ((m_threadedBasebandSampleSources.size() + m_basebandSampleSources.size()) > 1)
|
||||||
{
|
{
|
||||||
qDebug("DSPDeviceSinkEngine::work: multiple channel sources handling");
|
// qDebug("DSPDeviceSinkEngine::work: multiple channel sources handling");
|
||||||
// TODO properly
|
|
||||||
if (m_threadedBasebandSampleSources.size() > 0)
|
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;
|
// SampleVector::iterator writeBegin;
|
||||||
// sampleFifo->getWriteIterator(writeBegin);
|
// sampleFifo->getWriteIterator(writeBegin);
|
||||||
// SampleVector::iterator writeAt = 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++)
|
for(BasebandSampleSources::const_iterator it = m_basebandSampleSources.begin(); it != m_basebandSampleSources.end(); it++)
|
||||||
{
|
{
|
||||||
qDebug() << "DSPDeviceSinkEngine::gotoRunning: starting " << (*it)->objectName().toStdString().c_str();
|
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();
|
(*it)->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ThreadedBasebandSampleSources::const_iterator it = m_threadedBasebandSampleSources.begin(); it != m_threadedBasebandSampleSources.end(); ++it)
|
for (ThreadedBasebandSampleSources::const_iterator it = m_threadedBasebandSampleSources.begin(); it != m_threadedBasebandSampleSources.end(); ++it)
|
||||||
{
|
{
|
||||||
qDebug() << "DSPDeviceSinkEngine::gotoRunning: starting ThreadedSampleSource(" << (*it)->getSampleSourceObjectName().toStdString().c_str() << ")";
|
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();
|
(*it)->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -507,6 +563,10 @@ void DSPDeviceSinkEngine::handleSynchronousMessages()
|
|||||||
{
|
{
|
||||||
BasebandSampleSource* source = ((DSPAddSource*) message)->getSampleSource();
|
BasebandSampleSource* source = ((DSPAddSource*) message)->getSampleSource();
|
||||||
m_basebandSampleSources.push_back(source);
|
m_basebandSampleSources.push_back(source);
|
||||||
|
BasebandSampleSourcesIteratorMapKV kv;
|
||||||
|
kv.first = source;
|
||||||
|
(source->getSampleSourceFifo()).getReadIterator(kv.second);
|
||||||
|
m_basebandSampleSourcesIteratorMap.insert(kv);
|
||||||
}
|
}
|
||||||
else if (DSPRemoveSource::match(*message))
|
else if (DSPRemoveSource::match(*message))
|
||||||
{
|
{
|
||||||
@ -516,18 +576,24 @@ void DSPDeviceSinkEngine::handleSynchronousMessages()
|
|||||||
source->stop();
|
source->stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_basebandSampleSourcesIteratorMap.erase(source);
|
||||||
m_basebandSampleSources.remove(source);
|
m_basebandSampleSources.remove(source);
|
||||||
}
|
}
|
||||||
else if (DSPAddThreadedSampleSource::match(*message))
|
else if (DSPAddThreadedSampleSource::match(*message))
|
||||||
{
|
{
|
||||||
ThreadedBasebandSampleSource *threadedSource = ((DSPAddThreadedSampleSource*) message)->getThreadedSampleSource();
|
ThreadedBasebandSampleSource *threadedSource = ((DSPAddThreadedSampleSource*) message)->getThreadedSampleSource();
|
||||||
m_threadedBasebandSampleSources.push_back(threadedSource);
|
m_threadedBasebandSampleSources.push_back(threadedSource);
|
||||||
|
ThreadedBasebandSampleSourcesIteratorMapKV kv;
|
||||||
|
kv.first = threadedSource;
|
||||||
|
(threadedSource->getSampleSourceFifo()).getReadIterator(kv.second);
|
||||||
|
m_threadedBasebandSampleSourcesIteratorMap.insert(kv);
|
||||||
threadedSource->start();
|
threadedSource->start();
|
||||||
}
|
}
|
||||||
else if (DSPRemoveThreadedSampleSource::match(*message))
|
else if (DSPRemoveThreadedSampleSource::match(*message))
|
||||||
{
|
{
|
||||||
ThreadedBasebandSampleSource* threadedSource = ((DSPRemoveThreadedSampleSource*) message)->getThreadedSampleSource();
|
ThreadedBasebandSampleSource* threadedSource = ((DSPRemoveThreadedSampleSource*) message)->getThreadedSampleSource();
|
||||||
threadedSource->stop();
|
threadedSource->stop();
|
||||||
|
m_threadedBasebandSampleSourcesIteratorMap.erase(threadedSource);
|
||||||
m_threadedBasebandSampleSources.remove(threadedSource);
|
m_threadedBasebandSampleSources.remove(threadedSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QWaitCondition>
|
#include <QWaitCondition>
|
||||||
#include <list>
|
#include <list>
|
||||||
|
#include <map>
|
||||||
#include "dsp/dsptypes.h"
|
#include "dsp/dsptypes.h"
|
||||||
#include "dsp/fftwindow.h"
|
#include "dsp/fftwindow.h"
|
||||||
#include "util/messagequeue.h"
|
#include "util/messagequeue.h"
|
||||||
@ -99,6 +100,14 @@ private:
|
|||||||
typedef std::list<ThreadedBasebandSampleSource*> ThreadedBasebandSampleSources;
|
typedef std::list<ThreadedBasebandSampleSource*> ThreadedBasebandSampleSources;
|
||||||
ThreadedBasebandSampleSources m_threadedBasebandSampleSources; //!< baseband sample sources on their own threads (usually channels)
|
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;
|
BasebandSampleSink *m_spectrumSink;
|
||||||
|
|
||||||
uint m_sampleRate;
|
uint m_sampleRate;
|
||||||
|
@ -49,7 +49,7 @@ void SampleSourceFifo::init()
|
|||||||
void SampleSourceFifo::readAdvance(SampleVector::iterator& readUntil, unsigned int nbSamples)
|
void SampleSourceFifo::readAdvance(SampleVector::iterator& readUntil, unsigned int nbSamples)
|
||||||
{
|
{
|
||||||
// QMutexLocker mutexLocker(&m_mutex);
|
// QMutexLocker mutexLocker(&m_mutex);
|
||||||
assert(nbSamples < m_size/4);
|
assert(nbSamples <= m_size/2);
|
||||||
|
|
||||||
m_ir = (m_ir + nbSamples) % m_size;
|
m_ir = (m_ir + nbSamples) % m_size;
|
||||||
readUntil = m_data.begin() + m_size + m_ir;
|
readUntil = m_data.begin() + m_size + m_ir;
|
||||||
|
@ -32,6 +32,7 @@ public:
|
|||||||
~SampleSourceFifo();
|
~SampleSourceFifo();
|
||||||
|
|
||||||
void resize(uint32_t size);
|
void resize(uint32_t size);
|
||||||
|
uint32_t size() const { return m_size; }
|
||||||
void init();
|
void init();
|
||||||
/** advance read pointer for the given length and activate R/W signals */
|
/** advance read pointer for the given length and activate R/W signals */
|
||||||
void readAdvance(SampleVector::iterator& readUntil, unsigned int nbSamples);
|
void readAdvance(SampleVector::iterator& readUntil, unsigned int nbSamples);
|
||||||
|
@ -46,11 +46,14 @@ public:
|
|||||||
|
|
||||||
bool handleSourceMessage(const Message& cmd); //!< Send message to source synchronously
|
bool handleSourceMessage(const Message& cmd); //!< Send message to source synchronously
|
||||||
void pull(Sample& sample); //!< Pull one sample from source
|
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 */
|
/** direct feeding of sample source FIFO */
|
||||||
void feed(SampleSourceFifo* sampleFifo,
|
void feed(SampleSourceFifo* sampleFifo,
|
||||||
int nbSamples);
|
int nbSamples);
|
||||||
|
|
||||||
|
SampleSourceFifo& getSampleSourceFifo() { return m_basebandSampleSource->getSampleSourceFifo(); }
|
||||||
|
|
||||||
QString getSampleSourceObjectName() const;
|
QString getSampleSourceObjectName() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
Loading…
Reference in New Issue
Block a user