From f6c596d55a06bdb19c4e2100989882ea76d8f8e5 Mon Sep 17 00:00:00 2001 From: f4exb Date: Fri, 6 Jul 2018 01:34:05 +0200 Subject: [PATCH] Spectrum: implemented linear scale mode --- sdrgui/dsp/spectrumvis.cpp | 62 ++++++++++++++++++++---------------- sdrgui/dsp/spectrumvis.h | 7 ++-- sdrgui/gui/glspectrum.cpp | 16 +++++++++- sdrgui/gui/glspectrum.h | 2 ++ sdrgui/gui/glspectrumgui.cpp | 35 +++++++++++++++++--- sdrgui/gui/physicalunit.h | 3 +- sdrgui/gui/scaleengine.cpp | 7 +++- 7 files changed, 95 insertions(+), 37 deletions(-) diff --git a/sdrgui/dsp/spectrumvis.cpp b/sdrgui/dsp/spectrumvis.cpp index ae386182e..7bc7f5426 100644 --- a/sdrgui/dsp/spectrumvis.cpp +++ b/sdrgui/dsp/spectrumvis.cpp @@ -20,18 +20,20 @@ SpectrumVis::SpectrumVis(Real scalef, GLSpectrum* glSpectrum) : BasebandSampleSink(), m_fft(FFTEngine::create()), m_fftBuffer(MAX_FFT_SIZE), - m_logPowerSpectrum(MAX_FFT_SIZE), + m_powerSpectrum(MAX_FFT_SIZE), m_fftBufferFill(0), m_needMoreSamples(false), m_scalef(scalef), m_glSpectrum(glSpectrum), m_averageNb(0), m_averagingMode(AvgModeNone), + m_linear(false), m_ofs(0), + m_powFFTDiv(1.0), m_mutex(QMutex::Recursive) { setObjectName("SpectrumVis"); - handleConfigure(1024, 0, 0, AvgModeNone, FFTWindow::BlackmanHarris); + handleConfigure(1024, 0, 0, AvgModeNone, FFTWindow::BlackmanHarris, false); } SpectrumVis::~SpectrumVis() @@ -120,9 +122,9 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV { c = fftOut[i]; v = c.real() * c.real() + c.imag() * c.imag(); - v = m_mult * log2f(v) + m_ofs; - m_logPowerSpectrum[i * 2] = v; - m_logPowerSpectrum[i * 2 + 1] = v; + v = m_linear ? v/m_powFFTDiv : m_mult * log2f(v) + m_ofs; + m_powerSpectrum[i * 2] = v; + m_powerSpectrum[i * 2 + 1] = v; } } else @@ -131,18 +133,18 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV { c = fftOut[i + halfSize]; v = c.real() * c.real() + c.imag() * c.imag(); - v = m_mult * log2f(v) + m_ofs; - m_logPowerSpectrum[i] = v; + v = m_linear ? v/m_powFFTDiv : m_mult * log2f(v) + m_ofs; + m_powerSpectrum[i] = v; c = fftOut[i]; v = c.real() * c.real() + c.imag() * c.imag(); - v = m_mult * log2f(v) + m_ofs; - m_logPowerSpectrum[i + halfSize] = v; + v = m_linear ? v/m_powFFTDiv : m_mult * log2f(v) + m_ofs; + m_powerSpectrum[i + halfSize] = v; } } // send new data to visualisation - m_glSpectrum->newSpectrum(m_logPowerSpectrum, m_fftSize); + m_glSpectrum->newSpectrum(m_powerSpectrum, m_fftSize); } else if (m_averagingMode == AvgModeMoving) { @@ -153,9 +155,9 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV c = fftOut[i]; v = c.real() * c.real() + c.imag() * c.imag(); v = m_movingAverage.storeAndGetAvg(v, i); - v = m_mult * log2f(v) + m_ofs; - m_logPowerSpectrum[i * 2] = v; - m_logPowerSpectrum[i * 2 + 1] = v; + v = m_linear ? v/m_powFFTDiv : m_mult * log2f(v) + m_ofs; + m_powerSpectrum[i * 2] = v; + m_powerSpectrum[i * 2 + 1] = v; } } else @@ -165,19 +167,19 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV c = fftOut[i + halfSize]; v = c.real() * c.real() + c.imag() * c.imag(); v = m_movingAverage.storeAndGetAvg(v, i+halfSize); - v = m_mult * log2f(v) + m_ofs; - m_logPowerSpectrum[i] = v; + v = m_linear ? v/m_powFFTDiv : m_mult * log2f(v) + m_ofs; + m_powerSpectrum[i] = v; c = fftOut[i]; v = c.real() * c.real() + c.imag() * c.imag(); v = m_movingAverage.storeAndGetAvg(v, i); - v = m_mult * log2f(v) + m_ofs; - m_logPowerSpectrum[i + halfSize] = v; + v = m_linear ? v/m_powFFTDiv : m_mult * log2f(v) + m_ofs; + m_powerSpectrum[i + halfSize] = v; } } // send new data to visualisation - m_glSpectrum->newSpectrum(m_logPowerSpectrum, m_fftSize); + m_glSpectrum->newSpectrum(m_powerSpectrum, m_fftSize); m_movingAverage.nextAverage(); } else if (m_averagingMode == AvgModeFixed) @@ -193,9 +195,9 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV if (m_fixedAverage.storeAndGetAvg(avg, v, i)) { - avg = m_mult * log2f(avg) + m_ofs; - m_logPowerSpectrum[i * 2] = avg; - m_logPowerSpectrum[i * 2 + 1] = avg; + avg = m_linear ? v/m_powFFTDiv : m_mult * log2f(avg) + m_ofs; + m_powerSpectrum[i * 2] = avg; + m_powerSpectrum[i * 2 + 1] = avg; } } } @@ -208,8 +210,8 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV if (m_fixedAverage.storeAndGetAvg(avg, v, i+halfSize)) { // result available - avg = m_mult * log2f(avg) + m_ofs; - m_logPowerSpectrum[i] = avg; + avg = m_linear ? v/m_powFFTDiv : m_mult * log2f(avg) + m_ofs; + m_powerSpectrum[i] = avg; } c = fftOut[i]; @@ -217,8 +219,8 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV if (m_fixedAverage.storeAndGetAvg(avg, v, i)) { // result available - avg = m_mult * log2f(avg) + m_ofs; - m_logPowerSpectrum[i + halfSize] = avg; + avg = m_linear ? v/m_powFFTDiv : m_mult * log2f(avg) + m_ofs; + m_powerSpectrum[i + halfSize] = avg; } } } @@ -226,7 +228,7 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV if (m_fixedAverage.nextAverage()) { // result available // send new data to visualisation - m_glSpectrum->newSpectrum(m_logPowerSpectrum, m_fftSize); + m_glSpectrum->newSpectrum(m_powerSpectrum, m_fftSize); } } @@ -268,7 +270,8 @@ bool SpectrumVis::handleMessage(const Message& message) conf.getOverlapPercent(), conf.getAverageNb(), conf.getAveragingMode(), - conf.getWindow()); + conf.getWindow(), + conf.getLinear()); return true; } else @@ -281,7 +284,8 @@ void SpectrumVis::handleConfigure(int fftSize, int overlapPercent, unsigned int averageNb, AveragingMode averagingMode, - FFTWindow::Function window) + FFTWindow::Function window, + bool linear) { QMutexLocker mutexLocker(&m_mutex); @@ -317,5 +321,7 @@ void SpectrumVis::handleConfigure(int fftSize, m_fixedAverage.resize(fftSize, averageNb); m_averageNb = averageNb; m_averagingMode = averagingMode; + m_linear = linear; m_ofs = 20.0f * log10f(1.0f / m_fftSize); + m_powFFTDiv = m_fftSize*m_fftSize; } diff --git a/sdrgui/dsp/spectrumvis.h b/sdrgui/dsp/spectrumvis.h index de1c35236..a86a5c0fd 100644 --- a/sdrgui/dsp/spectrumvis.h +++ b/sdrgui/dsp/spectrumvis.h @@ -82,7 +82,7 @@ private: FFTWindow m_window; std::vector m_fftBuffer; - std::vector m_logPowerSpectrum; + std::vector m_powerSpectrum; std::size_t m_fftSize; std::size_t m_overlapPercent; @@ -97,8 +97,10 @@ private: FixedAverage2D m_fixedAverage; unsigned int m_averageNb; AveragingMode m_averagingMode; + bool m_linear; Real m_ofs; + Real m_powFFTDiv; static const Real m_mult; QMutex m_mutex; @@ -107,7 +109,8 @@ private: int overlapPercent, unsigned int averageNb, AveragingMode averagingMode, - FFTWindow::Function window); + FFTWindow::Function window, + bool linear); }; #endif // INCLUDE_SPECTRUMVIS_H diff --git a/sdrgui/gui/glspectrum.cpp b/sdrgui/gui/glspectrum.cpp index f565a0c95..1a9356469 100644 --- a/sdrgui/gui/glspectrum.cpp +++ b/sdrgui/gui/glspectrum.cpp @@ -39,6 +39,7 @@ GLSpectrum::GLSpectrum(QWidget* parent) : m_centerFrequency(100000000), m_referenceLevel(0), m_powerRange(100), + m_linear(false), m_decay(0), m_sampleRate(500000), m_timingRate(1), @@ -291,6 +292,13 @@ void GLSpectrum::setDisplayTraceIntensity(int intensity) update(); } +void GLSpectrum::setLinear(bool linear) +{ + m_linear = linear; + m_changesPending = true; + update(); +} + void GLSpectrum::addChannelMarker(ChannelMarker* channelMarker) { QMutexLocker mutexLocker(&m_mutex); @@ -1075,7 +1083,13 @@ void GLSpectrum::applyChanges() } m_powerScale.setSize(histogramHeight); - m_powerScale.setRange(Unit::Decibel, m_referenceLevel - m_powerRange, m_referenceLevel); + + if (m_linear) { + m_powerScale.setRange(Unit::Scientific, m_referenceLevel - m_powerRange, m_referenceLevel); + } else { + m_powerScale.setRange(Unit::Decibel, m_referenceLevel - m_powerRange, m_referenceLevel); + } + leftMargin = m_timeScale.getScaleWidth(); if(m_powerScale.getScaleWidth() > leftMargin) diff --git a/sdrgui/gui/glspectrum.h b/sdrgui/gui/glspectrum.h index 21301ba19..c1be4bdf9 100644 --- a/sdrgui/gui/glspectrum.h +++ b/sdrgui/gui/glspectrum.h @@ -81,6 +81,7 @@ public: void setDisplayGrid(bool display); void setDisplayGridIntensity(int intensity); void setDisplayTraceIntensity(int intensity); + void setLinear(bool linear); qint32 getSampleRate() const { return m_sampleRate; } void addChannelMarker(ChannelMarker* channelMarker); @@ -130,6 +131,7 @@ private: qint64 m_centerFrequency; Real m_referenceLevel; Real m_powerRange; + bool m_linear; int m_decay; quint32 m_sampleRate; quint32 m_timingRate; diff --git a/sdrgui/gui/glspectrumgui.cpp b/sdrgui/gui/glspectrumgui.cpp index e9040f870..10f11e7ad 100644 --- a/sdrgui/gui/glspectrumgui.cpp +++ b/sdrgui/gui/glspectrumgui.cpp @@ -77,6 +77,7 @@ void GLSpectrumGUI::resetToDefaults() m_invert = true; m_averagingMode = AvgModeNone; m_averagingIndex = 0; + m_linear = false; applySettings(); } @@ -103,6 +104,7 @@ QByteArray GLSpectrumGUI::serialize() const s.writeReal(18, m_glSpectrum->getWaterfallShare()); s.writeS32(19, (int) m_averagingMode); s.writeS32(20, (qint32) getAveragingValue(m_averagingIndex)); + s.writeBool(21, m_linear); return s.final(); } @@ -142,6 +144,7 @@ bool GLSpectrumGUI::deserialize(const QByteArray& data) d.readS32(20, &tmp, 0); m_averagingIndex = getAveragingIndex(tmp); m_averagingNb = getAveragingValue(m_averagingIndex); + d.readBool(21, &m_linear, false); m_glSpectrum->setWaterfallShare(waterfallShare); applySettings(); @@ -165,6 +168,7 @@ void GLSpectrumGUI::applySettings() ui->levelRange->setCurrentIndex((100 - m_powerRange) / 5); ui->averaging->setCurrentIndex(m_averagingIndex); ui->averagingMode->setCurrentIndex((int) m_averagingMode); + ui->linscale->setChecked(m_linear); ui->decay->setSliderPosition(m_decay); ui->holdoff->setSliderPosition(m_histogramLateHoldoff); ui->stroke->setSliderPosition(m_histogramStroke); @@ -193,6 +197,7 @@ void GLSpectrumGUI::applySettings() m_glSpectrum->setInvertedWaterfall(m_invert); m_glSpectrum->setDisplayGrid(m_displayGrid); m_glSpectrum->setDisplayGridIntensity(m_displayGridIntensity); + m_glSpectrum->setLinear(m_linear); if (m_spectrumVis) { m_spectrumVis->configure(m_messageQueueToVis, @@ -298,21 +303,43 @@ void GLSpectrumGUI::on_linscale_toggled(bool checked) (FFTWindow::Function)m_fftWindow, m_linear); } + + if(m_glSpectrum != 0) + { + Real refLevel = m_linear ? pow(10.0, m_refLevel/10.0) : m_refLevel; + Real powerRange = m_linear ? pow(10.0, m_refLevel/10.0) : m_powerRange; + qDebug("GLSpectrumGUI::on_linscale_toggled: refLevel: %e powerRange: %e", refLevel, powerRange); + m_glSpectrum->setReferenceLevel(refLevel); + m_glSpectrum->setPowerRange(powerRange); + m_glSpectrum->setLinear(m_linear); + } } void GLSpectrumGUI::on_refLevel_currentIndexChanged(int index) { m_refLevel = 0 - index * 5; - if(m_glSpectrum != 0) { - m_glSpectrum->setReferenceLevel(m_refLevel); + + if(m_glSpectrum != 0) + { + Real refLevel = m_linear ? pow(10.0, m_refLevel/10.0) : m_refLevel; + Real powerRange = m_linear ? pow(10.0, m_refLevel/10.0) : m_powerRange; + qDebug("GLSpectrumGUI::on_refLevel_currentIndexChanged: refLevel: %e ", refLevel); + m_glSpectrum->setReferenceLevel(refLevel); + m_glSpectrum->setPowerRange(powerRange); } } void GLSpectrumGUI::on_levelRange_currentIndexChanged(int index) { m_powerRange = 100 - index * 5; - if(m_glSpectrum != 0) { - m_glSpectrum->setPowerRange(m_powerRange); + + if(m_glSpectrum != 0) + { + Real refLevel = m_linear ? pow(10.0, m_refLevel/10.0) : m_refLevel; + Real powerRange = m_linear ? pow(10.0, m_refLevel/10.0) : m_powerRange; + qDebug("GLSpectrumGUI::on_levelRange_currentIndexChanged: powerRange: %e", powerRange); + m_glSpectrum->setReferenceLevel(refLevel); + m_glSpectrum->setPowerRange(powerRange); } } diff --git a/sdrgui/gui/physicalunit.h b/sdrgui/gui/physicalunit.h index 27399a121..8ce16e6cc 100644 --- a/sdrgui/gui/physicalunit.h +++ b/sdrgui/gui/physicalunit.h @@ -30,7 +30,8 @@ namespace Unit { AngleDegrees, Time, TimeHMS, - Volt + Volt, + Scientific }; }; diff --git a/sdrgui/gui/scaleengine.cpp b/sdrgui/gui/scaleengine.cpp index 195aac116..a46e2b813 100644 --- a/sdrgui/gui/scaleengine.cpp +++ b/sdrgui/gui/scaleengine.cpp @@ -31,7 +31,11 @@ QString ScaleEngine::formatTick(double value, int decimalPlaces) { if (m_physicalUnit != Unit::TimeHMS) { - return QString("%1").arg(m_makeOpposite ? -value : value, 0, 'f', decimalPlaces); + if (m_physicalUnit == Unit::Scientific) { + return QString("%1").arg(m_makeOpposite ? -value : value, 0, 'e', 2); + } else { + return QString("%1").arg(m_makeOpposite ? -value : value, 0, 'f', decimalPlaces); + } } else { @@ -106,6 +110,7 @@ void ScaleEngine::calcScaleFactor() switch(m_physicalUnit) { case Unit::None: + case Unit::Scientific: m_unitStr.clear(); break;