mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-17 05:41:56 -05: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
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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_ */
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user