summaryrefslogtreecommitdiffstats
path: root/sdrbase
diff options
context:
space:
mode:
authorChristian Daniel <cd@maintech.de>2014-08-15 11:37:26 +0200
committerChristian Daniel <cd@maintech.de>2014-08-16 22:32:45 +0200
commit5864e48bd8d559223bed4a9eabbc4f894dc128ef (patch)
treee2a6d36abad80e0bcccbd79c48b34b4b4ecf80bc /sdrbase
parent78201046667987b25ade0b4023805a93353133fe (diff)
major rewrite
Diffstat (limited to 'sdrbase')
-rw-r--r--sdrbase/audio/audiodeviceinfo.cpp28
-rw-r--r--sdrbase/audio/audiofifo.cpp4
-rw-r--r--sdrbase/audio/audiooutput.cpp71
-rw-r--r--sdrbase/dsp/channelizer.cpp164
-rw-r--r--sdrbase/dsp/dspcommands.cpp1
-rw-r--r--sdrbase/dsp/dspengine.cpp97
-rw-r--r--sdrbase/dsp/fftwengine.cpp2
-rw-r--r--sdrbase/dsp/nco.cpp17
-rw-r--r--sdrbase/dsp/pidcontroller.cpp2
-rw-r--r--sdrbase/dsp/pidcontroller.h28
-rw-r--r--sdrbase/dsp/samplefifo.cpp31
-rw-r--r--sdrbase/dsp/spectrumvis.cpp2
-rw-r--r--sdrbase/dsp/threadedsamplesink.cpp33
-rw-r--r--sdrbase/gui/glspectrumgui.cpp2
-rw-r--r--sdrbase/gui/glspectrumgui.ui16
-rw-r--r--sdrbase/gui/preferencesdialog.cpp77
-rw-r--r--sdrbase/gui/preferencesdialog.ui110
-rw-r--r--sdrbase/gui/scopewindow.cpp8
-rw-r--r--sdrbase/mainwindow.cpp34
-rw-r--r--sdrbase/plugin/pluginmanager.cpp6
-rw-r--r--sdrbase/settings/preferences.cpp20
-rw-r--r--sdrbase/util/message.cpp2
22 files changed, 334 insertions, 421 deletions
diff --git a/sdrbase/audio/audiodeviceinfo.cpp b/sdrbase/audio/audiodeviceinfo.cpp
deleted file mode 100644
index e422878..0000000
--- a/sdrbase/audio/audiodeviceinfo.cpp
+++ /dev/null
@@ -1,28 +0,0 @@
-///////////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
-// written by Christian Daniel //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation as version 3 of the License, or //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License V3 for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program. If not, see <http://www.gnu.org/licenses/>. //
-///////////////////////////////////////////////////////////////////////////////////
-
-#include "audio/audiodeviceinfo.h"
-
-AudioDeviceInfo::AudioDeviceInfo()
-{
-}
-
-int AudioDeviceInfo::match(const QString& api, const QString device) const
-{
- // nothing found - fall back to default
- return 0;
-}
diff --git a/sdrbase/audio/audiofifo.cpp b/sdrbase/audio/audiofifo.cpp
index dd475ca..41d19df 100644
--- a/sdrbase/audio/audiofifo.cpp
+++ b/sdrbase/audio/audiofifo.cpp
@@ -22,7 +22,9 @@
#define MIN(x, y) ((x) < (y) ? (x) : (y))
AudioFifo::AudioFifo() :
- m_fifo(NULL)
+ m_fifo(NULL),
+ m_sampleRate(0),
+ m_stopped(true)
{
m_size = 0;
m_fill = 0;
diff --git a/sdrbase/audio/audiooutput.cpp b/sdrbase/audio/audiooutput.cpp
index 455241a..b5e1792 100644
--- a/sdrbase/audio/audiooutput.cpp
+++ b/sdrbase/audio/audiooutput.cpp
@@ -24,6 +24,9 @@
AudioOutput::AudioOutput() :
m_mutex(),
+ m_error(),
+ m_deviceName(),
+ m_rate(0),
m_audioOutput(NULL),
m_audioFifos()
{
@@ -39,17 +42,38 @@ AudioOutput::~AudioOutput()
m_audioFifos.clear();
}
-bool AudioOutput::start(int device, int rate)
+void AudioOutput::configure(const QString& deviceName, uint rate)
{
QMutexLocker mutexLocker(&m_mutex);
- Q_UNUSED(device);
- Q_UNUSED(rate);
+ m_deviceName = deviceName;
+ m_rate = rate;
+}
+
+bool AudioOutput::start()
+{
+ QMutexLocker mutexLocker(&m_mutex);
QAudioFormat format;
QAudioDeviceInfo devInfo(QAudioDeviceInfo::defaultOutputDevice());
- format.setSampleRate(41000);
+ if(!m_deviceName.isEmpty()) {
+ QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
+ bool found = false;
+ for(int i = 0; i < devices.count(); ++i) {
+ if(devices[i].deviceName() == m_deviceName) {
+ devInfo = devices[i];
+ found = true;
+ break;
+ }
+ }
+ if(!found) {
+ m_error = tr("Audio output device %1 not available").arg(m_deviceName);
+ return false;
+ }
+ }
+
+ format.setSampleRate(m_rate);
format.setChannelCount(2);
format.setSampleSize(16);
format.setCodec("audio/pcm");
@@ -60,26 +84,33 @@ bool AudioOutput::start(int device, int rate)
qDebug("default format not supported - try to use nearest");
format = devInfo.nearestFormat(format);
}
+ qDebug("Audio output %s using samplerate %d", qPrintable(devInfo.deviceName()), format.sampleRate());
if(format.sampleSize() != 16) {
- qDebug("audio device doesn't support 16 bit samples (%s)", qPrintable(devInfo.defaultOutputDevice().deviceName()));
+ m_error = tr("Audio output %1 doesn't support 16 bit samples").arg(devInfo.deviceName());
return false;
}
- m_audioOutput = new QAudioOutput(format);
+ m_audioOutput = new QAudioOutput(devInfo, format);
QIODevice::open(QIODevice::ReadOnly);
+ //m_audioOutput->setBufferSize(3 * 4096);
m_audioOutput->start(this);
- return true;
+ for(AudioFifos::iterator it = m_audioFifos.begin(); it != m_audioFifos.end(); ++it)
+ (*it)->setSampleRate(m_audioOutput->format().sampleRate());
+ return true;
}
void AudioOutput::stop()
{
QMutexLocker mutexLocker(&m_mutex);
+ for(AudioFifos::iterator it = m_audioFifos.begin(); it != m_audioFifos.end(); ++it)
+ (*it)->setSampleRate(0);
+
if(m_audioOutput != NULL) {
m_audioOutput->stop();
delete m_audioOutput;
@@ -92,6 +123,10 @@ void AudioOutput::addFifo(AudioFifo* audioFifo)
{
QMutexLocker mutexLocker(&m_mutex);
+ if(m_audioOutput == NULL)
+ audioFifo->setSampleRate(0);
+ else audioFifo->setSampleRate(m_audioOutput->format().sampleRate());
+
m_audioFifos.push_back(audioFifo);
}
@@ -99,9 +134,19 @@ void AudioOutput::removeFifo(AudioFifo* audioFifo)
{
QMutexLocker mutexLocker(&m_mutex);
+ audioFifo->setSampleRate(0);
m_audioFifos.remove(audioFifo);
}
+quint32 AudioOutput::getCurrentRate()
+{
+ QMutexLocker mutexLocker(&m_mutex);
+
+ if(m_audioOutput == NULL)
+ return 0;
+ else return m_audioOutput->format().sampleRate();
+}
+
bool AudioOutput::open(OpenMode mode)
{
Q_UNUSED(mode);
@@ -110,9 +155,6 @@ bool AudioOutput::open(OpenMode mode)
qint64 AudioOutput::readData(char* data, qint64 maxLen)
{
- if(maxLen == 0)
- return 0;
-
QMutexLocker mutexLocker(&m_mutex);
maxLen -= maxLen % 4;
@@ -120,13 +162,18 @@ qint64 AudioOutput::readData(char* data, qint64 maxLen)
if((int)m_mixBuffer.size() < framesPerBuffer * 2) {
m_mixBuffer.resize(framesPerBuffer * 2); // allocate 2 qint32 per frame (stereo)
- if(m_mixBuffer.size() != framesPerBuffer * 2)
+ if(m_mixBuffer.size() != framesPerBuffer * 2) {
+ qDebug("KAPUTT");
return 0;
+ }
}
memset(&m_mixBuffer[0], 0x00, 2 * framesPerBuffer * sizeof(m_mixBuffer[0])); // start with silence
// sum up a block from all fifos
for(AudioFifos::iterator it = m_audioFifos.begin(); it != m_audioFifos.end(); ++it) {
+ if((*it)->isStopped())
+ continue;
+
// use outputBuffer as temp - yes, one memcpy could be saved
uint samples = (*it)->read((quint8*)data, framesPerBuffer, 1);
const qint16* src = (const qint16*)data;
@@ -141,7 +188,7 @@ qint64 AudioOutput::readData(char* data, qint64 maxLen)
}
}
- // convert to int16
+ // convert to int16 and do saturation
std::vector<qint32>::const_iterator src = m_mixBuffer.begin();
qint16* dst = (qint16*)data;
for(int i = 0; i < framesPerBuffer; ++i) {
diff --git a/sdrbase/dsp/channelizer.cpp b/sdrbase/dsp/channelizer.cpp
index 2028a0f..41300e1 100644
--- a/sdrbase/dsp/channelizer.cpp
+++ b/sdrbase/dsp/channelizer.cpp
@@ -27,13 +27,15 @@ void Channelizer::feed(SampleVector::const_iterator begin, SampleVector::const_i
{
for(SampleVector::const_iterator sample = begin; sample != end; ++sample) {
Sample s(*sample);
+ bool haveSample = true;
FilterStages::iterator stage = m_filterStages.begin();
while(stage != m_filterStages.end()) {
- if(!(*stage)->work(&s))
+ haveSample = (*stage)->work(&s);
+ if(!haveSample)
break;
++stage;
}
- if(stage == m_filterStages.end())
+ if((stage == m_filterStages.end()) && haveSample)
m_sampleBuffer.push_back(s);
}
@@ -58,7 +60,7 @@ void Channelizer::stop()
bool Channelizer::handleMessage(Message* cmd)
{
if(DSPSignalNotification::match(cmd)) {
- DSPSignalNotification* signal = (DSPSignalNotification*)cmd;
+ DSPSignalNotification* signal = DSPSignalNotification::cast(cmd);
m_inputSampleRate = signal->getSampleRate();
applyConfiguration();
cmd->completed();
@@ -69,7 +71,7 @@ bool Channelizer::handleMessage(Message* cmd)
}
return true;
} else if(DSPConfigureChannelizer::match(cmd)) {
- DSPConfigureChannelizer* chan = (DSPConfigureChannelizer*)cmd;
+ DSPConfigureChannelizer* chan = DSPConfigureChannelizer::cast(cmd);
m_requestedOutputSampleRate = chan->getSampleRate();
m_requestedCenterFrequency = chan->getCenterFrequency();
applyConfiguration();
@@ -172,157 +174,3 @@ void Channelizer::freeFilterChain()
delete *it;
m_filterStages.clear();
}
-
-#if 0
-
-///////////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
-// written by Christian Daniel //
-// //
-// This program is free software; you can redistribute it and/or modify //
-// it under the terms of the GNU General Public License as published by //
-// the Free Software Foundation as version 3 of the License, or //
-// //
-// This program is distributed in the hope that it will be useful, //
-// but WITHOUT ANY WARRANTY; without even the implied warranty of //
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
-// GNU General Public License V3 for more details. //
-// //
-// You should have received a copy of the GNU General Public License //
-// along with this program. If not, see <http://www.gnu.org/licenses/>. //
-///////////////////////////////////////////////////////////////////////////////////
-
-#include <QTime>
-#include <stdio.h>
-#include "channelizer.h"
-#include "hardware/audiooutput.h"
-
-Channelizer::Channelizer()
-{
-#if 0
- m_spectrum.configure(128 , 25, FFTWindow::Bartlett);
- m_buffer.resize(2048);
- m_bufferFill = 0;
- m_nco.setFreq(-100000, 500000);
- m_interpolator.create(51, 32, 32 * 500000, 150000 / 2);
- m_distance = 500000.0 / 176400.0;
-
- m_interpolator2.create(19, 8, 8 * 176400, 15000 / 2);
- m_distance2 = 4;
-
- m_audioFifo.setSize(4, 44100 / 2 * 4);
- m_audioOutput = new AudioOutput;
- m_audioOutput->start(0, 44100, &m_audioFifo);
- m_resampler = 1.0;
-
- m_resamplerCtrl.setup(0.00001, 0, -0.00001);
-#endif
-}
-
-Channelizer::~Channelizer()
-{
-#if 0
- m_audioOutput->stop();
- delete m_audioOutput;
-#endif
-}
-
-#if 0
-void Channelizer::setGLSpectrum(GLSpectrum* glSpectrum)
-{
- m_spectrum.setGLSpectrum(glSpectrum);
-}
-#endif
-
-size_t Channelizer::workUnitSize()
-{
-#if 0
- return m_buffer.size();
-#endif
- return 0;
-}
-
-size_t Channelizer::work(SampleVector::const_iterator begin, SampleVector::const_iterator end)
-{
-#if 0
- int buffered = m_audioOutput->bufferedSamples();
-
- if(m_audioFifo.fill() < (m_audioFifo.size() / 6)) {
- while(m_audioFifo.fill() < (m_audioFifo.size() / 2)) {
- quint32 d = 0;
- m_audioFifo.write((quint8*)&d, 4);
- }
- qDebug("underflow - fill %d (vs %d)", m_audioFifo.fill(), m_audioFifo.size() / 4 / 2);
- }
-
- buffered = m_audioOutput->bufferedSamples();
- int fill = m_audioFifo.fill() / 4 + buffered;
- float err = (float)fill / ((m_audioFifo.size() / 4) / 2);
-
- float ctrl = m_resamplerCtrl.feed(err);
- //float resamplerRate = (ctrl / 1.0);
- float resamplerRate = err;
-
- if(resamplerRate < 0.9999)
- resamplerRate = 0.9999;
- else if(resamplerRate > 1.0001)
- resamplerRate = 1.0001;
- m_resampler = m_resampler * 0.99 + resamplerRate * 0.01;
- //m_resampler = resamplerRate;
-
- if(m_resampler < 0.995)
- m_resampler = 0.995;
- else if(m_resampler > 1.005)
- m_resampler = 1.005;
-
- //qDebug("%lld %5d %f %f %f", QDateTime::currentMSecsSinceEpoch(), fill, ctrl, m_resampler, err);
-
- struct AudioSample {
- qint16 l;
- qint16 r;
- };
-
- size_t count = end - begin;
- Complex ci;
- bool consumed;
- bool consumed2;
-
- for(SampleVector::const_iterator it = begin; it < end; it++) {
- Complex c(it->real() / 32768.0, it->imag() / 32768.0);
- c *= m_nco.nextIQ();
-
- consumed = false;
- if(m_interpolator.interpolate(&m_distance, c, &consumed, &ci)) {
-
- Complex d = ci * conj(m_lastSample);
- m_lastSample = ci;
- //Complex demod(atan2(d.imag(), d.real()) * 0.5, 0);
- Real demod = atan2(d.imag(), d.real()) / M_PI;
-
- consumed2 = false;
- c = Complex(demod, 0);
- while(!consumed2) {
- if(m_interpolator2.interpolate(&m_distance2, c, &consumed2, &ci)) {
- m_buffer[m_bufferFill++] = Sample(ci.real() * 32767.0, 0.0);
-
- AudioSample s;
- s.l = ci.real() * 32767.0;
- s.r = s.l;
- m_audioFifo.write((quint8*)&s, 4, 1);
-
- if(m_bufferFill >= m_buffer.size()) {
- m_spectrum.feed(m_buffer.begin(), m_buffer.end());
- m_bufferFill = 0;
- }
- m_distance2 += 4.0 * m_resampler;
- }
- }
- m_distance += 500000 / 176400.0;
- }
- }
-
- return count;
-#endif
-}
-
-#endif
diff --git a/sdrbase/dsp/dspcommands.cpp b/sdrbase/dsp/dspcommands.cpp
index 21bdddc..9e19da2 100644
--- a/sdrbase/dsp/dspcommands.cpp
+++ b/sdrbase/dsp/dspcommands.cpp
@@ -13,6 +13,7 @@ MESSAGE_CLASS_DEFINITION(DSPAddAudioSource, Message)
MESSAGE_CLASS_DEFINITION(DSPRemoveAudioSource, Message)
MESSAGE_CLASS_DEFINITION(DSPConfigureSpectrumVis, Message)
MESSAGE_CLASS_DEFINITION(DSPConfigureCorrection, Message)
+MESSAGE_CLASS_DEFINITION(DSPConfigureAudioOutput, Message)
MESSAGE_CLASS_DEFINITION(DSPEngineReport, Message)
MESSAGE_CLASS_DEFINITION(DSPConfigureScopeVis, Message)
MESSAGE_CLASS_DEFINITION(DSPSignalNotification, Message)
diff --git a/sdrbase/dsp/dspengine.cpp b/sdrbase/dsp/dspengine.cpp
index 369403f..63b3f58 100644
--- a/sdrbase/dsp/dspengine.cpp
+++ b/sdrbase/dsp/dspengine.cpp
@@ -109,6 +109,12 @@ void DSPEngine::configureCorrections(bool dcOffsetCorrection, bool iqImbalanceCo
cmd->submit(&m_messageQueue);
}
+void DSPEngine::configureAudioOutput(const QString& audioOutput, quint32 audioOutputRate)
+{
+ Message* cmd = DSPConfigureAudioOutput::create(audioOutput, audioOutputRate);
+ cmd->submit(&m_messageQueue);
+}
+
QString DSPEngine::errorMessage()
{
DSPGetErrorMessage cmd;
@@ -174,7 +180,6 @@ void DSPEngine::imbalance(SampleVector::iterator begin, SampleVector::iterator e
qMin = it->imag();
else if(it->imag() > qMax)
qMax = it->imag();
-
} else {
iMin = it->real();
iMax = it->real();
@@ -202,7 +207,7 @@ void DSPEngine::work()
size_t samplesDone = 0;
bool firstOfBurst = true;
- while((sampleFifo->fill() > 0) && (m_messageQueue.countPending() == 0) && (samplesDone < m_sampleRate)) {
+ while((sampleFifo->fill() > 0) && (m_messageQueue.countPending() == 0) && (samplesDone < m_sampleRate / 2)) {
SampleVector::iterator part1begin;
SampleVector::iterator part1end;
SampleVector::iterator part2begin;
@@ -218,7 +223,7 @@ void DSPEngine::work()
if(m_iqImbalanceCorrection)
imbalance(part1begin, part1end);
// feed data to handlers
- for(SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); it++)
+ for(SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); ++it)
(*it)->feed(part1begin, part1end, firstOfBurst);
firstOfBurst = false;
}
@@ -230,7 +235,7 @@ void DSPEngine::work()
if(m_iqImbalanceCorrection)
imbalance(part2begin, part2end);
// feed data to handlers
- for(SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); it++)
+ for(SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); ++it)
(*it)->feed(part2begin, part2end, firstOfBurst);
firstOfBurst = false;
}
@@ -239,69 +244,6 @@ void DSPEngine::work()
sampleFifo->readCommit(count);
samplesDone += count;
}
-
-#if 0
- size_t wus;
- size_t maxWorkUnitSize = 0;
- size_t samplesDone = 0;
-
- wus = m_spectrum.workUnitSize();
- if(wus > maxWorkUnitSize)
- maxWorkUnitSize = wus;
- for(SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); it++) {
- wus = (*it)->workUnitSize();
- if(wus > maxWorkUnitSize)
- maxWorkUnitSize = wus;
- }
-
- while((m_sampleFifo.fill() > maxWorkUnitSize) && (m_commandQueue.countPending() == 0) && (samplesDone < m_sampleRate)) {
- SampleVector::iterator part1begin;
- SampleVector::iterator part1end;
- SampleVector::iterator part2begin;
- SampleVector::iterator part2end;
-
- size_t count = m_sampleFifo.readBegin(m_sampleFifo.fill(), &part1begin, &part1end, &part2begin, &part2end);
-
- // first part of FIFO data
- if(part1begin != part1end) {
- // correct stuff
- if(m_settings.dcOffsetCorrection())
- dcOffset(part1begin, part1end);
- if(m_settings.iqImbalanceCorrection())
- imbalance(part1begin, part1end);
- // feed data to handlers
- m_spectrum.feed(part1begin, part1end);
- for(SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); it++)
- (*it)->feed(part1begin, part1end);
- }
- // second part of FIFO data (used when block wraps around)
- if(part2begin != part2end) {
- // correct stuff
- if(m_settings.dcOffsetCorrection())
- dcOffset(part2begin, part2end);
- if(m_settings.iqImbalanceCorrection())
- imbalance(part2begin, part2end);
- // feed data to handlers
- m_spectrum.feed(part2begin, part2end);
- for(SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); it++)
- (*it)->feed(part1begin, part1end);
- }
-
- // adjust FIFO pointers
- m_sampleFifo.readCommit(count);
- samplesDone += count;
- }
-
- // check if the center frequency has changed (has to be responsive)
- if(m_settings.isModifiedCenterFreq())
- m_sampleSource->setCenterFrequency(m_settings.centerFreq());
- // check if decimation has changed (needed to be done here, because to high a sample rate can clog the switch)
- if(m_settings.isModifiedDecimation()) {
- m_sampleSource->setDecimation(m_settings.decimation());
- m_sampleRate = 4000000 / (1 << m_settings.decimation());
- qDebug("New rate: %d", m_sampleRate);
- }
-#endif
}
DSPEngine::State DSPEngine::gotoIdle()
@@ -357,7 +299,11 @@ DSPEngine::State DSPEngine::gotoRunning()
return gotoError("Could not start sample source");
m_deviceDescription = m_sampleSource->getDeviceDescription();
- m_audioOutput.start(0, 44100);
+ if(!m_audioOutput.start()) {
+ m_sampleSource->stopInput();
+ return gotoError(m_audioOutput.getError());
+ }
+
for(SampleSinks::const_iterator it = m_sampleSinks.begin(); it != m_sampleSinks.end(); it++)
(*it)->start();
m_sampleRate = 0; // make sure, report is sent
@@ -447,7 +393,7 @@ void DSPEngine::handleMessages()
{
Message* message;
while((message = m_messageQueue.accept()) != NULL) {
- qDebug("Message: %s", message->getIdentifier());
+ //qDebug("Message: %s", message->getIdentifier());
if(DSPPing::match(message)) {
message->completed(m_state);
@@ -465,16 +411,16 @@ void DSPEngine::handleMessages()
m_state = gotoIdle();
message->completed(m_state);
} else if(DSPGetDeviceDescription::match(message)) {
- ((DSPGetDeviceDescription*)message)->setDeviceDescription(m_deviceDescription);
+ DSPGetDeviceDescription::cast(message)->setDeviceDescription(m_deviceDescription);
message->completed();
} else if(DSPGetErrorMessage::match(message)) {
((DSPGetErrorMessage*)message)->setErrorMessage(m_errorMessage);
message->completed();
} else if(DSPSetSource::match(message)) {
- handleSetSource(((DSPSetSource*)message)->getSampleSource());
+ handleSetSource(DSPSetSource::cast(message)->getSampleSource());
message->completed();
} else if(DSPAddSink::match(message)) {
- SampleSink* sink = ((DSPAddSink*)message)->getSampleSink();
+ SampleSink* sink = DSPAddSink::cast(message)->getSampleSink();
if(m_state == StRunning) {
DSPSignalNotification* signal = DSPSignalNotification::create(m_sampleRate, 0);
signal->submit(&m_messageQueue, sink);
@@ -489,13 +435,16 @@ void DSPEngine::handleMessages()
m_sampleSinks.remove(sink);
message->completed();
} else if(DSPAddAudioSource::match(message)) {
- m_audioOutput.addFifo(((DSPAddAudioSource*)message)->getAudioFifo());
+ m_audioOutput.addFifo(DSPAddAudioSource::cast(message)->getAudioFifo());
message->completed();
} else if(DSPRemoveAudioSource::match(message)) {
m_audioOutput.removeFifo(((DSPAddAudioSource*)message)->getAudioFifo());
message->completed();
+ } else if(DSPConfigureAudioOutput::match(message)) {
+ DSPConfigureAudioOutput* conf = DSPConfigureAudioOutput::cast(message);
+ m_audioOutput.configure(conf->getAudioOutputDevice(), conf->getAudioOutputRate());
} else if(DSPConfigureCorrection::match(message)) {
- DSPConfigureCorrection* conf = (DSPConfigureCorrection*)message;
+ DSPConfigureCorrection* conf = DSPConfigureCorrection::cast(message);
m_iqImbalanceCorrection = conf->getIQImbalanceCorrection();
if(m_dcOffsetCorrection != conf->getDCOffsetCorrection()) {
m_dcOffsetCorrection = conf->getDCOffsetCorrection();
diff --git a/sdrbase/dsp/fftwengine.cpp b/sdrbase/dsp/fftwengine.cpp
index 76b189e..f5062fb 100644
--- a/sdrbase/dsp/fftwengine.cpp
+++ b/sdrbase/dsp/fftwengine.cpp
@@ -21,6 +21,7 @@ void FFTWEngine::configure(int n, bool inverse)
}
}
+ m_globalPlanMutex.lock();
m_currentPlan = new Plan;
m_currentPlan->n = n;
m_currentPlan->inverse = inverse;
@@ -28,7 +29,6 @@ void FFTWEngine::configure(int n, bool inverse)
m_currentPlan->out = (fftwf_complex*)fftwf_malloc(sizeof(fftwf_complex) * n);
QTime t;
t.start();
- m_globalPlanMutex.lock();
m_currentPlan->plan = fftwf_plan_dft_1d(n, m_currentPlan->in, m_currentPlan->out, inverse ? FFTW_BACKWARD : FFTW_FORWARD, FFTW_PATIENT);
m_globalPlanMutex.unlock();
qDebug("FFT: creating FFTW plan (n=%d,%s) took %dms", n, inverse ? "inverse" : "forward", t.elapsed());
diff --git a/sdrbase/dsp/nco.cpp b/sdrbase/dsp/nco.cpp
index 1143cf8..1982750 100644
--- a/sdrbase/dsp/nco.cpp
+++ b/sdrbase/dsp/nco.cpp
@@ -30,7 +30,7 @@ void NCO::initTable()
return;
for(int i = 0; i < TableSize; i++)
- m_table[i] = cos((2.0 * M_PI * i) / TableSize);
+ m_table[i] = cos((2.0 * M_PI * (Real)i) / ((Real)TableSize));
m_tableInitialized = true;
}
@@ -43,8 +43,15 @@ NCO::NCO()
void NCO::setFreq(Real freq, Real sampleRate)
{
- m_phaseIncrement = (freq * TableSize) / sampleRate;
- qDebug("NCO phase inc %d", m_phaseIncrement);
+ if(sampleRate > 0) {
+ m_phaseIncrement = (freq * TableSize) / sampleRate;
+ if(m_phaseIncrement != 0)
+ qDebug("NCO phase inc %d (period %f)", m_phaseIncrement, (Real)TableSize / (Real)m_phaseIncrement);
+ else qDebug("NCO phase inc %d (period oo)", m_phaseIncrement);
+ } else {
+ qDebug("cannot calculate NCO phase increment since samplerate is 0");
+ m_phaseIncrement = 1;
+ }
}
float NCO::next()
@@ -66,5 +73,7 @@ Complex NCO::nextIQ()
while(m_phase < 0)
m_phase += TableSize;
- return Complex(m_table[m_phase], -m_table[(m_phase + TableSize / 4) % TableSize]);
+ int idxQuad = (m_phase + (TableSize / 4) + (TableSize / 2)) % TableSize;
+
+ return Complex(m_table[m_phase], m_table[idxQuad]);
}
diff --git a/sdrbase/dsp/pidcontroller.cpp b/sdrbase/dsp/pidcontroller.cpp
index 8b015f6..a5d5356 100644
--- a/sdrbase/dsp/pidcontroller.cpp
+++ b/sdrbase/dsp/pidcontroller.cpp
@@ -1,4 +1,4 @@
-#include "pidcontroller.h"
+#include "dsp/pidcontroller.h"
PIDController::PIDController() :
m_p(0.0),
diff --git a/sdrbase/dsp/pidcontroller.h b/sdrbase/dsp/pidcontroller.h
deleted file mode 100644
index 7b96793..0000000
--- a/sdrbase/dsp/pidcontroller.h
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef INCLUDE_PIDCONTROLLER_H
-#define INCLUDE_PIDCONTROLLER_H
-
-#include "dsp/dsptypes.h"
-
-class PIDController {
-private:
- Real m_p;
- Real m_i;
- Real m_d;
- Real m_int;
- Real m_diff;
-
-public:
- PIDController();
-
- void setup(Real p, Real i, Real d);
-
- Real feed(Real v)
- {
- m_int += v * m_i;
- Real d = m_d * (m_diff - v);
- m_diff = v;
- return (v * m_p) + m_int + d;
- }
-};
-
-#endif // INCLUDE_PIDCONTROLLER_H
diff --git a/sdrbase/dsp/samplefifo.cpp b/sdrbase/dsp/samplefifo.cpp
index caa4969..e9d29b8 100644
--- a/sdrbase/dsp/samplefifo.cpp
+++ b/sdrbase/dsp/samplefifo.cpp
@@ -64,17 +64,21 @@ bool SampleFifo::setSize(int size)
{
create(size);
- return m_data.size() == (uint)size;
+ return m_size == (uint)size;
}
uint SampleFifo::write(const quint8* data, uint count)
{
+ return write(SampleVector::const_iterator((Sample*)data), SampleVector::const_iterator((Sample*)(data + count)));
+#if 0
QMutexLocker mutexLocker(&m_mutex);
uint total;
uint remaining;
uint len;
const Sample* begin = (const Sample*)data;
- count /= 4;
+ count /= sizeof(Sample);
+
+ //qDebug("write pre count %d %u", count, m_fill);
total = MIN(count, m_size - m_fill);
if(total < count) {
@@ -96,6 +100,7 @@ uint SampleFifo::write(const quint8* data, uint count)
remaining = total;
while(remaining > 0) {
len = MIN(remaining, m_size - m_tail);
+ //qDebug("write remaining %u, len %u", remaining, len);
std::copy(begin, begin + len, m_data.begin() + m_tail);
m_tail += len;
m_tail %= m_size;
@@ -104,10 +109,13 @@ uint SampleFifo::write(const quint8* data, uint count)
remaining -= len;
}
+ //qDebug("write post count %d %u [%u;%u]", count, m_fill, m_head, m_tail);
+
if(m_fill > 0)
emit dataReady();
return total;
+#endif
}
uint SampleFifo::write(SampleVector::const_iterator begin, SampleVector::const_iterator end)
@@ -139,8 +147,7 @@ uint SampleFifo::write(SampleVector::const_iterator begin, SampleVector::const_i
while(remaining > 0) {
len = MIN(remaining, m_size - m_tail);
std::copy(begin, begin + len, m_data.begin() + m_tail);
- m_tail += len;
- m_tail %= m_size;
+ m_tail = (m_tail + len) % m_size;
m_fill += len;
begin += len;
remaining -= len;
@@ -151,7 +158,7 @@ uint SampleFifo::write(SampleVector::const_iterator begin, SampleVector::const_i
return total;
}
-
+/*
uint SampleFifo::read(SampleVector::iterator begin, SampleVector::iterator end)
{
QMutexLocker mutexLocker(&m_mutex);
@@ -177,13 +184,14 @@ uint SampleFifo::read(SampleVector::iterator begin, SampleVector::iterator end)
return total;
}
-
+*/
uint SampleFifo::readBegin(uint count,
SampleVector::iterator* part1Begin, SampleVector::iterator* part1End,
SampleVector::iterator* part2Begin, SampleVector::iterator* part2End)
{
QMutexLocker mutexLocker(&m_mutex);
uint total;
+ uint done = 0;
uint remaining;
uint len;
uint head = m_head;
@@ -196,10 +204,10 @@ uint SampleFifo::readBegin(uint count,
if(remaining > 0) {
len = MIN(remaining, m_size - head);
*part1Begin = m_data.begin() + head;
- *part1End = m_data.begin() + head + len;
- head += len;
- head %= m_size;
+ *part1End = *part1Begin + len;
+ head = (head + len) % m_size;
remaining -= len;
+ done += len;
} else {
*part1Begin = m_data.end();
*part1End = m_data.end();
@@ -207,13 +215,14 @@ uint SampleFifo::readBegin(uint count,
if(remaining > 0) {
len = MIN(remaining, m_size - head);
*part2Begin = m_data.begin() + head;
- *part2End = m_data.begin() + head + len;
+ *part2End = *part2Begin + len;
+ done += len;
} else {
*part2Begin = m_data.end();
*part2End = m_data.end();
}
- return total;
+ return done;
}
uint SampleFifo::readCommit(uint count)
diff --git a/sdrbase/dsp/spectrumvis.cpp b/sdrbase/dsp/spectrumvis.cpp
index 01c7dbe..627a093 100644
--- a/sdrbase/dsp/spectrumvis.cpp
+++ b/sdrbase/dsp/spectrumvis.cpp
@@ -3,7 +3,7 @@
#include "dsp/dspcommands.h"
#include "util/messagequeue.h"
-#define MAX_FFT_SIZE 4096
+#define MAX_FFT_SIZE 8192
#ifdef _WIN32
double log2f(double n)
diff --git a/sdrbase/dsp/threadedsamplesink.cpp b/sdrbase/dsp/threadedsamplesink.cpp
index ad157b9..313ed24 100644
--- a/sdrbase/dsp/threadedsamplesink.cpp
+++ b/sdrbase/dsp/threadedsamplesink.cpp
@@ -15,7 +15,7 @@ ThreadedSampleSink::ThreadedSampleSink(SampleSink* sampleSink) :
m_sampleFifo.moveToThread(m_thread);
connect(&m_sampleFifo, SIGNAL(dataReady()), this, SLOT(handleData()));
- m_sampleFifo.setSize(262144);
+ m_sampleFifo.setSize(128 * 1024);
sampleSink->moveToThread(m_thread);
}
@@ -55,8 +55,11 @@ bool ThreadedSampleSink::handleMessage(Message* cmd)
void ThreadedSampleSink::handleData()
{
bool firstOfBurst = true;
+ QTime time;
- while((m_sampleFifo.fill() > 0) && (m_messageQueue.countPending() == 0)) {
+ time.start();
+
+ while((m_sampleFifo.fill() > 0) && (m_messageQueue.countPending() == 0) && (time.elapsed() < 250)) {
SampleVector::iterator part1begin;
SampleVector::iterator part1end;
SampleVector::iterator part2begin;
@@ -64,19 +67,19 @@ void ThreadedSampleSink::handleData()
size_t count = m_sampleFifo.readBegin(m_sampleFifo.fill(), &part1begin, &part1end, &part2begin, &part2end);
- // first part of FIFO data
- if(part1begin != part1end) {
- // handle data
- if(m_sampleSink != NULL)
- m_sampleSink->feed(part1begin, part1end, firstOfBurst);
- firstOfBurst = false;
- }
- // second part of FIFO data (used when block wraps around)
- if(part2begin != part2end) {
- // handle data
- if(m_sampleSink != NULL)
+ if(m_sampleSink != NULL) {
+ // first part of FIFO data
+ if(part1begin != part1end) {
+ // handle data
m_sampleSink->feed(part1begin, part1end, firstOfBurst);
- firstOfBurst = false;
+ firstOfBurst = false;
+ }
+ // second part of FIFO data (used when block wraps around)
+ if(part2begin != part2end) {
+ // handle data
+ m_sampleSink->feed(part2begin, part2end, firstOfBurst);
+ firstOfBurst = false;
+ }
}
// adjust FIFO pointers
@@ -88,7 +91,7 @@ void ThreadedSampleSink::handleMessages()
{
Message* message;
while((message = m_messageQueue.accept()) != NULL) {
- qDebug("CMD: %s", message->getIdentifier());
+ //qDebug("CMD: %s", message->getIdentifier());
if(m_sampleSink != NULL) {
if(!m_sampleSink->handleMessage(message))
message->completed();
diff --git a/sdrbase/gui/glspectrumgui.cpp b/sdrbase/gui/glspectrumgui.cpp
index 1fbaaf2..6231e8d 100644
--- a/sdrbase/gui/glspectrumgui.cpp
+++ b/sdrbase/gui/glspectrumgui.cpp
@@ -112,7 +112,7 @@ bool GLSpectrumGUI::deserialize(const QByteArray& data)
void GLSpectrumGUI::applySettings()
{
ui->fftWindow->setCurrentIndex(m_fftWindow);
- for(int i = 0; i < 6; i++) {
+ for(int i = 0; i < 7; i++) {
if(m_fftSize == (1 << (i + 7))) {
ui->fftSize->setCurrentIndex(i);
break;
diff --git a/sdrbase/gui/glspectrumgui.ui b/sdrbase/gui/glspectrumgui.ui
index 2a9babe..a738255 100644
--- a/sdrbase/gui/glspectrumgui.ui
+++ b/sdrbase/gui/glspectrumgui.ui
@@ -14,7 +14,16 @@
<string>Oscilloscope</string>
</property>
<layout class="QGridLayout" name="gridLayout" columnstretch="1,1,1,1">
- <property name="margin">
+ <property name="leftMargin">
+ <number>2</number>
+ </property>
+ <property name="topMargin">
+ <number>2</number>
+ </property>
+ <property name="rightMargin">
+ <number>2</number>
+ </property>
+ <property name="bottomMargin">
<number>2</number>
</property>
<property name="spacing">
@@ -162,6 +171,11 @@
<string>4096</string>
</property>
</item>
+ <item>
+ <property name="text">
+ <string>8192</string>
+ </property>
+ </item>
</widget>
</item>
<item row="1" column="2">
diff --git a/sdrbase/gui/preferencesdialog.cpp b/sdrbase/gui/preferencesdialog.cpp
index 077ef45..5394150 100644
--- a/sdrbase/gui/preferencesdialog.cpp
+++ b/sdrbase/gui/preferencesdialog.cpp
@@ -1,47 +1,61 @@
#include <QTreeWidgetItem>
+#include <QAudioDeviceInfo>
#include "gui/preferencesdialog.h"
#include "ui_preferencesdialog.h"
-#include "audio/audiodeviceinfo.h"
+#include "settings/preferences.h"
-PreferencesDialog::PreferencesDialog(AudioDeviceInfo* audioDeviceInfo, QWidget* parent) :
+PreferencesDialog::PreferencesDialog(Preferences* preferences, QWidget* parent) :
QDialog(parent),
ui(new Ui::PreferencesDialog),
- m_audioDeviceInfo(audioDeviceInfo)
+ m_preferences(preferences)
{
ui->setupUi(this);
- const AudioDeviceInfo::Devices& devices = audioDeviceInfo->getDevices();
-
- QTreeWidgetItem* api;
QStringList sl;
- sl.append(tr("Default (use first suitable device)"));
- api = new QTreeWidgetItem(ui->audioTree, sl, ATDefault);
- api->setFirstColumnSpanned(true);
- for(AudioDeviceInfo::Devices::const_iterator it = devices.begin(); it != devices.end(); ++it) {
- int apiIndex;
- sl.clear();
+ bool found;
- for(apiIndex = 0; apiIndex < ui->audioTree->topLevelItemCount(); ++apiIndex) {
- if(ui->audioTree->topLevelItem(apiIndex)->text(0) == it->api)
- break;
- }
- if(apiIndex >= ui->audioTree->topLevelItemCount()) {
- sl.append(it->api);
- api = new QTreeWidgetItem(ui->audioTree, sl, ATInterface);
- api->setExpanded(true);
- api->setFirstColumnSpanned(true);
- sl.clear();
- } else {
- api = ui->audioTree->topLevelItem(apiIndex);
- }
+ QList<QAudioDeviceInfo> devices = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
- sl.append(it->name);
- new QTreeWidgetItem(api, sl, ATDevice);
+ sl.clear();
+ sl.append(tr("Default output device (use first suitable)"));
+ QTreeWidgetItem* dev = new QTreeWidgetItem(ui->audioTree, sl);
+ dev->setFirstColumnSpanned(true);
+ dev->setData(0, Qt::UserRole, "");
+ for(QList<QAudioDeviceInfo>::ConstIterator it = devices.begin(); it != devices.end(); ++it) {
+ sl.clear();
+ sl.append(it->deviceName());
+ QTreeWidgetItem* dev = new QTreeWidgetItem(ui->audioTree, sl);
+ dev->setFirstColumnSpanned(true);
+ dev->setData(0, Qt::UserRole, it->deviceName());
}
- if(ui->audioTree->currentItem() == NULL)
+ found = false;
+ for(int i = 0; i < ui->audioTree->topLevelItemCount(); ++i) {
+ if(ui->audioTree->topLevelItem(i)->data(0, Qt::UserRole).toString() == m_preferences->getAudioOutput()) {
+ ui->audioTree->setCurrentItem(ui->audioTree->topLevelItem(i));
+ found = true;
+ break;
+ }
+ }
+ if(!found)
ui->audioTree->setCurrentItem(ui->audioTree->topLevelItem(0));
- ui->tabWidget->setCurrentIndex(0);
+ ui->audioRate->addItem(tr("48000 Hz"), 48000);
+ ui->audioRate->addItem(tr("44100 Hz"), 44100);
+ ui->audioRate->addItem(tr("24000 Hz"), 24000);
+ ui->audioRate->addItem(tr("22050 Hz"), 22050);
+ found = false;
+ for(int i = 0; i < ui->audioRate->count(); ++i) {
+ if(ui->audioRate->itemData(i).toInt() == m_preferences->getAudioOutputRate()) {
+ ui->audioRate->setCurrentIndex(i);
+ found = true;
+ break;
+ }
+ }
+ if(!found)
+ ui->audioRate->setCurrentIndex(1);
+
+ ui->stackedWidget->setCurrentIndex(0);
+ ui->configTree->setCurrentItem(ui->configTree->topLevelItem(0));
}
PreferencesDialog::~PreferencesDialog()
@@ -51,5 +65,10 @@ PreferencesDialog::~PreferencesDialog()
void PreferencesDialog::accept()
{
+ if(ui->audioTree->currentItem() != NULL)
+ m_preferences->setAudioOutput(ui->audioTree->currentItem()->data(0, Qt::UserRole).toString());
+ else m_preferences->setAudioOutput(QString());
+ m_preferences->setAudioOutputRate(ui->audioRate->itemData(ui->audioRate->currentIndex()).toInt());
+
QDialog::accept();
}
diff --git a/sdrbase/gui/preferencesdialog.ui b/sdrbase/gui/preferencesdialog.ui
index 0545931..f98a149 100644
--- a/sdrbase/gui/preferencesdialog.ui
+++ b/sdrbase/gui/preferencesdialog.ui
@@ -6,42 +6,55 @@
<rect>
<x>0</x>
<y>0</y>
- <width>400</width>
- <height>300</height>
+ <width>454</width>
+ <height>435</height>
</rect>
</property>
<property name="windowTitle">
<string>Dialog</string>
</property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QTabWidget" name="tabWidget">
- <property name="currentIndex">
- <number>0</number>
+ <layout class="QGridLayout" name="gridLayout" columnstretch="1,3">
+ <item row="0" column="0">
+ <widget class="QTreeWidget" name="configTree">
+ <property name="rootIsDecorated">
+ <bool>false</bool>
</property>
- <widget class="QWidget" name="tab">
- <attribute name="title">
- <string>Receiver Hardware</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_2">
- <item>
- <widget class="QTreeWidget" name="treeWidget">
- <column>
- <property name="text">
- <string notr="true">1</string>
- </property>
- </column>
- </widget>
- </item>
- </layout>
- </widget>
- <widget class="QWidget" name="tab_2">
- <attribute name="title">
+ <attribute name="headerVisible">
+ <bool>false</bool>
+ </attribute>
+ <column>
+ <property name="text">
+ <string notr="true">Section</string>
+ </property>
+ </column>
+ <item>
+ <property name="text">
<string>Audio Output</string>
- </attribute>
- <layout class="QVBoxLayout" name="verticalLayout_3">
+ </property>
+ <property name="flags">
+ <set>ItemIsSelectable|ItemIsEnabled</set>
+ </property>
+ </item>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QStackedWidget" name="stackedWidget">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Expanding" vsizetype="Preferred">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <widget class="QWidget" name="page">
+ <layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QTreeWidget" name="audioTree">
+ <property name="rootIsDecorated">
+ <bool>false</bool>
+ </property>
<column>
<property name="text">
<string notr="true">Device</string>
@@ -49,11 +62,49 @@
</column>
</widget>
</item>
+ <item>
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QLabel" name="label">
+ <property name="text">
+ <string>Sample rate</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QComboBox" name="audioRate">
+ <property name="sizePolicy">
+ <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="sizeAdjustPolicy">
+ <enum>QComboBox::AdjustToContents</enum>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="horizontalSpacer">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>40</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </item>
</layout>
</widget>
+ <widget class="QWidget" name="page_2"/>
</widget>
</item>
- <item>
+ <item row="1" column="0" colspan="2">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
@@ -67,9 +118,6 @@
</widget>
<tabstops>
<tabstop>buttonBox</tabstop>
- <tabstop>tabWidget</tabstop>
- <tabstop>treeWidget</tabstop>
- <tabstop>audioTree</tabstop>
</tabstops>
<resources/>
<connections>
diff --git a/sdrbase/gui/scopewindow.cpp b/sdrbase/gui/scopewindow.cpp
index 2f6200f..486242a 100644
--- a/sdrbase/gui/scopewindow.cpp
+++ b/sdrbase/gui/scopewindow.cpp
@@ -19,14 +19,13 @@
#include "ui_scopewindow.h"
#include "util/simpleserializer.h"
-ScopeWindow::ScopeWindow(DSPEngine* dspEngine, QWidget* parent) :
+ScopeWindow::ScopeWindow(QWidget* parent) :
QWidget(parent),
ui(new Ui::ScopeWindow),
m_sampleRate(0),
m_timeBase(1)
{
ui->setupUi(this);
- ui->scope->setDSPEngine(dspEngine);
}
ScopeWindow::~ScopeWindow()
@@ -34,6 +33,11 @@ ScopeWindow::~ScopeWindow()
delete ui;
}
+void ScopeWindow::setDSPEngine(DSPEngine* dspEngine)
+{
+ ui->scope->setDSPEngine(dspEngine);
+}
+
void ScopeWindow::setSampleRate(int sampleRate)
{
m_sampleRate = sampleRate;
diff --git a/sdrbase/mainwindow.cpp b/sdrbase/mainwindow.cpp
index 9cbfb0f..904b3c9 100644
--- a/sdrbase/mainwindow.cpp
+++ b/sdrbase/mainwindow.cpp
@@ -20,7 +20,6 @@
#include <QLabel>
#include "mainwindow.h"
#include "ui_mainwindow.h"
-#include "audio/audiodeviceinfo.h"
#include "gui/indicator.h"
#include "gui/presetitem.h"
#include "gui/scopewindow.h"
@@ -39,7 +38,6 @@
MainWindow::MainWindow(QWidget* parent) :
QMainWindow(parent),
ui(new Ui::MainWindow),
- m_audioDeviceInfo(new AudioDeviceInfo),
m_messageQueue(new MessageQueue),
m_settings(),
m_dspEngine(new DSPEngine(m_messageQueue)),
@@ -196,6 +194,8 @@ void MainWindow::loadSettings(const Preset* preset)
m_pluginManager->loadSettings(preset);
+ m_dspEngine->configureAudioOutput(m_settings.getPreferences()->getAudioOutput(), m_settings.getPreferences()->getAudioOutputRate());
+
// has to be last step
restoreState(preset->getLayout());
}
@@ -306,12 +306,12 @@ void MainWindow::handleMessages()
{
Message* message;
while((message = m_messageQueue->accept()) != NULL) {
- qDebug("Message: %s", message->getIdentifier());
+ //qDebug("Message: %s", message->getIdentifier());
if(DSPEngineReport::match(message)) {
- DSPEngineReport* rep = (DSPEngineReport*)message;
+ DSPEngineReport* rep = DSPEngineReport::cast(message);
m_sampleRate = rep->getSampleRate();
m_centerFrequency = rep->getCenterFrequency();
- qDebug("SampleRate:%d, CenterFrequency:%llu", rep->getSampleRate(), rep->getCenterFrequency());
+ //qDebug("SampleRate:%d, CenterFrequency:%llu", rep->getSampleRate(), rep->getCenterFrequency());
updateCenterFreqDisplay();
updateSampleRate();
message->completed();
@@ -332,6 +332,7 @@ void MainWindow::updateStatus()
m_engineRunning->setColor(Qt::gray);
m_engineError->setColor(Qt::gray);
statusBar()->clearMessage();
+ updateEnables(false);
break;
case DSPEngine::StIdle:
@@ -339,6 +340,7 @@ void MainWindow::updateStatus()
m_engineRunning->setColor(Qt::gray);
m_engineError->setColor(Qt::gray);
statusBar()->clearMessage();
+ updateEnables(false);
if(m_startOsmoSDRUpdateAfterStop)
on_actionOsmoSDR_Firmware_Upgrade_triggered();
break;
@@ -348,6 +350,7 @@ void MainWindow::updateStatus()
m_engineRunning->setColor(Qt::green);
m_engineError->setColor(Qt::gray);
statusBar()->showMessage(tr("Sampling from %1").arg(m_dspEngine->deviceDescription()));
+ updateEnables(true);
break;
case DSPEngine::StError:
@@ -355,6 +358,8 @@ void MainWindow::updateStatus()
m_engineRunning->setColor(Qt::gray);
m_engineError->setColor(Qt::red);
statusBar()->showMessage(tr("Error: %1").arg(m_dspEngine->errorMessage()));
+ QMessageBox::critical(this, tr("Engine Error"), tr("%1").arg(m_dspEngine->errorMessage()), QMessageBox::Ok);
+ updateEnables(false);
if(m_startOsmoSDRUpdateAfterStop)
on_actionOsmoSDR_Firmware_Upgrade_triggered();
break;
@@ -363,6 +368,15 @@ void MainWindow::updateStatus()
}
}
+void MainWindow::updateEnables(bool running)
+{
+ if(running) {
+ ui->action_Preferences->setEnabled(false);
+ } else {
+ ui->action_Preferences->setEnabled(true);
+ }
+}
+
void MainWindow::scopeWindowDestroyed()
{
ui->action_Oscilloscope->setChecked(false);
@@ -490,7 +504,9 @@ void MainWindow::on_action_Oscilloscope_triggered()
QDockWidget* dock = new QDockWidget(tr("Signalscope"), this);
dock->setObjectName(QString::fromUtf8("scopeDock"));
- m_scopeWindow = new ScopeWindow(m_dspEngine);
+
+ m_scopeWindow = new ScopeWindow();
+ m_scopeWindow->setDSPEngine(m_dspEngine);
connect(m_scopeWindow, SIGNAL(destroyed()), this, SLOT(scopeWindowDestroyed()));
m_scopeWindow->setSampleRate(m_sampleRate);
dock->setWidget(m_scopeWindow);
@@ -509,9 +525,11 @@ void MainWindow::on_action_Loaded_Plugins_triggered()
void MainWindow::on_action_Preferences_triggered()
{
- PreferencesDialog preferencesDialog(m_audioDeviceInfo, this);
+ PreferencesDialog preferencesDialog(m_settings.getPreferences(), this);
- preferencesDialog.exec();
+ if(preferencesDialog.exec() == QDialog::Accepted) {
+ m_dspEngine->configureAudioOutput(m_settings.getPreferences()->getAudioOutput(), m_settings.getPreferences()->getAudioOutputRate());
+ }
}
void MainWindow::on_sampleSource_currentIndexChanged(int index)
diff --git a/sdrbase/plugin/pluginmanager.cpp b/sdrbase/plugin/pluginmanager.cpp
index 3338c01..325fb8b 100644
--- a/sdrbase/plugin/pluginmanager.cpp
+++ b/sdrbase/plugin/pluginmanager.cpp
@@ -72,7 +72,7 @@ void PluginManager::registerSampleSource(const QString& sourceName, PluginInterf
void PluginManager::loadSettings(const Preset* preset)
{
- qDebug("-------- [%s | %s] --------", qPrintable(preset->getGroup()), qPrintable(preset->getDescription()));
+ //qDebug("-------- [%s | %s] --------", qPrintable(preset->getGroup()), qPrintable(preset->getDescription()));
// copy currently open channels and clear list
ChannelInstanceRegistrations openChannels = m_channelInstanceRegistrations;
@@ -83,7 +83,7 @@ void PluginManager::loadSettings(const Preset* preset)
ChannelInstanceRegistration reg;
// if we have one instance available already, use it
for(int i = 0; i < openChannels.count(); i++) {
- qDebug("compare [%s] vs [%s]", qPrintable(openChannels[i].m_channelName), qPrintable(channelConfig.m_channel));
+ //qDebug("compare [%s] vs [%s]", qPrintable(openChannels[i].m_channelName), qPrintable(channelConfig.m_channel));
if(openChannels[i].m_channelName == channelConfig.m_channel) {
qDebug("channel [%s] found", qPrintable(openChannels[i].m_channelName));
reg = openChannels.takeAt(i);
@@ -235,7 +235,7 @@ int PluginManager::selectSampleSource(const QString& source)
qDebug("finding sample source [%s]", qPrintable(source));
for(int i = 0; i < m_sampleSourceDevices.count(); i++) {
- qDebug("*** %s vs %s", qPrintable(m_sampleSourceDevices[i].m_sourceName), qPrintable(source));
+ //qDebug("*** %s vs %s", qPrintable(m_sampleSourceDevices[i].m_sourceName), qPrintable(source));
if(m_sampleSourceDevices[i].m_sourceName == source) {
index = i;
break;
diff --git a/sdrbase/settings/preferences.cpp b/sdrbase/settings/preferences.cpp
index c649cda..e1391fb 100644
--- a/sdrbase/settings/preferences.cpp
+++ b/sdrbase/settings/preferences.cpp
@@ -8,19 +8,15 @@ Preferences::Preferences()
void Preferences::resetToDefaults()
{
- m_sourceType.clear();
- m_sourceDevice.clear();
- m_audioType.clear();
- m_audioDevice.clear();
+ m_audioOutput.clear();
+ m_audioOutputRate = 44100;
}
QByteArray Preferences::serialize() const
{
SimpleSerializer s(1);
- s.writeString(1, m_sourceType);
- s.writeString(2, m_sourceDevice);
- s.writeString(3, m_audioType);
- s.writeString(4, m_audioDevice);
+ s.writeString(1, m_audioOutput);
+ s.writeU32(2, m_audioOutputRate);
return s.final();
}
@@ -34,10 +30,10 @@ bool Preferences::deserialize(const QByteArray& data)
}
if(d.getVersion() == 1) {
- d.readString(1, &m_sourceType);
- d.readString(2, &m_sourceDevice);
- d.readString(3, &m_audioType);
- d.readString(4, &m_audioDevice);
+ d.readString(1, &m_audioOutput);
+ quint32 tmp;
+ d.readU32(2, &tmp, 44100);
+ m_audioOutputRate = tmp;
return true;
} else {
resetToDefaults();
diff --git a/sdrbase/util/message.cpp b/sdrbase/util/message.cpp
index 8431ca7..1ddf7af 100644
--- a/sdrbase/util/message.cpp
+++ b/sdrbase/util/message.cpp
@@ -29,6 +29,8 @@ const char* Message::getIdentifier() const
bool Message::matchIdentifier(const char* identifier) const
{
+ // Warning: this compares POINTERS - make sure, that each message has a unique name
+ // otherwise the linker might "optimize" stuff
return m_identifier == identifier;
}