1
0
mirror of https://github.com/f4exb/sdrangel.git synced 2024-11-17 05:41:56 -05:00

Demod Analyzer: allow complex input. Fixes #932

This commit is contained in:
f4exb 2021-06-30 19:40:04 +02:00
parent 9e2fef7cf0
commit 3c50274d1a
18 changed files with 186 additions and 75 deletions

View File

@ -387,7 +387,7 @@ void AISDemodSink::processOneSample(Complex &ci)
QList<DataFifo*>::iterator it = dataFifos->begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}

View File

@ -237,7 +237,7 @@ void AMDemodSink::processOneSample(Complex &ci)
QList<DataFifo*>::iterator it = dataFifos->begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}

View File

@ -442,7 +442,9 @@ void DABDemodSink::processOneAudioSample(Complex &ci)
m_audioBufferFill = 0;
}
m_demodBuffer[m_demodBufferFill++] = l; // FIXME: What about right channel?
m_demodBuffer[m_demodBufferFill++] = l;
m_demodBuffer[m_demodBufferFill++] = r;
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
@ -452,7 +454,7 @@ void DABDemodSink::processOneAudioSample(Complex &ci)
QList<DataFifo*>::iterator it = dataFifos->begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeCI16);
}
}
@ -477,7 +479,7 @@ DABDemodSink::DABDemodSink(DABDemod *packetDemod) :
m_magsq = 0.0;
m_demodBuffer.resize(1<<12);
m_demodBuffer.resize(1<<13);
m_demodBufferFill = 0;
applySettings(m_settings, true);

View File

@ -187,7 +187,7 @@ void DSDDemodSink::feed(const SampleVector::const_iterator& begin, const SampleV
QList<DataFifo*>::iterator it = dataFifos->begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}

View File

@ -274,7 +274,7 @@ void NFMDemodSink::processOneSample(Complex &ci)
QList<DataFifo*>::iterator it = dataFifos->begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}

View File

@ -254,7 +254,7 @@ void PacketDemodSink::processOneSample(Complex &ci)
QList<DataFifo*>::iterator it = dataFifos->begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}

View File

@ -192,6 +192,9 @@ void SSBDemodSink::processOneSample(Complex &ci)
m_audioBuffer[m_audioBufferFill].r = (qint16)(z.real() * m_volume);
m_audioBuffer[m_audioBufferFill].l = (qint16)(z.imag() * m_volume);
}
m_demodBuffer[m_demodBufferFill++] = z.real();
m_demodBuffer[m_demodBufferFill++] = z.imag();
}
else
{
@ -199,11 +202,9 @@ void SSBDemodSink::processOneSample(Complex &ci)
qint16 sample = (qint16)(demod * m_volume);
m_audioBuffer[m_audioBufferFill].l = sample;
m_audioBuffer[m_audioBufferFill].r = sample;
m_demodBuffer[m_demodBufferFill++] = (z.real() + z.imag()) * 0.7;
}
m_demodBuffer[m_demodBufferFill] = (z.real() + z.imag()) * 0.7;
++m_demodBufferFill;
if (m_demodBufferFill >= m_demodBuffer.size())
{
QList<DataFifo*> *dataFifos = MainCore::instance()->getDataPipes().getFifos(m_channel, "demod");
@ -212,8 +213,13 @@ void SSBDemodSink::processOneSample(Complex &ci)
{
QList<DataFifo*>::iterator it = dataFifos->begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
for (; it != dataFifos->end(); ++it)
{
(*it)->write(
(quint8*) &m_demodBuffer[0],
m_demodBuffer.size() * sizeof(qint16),
m_audioBinaual ? DataFifo::DataTypeCI16 : DataFifo::DataTypeI16
);
}
}

View File

@ -149,7 +149,7 @@ void WFMDemodSink::feed(const SampleVector::const_iterator& begin, const SampleV
QList<DataFifo*>::iterator it = dataFifos->begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}

View File

@ -267,7 +267,7 @@ void AISModSource::modulateSample()
QList<DataFifo*>::iterator it = dataFifos->begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}

View File

@ -119,7 +119,7 @@ void AMModSource::pullOne(Sample& sample)
QList<DataFifo*>::iterator it = dataFifos->begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}

View File

