mirror of
https://github.com/f4exb/sdrangel.git
synced 2025-02-03 09:44:01 -05:00
Deep redesign: debug AM demod removing extraneous interpolator init in start method
This commit is contained in:
parent
bc287a4c33
commit
19b234c4df
@ -18,11 +18,13 @@
|
||||
#ifndef INCLUDE_AUDIOFIFO_H
|
||||
#define INCLUDE_AUDIOFIFO_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QMutex>
|
||||
#include <QWaitCondition>
|
||||
#include "util/export.h"
|
||||
|
||||
class SDRANGELOVE_API AudioFifo {
|
||||
class SDRANGELOVE_API AudioFifo : public QObject {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AudioFifo();
|
||||
AudioFifo(uint sampleSize, uint numSamples);
|
||||
@ -30,8 +32,8 @@ public:
|
||||
|
||||
bool setSize(uint sampleSize, uint numSamples);
|
||||
|
||||
uint write(const quint8* data, uint numSamples, int timeout = INT_MAX);
|
||||
uint read(quint8* data, uint numSamples, int timeout = INT_MAX);
|
||||
uint write(const quint8* data, uint numSamples, int timeout_ms = INT_MAX);
|
||||
uint read(quint8* data, uint numSamples, int timeout_ms = INT_MAX);
|
||||
|
||||
uint drain(uint numSamples);
|
||||
void clear();
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include <QMutex>
|
||||
#include <QIODevice>
|
||||
#include <QAudioFormat>
|
||||
#include <list>
|
||||
#include <vector>
|
||||
#include "util/export.h"
|
||||
@ -39,6 +40,8 @@ public:
|
||||
void addFifo(AudioFifo* audioFifo);
|
||||
void removeFifo(AudioFifo* audioFifo);
|
||||
|
||||
uint getRate() const { return m_audioFormat.sampleRate(); }
|
||||
|
||||
private:
|
||||
QMutex m_mutex;
|
||||
QAudioOutput* m_audioOutput;
|
||||
@ -47,6 +50,8 @@ private:
|
||||
AudioFifos m_audioFifos;
|
||||
std::vector<qint32> m_mixBuffer;
|
||||
|
||||
QAudioFormat m_audioFormat;
|
||||
|
||||
//virtual bool open(OpenMode mode);
|
||||
virtual qint64 readData(char* data, qint64 maxLen);
|
||||
virtual qint64 writeData(const char* data, qint64 len);
|
||||
|
@ -55,6 +55,9 @@ public:
|
||||
MessageQueue* getInputMessageQueue() { return &m_inputMessageQueue; }
|
||||
MessageQueue* getOutputMessageQueue() { return &m_outputMessageQueue; }
|
||||
|
||||
uint getAudioSampleRate() const { return m_audioSampleRate; }
|
||||
void setAudioSampleRate(uint rate);
|
||||
|
||||
void start(); //!< This thread start
|
||||
void stop(); //!< This thread stop
|
||||
|
||||
@ -102,6 +105,7 @@ private:
|
||||
|
||||
uint m_sampleRate;
|
||||
quint64 m_centerFrequency;
|
||||
uint m_audioSampleRate;
|
||||
|
||||
bool m_dcOffsetCorrection;
|
||||
bool m_iqImbalanceCorrection;
|
||||
|
@ -20,13 +20,18 @@ public:
|
||||
void free();
|
||||
|
||||
// Original code allowed for upsampling, but was never used that way
|
||||
bool interpolate(Real* distance, const Complex& next, Complex* result)
|
||||
bool interpolate(Real *distance, const Complex& next, Complex* result)
|
||||
{
|
||||
advanceFilter(next);
|
||||
*distance -= 1.0;
|
||||
|
||||
if (*distance >= 1.0)
|
||||
{
|
||||
return false;
|
||||
doInterpolate((int)floor(*distance * (Real)m_phaseSteps), result);
|
||||
}
|
||||
|
||||
doInterpolate((int) floor(*distance * (Real)m_phaseSteps), result);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -103,15 +103,15 @@ private:
|
||||
PluginManager* m_pluginManager;
|
||||
|
||||
void loadSettings();
|
||||
void loadSettings(const Preset* preset);
|
||||
void saveSettings(Preset* preset);
|
||||
void loadPresetSettings(const Preset* preset);
|
||||
void savePresetSettings(Preset* preset);
|
||||
void saveSettings();
|
||||
|
||||
void createStatusBar();
|
||||
void closeEvent(QCloseEvent*);
|
||||
void updateCenterFreqDisplay();
|
||||
void updateSampleRate();
|
||||
void updatePresets();
|
||||
void updatePresetControls();
|
||||
QTreeWidgetItem* addPresetToTree(const Preset* preset);
|
||||
void applySettings();
|
||||
|
||||
|
@ -23,11 +23,29 @@
|
||||
#include "dsp/samplefifo.h"
|
||||
#include "util/messagequeue.h"
|
||||
#include "util/export.h"
|
||||
#include "util/syncmessenger.h"
|
||||
|
||||
class SampleSink;
|
||||
class QThread;
|
||||
|
||||
/**
|
||||
* Because Qt is a piece of shit this class cannot be a nested protected class of ThreadedSampleSink
|
||||
* So let's make everything public
|
||||
*/
|
||||
class ThreadedSampleFifo : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
ThreadedSampleFifo(SampleSink* sampleSink, std::size_t size = 1<<18);
|
||||
~ThreadedSampleFifo();
|
||||
void writeToFifo(SampleVector::const_iterator& begin, SampleVector::const_iterator& end);
|
||||
|
||||
SampleSink* m_sampleSink;
|
||||
SampleFifo m_sampleFifo;
|
||||
|
||||
public slots:
|
||||
void handleFifoData();
|
||||
};
|
||||
|
||||
/**
|
||||
* This class is a wrapper for SampleSink that runs the SampleSink object in its own thread
|
||||
*/
|
||||
@ -51,13 +69,10 @@ public:
|
||||
QString getSampleSinkObjectName() const;
|
||||
|
||||
protected:
|
||||
QThread *m_thread; //!< The thead object
|
||||
SyncMessenger m_syncMessenger; //!< Used to process messages synchronously with the thread
|
||||
SampleSink* m_sampleSink;
|
||||
SampleFifo m_sampleFifo;
|
||||
|
||||
protected slots:
|
||||
void handleData();
|
||||
QThread *m_thread; //!< The thead object
|
||||
ThreadedSampleFifo *m_threadedSampleFifo;
|
||||
SampleSink* m_sampleSink;
|
||||
};
|
||||
|
||||
#endif // INCLUDE_THREADEDSAMPLESINK_H
|
||||
|
@ -21,14 +21,15 @@
|
||||
#include <stdio.h>
|
||||
#include <complex.h>
|
||||
#include "audio/audiooutput.h"
|
||||
#include "dsp/dspengine.h"
|
||||
#include "dsp/channelizer.h"
|
||||
#include "dsp/pidcontroller.h"
|
||||
|
||||
MESSAGE_CLASS_DEFINITION(AMDemod::MsgConfigureAMDemod, Message)
|
||||
|
||||
AMDemod::AMDemod(AudioFifo* audioFifo, SampleSink* sampleSink) :
|
||||
AMDemod::AMDemod(SampleSink* sampleSink) :
|
||||
m_sampleSink(sampleSink),
|
||||
m_audioFifo(audioFifo)
|
||||
m_audioFifo(4, 48000)
|
||||
{
|
||||
setObjectName("AMDemod");
|
||||
|
||||
@ -38,15 +39,17 @@ AMDemod::AMDemod(AudioFifo* audioFifo, SampleSink* sampleSink) :
|
||||
m_config.m_afBandwidth = 3000;
|
||||
m_config.m_squelch = -40.0;
|
||||
m_config.m_volume = 2.0;
|
||||
m_config.m_audioSampleRate = 48000;
|
||||
m_config.m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
|
||||
|
||||
apply();
|
||||
|
||||
m_audioBuffer.resize(16384);
|
||||
m_audioBuffer.resize(1<<14);
|
||||
m_audioBufferFill = 0;
|
||||
|
||||
m_movingAverage.resize(16, 0);
|
||||
m_volumeAGC.resize(4096, 0.003, 0);
|
||||
|
||||
DSPEngine::instance()->addAudioSink(&m_audioFifo);
|
||||
}
|
||||
|
||||
AMDemod::~AMDemod()
|
||||
@ -63,7 +66,7 @@ void AMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_itera
|
||||
{
|
||||
Complex ci;
|
||||
|
||||
if (m_audioFifo->size() == 0)
|
||||
if (m_audioFifo.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@ -82,7 +85,7 @@ void AMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_itera
|
||||
|
||||
if (m_movingAverage.average() >= m_squelchLevel)
|
||||
{
|
||||
m_squelchState = m_running.m_audioSampleRate/ 20;
|
||||
m_squelchState = m_running.m_audioSampleRate / 20;
|
||||
}
|
||||
|
||||
qint16 sample;
|
||||
@ -122,12 +125,11 @@ void AMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_itera
|
||||
|
||||
if (m_audioBufferFill >= m_audioBuffer.size())
|
||||
{
|
||||
uint res = m_audioFifo->write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 1);
|
||||
uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 10);
|
||||
|
||||
// FIXME: Not necessarily bad, There is a race between threads but generally it works i.e. samples are not lost
|
||||
if (res != m_audioBufferFill)
|
||||
{
|
||||
qDebug("AMDemod::feed: %u/%u audio samples lost", m_audioBufferFill - res, m_audioBufferFill);
|
||||
qDebug("AMDemod::feed: %u/%u audio samples written", res, m_audioBufferFill);
|
||||
}
|
||||
|
||||
m_audioBufferFill = 0;
|
||||
@ -139,14 +141,12 @@ void AMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_itera
|
||||
|
||||
if (m_audioBufferFill > 0)
|
||||
{
|
||||
uint res = m_audioFifo->write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 1);
|
||||
uint res = m_audioFifo.write((const quint8*)&m_audioBuffer[0], m_audioBufferFill, 10);
|
||||
|
||||
// Same remark as above
|
||||
/*
|
||||
if (res != m_audioBufferFill)
|
||||
{
|
||||
qDebug("AMDemod::feed: %u samples written vs %u requested", res, m_audioBufferFill);
|
||||
}*/
|
||||
qDebug("AMDemod::feed: %u/%u tail samples written", res, m_audioBufferFill);
|
||||
}
|
||||
|
||||
m_audioBufferFill = 0;
|
||||
}
|
||||
@ -161,12 +161,11 @@ void AMDemod::feed(SampleVector::const_iterator begin, SampleVector::const_itera
|
||||
|
||||
void AMDemod::start()
|
||||
{
|
||||
qDebug() << "AMDemod::start: m_inputSampleRate: " << m_config.m_inputSampleRate
|
||||
<< " m_inputFrequencyOffset: " << m_config.m_inputFrequencyOffset;
|
||||
|
||||
m_squelchState = 0;
|
||||
m_audioFifo->clear();
|
||||
m_interpolatorRegulation = 0.9999;
|
||||
m_interpolatorDistance = 1.0;
|
||||
m_interpolatorDistanceRemain = 0.0;
|
||||
m_lastSample = 0;
|
||||
m_audioFifo.clear();
|
||||
}
|
||||
|
||||
void AMDemod::stop()
|
||||
@ -203,7 +202,7 @@ bool AMDemod::handleMessage(const Message& cmd)
|
||||
|
||||
apply();
|
||||
|
||||
qDebug() << " - MsgConfigureAMDemod:"
|
||||
qDebug() << "AMDemod::handleMessage: MsgConfigureAMDemod:"
|
||||
<< " m_rfBandwidth: " << m_config.m_rfBandwidth
|
||||
<< " m_afBandwidth: " << m_config.m_afBandwidth
|
||||
<< " m_volume: " << m_config.m_volume
|
||||
@ -239,6 +238,8 @@ void AMDemod::apply()
|
||||
m_interpolator.create(16, m_config.m_inputSampleRate, m_config.m_rfBandwidth / 2.2);
|
||||
m_interpolatorDistanceRemain = 0;
|
||||
m_interpolatorDistance = (Real) m_config.m_inputSampleRate / (Real) m_config.m_audioSampleRate;
|
||||
qDebug() << "AMDemod::apply: m_inputSampleRate: " << m_config.m_inputSampleRate
|
||||
<< " m_interpolatorDistance: " << m_interpolatorDistance;
|
||||
}
|
||||
|
||||
if((m_config.m_afBandwidth != m_running.m_afBandwidth) ||
|
||||
|
@ -30,8 +30,9 @@
|
||||
class AudioFifo;
|
||||
|
||||
class AMDemod : public SampleSink {
|
||||
Q_OBJECT
|
||||
public:
|
||||
AMDemod(AudioFifo* audioFifo, SampleSink* sampleSink);
|
||||
AMDemod(SampleSink* sampleSink);
|
||||
~AMDemod();
|
||||
|
||||
void configure(MessageQueue* messageQueue, Real rfBandwidth, Real afBandwidth, Real volume, Real squelch);
|
||||
@ -106,7 +107,6 @@ private:
|
||||
Config m_running;
|
||||
|
||||
NCO m_nco;
|
||||
Real m_interpolatorRegulation;
|
||||
Interpolator m_interpolator;
|
||||
Real m_interpolatorDistance;
|
||||
Real m_interpolatorDistanceRemain;
|
||||
@ -115,8 +115,6 @@ private:
|
||||
Real m_squelchLevel;
|
||||
int m_squelchState;
|
||||
|
||||
Real m_lastArgument;
|
||||
Complex m_lastSample;
|
||||
MovingAverage<Real> m_movingAverage;
|
||||
SimpleAGC m_volumeAGC;
|
||||
|
||||
@ -124,7 +122,7 @@ private:
|
||||
uint m_audioBufferFill;
|
||||
|
||||
SampleSink* m_sampleSink;
|
||||
AudioFifo* m_audioFifo;
|
||||
AudioFifo m_audioFifo;
|
||||
SampleVector m_sampleBuffer;
|
||||
|
||||
void apply();
|
||||
|
@ -201,11 +201,9 @@ AMDemodGUI::AMDemodGUI(PluginAPI* pluginAPI, QWidget* parent) :
|
||||
connect(this, SIGNAL(widgetRolled(QWidget*,bool)), this, SLOT(onWidgetRolled(QWidget*,bool)));
|
||||
connect(this, SIGNAL(menuDoubleClickEvent()), this, SLOT(onMenuDoubleClicked()));
|
||||
|
||||
m_audioFifo = new AudioFifo(4, 48000);
|
||||
m_amDemod = new AMDemod(m_audioFifo, 0);
|
||||
m_amDemod = new AMDemod(0);
|
||||
m_channelizer = new Channelizer(m_amDemod);
|
||||
m_threadedChannelizer = new ThreadedSampleSink(m_channelizer, this);
|
||||
DSPEngine::instance()->addAudioSink(m_audioFifo);
|
||||
DSPEngine::instance()->addThreadedSink(m_threadedChannelizer);
|
||||
|
||||
m_channelMarker = new ChannelMarker(this);
|
||||
@ -227,7 +225,6 @@ AMDemodGUI::~AMDemodGUI()
|
||||
delete m_threadedChannelizer;
|
||||
delete m_channelizer;
|
||||
delete m_amDemod;
|
||||
delete m_audioFifo;
|
||||
delete m_channelMarker;
|
||||
delete ui;
|
||||
}
|
||||
|
@ -62,7 +62,7 @@ bool AudioFifo::setSize(uint sampleSize, uint numSamples)
|
||||
return create(sampleSize, numSamples);
|
||||
}
|
||||
|
||||
uint AudioFifo::write(const quint8* data, uint numSamples, int timeout)
|
||||
uint AudioFifo::write(const quint8* data, uint numSamples, int timeout_ms)
|
||||
{
|
||||
QTime time;
|
||||
uint total;
|
||||
@ -77,7 +77,7 @@ uint AudioFifo::write(const quint8* data, uint numSamples, int timeout)
|
||||
time.start();
|
||||
m_mutex.lock();
|
||||
|
||||
if(timeout == 0)
|
||||
if(timeout_ms == 0)
|
||||
{
|
||||
total = MIN(numSamples, m_size - m_fill);
|
||||
}
|
||||
@ -92,11 +92,11 @@ uint AudioFifo::write(const quint8* data, uint numSamples, int timeout)
|
||||
{
|
||||
if (isFull())
|
||||
{
|
||||
if (time.elapsed() < timeout)
|
||||
if (time.elapsed() < timeout_ms)
|
||||
{
|
||||
m_writeWaitLock.lock();
|
||||
m_mutex.unlock();
|
||||
int ms = timeout - time.elapsed();
|
||||
int ms = timeout_ms - time.elapsed();
|
||||
|
||||
if(ms < 1)
|
||||
{
|
||||
@ -141,7 +141,7 @@ uint AudioFifo::write(const quint8* data, uint numSamples, int timeout)
|
||||
return total;
|
||||
}
|
||||
|
||||
uint AudioFifo::read(quint8* data, uint numSamples, int timeout)
|
||||
uint AudioFifo::read(quint8* data, uint numSamples, int timeout_ms)
|
||||
{
|
||||
QTime time;
|
||||
uint total;
|
||||
@ -156,7 +156,7 @@ uint AudioFifo::read(quint8* data, uint numSamples, int timeout)
|
||||
time.start();
|
||||
m_mutex.lock();
|
||||
|
||||
if(timeout == 0)
|
||||
if(timeout_ms == 0)
|
||||
{
|
||||
total = MIN(numSamples, m_fill);
|
||||
}
|
||||
@ -171,11 +171,11 @@ uint AudioFifo::read(quint8* data, uint numSamples, int timeout)
|
||||
{
|
||||
if(isEmpty())
|
||||
{
|
||||
if(time.elapsed() < timeout)
|
||||
if(time.elapsed() < timeout_ms)
|
||||
{
|
||||
m_readWaitLock.lock();
|
||||
m_mutex.unlock();
|
||||
int ms = timeout - time.elapsed();
|
||||
int ms = timeout_ms - time.elapsed();
|
||||
|
||||
if(ms < 1)
|
||||
{
|
||||
|
@ -50,7 +50,6 @@ bool AudioOutput::start(int device, int rate)
|
||||
//Q_UNUSED(device);
|
||||
//Q_UNUSED(rate);
|
||||
|
||||
QAudioFormat format;
|
||||
QAudioDeviceInfo devInfo;
|
||||
|
||||
if (device < 0)
|
||||
@ -76,31 +75,36 @@ bool AudioOutput::start(int device, int rate)
|
||||
|
||||
//QAudioDeviceInfo devInfo(QAudioDeviceInfo::defaultOutputDevice());
|
||||
|
||||
format.setSampleRate(rate);
|
||||
format.setChannelCount(2);
|
||||
format.setSampleSize(16);
|
||||
format.setCodec("audio/pcm");
|
||||
format.setByteOrder(QAudioFormat::LittleEndian);
|
||||
format.setSampleType(QAudioFormat::SignedInt);
|
||||
m_audioFormat.setSampleRate(rate);
|
||||
m_audioFormat.setChannelCount(2);
|
||||
m_audioFormat.setSampleSize(16);
|
||||
m_audioFormat.setCodec("audio/pcm");
|
||||
m_audioFormat.setByteOrder(QAudioFormat::LittleEndian);
|
||||
m_audioFormat.setSampleType(QAudioFormat::SignedInt);
|
||||
|
||||
if (!devInfo.isFormatSupported(format))
|
||||
if (!devInfo.isFormatSupported(m_audioFormat))
|
||||
{
|
||||
qWarning("AudioOutput::start: %d Hz S16_LE audio format not supported", rate);
|
||||
format = devInfo.nearestFormat(format);
|
||||
m_audioFormat = devInfo.nearestFormat(m_audioFormat);
|
||||
qWarning("AudioOutput::start: %d Hz S16_LE audio format not supported. New rate: %d", rate, m_audioFormat.sampleRate());
|
||||
}
|
||||
|
||||
if (format.sampleSize() != 16)
|
||||
if (m_audioFormat.sampleSize() != 16)
|
||||
{
|
||||
qWarning("AudioOutput::start: Audio device ( %s ) failed", qPrintable(devInfo.defaultOutputDevice().deviceName()));
|
||||
return false;
|
||||
}
|
||||
|
||||
m_audioOutput = new QAudioOutput(devInfo, format);
|
||||
m_audioOutput = new QAudioOutput(devInfo, m_audioFormat);
|
||||
|
||||
QIODevice::open(QIODevice::ReadOnly);
|
||||
|
||||
m_audioOutput->start(this);
|
||||
|
||||
if (m_audioOutput->state() != QAudio::ActiveState)
|
||||
{
|
||||
qWarning("AudioOutput::start: cannot start");
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ void Channelizer::configure(MessageQueue* messageQueue, int sampleRate, int cent
|
||||
|
||||
void Channelizer::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
|
||||
{
|
||||
if(m_sampleSink == NULL) {
|
||||
if(m_sampleSink == 0) {
|
||||
m_sampleBuffer.clear();
|
||||
return;
|
||||
}
|
||||
@ -55,16 +55,19 @@ void Channelizer::feed(SampleVector::const_iterator begin, SampleVector::const_i
|
||||
|
||||
void Channelizer::start()
|
||||
{
|
||||
if(m_sampleSink != NULL)
|
||||
if(m_sampleSink != 0)
|
||||
{
|
||||
qDebug() << "Channelizer::start: thread: " << thread();
|
||||
qDebug() << "Channelizer::start: thread: " << thread()
|
||||
<< " m_inputSampleRate: " << m_inputSampleRate
|
||||
<< " m_requestedOutputSampleRate: " << m_requestedOutputSampleRate
|
||||
<< " m_requestedCenterFrequency: " << m_requestedCenterFrequency;
|
||||
m_sampleSink->start();
|
||||
}
|
||||
}
|
||||
|
||||
void Channelizer::stop()
|
||||
{
|
||||
if(m_sampleSink != NULL)
|
||||
if(m_sampleSink != 0)
|
||||
m_sampleSink->stop();
|
||||
}
|
||||
|
||||
@ -79,7 +82,7 @@ bool Channelizer::handleMessage(const Message& cmd)
|
||||
qDebug() << "Channelizer::handleMessage: DSPSignalNotification: m_inputSampleRate: " << m_inputSampleRate;
|
||||
applyConfiguration();
|
||||
|
||||
if (m_sampleSink != NULL)
|
||||
if (m_sampleSink != 0)
|
||||
{
|
||||
m_sampleSink->handleMessage(notif);
|
||||
}
|
||||
@ -99,17 +102,11 @@ bool Channelizer::handleMessage(const Message& cmd)
|
||||
|
||||
applyConfiguration();
|
||||
|
||||
if (m_sampleSink != NULL)
|
||||
{
|
||||
MsgChannelizerNotification notif(m_currentOutputSampleRate, m_currentCenterFrequency);
|
||||
m_sampleSink->handleMessage(notif);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_sampleSink != NULL)
|
||||
if (m_sampleSink != 0)
|
||||
{
|
||||
return m_sampleSink->handleMessage(cmd);
|
||||
}
|
||||
@ -132,11 +129,17 @@ void Channelizer::applyConfiguration()
|
||||
<< ", req=" << m_requestedOutputSampleRate
|
||||
<< ", out=" << m_currentOutputSampleRate
|
||||
<< ", fc=" << m_currentCenterFrequency;
|
||||
|
||||
if (m_sampleSink != 0)
|
||||
{
|
||||
MsgChannelizerNotification notif(m_currentOutputSampleRate, m_currentCenterFrequency);
|
||||
m_sampleSink->handleMessage(notif);
|
||||
}
|
||||
}
|
||||
|
||||
Channelizer::FilterStage::FilterStage(Mode mode) :
|
||||
m_filter(new IntHalfbandFilter),
|
||||
m_workFunction(NULL)
|
||||
m_workFunction(0)
|
||||
{
|
||||
switch(mode) {
|
||||
case ModeCenter:
|
||||
|
@ -32,6 +32,7 @@ DSPEngine::DSPEngine(QObject* parent) :
|
||||
m_sampleSinks(),
|
||||
m_sampleRate(0),
|
||||
m_centerFrequency(0),
|
||||
m_audioSampleRate(48000),
|
||||
m_dcOffsetCorrection(false),
|
||||
m_iqImbalanceCorrection(false),
|
||||
m_iOffset(0),
|
||||
@ -411,13 +412,13 @@ DSPEngine::State DSPEngine::gotoInit()
|
||||
|
||||
for (SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); ++it)
|
||||
{
|
||||
qDebug() << " - initializing " << (*it)->objectName().toStdString().c_str();
|
||||
qDebug() << "DSPEngine::gotoInit: initializing " << (*it)->objectName().toStdString().c_str();
|
||||
(*it)->handleMessage(notif);
|
||||
}
|
||||
|
||||
for (ThreadedSampleSinks::const_iterator it = m_threadedSampleSinks.begin(); it != m_threadedSampleSinks.end(); ++it)
|
||||
{
|
||||
qDebug() << " - initializing ThreadedSampleSink(" << (*it)->getSampleSinkObjectName().toStdString().c_str() << ")";
|
||||
qDebug() << "DSPEngine::gotoInit: initializing ThreadedSampleSink(" << (*it)->getSampleSinkObjectName().toStdString().c_str() << ")";
|
||||
(*it)->handleSinkMessage(notif);
|
||||
}
|
||||
|
||||
@ -431,8 +432,8 @@ DSPEngine::State DSPEngine::gotoInit()
|
||||
|
||||
DSPEngine::State DSPEngine::gotoRunning()
|
||||
{
|
||||
qDebug() << "DSPEngine::gotoRunning";
|
||||
|
||||
qDebug() << "DSPEngine::gotoRunning";
|
||||
|
||||
switch(m_state)
|
||||
{
|
||||
case StNotStarted:
|
||||
@ -450,10 +451,10 @@ DSPEngine::State DSPEngine::gotoRunning()
|
||||
}
|
||||
|
||||
if(m_sampleSource == NULL) {
|
||||
return gotoError("No sample source configured");
|
||||
return gotoError("DSPEngine::gotoRunning: No sample source configured");
|
||||
}
|
||||
|
||||
qDebug() << " - " << m_deviceDescription.toStdString().c_str() << " started";
|
||||
qDebug() << "DSPEngine::gotoRunning: " << m_deviceDescription.toStdString().c_str() << " started";
|
||||
|
||||
// Start everything
|
||||
|
||||
@ -463,20 +464,21 @@ DSPEngine::State DSPEngine::gotoRunning()
|
||||
}
|
||||
|
||||
m_audioOutput.start(-1, 48000); // Use default output device at 48 kHz
|
||||
m_audioSampleRate = m_audioOutput.getRate();
|
||||
|
||||
for(SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); it++)
|
||||
{
|
||||
qDebug() << " - starting " << (*it)->objectName().toStdString().c_str();
|
||||
qDebug() << "DSPEngine::gotoRunning: starting " << (*it)->objectName().toStdString().c_str();
|
||||
(*it)->start();
|
||||
}
|
||||
|
||||
for (ThreadedSampleSinks::const_iterator it = m_threadedSampleSinks.begin(); it != m_threadedSampleSinks.end(); ++it)
|
||||
{
|
||||
qDebug() << " - starting ThreadedSampleSink(" << (*it)->getSampleSinkObjectName().toStdString().c_str() << ")";
|
||||
qDebug() << "DSPEngine::gotoRunning: starting ThreadedSampleSink(" << (*it)->getSampleSinkObjectName().toStdString().c_str() << ")";
|
||||
(*it)->start();
|
||||
}
|
||||
|
||||
qDebug() << " - input message queue pending: " << m_inputMessageQueue.size();
|
||||
qDebug() << "DSPEngine::gotoRunning:input message queue pending: " << m_inputMessageQueue.size();
|
||||
|
||||
return StRunning;
|
||||
}
|
||||
@ -681,3 +683,8 @@ void DSPEngine::handleSourceMessages()
|
||||
delete message;
|
||||
}
|
||||
}
|
||||
|
||||
void DSPEngine::setAudioSampleRate(uint rate)
|
||||
{
|
||||
m_audioSampleRate = rate;
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ bool FileSink::handleMessage(const Message& message)
|
||||
DSPSignalNotification& notif = (DSPSignalNotification&) message;
|
||||
m_sampleRate = notif.getSampleRate();
|
||||
m_centerFrequency = notif.getCenterFrequency();
|
||||
qDebug() << " - DSPSignalNotification: m_inputSampleRate: " << m_sampleRate
|
||||
qDebug() << "FileSink::handleMessage: DSPSignalNotification: m_inputSampleRate: " << m_sampleRate
|
||||
<< " m_centerFrequency: " << m_centerFrequency;
|
||||
return true;
|
||||
}
|
||||
@ -98,7 +98,7 @@ bool FileSink::handleMessage(const Message& message)
|
||||
{
|
||||
MsgConfigureFileSink& conf = (MsgConfigureFileSink&) message;
|
||||
handleConfigure(conf.getFileName());
|
||||
qDebug() << " - MsgConfigureFileSink: fileName: " << m_fileName.c_str();
|
||||
qDebug() << "FileSink::handleMessage: MsgConfigureFileSink: fileName: " << m_fileName.c_str();
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
@ -1,10 +1,26 @@
|
||||
#include <QThread>
|
||||
#include <QDebug>
|
||||
#include <QApplication>
|
||||
#include "dsp/threadedsamplesink.h"
|
||||
#include "dsp/dspcommands.h"
|
||||
#include "util/message.h"
|
||||
|
||||
ThreadedSampleFifo::ThreadedSampleFifo(SampleSink *sampleSink, std::size_t size) :
|
||||
m_sampleSink(sampleSink)
|
||||
{
|
||||
connect(&m_sampleFifo, SIGNAL(dataReady()), this, SLOT(handleFifoData()));
|
||||
m_sampleFifo.setSize(size);
|
||||
}
|
||||
|
||||
ThreadedSampleFifo::~ThreadedSampleFifo()
|
||||
{
|
||||
m_sampleFifo.readCommit(m_sampleFifo.fill());
|
||||
}
|
||||
|
||||
void ThreadedSampleFifo::writeToFifo(SampleVector::const_iterator& begin, SampleVector::const_iterator& end)
|
||||
{
|
||||
m_sampleFifo.write(begin, end);
|
||||
}
|
||||
|
||||
ThreadedSampleSink::ThreadedSampleSink(SampleSink* sampleSink, QObject *parent) :
|
||||
m_sampleSink(sampleSink)
|
||||
{
|
||||
@ -14,11 +30,13 @@ ThreadedSampleSink::ThreadedSampleSink(SampleSink* sampleSink, QObject *parent)
|
||||
qDebug() << "ThreadedSampleSink::ThreadedSampleSink: " << name;
|
||||
|
||||
m_thread = new QThread(parent);
|
||||
moveToThread(m_thread); // FIXME: the intermediate FIFO should be handled within the sink. Define a new type of sink that is compatible with threading
|
||||
m_threadedSampleFifo = new ThreadedSampleFifo(m_sampleSink);
|
||||
//moveToThread(m_thread); // FIXME: Fixed? the intermediate FIFO should be handled within the sink. Define a new type of sink that is compatible with threading
|
||||
m_sampleSink->moveToThread(m_thread);
|
||||
m_sampleFifo.moveToThread(m_thread);
|
||||
connect(&m_sampleFifo, SIGNAL(dataReady()), this, SLOT(handleData()));
|
||||
m_sampleFifo.setSize(262144);
|
||||
m_threadedSampleFifo->moveToThread(m_thread);
|
||||
//m_sampleFifo.moveToThread(m_thread);
|
||||
//connect(&m_sampleFifo, SIGNAL(dataReady()), this, SLOT(handleData()));
|
||||
//m_sampleFifo.setSize(262144);
|
||||
|
||||
qDebug() << "ThreadedSampleSink::ThreadedSampleSink: thread: " << thread() << " m_thread: " << m_thread;
|
||||
}
|
||||
@ -41,14 +59,13 @@ void ThreadedSampleSink::stop()
|
||||
m_sampleSink->stop();
|
||||
m_thread->exit();
|
||||
m_thread->wait();
|
||||
m_sampleFifo.readCommit(m_sampleFifo.fill());
|
||||
|
||||
}
|
||||
|
||||
void ThreadedSampleSink::feed(SampleVector::const_iterator begin, SampleVector::const_iterator end, bool positiveOnly)
|
||||
{
|
||||
// m_sampleSink->feed(begin, end, positiveOnly);
|
||||
m_sampleFifo.write(begin, end);
|
||||
//m_sampleSink->feed(begin, end, positiveOnly);
|
||||
//m_sampleFifo.write(begin, end);
|
||||
m_threadedSampleFifo->writeToFifo(begin, end);
|
||||
}
|
||||
|
||||
bool ThreadedSampleSink::handleSinkMessage(Message& cmd)
|
||||
@ -62,7 +79,7 @@ QString ThreadedSampleSink::getSampleSinkObjectName() const
|
||||
}
|
||||
|
||||
|
||||
void ThreadedSampleSink::handleData() // FIXME: Move it to the new threadable sink class
|
||||
void ThreadedSampleFifo::handleFifoData() // FIXME: Fixed? Move it to the new threadable sink class
|
||||
{
|
||||
bool positiveOnly = false;
|
||||
|
||||
|
@ -100,14 +100,13 @@ MainWindow::MainWindow(QWidget* parent) :
|
||||
ui->sampleSource->blockSignals(sampleSourceSignalsBlocked);
|
||||
|
||||
m_spectrumVis = new SpectrumVis(ui->glSpectrum);
|
||||
ui->glSpectrum->connectTimer(m_masterTimer);
|
||||
ui->glSpectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
||||
m_dspEngine->addSink(m_spectrumVis);
|
||||
|
||||
m_fileSink = new FileSink();
|
||||
m_dspEngine->addSink(m_fileSink);
|
||||
|
||||
ui->glSpectrum->connectTimer(m_masterTimer);
|
||||
ui->glSpectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
|
||||
|
||||
qDebug() << "MainWindow::MainWindow: loadSettings...";
|
||||
|
||||
loadSettings();
|
||||
@ -123,17 +122,17 @@ MainWindow::MainWindow(QWidget* parent) :
|
||||
ui->sampleSource->blockSignals(sampleSourceSignalsBlocked);
|
||||
}
|
||||
|
||||
qDebug() << "MainWindow::MainWindow: load current settings...";
|
||||
qDebug() << "MainWindow::MainWindow: load current preset settings...";
|
||||
|
||||
loadSettings(m_settings.getCurrent());
|
||||
loadPresetSettings(m_settings.getCurrent());
|
||||
|
||||
qDebug() << "MainWindow::MainWindow: apply settings...";
|
||||
|
||||
applySettings();
|
||||
|
||||
qDebug() << "MainWindow::MainWindow: update presets...";
|
||||
qDebug() << "MainWindow::MainWindow: update preset controls...";
|
||||
|
||||
updatePresets();
|
||||
updatePresetControls();
|
||||
|
||||
qDebug() << "MainWindow::MainWindow: end";
|
||||
}
|
||||
@ -203,15 +202,11 @@ void MainWindow::loadSettings()
|
||||
{
|
||||
addPresetToTree(m_settings.getPreset(i));
|
||||
}
|
||||
|
||||
Preset* current = m_settings.getCurrent();
|
||||
|
||||
//loadSettings(current);
|
||||
}
|
||||
|
||||
void MainWindow::loadSettings(const Preset* preset)
|
||||
void MainWindow::loadPresetSettings(const Preset* preset)
|
||||
{
|
||||
qDebug() << "MainWindow::loadSettings(preset): " << preset->getSource().toStdString().c_str();
|
||||
qDebug() << "MainWindow::loadPresetSettings: preset: " << preset->getSource().toStdString().c_str();
|
||||
|
||||
ui->glSpectrumGUI->deserialize(preset->getSpectrumConfig());
|
||||
ui->dcOffset->setChecked(preset->getDCOffsetCorrection());
|
||||
@ -227,14 +222,14 @@ void MainWindow::saveSettings()
|
||||
{
|
||||
qDebug() << "MainWindow::saveSettings";
|
||||
|
||||
saveSettings(m_settings.getCurrent());
|
||||
savePresetSettings(m_settings.getCurrent());
|
||||
m_settings.save();
|
||||
|
||||
}
|
||||
|
||||
void MainWindow::saveSettings(Preset* preset)
|
||||
void MainWindow::savePresetSettings(Preset* preset)
|
||||
{
|
||||
qDebug() << "MainWindow::saveSettings(preset): " << preset->getSource().toStdString().c_str();
|
||||
qDebug() << "MainWindow::savePresetSettings: preset: " << preset->getSource().toStdString().c_str();
|
||||
|
||||
preset->setSpectrumConfig(ui->glSpectrumGUI->serialize());
|
||||
preset->clearChannels();
|
||||
@ -281,13 +276,17 @@ void MainWindow::updateSampleRate()
|
||||
m_sampleRateWidget->setText(tr("Rate: %1 kHz").arg((float)m_sampleRate / 1000));
|
||||
}
|
||||
|
||||
void MainWindow::updatePresets()
|
||||
void MainWindow::updatePresetControls()
|
||||
{
|
||||
ui->presetTree->resizeColumnToContents(0);
|
||||
if(ui->presetTree->currentItem() != 0) {
|
||||
|
||||
if(ui->presetTree->currentItem() != 0)
|
||||
{
|
||||
ui->presetDelete->setEnabled(true);
|
||||
ui->presetLoad->setEnabled(true);
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->presetDelete->setEnabled(false);
|
||||
ui->presetLoad->setEnabled(false);
|
||||
}
|
||||
@ -318,7 +317,7 @@ QTreeWidgetItem* MainWindow::addPresetToTree(const Preset* preset)
|
||||
item->setData(0, Qt::UserRole, qVariantFromValue(preset));
|
||||
ui->presetTree->resizeColumnToContents(0);
|
||||
|
||||
updatePresets();
|
||||
updatePresetControls();
|
||||
return item;
|
||||
}
|
||||
|
||||
@ -477,7 +476,7 @@ void MainWindow::on_presetSave_clicked()
|
||||
|
||||
if(dlg.exec() == QDialog::Accepted) {
|
||||
Preset* preset = m_settings.newPreset(dlg.group(), dlg.description());
|
||||
saveSettings(preset);
|
||||
savePresetSettings(preset);
|
||||
|
||||
ui->presetTree->setCurrentItem(addPresetToTree(preset));
|
||||
}
|
||||
@ -492,7 +491,7 @@ void MainWindow::on_presetUpdate_clicked()
|
||||
const Preset* preset = qvariant_cast<const Preset*>(item->data(0, Qt::UserRole));
|
||||
if (preset != 0) {
|
||||
Preset* preset_mod = const_cast<Preset*>(preset);
|
||||
saveSettings(preset_mod);
|
||||
savePresetSettings(preset_mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -504,7 +503,7 @@ void MainWindow::on_presetLoad_clicked()
|
||||
|
||||
QTreeWidgetItem* item = ui->presetTree->currentItem();
|
||||
if(item == 0) {
|
||||
updatePresets();
|
||||
updatePresetControls();
|
||||
return;
|
||||
}
|
||||
const Preset* preset = qvariant_cast<const Preset*>(item->data(0, Qt::UserRole));
|
||||
@ -512,7 +511,7 @@ void MainWindow::on_presetLoad_clicked()
|
||||
return;
|
||||
}
|
||||
|
||||
loadSettings(preset);
|
||||
loadPresetSettings(preset);
|
||||
applySettings();
|
||||
}
|
||||
|
||||
@ -520,7 +519,7 @@ void MainWindow::on_presetDelete_clicked()
|
||||
{
|
||||
QTreeWidgetItem* item = ui->presetTree->currentItem();
|
||||
if(item == 0) {
|
||||
updatePresets();
|
||||
updatePresetControls();
|
||||
return;
|
||||
}
|
||||
const Preset* preset = qvariant_cast<const Preset*>(item->data(0, Qt::UserRole));
|
||||
@ -535,7 +534,7 @@ void MainWindow::on_presetDelete_clicked()
|
||||
|
||||
void MainWindow::on_presetTree_currentItemChanged(QTreeWidgetItem *current, QTreeWidgetItem *previous)
|
||||
{
|
||||
updatePresets();
|
||||
updatePresetControls();
|
||||
}
|
||||
|
||||
void MainWindow::on_presetTree_itemActivated(QTreeWidgetItem *item, int column)
|
||||
|
Loading…
Reference in New Issue
Block a user