diff --git a/plugins/channelrx/demodbfm/bfmdemodgui.cpp b/plugins/channelrx/demodbfm/bfmdemodgui.cpp
index cda2d6889..87dfc9ac8 100644
--- a/plugins/channelrx/demodbfm/bfmdemodgui.cpp
+++ b/plugins/channelrx/demodbfm/bfmdemodgui.cpp
@@ -359,7 +359,7 @@ BFMDemodGUI::BFMDemodGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, Baseban
ui->glSpectrum->setDisplayWaterfall(false);
ui->glSpectrum->setDisplayMaxHold(false);
ui->glSpectrum->setSsbSpectrum(true);
- m_spectrumVis->configure(m_spectrumVis->getInputMessageQueue(), 64, 10, 0, FFTWindow::BlackmanHarris);
+ m_spectrumVis->configure(m_spectrumVis->getInputMessageQueue(), 64, 10, 0, 0, FFTWindow::BlackmanHarris);
connect(&MainWindow::getInstance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
m_channelMarker.blockSignals(true);
diff --git a/plugins/channelrx/udpsrc/udpsrcgui.cpp b/plugins/channelrx/udpsrc/udpsrcgui.cpp
index 66826ec56..2a645c287 100644
--- a/plugins/channelrx/udpsrc/udpsrcgui.cpp
+++ b/plugins/channelrx/udpsrc/udpsrcgui.cpp
@@ -187,7 +187,7 @@ UDPSrcGUI::UDPSrcGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandSam
ui->glSpectrum->setSampleRate(ui->sampleRate->text().toInt());
ui->glSpectrum->setDisplayWaterfall(true);
ui->glSpectrum->setDisplayMaxHold(true);
- m_spectrumVis->configure(m_spectrumVis->getInputMessageQueue(), 64, 10, 0, FFTWindow::BlackmanHarris);
+ m_spectrumVis->configure(m_spectrumVis->getInputMessageQueue(), 64, 10, 0, 0, FFTWindow::BlackmanHarris);
ui->glSpectrum->connectTimer(MainWindow::getInstance()->getMasterTimer());
connect(&MainWindow::getInstance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
diff --git a/plugins/channeltx/udpsink/udpsinkgui.cpp b/plugins/channeltx/udpsink/udpsinkgui.cpp
index 4e40e2cce..88e33c399 100644
--- a/plugins/channeltx/udpsink/udpsinkgui.cpp
+++ b/plugins/channeltx/udpsink/udpsinkgui.cpp
@@ -142,7 +142,7 @@ UDPSinkGUI::UDPSinkGUI(PluginAPI* pluginAPI, DeviceUISet *deviceUISet, BasebandS
ui->glSpectrum->setSampleRate(ui->sampleRate->text().toInt());
ui->glSpectrum->setDisplayWaterfall(true);
ui->glSpectrum->setDisplayMaxHold(true);
- m_spectrumVis->configure(m_spectrumVis->getInputMessageQueue(), 64, 10, 0, FFTWindow::BlackmanHarris);
+ m_spectrumVis->configure(m_spectrumVis->getInputMessageQueue(), 64, 10, 0, 0, FFTWindow::BlackmanHarris);
ui->glSpectrum->connectTimer(MainWindow::getInstance()->getMasterTimer());
connect(&MainWindow::getInstance()->getMasterTimer(), SIGNAL(timeout()), this, SLOT(tick()));
diff --git a/sdrbase/util/fixedaverage2d.h b/sdrbase/util/fixedaverage2d.h
new file mode 100644
index 000000000..a4735889b
--- /dev/null
+++ b/sdrbase/util/fixedaverage2d.h
@@ -0,0 +1,121 @@
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2018 F4EXB //
+// written by Edouard Griffiths //
+// //
+// 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 . //
+///////////////////////////////////////////////////////////////////////////////////
+
+#ifndef SDRBASE_UTIL_FIXEDAVERAGE2D_H_
+#define SDRBASE_UTIL_FIXEDAVERAGE2D_H_
+
+#include
+
+template
+class FixedAverage2D
+{
+public:
+ FixedAverage2D() : m_sum(0), m_sumSize(0), m_width(0), m_size(0), m_avgIndex(0) {}
+
+ ~FixedAverage2D()
+ {
+ if (m_sum) {
+ delete[] m_sum;
+ }
+ }
+
+ void resize(unsigned int width, unsigned int size)
+ {
+ if (width > m_sumSize)
+ {
+ m_sumSize = width;
+ if (m_sum) {
+ delete[] m_sum;
+ }
+ m_sum = new T[m_sumSize];
+ }
+
+ m_width = width;
+ m_size = size;
+
+ std::fill(m_sum, m_sum+m_width, 0);
+ m_avgIndex = 0;
+ }
+
+ bool storeAndGetAvg(T& avg, T v, unsigned int index)
+ {
+ if (m_size <= 1)
+ {
+ avg = v;
+ return true;
+ }
+
+ m_sum[index] += v;
+
+ if (m_avgIndex == m_size - 1)
+ {
+ avg = m_sum[index]/m_size;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ bool storeAndGetSum(T& sum, T v, unsigned int index)
+ {
+ if (m_size <= 1)
+ {
+ sum = v;
+ return true;
+ }
+
+ m_sum[index] += v;
+
+ if (m_avgIndex < m_size - 1)
+ {
+ sum = m_sum[index];
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+ }
+
+ bool nextAverage()
+ {
+ if (m_avgIndex == m_size - 1)
+ {
+ m_avgIndex = 0;
+ std::fill(m_sum, m_sum+m_width, 0);
+ return true;
+ }
+ else
+ {
+ m_avgIndex++;
+ return false;
+ }
+ }
+
+private:
+ T *m_sum;
+ unsigned int m_sumSize;
+ unsigned int m_width;
+ unsigned int m_size;
+ unsigned int m_avgIndex;
+};
+
+
+
+#endif /* SDRBASE_UTIL_FIXEDAVERAGE2D_H_ */
diff --git a/sdrgui/dsp/spectrumvis.cpp b/sdrgui/dsp/spectrumvis.cpp
index 27eb7a5c0..f3d30aef7 100644
--- a/sdrgui/dsp/spectrumvis.cpp
+++ b/sdrgui/dsp/spectrumvis.cpp
@@ -26,11 +26,12 @@ SpectrumVis::SpectrumVis(Real scalef, GLSpectrum* glSpectrum) :
m_scalef(scalef),
m_glSpectrum(glSpectrum),
m_averageNb(0),
+ m_averagingMode(AvgModeMoving),
m_ofs(0),
m_mutex(QMutex::Recursive)
{
setObjectName("SpectrumVis");
- handleConfigure(1024, 0, 0, FFTWindow::BlackmanHarris);
+ handleConfigure(1024, 0, 0, AvgModeMoving, FFTWindow::BlackmanHarris);
}
SpectrumVis::~SpectrumVis()
@@ -38,9 +39,14 @@ SpectrumVis::~SpectrumVis()
delete m_fft;
}
-void SpectrumVis::configure(MessageQueue* msgQueue, int fftSize, int overlapPercent, unsigned int averagingNb, FFTWindow::Function window)
+void SpectrumVis::configure(MessageQueue* msgQueue,
+ int fftSize,
+ int overlapPercent,
+ unsigned int averagingNb,
+ int averagingMode,
+ FFTWindow::Function window)
{
- MsgConfigureSpectrumVis* cmd = new MsgConfigureSpectrumVis(fftSize, overlapPercent, averagingNb, window);
+ MsgConfigureSpectrumVis* cmd = new MsgConfigureSpectrumVis(fftSize, overlapPercent, averagingNb, averagingMode, window);
msgQueue->push(cmd);
}
@@ -105,40 +111,92 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV
Real v;
std::size_t halfSize = m_fftSize / 2;
- if ( positiveOnly )
+ if (m_averagingMode == AvgModeMoving)
{
- for (std::size_t i = 0; i < halfSize; i++)
- {
- c = fftOut[i];
- v = c.real() * c.real() + c.imag() * c.imag();
- v = m_average.storeAndGetAvg(v, i);
- v = m_mult * log2f(v) + m_ofs;
- m_logPowerSpectrum[i * 2] = v;
- m_logPowerSpectrum[i * 2 + 1] = v;
- }
+ if ( positiveOnly )
+ {
+ for (std::size_t i = 0; i < halfSize; i++)
+ {
+ 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;
+ }
+ }
+ else
+ {
+ for (std::size_t i = 0; i < halfSize; i++)
+ {
+ 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;
+
+ 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;
+ }
+ }
+
+ // send new data to visualisation
+ m_glSpectrum->newSpectrum(m_logPowerSpectrum, m_fftSize);
+ m_movingAverage.nextAverage();
}
- else
+ else if (m_averagingMode == AvgModeFixed)
{
- for (std::size_t i = 0; i < halfSize; i++)
- {
- c = fftOut[i + halfSize];
- v = c.real() * c.real() + c.imag() * c.imag();
- v = m_average.storeAndGetAvg(v, i+halfSize);
- v = m_mult * log2f(v) + m_ofs;
- m_logPowerSpectrum[i] = v;
+ double avg;
- c = fftOut[i];
- v = c.real() * c.real() + c.imag() * c.imag();
- v = m_average.storeAndGetAvg(v, i);
- v = m_mult * log2f(v) + m_ofs;
- m_logPowerSpectrum[i + halfSize] = v;
- }
+ if ( positiveOnly )
+ {
+ for (std::size_t i = 0; i < halfSize; i++)
+ {
+ c = fftOut[i];
+ v = c.real() * c.real() + c.imag() * c.imag();
+
+ 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;
+ }
+ }
+ }
+ else
+ {
+ for (std::size_t i = 0; i < halfSize; i++)
+ {
+ c = fftOut[i + halfSize];
+ v = c.real() * c.real() + c.imag() * c.imag();
+
+ if (m_fixedAverage.storeAndGetAvg(avg, v, i+halfSize))
+ { // result available
+ avg = m_mult * log2f(avg) + m_ofs;
+ m_logPowerSpectrum[i] = avg;
+ }
+
+ c = fftOut[i];
+ v = c.real() * c.real() + c.imag() * c.imag();
+
+ if (m_fixedAverage.storeAndGetAvg(avg, v, i))
+ { // result available
+ avg = m_mult * log2f(avg) + m_ofs;
+ m_logPowerSpectrum[i + halfSize] = avg;
+ }
+ }
+ }
+
+ if (m_fixedAverage.nextAverage())
+ { // result available
+ // send new data to visualisation
+ m_glSpectrum->newSpectrum(m_logPowerSpectrum, m_fftSize);
+ }
}
- // send new data to visualisation
- m_glSpectrum->newSpectrum(m_logPowerSpectrum, m_fftSize);
- m_average.nextAverage();
-
// advance buffer respecting the fft overlap factor
std::copy(m_fftBuffer.begin() + m_refillSize, m_fftBuffer.end(), m_fftBuffer.begin());
@@ -173,7 +231,11 @@ bool SpectrumVis::handleMessage(const Message& message)
if (MsgConfigureSpectrumVis::match(message))
{
MsgConfigureSpectrumVis& conf = (MsgConfigureSpectrumVis&) message;
- handleConfigure(conf.getFFTSize(), conf.getOverlapPercent(), conf.getAverageNb(), conf.getWindow());
+ handleConfigure(conf.getFFTSize(),
+ conf.getOverlapPercent(),
+ conf.getAverageNb(),
+ conf.getAveragingMode(),
+ conf.getWindow());
return true;
}
else
@@ -182,7 +244,11 @@ bool SpectrumVis::handleMessage(const Message& message)
}
}
-void SpectrumVis::handleConfigure(int fftSize, int overlapPercent, unsigned int averageNb, FFTWindow::Function window)
+void SpectrumVis::handleConfigure(int fftSize,
+ int overlapPercent,
+ unsigned int averageNb,
+ AveragingMode averagingMode,
+ FFTWindow::Function window)
{
QMutexLocker mutexLocker(&m_mutex);
@@ -214,7 +280,9 @@ void SpectrumVis::handleConfigure(int fftSize, int overlapPercent, unsigned int
m_overlapSize = (m_fftSize * m_overlapPercent) / 100;
m_refillSize = m_fftSize - m_overlapSize;
m_fftBufferFill = m_overlapSize;
- m_average.resize(fftSize, averageNb);
+ m_movingAverage.resize(fftSize, averageNb);
+ m_fixedAverage.resize(fftSize, averageNb);
m_averageNb = averageNb;
+ m_averagingMode = averagingMode;
m_ofs = 20.0f * log10f(1.0f / m_fftSize);
}
diff --git a/sdrgui/dsp/spectrumvis.h b/sdrgui/dsp/spectrumvis.h
index 8faa38647..e2b81c2ca 100644
--- a/sdrgui/dsp/spectrumvis.h
+++ b/sdrgui/dsp/spectrumvis.h
@@ -8,6 +8,7 @@
#include "export.h"
#include "util/message.h"
#include "util/movingaverage2d.h"
+#include "util/fixedaverage2d.h"
class GLSpectrum;
class MessageQueue;
@@ -15,34 +16,49 @@ class MessageQueue;
class SDRGUI_API SpectrumVis : public BasebandSampleSink {
public:
+ enum AveragingMode
+ {
+ AvgModeMoving,
+ AvgModeFixed
+ };
+
class MsgConfigureSpectrumVis : public Message {
MESSAGE_CLASS_DECLARATION
public:
- MsgConfigureSpectrumVis(int fftSize, int overlapPercent, unsigned int averageNb, FFTWindow::Function window) :
+ MsgConfigureSpectrumVis(int fftSize, int overlapPercent, unsigned int averageNb, int averagingMode, FFTWindow::Function window) :
Message(),
m_fftSize(fftSize),
m_overlapPercent(overlapPercent),
m_averageNb(averageNb),
m_window(window)
- { }
+ {
+ m_averagingMode = averagingMode < 0 ? AvgModeMoving : averagingMode > 1 ? AvgModeFixed : (SpectrumVis::AveragingMode) averagingMode;
+ }
int getFFTSize() const { return m_fftSize; }
int getOverlapPercent() const { return m_overlapPercent; }
unsigned int getAverageNb() const { return m_averageNb; }
+ SpectrumVis::AveragingMode getAveragingMode() const { return m_averagingMode; }
FFTWindow::Function getWindow() const { return m_window; }
private:
int m_fftSize;
int m_overlapPercent;
unsigned int m_averageNb;
+ SpectrumVis::AveragingMode m_averagingMode;
FFTWindow::Function m_window;
};
SpectrumVis(Real scalef, GLSpectrum* glSpectrum = 0);
virtual ~SpectrumVis();
- void configure(MessageQueue* msgQueue, int fftSize, int overlapPercent, unsigned int averagingNb, FFTWindow::Function window);
+ void configure(MessageQueue* msgQueue,
+ int fftSize,
+ int overlapPercent,
+ unsigned int averagingNb,
+ int averagingMode,
+ FFTWindow::Function window);
virtual void feed(const SampleVector::const_iterator& begin, const SampleVector::const_iterator& end, bool positiveOnly);
void feedTriggered(const SampleVector::const_iterator& triggerPoint, const SampleVector::const_iterator& end, bool positiveOnly);
@@ -66,15 +82,21 @@ private:
Real m_scalef;
GLSpectrum* m_glSpectrum;
- MovingAverage2D m_average;
+ MovingAverage2D m_movingAverage;
+ FixedAverage2D m_fixedAverage;
unsigned int m_averageNb;
+ AveragingMode m_averagingMode;
Real m_ofs;
static const Real m_mult;
QMutex m_mutex;
- void handleConfigure(int fftSize, int overlapPercent, unsigned int averageNb, FFTWindow::Function window);
+ void handleConfigure(int fftSize,
+ int overlapPercent,
+ unsigned int averageNb,
+ AveragingMode averagingMode,
+ FFTWindow::Function window);
};
#endif // INCLUDE_SPECTRUMVIS_H
diff --git a/sdrgui/gui/glspectrumgui.cpp b/sdrgui/gui/glspectrumgui.cpp
index f3706a109..6933fcf75 100644
--- a/sdrgui/gui/glspectrumgui.cpp
+++ b/sdrgui/gui/glspectrumgui.cpp
@@ -191,7 +191,12 @@ void GLSpectrumGUI::applySettings()
m_glSpectrum->setDisplayGridIntensity(m_displayGridIntensity);
if (m_spectrumVis) {
- m_spectrumVis->configure(m_messageQueue, m_fftSize, m_fftOverlap, m_averagingNb, (FFTWindow::Function)m_fftWindow);
+ m_spectrumVis->configure(m_messageQueue,
+ m_fftSize,
+ m_fftOverlap,
+ m_averagingNb,
+ m_averagingMode,
+ (FFTWindow::Function)m_fftWindow);
}
}
@@ -199,7 +204,12 @@ void GLSpectrumGUI::on_fftWindow_currentIndexChanged(int index)
{
m_fftWindow = index;
if(m_spectrumVis != 0) {
- m_spectrumVis->configure(m_messageQueue, m_fftSize, m_fftOverlap, m_averagingNb, (FFTWindow::Function)m_fftWindow);
+ m_spectrumVis->configure(m_messageQueue,
+ m_fftSize,
+ m_fftOverlap,
+ m_averagingNb,
+ m_averagingMode,
+ (FFTWindow::Function)m_fftWindow);
}
}
@@ -207,12 +217,26 @@ void GLSpectrumGUI::on_fftSize_currentIndexChanged(int index)
{
m_fftSize = 1 << (7 + index);
if(m_spectrumVis != 0) {
- m_spectrumVis->configure(m_messageQueue, m_fftSize, m_fftOverlap, m_averagingNb, (FFTWindow::Function)m_fftWindow);
+ m_spectrumVis->configure(m_messageQueue,
+ m_fftSize,
+ m_fftOverlap,
+ m_averagingNb,
+ m_averagingMode,
+ (FFTWindow::Function)m_fftWindow);
}
}
-void GLSpectrumGUI::on_averagingMode_currentIndexChanged(int index __attribute__((unused)))
+void GLSpectrumGUI::on_averagingMode_currentIndexChanged(int index)
{
+ m_averagingMode = index < 0 ? AvgModeMoving : index > 1 ? AvgModeFixed : (AveragingMode) index;
+ if(m_spectrumVis != 0) {
+ m_spectrumVis->configure(m_messageQueue,
+ m_fftSize,
+ m_fftOverlap,
+ m_averagingNb,
+ m_averagingMode,
+ (FFTWindow::Function)m_fftWindow);
+ }
}
void GLSpectrumGUI::on_averaging_currentIndexChanged(int index)
@@ -220,7 +244,12 @@ void GLSpectrumGUI::on_averaging_currentIndexChanged(int index)
m_averagingIndex = index;
m_averagingNb = getAveragingValue(index);
if(m_spectrumVis != 0) {
- m_spectrumVis->configure(m_messageQueue, m_fftSize, m_fftOverlap, m_averagingNb, (FFTWindow::Function)m_fftWindow);
+ m_spectrumVis->configure(m_messageQueue,
+ m_fftSize,
+ m_fftOverlap,
+ m_averagingNb,
+ m_averagingMode,
+ (FFTWindow::Function)m_fftWindow);
}
}