@ -180,7 +180,7 @@ void NFMModSource::modulateSample()
QList<DataFifo*>::iterator it = dataFifos->begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}

View File

@ -287,7 +287,7 @@ void PacketModSource::modulateSample()
QList<DataFifo*>::iterator it = dataFifos->begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}

View File

@ -171,9 +171,16 @@ void SSBModSource::modulateSample()
calculateLevel(m_modSample);
// take projection on real axis
m_demodBuffer[m_demodBufferFill] = m_modSample.real() * std::numeric_limits<int16_t>::max();
++m_demodBufferFill;
if (m_settings.m_audioBinaural)
{
m_demodBuffer[m_demodBufferFill++] = m_modSample.real() * std::numeric_limits<int16_t>::max();
m_demodBuffer[m_demodBufferFill++] = m_modSample.imag() * std::numeric_limits<int16_t>::max();
}
else
{
// take projection on real axis
m_demodBuffer[m_demodBufferFill++] = m_modSample.real() * std::numeric_limits<int16_t>::max();
}
if (m_demodBufferFill >= m_demodBuffer.size())
{
@ -183,8 +190,13 @@ void SSBModSource::modulateSample()
{
QList<DataFifo*>::iterator it = dataFifos->begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
for (; it != dataFifos->end(); ++it)
{
(*it)->write(
(quint8*) &m_demodBuffer[0],
m_demodBuffer.size() * sizeof(qint16),
m_settings.m_audioBinaural ? DataFifo::DataTypeCI16 : DataFifo::DataTypeI16
);
}
}

View File

@ -159,7 +159,7 @@ void WFMModSource::pullOne(Sample& sample)
QList<DataFifo*>::iterator it = dataFifos->begin();
for (; it != dataFifos->end(); ++it) {
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16));
(*it)->write((quint8*) &m_demodBuffer[0], m_demodBuffer.size() * sizeof(qint16), DataFifo::DataTypeI16);
}
}

View File

