From 03eb1cd97019422318396446929dc0de178ec4ae Mon Sep 17 00:00:00 2001 From: Hannes Matuschek Date: Wed, 23 Jul 2014 18:36:40 +0200 Subject: [PATCH] Implemented waterfall spectrogram. --- src/gui/gui.hh | 1 + src/gui/waterfallview.cc | 83 ++++++++++++++++++++++++++++++++++++++-- src/gui/waterfallview.hh | 58 +++++++++++++++++++++++++++- 3 files changed, 137 insertions(+), 5 deletions(-) diff --git a/src/gui/gui.hh b/src/gui/gui.hh index ea7d540..63036f9 100644 --- a/src/gui/gui.hh +++ b/src/gui/gui.hh @@ -2,5 +2,6 @@ #define __SDR_GUI_GUI_HH__ #include "spectrumview.hh" +#include "waterfallview.hh" #endif diff --git a/src/gui/waterfallview.cc b/src/gui/waterfallview.cc index f647364..00fdbd2 100644 --- a/src/gui/waterfallview.cc +++ b/src/gui/waterfallview.cc @@ -1,11 +1,88 @@ #include "waterfallview.hh" +#include +#include using namespace sdr; using namespace sdr::gui; -WaterFallView::WaterFallView(Spectrum *spectrum, QWidget *parent) - : QWidget(parent), _spectrum(spectrum) -{ +/* ****************************************************************************************** * + * Implementation of ColorMap + * ****************************************************************************************** */ +ColorMap::ColorMap() { + // pass... } + +ColorMap::~ColorMap() { + // pass... +} + +/* ****************************************************************************************** * + * Implementation of GrayScaleColorMap + * ****************************************************************************************** */ +GrayScaleColorMap::GrayScaleColorMap(double mindB) + : ColorMap(), _mindB(mindB) +{ + // pass... +} + +GrayScaleColorMap::~GrayScaleColorMap() { + // pass... +} + +QColor +GrayScaleColorMap::operator ()(const double &value) { + if (value > 0) { return Qt::white; } + if (value < _mindB) { return Qt::black; } + int h = (255*(value-_mindB))/std::abs(_mindB); + return QColor(h,h,h); +} + + +/* ****************************************************************************************** * + * Implementation of GrayScaleColorMap + * ****************************************************************************************** */ +WaterFallView::WaterFallView(Spectrum *spectrum, size_t height, QWidget *parent) + : QWidget(parent), _spectrum(spectrum), _N(_spectrum->fftSize()), _M(height), _waterfall(_N,_M) +{ + // Fill waterfall pixmap + _waterfall.fill(Qt::black); + // Create color map + _colorMap = new GrayScaleColorMap(); + + // Get notified once a new spectrum is available: + QObject::connect(_spectrum, SIGNAL(spectrumUpdated()), this, SLOT(_onSpectrumUpdated())); +} + +void +WaterFallView::_onSpectrumUpdated() { + if (_waterfall.isNull() || (_M==0) || (_N==0)) { return; } + QPainter painter(&_waterfall); + // scroll pixmap one pixel up + QRect target(0,0, _N, _M-1), source(0,1,_N,_M-1); + painter.drawPixmap(target, _waterfall, source); + + // Draw new spectrum + for (size_t i=0; i<_N; i++) { + double value = 10*log10(_spectrum->spectrum()[i])-10*log10(_N); + painter.setPen((*_colorMap)(value)); + painter.drawPoint(i, _M-1); + } + + // Trigger update + this->update(); +} + +void +WaterFallView::paintEvent(QPaintEvent *evt) { + QPainter painter(this); + painter.save(); + // Draw scaled pixmap + painter.drawPixmap(evt->rect(), _waterfall.scaled(this->width(), this->height()), evt->rect()); + painter.restore(); +} + + + + diff --git a/src/gui/waterfallview.hh b/src/gui/waterfallview.hh index 2b54b9f..40bbcc9 100644 --- a/src/gui/waterfallview.hh +++ b/src/gui/waterfallview.hh @@ -9,16 +9,70 @@ namespace sdr { namespace gui { +/** Interface for all color maps. */ +class ColorMap +{ +protected: + /** Hidden constructor. */ + ColorMap(); + +public: + /** Destructor. */ + virtual ~ColorMap(); + /** Needs to be implemented by all sub-classes. Maps the value (dB) to a color value. */ + virtual QColor operator()(const double &value) = 0; +}; + +/** A simple gray-scale color map. */ +class GrayScaleColorMap: public ColorMap +{ +public: + /** Constructor. + * @param mindB Specifices the minimum value in dB of the color-scale. Mapping values [0, mindB] + * to a gray-scale. */ + GrayScaleColorMap(double mindB=-120); + /** Destructor. */ + virtual ~GrayScaleColorMap(); + /** Implements the color mapping. */ + virtual QColor operator()(const double &value); + +protected: + /** The minimum value. */ + double _mindB; +}; + + +/** A simple waterfall display of the spectrogram. */ class WaterFallView : public QWidget { Q_OBJECT public: - explicit WaterFallView(Spectrum *spectrum, QWidget *parent = 0); + /** Constructor. + * @param spectrum Specifies the spectrum sink. + * @param height Specifies the number of PSDs to display. + * @param parent The parent widget. */ + explicit WaterFallView(Spectrum *spectrum, size_t height=100, QWidget *parent = 0); protected: + /** Draws the scaled waterfall spectrogram. */ + virtual void paintEvent(QPaintEvent *evt); + +protected slots: + /** Gets called once a new PSD is available. */ + void _onSpectrumUpdated(); + +protected: + /** The spectrum sink. */ Spectrum *_spectrum; - QImage *_waterfall; + /** The size of the spectrum. */ + size_t _N; + /** "Height of the spectrum. */ + size_t _M; + /** The waterfall spectrogram. */ + QPixmap _waterfall; + /** The color map to be used. */ + ColorMap *_colorMap; }; }