@ -61,10 +61,25 @@ void DemodAnalyzerWorker::stopWork()
m_running = false;
}
void DemodAnalyzerWorker::feedPart(const QByteArray::const_iterator& begin, const QByteArray::const_iterator& end)
void DemodAnalyzerWorker::feedPart(
const QByteArray::const_iterator& begin,
const QByteArray::const_iterator& end,
DataFifo::DataType dataType
)
{
int countSamples = (end - begin) / sizeof(int16_t);
int16_t *s = (int16_t*) begin;
int nbBytes;
switch(dataType)
{
case DataFifo::DataTypeCI16:
nbBytes = 4;
break;
case DataFifo::DataTypeI16:
default:
nbBytes = 2;
}
int countSamples = (end - begin) / nbBytes;
if (countSamples > m_sampleBufferSize)
{
@ -73,26 +88,8 @@ void DemodAnalyzerWorker::feedPart(const QByteArray::const_iterator& begin, cons
m_sampleBufferSize = countSamples;
}
for(int i = 0; i < countSamples; i++)
{
double re = s[i] / (double) std::numeric_limits<int16_t>::max();
m_magsq = re*re;
m_channelPowerAvg(m_magsq);
if (m_settings.m_log2Decim == 0)
{
m_sampleBuffer[i].setReal(re * SDR_RX_SCALEF);
m_sampleBuffer[i].setImag(0);
}
else
{
m_convBuffer[2*i] = s[i];
m_convBuffer[2*i+1] = 0;
if (i == countSamples - 1) {
decimate(countSamples);
}
}
for (int i = 0; i < countSamples; i++) {
processSample(dataType, begin, countSamples, i);
}
if (m_scopeVis)
@ -211,17 +208,18 @@ void DemodAnalyzerWorker::handleData()
QByteArray::iterator part1end;
QByteArray::iterator part2begin;
QByteArray::iterator part2end;
DataFifo::DataType dataType;
std::size_t count = m_dataFifo->readBegin(m_dataFifo->fill(), &part1begin, &part1end, &part2begin, &part2end);
std::size_t count = m_dataFifo->readBegin(m_dataFifo->fill(), &part1begin, &part1end, &part2begin, &part2end, dataType);
// first part of FIFO data
if (part1begin != part1end) {
feedPart(part1begin, part1end);
feedPart(part1begin, part1end, dataType);
}
// second part of FIFO data (used when block wraps around)
if (part2begin != part2end) {
feedPart(part2begin, part2end);
feedPart(part2begin, part2end, dataType);
}
m_dataFifo->readCommit((unsigned int) count);

View File

@ -26,6 +26,7 @@
#include "dsp/dsptypes.h"
#include "dsp/decimators.h"
#include "dsp/datafifo.h"
#include "util/movingaverage.h"
#include "util/message.h"
#include "util/messagequeue.h"
@ -36,8 +37,6 @@ class BasebandSampleSink;
class ScopeVis;
class ChannelAPI;
class Feature;
class DataFifo;
class DemodAnalyzerWorker : public QObject {
Q_OBJECT
public:
@ -93,7 +92,11 @@ public:
MessageQueue *getInputMessageQueue() { return &m_inputMessageQueue; }
void setMessageQueueToFeature(MessageQueue *messageQueue) { m_msgQueueToFeature = messageQueue; }
void feedPart(const QByteArray::const_iterator& begin, const QByteArray::const_iterator& end);
void feedPart(
const QByteArray::const_iterator& begin,
const QByteArray::const_iterator& end,
DataFifo::DataType dataType
);
void applySampleRate(int sampleRate);
void applySettings(const DemodAnalyzerSettings& settings, bool force = false);
@ -125,6 +128,63 @@ private:
bool handleMessage(const Message& cmd);
void decimate(int countSamples);
inline void processSample(
DataFifo::DataType dataType,
const QByteArray::const_iterator& begin,
int countSamples,
int i
)
{
switch(dataType)
{
case DataFifo::DataTypeI16: {
int16_t *s = (int16_t*) begin;
double re = s[i] / (double) std::numeric_limits<int16_t>::max();
m_magsq = re*re;
m_channelPowerAvg(m_magsq);
if (m_settings.m_log2Decim == 0)
{
m_sampleBuffer[i].setReal(re * SDR_RX_SCALEF);
m_sampleBuffer[i].setImag(0);
}
else
{
m_convBuffer[2*i] = s[i];
m_convBuffer[2*i+1] = 0;
if (i == countSamples - 1) {
decimate(countSamples);
}
}
}
break;
case DataFifo::DataTypeCI16: {
int16_t *s = (int16_t*) begin;
double re = s[2*i] / (double) std::numeric_limits<int16_t>::max();
double im = s[2*i+1] / (double) std::numeric_limits<int16_t>::max();
m_magsq = re*re + im*im;
m_channelPowerAvg(m_magsq);
if (m_settings.m_log2Decim == 0)
{
m_sampleBuffer[i].setReal(re * SDR_RX_SCALEF);
m_sampleBuffer[i].setImag(im * SDR_RX_SCALEF);
}
else
{
m_convBuffer[2*i] = s[2*i];
m_convBuffer[2*i+1] = s[2*i+1];
if (i == countSamples - 1) {
decimate(countSamples);
}
}
}
break;
}
}
private slots:
void handleInputMessages();
void handleData(); //!< Handle data when samples have to be processed

View File

@ -41,6 +41,7 @@ void DataFifo::reset()
DataFifo::DataFifo(QObject* parent) :
QObject(parent),
m_data(),
m_currentDataType(DataTypeI16),
m_mutex(QMutex::Recursive)
{
m_suppressed = -1;
@ -53,6 +54,7 @@ DataFifo::DataFifo(QObject* parent) :
DataFifo::DataFifo(int size, QObject* parent) :
QObject(parent),
m_data(),
m_currentDataType(DataTypeI16),
m_mutex(QMutex::Recursive)
{
m_suppressed = -1;
@ -62,6 +64,7 @@ DataFifo::DataFifo(int size, QObject* parent) :
DataFifo::DataFifo(const DataFifo& other) :
QObject(other.parent()),
m_data(other.m_data),
m_currentDataType(DataTypeI16),
m_mutex(QMutex::Recursive)
{
m_suppressed = -1;
@ -84,9 +87,19 @@ bool DataFifo::setSize(int size)
return m_data.size() == size;
}
unsigned int DataFifo::write(const quint8* data, unsigned int count)
unsigned int DataFifo::write(const quint8* data, unsigned int count, DataType dataType)
{
QMutexLocker mutexLocker(&m_mutex);
if (dataType != m_currentDataType)
{
m_suppressed = -1;
m_fill = 0;
m_head = 0;
m_tail = 0;
m_currentDataType = dataType;
}
unsigned int total;
unsigned int remaining;
unsigned int len;
@ -138,9 +151,19 @@ unsigned int DataFifo::write(const quint8* data, unsigned int count)
return total;
}
unsigned int DataFifo::write(QByteArray::const_iterator begin, QByteArray::const_iterator end)
unsigned int DataFifo::write(QByteArray::const_iterator begin, QByteArray::const_iterator end, DataType dataType)
{
QMutexLocker mutexLocker(&m_mutex);
if (dataType != m_currentDataType)
{
m_suppressed = -1;
m_fill = 0;
m_head = 0;
m_tail = 0;
m_currentDataType = dataType;
}
unsigned int count = end - begin;
unsigned int total;
unsigned int remaining;
@ -191,9 +214,10 @@ unsigned int DataFifo::write(QByteArray::const_iterator begin, QByteArray::const
return total;
}
unsigned int DataFifo::read(QByteArray::iterator begin, QByteArray::iterator end)
unsigned int DataFifo::read(QByteArray::iterator begin, QByteArray::iterator end, DataType& dataType)
{
QMutexLocker mutexLocker(&m_mutex);
dataType = m_currentDataType;
unsigned int count = end - begin;
unsigned int total;
unsigned int remaining;
@ -223,9 +247,11 @@ unsigned int DataFifo::read(QByteArray::iterator begin, QByteArray::iterator end
unsigned int DataFifo::readBegin(unsigned int count,
QByteArray::iterator* part1Begin, QByteArray::iterator* part1End,
QByteArray::iterator* part2Begin, QByteArray::iterator* part2End)
QByteArray::iterator* part2Begin, QByteArray::iterator* part2End,
DataType& dataType)
{
QMutexLocker mutexLocker(&m_mutex);
dataType = m_currentDataType;
unsigned int total;
unsigned int remaining;
unsigned int len;

View File

@ -29,21 +29,13 @@
class SDRBASE_API DataFifo : public QObject {
Q_OBJECT
private:
QElapsedTimer m_msgRateTimer;
int m_suppressed;
QByteArray m_data;
QMutex m_mutex;
unsigned int m_size;
unsigned int m_fill;
unsigned int m_head;
unsigned int m_tail;
void create(unsigned int s);
public:
enum DataType
{
DataTypeI16, //!< 16 bit signed integer
DataTypeCI16 //!< Complex (i.e. Re, Im pair of) 16 bit signed integer
};
DataFifo(QObject* parent = nullptr);
DataFifo(int size, QObject* parent = nullptr);
DataFifo(const DataFifo& other);
@ -54,18 +46,33 @@ public:
inline unsigned int size() const { return m_size; }
inline unsigned int fill() { QMutexLocker mutexLocker(&m_mutex); unsigned int fill = m_fill; return fill; }
unsigned int write(const quint8* data, unsigned int count);
unsigned int write(QByteArray::const_iterator begin, QByteArray::const_iterator end);
unsigned int write(const quint8* data, unsigned int count, DataType dataType);
unsigned int write(QByteArray::const_iterator begin, QByteArray::const_iterator end, DataType dataType);
unsigned int read(QByteArray::iterator begin, QByteArray::iterator end);
unsigned int read(QByteArray::iterator begin, QByteArray::iterator end, DataType& dataType);
unsigned int readBegin(unsigned int count,
QByteArray::iterator* part1Begin, QByteArray::iterator* part1End,
QByteArray::iterator* part2Begin, QByteArray::iterator* part2End);
QByteArray::iterator* part2Begin, QByteArray::iterator* part2End,
DataType& daaType);
unsigned int readCommit(unsigned int count);
signals:
void dataReady();
private:
QElapsedTimer m_msgRateTimer;
int m_suppressed;
QByteArray m_data;
DataType m_currentDataType;
QMutex m_mutex;
unsigned int m_size;
unsigned int m_fill;
unsigned int m_head;
unsigned int m_tail;
void create(unsigned int s);
};
#endif // INCLUDE_DATAFIFO_H