mirror of https://github.com/hmatuschek/libsdr
Cleanup.
parent
cbaa2e0ec6
commit
f1d9b03254
@ -1,7 +0,0 @@
|
|||||||
#ifndef __SDR_GUI_GUI_HH__
|
|
||||||
#define __SDR_GUI_GUI_HH__
|
|
||||||
|
|
||||||
#include "spectrumview.hh"
|
|
||||||
#include "waterfallview.hh"
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,271 +0,0 @@
|
|||||||
#include "spectrum.hh"
|
|
||||||
#include "config.hh"
|
|
||||||
|
|
||||||
using namespace sdr;
|
|
||||||
using namespace sdr::gui;
|
|
||||||
|
|
||||||
|
|
||||||
/* ********************************************************************************************* *
|
|
||||||
* SpectrumProvider
|
|
||||||
* ********************************************************************************************* */
|
|
||||||
SpectrumProvider::SpectrumProvider(QObject *parent)
|
|
||||||
: QObject(parent)
|
|
||||||
{
|
|
||||||
// pass...
|
|
||||||
}
|
|
||||||
|
|
||||||
SpectrumProvider::~SpectrumProvider() {
|
|
||||||
// pass...
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ********************************************************************************************* *
|
|
||||||
* Spectrum
|
|
||||||
* ********************************************************************************************* */
|
|
||||||
Spectrum::Spectrum(double rrate, size_t fftsize, size_t max_avg, QObject *parent) :
|
|
||||||
SpectrumProvider(parent), _rrate(rrate), _fft_size(fftsize), _fft_buffer(fftsize),
|
|
||||||
_compute(fftsize), _spectrum(fftsize), _sample_count(0), _N_samples(0),
|
|
||||||
_trafo_count(0), _Ntrafo(max_avg),
|
|
||||||
_samples_left(0), _input_type(Config::Type_UNDEFINED), _sample_rate(0)
|
|
||||||
{
|
|
||||||
// Construct FFT plan
|
|
||||||
_plan = fftw_plan_dft_1d(
|
|
||||||
fftsize, (fftw_complex *)_fft_buffer.ptr(), (fftw_complex *)_fft_buffer.ptr(),
|
|
||||||
FFTW_FORWARD, FFTW_ESTIMATE);
|
|
||||||
|
|
||||||
// Set spectrum to 0:
|
|
||||||
for (size_t i=0; i<_fft_size; i++) { _spectrum[i] = 0; _compute[i] = 0; }
|
|
||||||
}
|
|
||||||
|
|
||||||
Spectrum::~Spectrum() {
|
|
||||||
fftw_destroy_plan(_plan);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Spectrum::config(const Config &src_cfg) {
|
|
||||||
// Requires at least sample rate and type
|
|
||||||
if (!src_cfg.hasType() || !src_cfg.hasSampleRate()) { return; }
|
|
||||||
|
|
||||||
// Store sample rate
|
|
||||||
_sample_rate = src_cfg.sampleRate();
|
|
||||||
_samples_left = 0;
|
|
||||||
_trafo_count = 0; _sample_count=0;
|
|
||||||
_input_type = src_cfg.type();
|
|
||||||
// Compute number of averages to compute to meet rrate approximately
|
|
||||||
_N_samples = _sample_rate/(_Ntrafo*_rrate);
|
|
||||||
|
|
||||||
LogMessage msg(LOG_DEBUG);
|
|
||||||
msg << "Configured SpectrumView: " << std::endl
|
|
||||||
<< " Data type: " << _input_type << std::endl
|
|
||||||
<< " sample-rate: " << _sample_rate << std::endl
|
|
||||||
<< " FFT size: " << _fft_size << std::endl
|
|
||||||
<< " # sample drops: " << _N_samples-1 << std::endl
|
|
||||||
<< " # averages: " << _Ntrafo << std::endl
|
|
||||||
<< " refresh rate: " << _sample_rate/(_N_samples*_Ntrafo) << "Hz";
|
|
||||||
Logger::get().log(msg);
|
|
||||||
|
|
||||||
// Signal spectrum reconfiguration
|
|
||||||
emit spectrumConfigured();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
Spectrum::isInputReal() const {
|
|
||||||
switch (_input_type) {
|
|
||||||
case Config::Type_u8:
|
|
||||||
case Config::Type_s8:
|
|
||||||
case Config::Type_u16:
|
|
||||||
case Config::Type_s16:
|
|
||||||
case Config::Type_f32:
|
|
||||||
case Config::Type_f64:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
double
|
|
||||||
Spectrum::sampleRate() const {
|
|
||||||
return _sample_rate;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t
|
|
||||||
Spectrum::fftSize() const {
|
|
||||||
return _fft_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Buffer<double> &
|
|
||||||
Spectrum::spectrum() const {
|
|
||||||
return _spectrum;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Spectrum::handleBuffer(const RawBuffer &buffer, bool allow_overwrite)
|
|
||||||
{
|
|
||||||
double scale=1, offset=0;
|
|
||||||
switch (_input_type) {
|
|
||||||
case Config::Type_u8: scale = 1<<8; offset=-128; break;
|
|
||||||
case Config::Type_cu8: scale = 1<<8; offset=-128; break;
|
|
||||||
case Config::Type_s8: scale = 1<<8; offset=0; break;
|
|
||||||
case Config::Type_cs8: scale = 1<<8; offset=0; break;
|
|
||||||
case Config::Type_u16: scale = 1<<16; offset=-32768; break;
|
|
||||||
case Config::Type_cu16: scale = 1<<16; offset=-32768; break;
|
|
||||||
case Config::Type_s16: scale = 1<<16; offset=0; break;
|
|
||||||
case Config::Type_cs16: scale = 1<<16; offset=0; break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Dispatch by input type:
|
|
||||||
if (Config::Type_u8 == _input_type) {
|
|
||||||
Buffer<uint8_t> input(buffer);
|
|
||||||
for (size_t i=0; i<input.size(); i++, _sample_count++) {
|
|
||||||
// Skip until _N_samples is reached
|
|
||||||
if (_sample_count < _N_samples) { continue; }
|
|
||||||
// Copy value into buffer
|
|
||||||
_fft_buffer[_samples_left] = (double(input[i])+offset)/scale; _samples_left++;
|
|
||||||
// Once a FFT buffer is completed -> transform
|
|
||||||
if (_samples_left == _fft_size) { _updateFFT(); _samples_left=0; _sample_count=0; }
|
|
||||||
}
|
|
||||||
} else if (Config::Type_s8 == _input_type) {
|
|
||||||
Buffer<int8_t> input(buffer);
|
|
||||||
for (size_t i=0; i<input.size(); i++, _sample_count++) {
|
|
||||||
// Skip until _N_samples is reached
|
|
||||||
if (_sample_count < _N_samples) { continue; }
|
|
||||||
// Copy value into buffer
|
|
||||||
_fft_buffer[_samples_left] = (double(input[i])+offset)/scale; _samples_left++;
|
|
||||||
// Once a FFT buffer is completed -> transform
|
|
||||||
if (_samples_left == _fft_size) { _updateFFT(); _samples_left=0; _sample_count=0; }
|
|
||||||
}
|
|
||||||
} else if (Config::Type_u16 == _input_type) {
|
|
||||||
Buffer<uint16_t> input(buffer);
|
|
||||||
for (size_t i=0; i<input.size(); i++, _sample_count++) {
|
|
||||||
// Skip until _N_samples is reached
|
|
||||||
if (_sample_count < _N_samples) { continue; }
|
|
||||||
// Copy value into buffer
|
|
||||||
_fft_buffer[_samples_left] = (double(input[i])+offset)/scale; _samples_left++;
|
|
||||||
if (_samples_left == _fft_size) { _updateFFT(); _samples_left=0; _sample_count=0; }
|
|
||||||
}
|
|
||||||
} else if (Config::Type_s16 == _input_type) {
|
|
||||||
Buffer<int16_t> input(buffer);
|
|
||||||
for (size_t i=0; i<input.size(); i++, _sample_count++) {
|
|
||||||
// Skip until _N_samples is reached
|
|
||||||
if (_sample_count < _N_samples) { continue; }
|
|
||||||
// Copy value into buffer
|
|
||||||
_fft_buffer[_samples_left] = (double(input[i])+offset)/scale; _samples_left++;
|
|
||||||
if (_samples_left == _fft_size) { _updateFFT(); _samples_left=0; _sample_count=0; }
|
|
||||||
}
|
|
||||||
} else if (Config::Type_f32 == _input_type) {
|
|
||||||
Buffer<float> input(buffer);
|
|
||||||
for (size_t i=0; i<input.size(); i++, _sample_count++) {
|
|
||||||
// Skip until _N_samples is reached
|
|
||||||
if (_sample_count < _N_samples) { continue; }
|
|
||||||
// Copy value into buffer
|
|
||||||
_fft_buffer[_samples_left] = input[i]; _samples_left++;
|
|
||||||
if (_samples_left == _fft_size) { _updateFFT(); _samples_left=0; _sample_count=0; }
|
|
||||||
}
|
|
||||||
} else if (Config::Type_f64 == _input_type) {
|
|
||||||
Buffer<double> input(buffer);
|
|
||||||
for (size_t i=0; i<input.size(); i++, _sample_count++) {
|
|
||||||
// Skip until _N_samples is reached
|
|
||||||
if (_sample_count < _N_samples) { continue; }
|
|
||||||
// Copy value into buffer
|
|
||||||
_fft_buffer[_samples_left] = input[i]; _samples_left++;
|
|
||||||
if (_samples_left == _fft_size) { _updateFFT(); _samples_left=0; _sample_count=0;}
|
|
||||||
}
|
|
||||||
} else if (Config::Type_cu8 == _input_type) {
|
|
||||||
Buffer< std::complex<uint8_t> > input(buffer);
|
|
||||||
for (size_t i=0; i<input.size(); i++, _sample_count++) {
|
|
||||||
// Skip until _N_samples is reached
|
|
||||||
if (_sample_count < _N_samples) { continue; }
|
|
||||||
// Copy value into buffer
|
|
||||||
_fft_buffer[_samples_left] = std::complex<double>(
|
|
||||||
double(input[i].real())+offset,
|
|
||||||
double(input[i].imag())+offset)/scale;
|
|
||||||
_samples_left++;
|
|
||||||
if (_samples_left == _fft_size) { _updateFFT(); _samples_left=0; _sample_count=0; }
|
|
||||||
}
|
|
||||||
} else if (Config::Type_cs8 == _input_type) {
|
|
||||||
Buffer< std::complex<int8_t> > input(buffer);
|
|
||||||
for (size_t i=0; i<input.size(); i++, _sample_count++) {
|
|
||||||
// Skip until _N_samples is reached
|
|
||||||
if (_sample_count < _N_samples) { continue; }
|
|
||||||
// Copy value into buffer
|
|
||||||
_fft_buffer[_samples_left] = std::complex<double>(
|
|
||||||
double(input[i].real())+offset,
|
|
||||||
double(input[i].imag())+offset)/scale;
|
|
||||||
_samples_left++;
|
|
||||||
if (_samples_left == _fft_size) { _updateFFT(); _samples_left=0; _sample_count=0; }
|
|
||||||
}
|
|
||||||
} else if (Config::Type_cu16 == _input_type) {
|
|
||||||
Buffer< std::complex<uint16_t> > input(buffer);
|
|
||||||
for (size_t i=0; i<input.size(); i++, _sample_count++) {
|
|
||||||
// Skip until _N_samples is reached
|
|
||||||
if (_sample_count < _N_samples) { continue; }
|
|
||||||
// Copy value into buffer
|
|
||||||
_fft_buffer[_samples_left] = std::complex<double>(
|
|
||||||
double(input[i].real())+offset,double(input[i].imag())+offset)/scale;
|
|
||||||
_samples_left++;
|
|
||||||
if (_samples_left == _fft_size) { _updateFFT(); _samples_left=0; _sample_count=0; }
|
|
||||||
}
|
|
||||||
} else if (Config::Type_cs16 == _input_type) {
|
|
||||||
Buffer< std::complex<int16_t> > input(buffer);
|
|
||||||
for (size_t i=0; i<input.size(); i++, _sample_count++) {
|
|
||||||
// Skip until _N_samples is reached
|
|
||||||
if (_sample_count < _N_samples) { continue; }
|
|
||||||
// Copy value into buffer
|
|
||||||
_fft_buffer[_samples_left] = std::complex<double>(
|
|
||||||
double(input[i].real())+offset,double(input[i].imag())+offset)/scale;
|
|
||||||
_samples_left++;
|
|
||||||
if (_samples_left == _fft_size) { _updateFFT(); _samples_left=0; _sample_count=0; }
|
|
||||||
}
|
|
||||||
} else if (Config::Type_cf32 == _input_type) {
|
|
||||||
Buffer< std::complex<float> > input(buffer);
|
|
||||||
for (size_t i=0; i<input.size(); i++, _sample_count++) {
|
|
||||||
// Skip until _N_samples is reached
|
|
||||||
if (_sample_count < _N_samples) { continue; }
|
|
||||||
// Copy value into buffer
|
|
||||||
_fft_buffer[_samples_left] = input[i]; _samples_left++;
|
|
||||||
if (_samples_left == _fft_size) { _updateFFT(); _samples_left=0; _sample_count=0; }
|
|
||||||
}
|
|
||||||
} else if (Config::Type_cf64 == _input_type) {
|
|
||||||
Buffer< std::complex<double> > input(buffer);
|
|
||||||
for (size_t i=0; i<input.size(); i++, _sample_count++) {
|
|
||||||
// Skip until _N_samples is reached
|
|
||||||
if (_sample_count < _N_samples) { continue; }
|
|
||||||
// Copy value into buffer
|
|
||||||
_fft_buffer[_samples_left] = input[i]; _samples_left++;
|
|
||||||
if (_samples_left == _fft_size) { _updateFFT(); _samples_left=0; _sample_count=0; }
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
RuntimeError err;
|
|
||||||
err << "SpectrumView: Can not process buffer of type " << _input_type
|
|
||||||
<< ", unsupported type.";
|
|
||||||
throw err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
Spectrum::_updateFFT() {
|
|
||||||
// calc fft
|
|
||||||
fftw_execute(_plan);
|
|
||||||
// Update _compute with PSD
|
|
||||||
for(size_t i=0; i<_fft_size; i++) {
|
|
||||||
_compute[i] += std::real(std::conj(_fft_buffer[i])*_fft_buffer[i])/_Ntrafo;
|
|
||||||
}
|
|
||||||
_trafo_count++;
|
|
||||||
// If number of averages reached:
|
|
||||||
if (_trafo_count == _Ntrafo) {
|
|
||||||
// copy _compute to _spectrum and reset _compute to 0
|
|
||||||
for (size_t i=0; i<_fft_size; i++) {
|
|
||||||
_spectrum[i] = _compute[i];
|
|
||||||
_compute[i] = 0;
|
|
||||||
}
|
|
||||||
// done...
|
|
||||||
_trafo_count=0;
|
|
||||||
// signal spectrum update
|
|
||||||
emit spectrumUpdated();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,114 +0,0 @@
|
|||||||
#ifndef __SDR_GUI_SPECTRUM_HH__
|
|
||||||
#define __SDR_GUI_SPECTRUM_HH__
|
|
||||||
|
|
||||||
#include <QObject>
|
|
||||||
#include <fftw3.h>
|
|
||||||
#include "sdr.hh"
|
|
||||||
|
|
||||||
|
|
||||||
namespace sdr {
|
|
||||||
namespace gui {
|
|
||||||
|
|
||||||
|
|
||||||
class SpectrumProvider: public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
SpectrumProvider(QObject *parent=0);
|
|
||||||
|
|
||||||
virtual ~SpectrumProvider();
|
|
||||||
|
|
||||||
/** Returns true if the input is real. */
|
|
||||||
virtual bool isInputReal() const = 0;
|
|
||||||
|
|
||||||
/** Retunrs the sample rate. */
|
|
||||||
virtual double sampleRate() const = 0;
|
|
||||||
|
|
||||||
/** Returns the FFT size. */
|
|
||||||
virtual size_t fftSize() const = 0;
|
|
||||||
|
|
||||||
/** Returns the current spectrum. */
|
|
||||||
virtual const Buffer<double> &spectrum() const = 0;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
/** Gets emitted once the spectrum was updated. */
|
|
||||||
void spectrumUpdated();
|
|
||||||
/** Gets emitted once the spectrum was reconfigured. */
|
|
||||||
void spectrumConfigured();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** Calculates the power spectrum of a singnal. The spectrum gets updated with a specified
|
|
||||||
* rate (if possible). */
|
|
||||||
class Spectrum : public SpectrumProvider, public SinkBase
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** Constructs a new spectrum recorder (sink).
|
|
||||||
* @param rrate Specifies the desired refresh-rate of the spectrum.
|
|
||||||
* @param fftsize Specifies the size (bins) of the spectrum.
|
|
||||||
* @param max_avg Specifies the max. number of averages to take.
|
|
||||||
* @param parent Specifies the parent of the @c Spectrum instance. */
|
|
||||||
explicit Spectrum(double rrate=2, size_t fftsize=1024, size_t max_avg=1, QObject *parent = 0);
|
|
||||||
|
|
||||||
/** Destructor. */
|
|
||||||
virtual ~Spectrum();
|
|
||||||
|
|
||||||
/** Configures the Sink. */
|
|
||||||
virtual void config(const Config &src_cfg);
|
|
||||||
|
|
||||||
/** Receives the data stream and updates the _fft_buffer. */
|
|
||||||
virtual void handleBuffer(const RawBuffer &buffer, bool allow_overwrite);
|
|
||||||
|
|
||||||
/** Returns true if the input is real. */
|
|
||||||
bool isInputReal() const;
|
|
||||||
|
|
||||||
/** Retunrs the sample rate. */
|
|
||||||
double sampleRate() const;
|
|
||||||
|
|
||||||
/** Returns the FFT size. */
|
|
||||||
size_t fftSize() const;
|
|
||||||
|
|
||||||
/** Returns the current spectrum. */
|
|
||||||
const Buffer<double> &spectrum() const;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/** Updates the FFT in the _compute buffer. */
|
|
||||||
void _updateFFT();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/** The desired refresh rate for the spectrum plot. */
|
|
||||||
double _rrate;
|
|
||||||
/** Size of the FFT (resolution). */
|
|
||||||
size_t _fft_size;
|
|
||||||
/** Input and compute buffer for the FFT. */
|
|
||||||
Buffer< std::complex<double> > _fft_buffer;
|
|
||||||
/** Summation buffer of the spectrum. */
|
|
||||||
Buffer< double > _compute;
|
|
||||||
/** The current spectrum. */
|
|
||||||
Buffer< double > _spectrum;
|
|
||||||
/** Specifies the number of received samples since last FFT. */
|
|
||||||
size_t _sample_count;
|
|
||||||
/** Specifies the number of samples to drop before performing a FFT. */
|
|
||||||
size_t _N_samples;
|
|
||||||
/** Number of transforms in the _compute buffer. */
|
|
||||||
size_t _trafo_count;
|
|
||||||
/** Max. number of transforms. */
|
|
||||||
size_t _Ntrafo;
|
|
||||||
/** Number of samples, left in the buffer by the previous input. */
|
|
||||||
size_t _samples_left;
|
|
||||||
/** The input type. */
|
|
||||||
Config::Type _input_type;
|
|
||||||
/** The sample-rate of the input. */
|
|
||||||
double _sample_rate;
|
|
||||||
/** The FFTW plan. */
|
|
||||||
fftw_plan _plan;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // SPECTRUM_HH
|
|
||||||
@ -1,192 +0,0 @@
|
|||||||
#include "spectrumview.hh"
|
|
||||||
#include <QPaintEvent>
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QPaintEngine>
|
|
||||||
#include <QResizeEvent>
|
|
||||||
#include <QFontMetrics>
|
|
||||||
|
|
||||||
using namespace sdr;
|
|
||||||
using namespace sdr::gui;
|
|
||||||
|
|
||||||
SpectrumView::SpectrumView(SpectrumProvider *spectrum, QWidget *parent)
|
|
||||||
: QWidget(parent), _spectrum(spectrum), _numXTicks(11), _numYTicks(6),
|
|
||||||
_maxF(std::numeric_limits<double>::infinity()), _mindB(-60)
|
|
||||||
{
|
|
||||||
// Assemble pens
|
|
||||||
_axisPen = QPen(Qt::black);
|
|
||||||
_axisPen.setWidth(3);
|
|
||||||
_axisPen.setStyle(Qt::SolidLine);
|
|
||||||
_graphPen = QPen(Qt::blue);
|
|
||||||
_axisPen.setWidth(2);
|
|
||||||
_axisPen.setStyle(Qt::SolidLine);
|
|
||||||
|
|
||||||
// Connect to update signal
|
|
||||||
QObject::connect(_spectrum, SIGNAL(spectrumUpdated()), this, SLOT(update()));
|
|
||||||
QObject::connect(_spectrum, SIGNAL(spectrumConfigured()), this, SLOT(update()));
|
|
||||||
}
|
|
||||||
|
|
||||||
SpectrumView::~SpectrumView() {
|
|
||||||
// pass...
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
SpectrumView::mouseReleaseEvent(QMouseEvent *evt) {
|
|
||||||
// If event is accepted -> determine frequency
|
|
||||||
if ((evt->pos().x() < _plotArea.left()) || (evt->pos().x() > _plotArea.right())) { return; }
|
|
||||||
double f=0;
|
|
||||||
|
|
||||||
if (_spectrum->isInputReal()) {
|
|
||||||
double dfdx = _spectrum->sampleRate()/(2*_plotArea.width());
|
|
||||||
f = dfdx * (evt->pos().x()-_plotArea.left());
|
|
||||||
} else {
|
|
||||||
double dfdx = _spectrum->sampleRate()/_plotArea.width();
|
|
||||||
f = -_spectrum->sampleRate()/2 + dfdx * (evt->pos().x()-_plotArea.left());
|
|
||||||
}
|
|
||||||
|
|
||||||
emit click(f);
|
|
||||||
|
|
||||||
// Forward to default impl:
|
|
||||||
QWidget::mouseReleaseEvent(evt);
|
|
||||||
// redraw
|
|
||||||
update();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
SpectrumView::resizeEvent(QResizeEvent *evt) {
|
|
||||||
// First, forward to default impl.
|
|
||||||
QWidget::resizeEvent(evt);
|
|
||||||
|
|
||||||
// If resize event was accepted, recalc plot area
|
|
||||||
if (evt->isAccepted()) {
|
|
||||||
QSize ws = evt->size();
|
|
||||||
QFontMetrics fm(_axisFont);
|
|
||||||
int leftMargin = 15 + 6*fm.width("x");
|
|
||||||
int topMargin = 10;
|
|
||||||
int rightMargin = 3*fm.width("x");
|
|
||||||
int bottomMargin = 15 + 2*fm.xHeight();
|
|
||||||
_plotArea = QRect(
|
|
||||||
leftMargin, topMargin,
|
|
||||||
ws.width()-leftMargin-rightMargin,
|
|
||||||
ws.height()-bottomMargin-topMargin);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
SpectrumView::paintEvent(QPaintEvent *evt) {
|
|
||||||
QPainter painter(this);
|
|
||||||
painter.setRenderHint(QPainter::Antialiasing);
|
|
||||||
painter.save();
|
|
||||||
|
|
||||||
// Clip region to update
|
|
||||||
painter.setClipRect(evt->rect());
|
|
||||||
|
|
||||||
// Draw background
|
|
||||||
painter.fillRect(QRect(0,0, this->width(), this->height()), QColor(Qt::white));
|
|
||||||
|
|
||||||
_drawAxis(painter);
|
|
||||||
|
|
||||||
_drawGraph(painter);
|
|
||||||
|
|
||||||
painter.restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
SpectrumView::_drawGraph(QPainter &painter) {
|
|
||||||
// Draw spectrum
|
|
||||||
painter.save();
|
|
||||||
painter.setClipRect(_plotArea);
|
|
||||||
painter.setPen(_graphPen);
|
|
||||||
double height = _plotArea.height();
|
|
||||||
double width = _plotArea.width();
|
|
||||||
|
|
||||||
if (_spectrum->isInputReal()) {
|
|
||||||
double df = double(2*width)/_spectrum->fftSize();
|
|
||||||
double dh = double(height)/_mindB;
|
|
||||||
int xoff = _plotArea.x();
|
|
||||||
int yoff = _plotArea.y();
|
|
||||||
for (size_t i=1; i<_spectrum->fftSize()/2; i++) {
|
|
||||||
int x1 = xoff+df*(i-1), x2 = xoff+df*(i);
|
|
||||||
int y1 = yoff+dh*(10*log10(_spectrum->spectrum()[i-1])-10*log10(_spectrum->fftSize()));
|
|
||||||
int y2 = yoff+dh*(10*log10(_spectrum->spectrum()[i])-10*log10(_spectrum->fftSize()));
|
|
||||||
painter.drawLine(x1, y1, x2, y2);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
double df = double(width)/_spectrum->fftSize();
|
|
||||||
double dh = double(height)/_mindB;
|
|
||||||
int xoff = _plotArea.x();
|
|
||||||
int yoff = _plotArea.y();
|
|
||||||
for (size_t i=1; i<_spectrum->fftSize(); i++) {
|
|
||||||
int idx1 = (_spectrum->fftSize()/2+i-1) % _spectrum->fftSize();
|
|
||||||
int idx2 = (_spectrum->fftSize()/2+i) % _spectrum->fftSize();
|
|
||||||
int x1 = xoff+df*(i-1), x2 = xoff+df*(i);
|
|
||||||
int y1 = yoff+dh*(10*log10(_spectrum->spectrum()[idx1])-10*log10(_spectrum->fftSize()));
|
|
||||||
int y2 = yoff+dh*(10*log10(_spectrum->spectrum()[idx2])-10*log10(_spectrum->fftSize()));
|
|
||||||
painter.drawLine(x1,y1, x2,y2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
painter.restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
SpectrumView::_drawAxis(QPainter &painter) {
|
|
||||||
painter.save();
|
|
||||||
// Get some sizes
|
|
||||||
double height = _plotArea.height();
|
|
||||||
double width = _plotArea.width();
|
|
||||||
|
|
||||||
painter.setPen(_axisPen);
|
|
||||||
|
|
||||||
// Axes
|
|
||||||
painter.drawLine(_plotArea.topLeft(), _plotArea.bottomLeft());
|
|
||||||
painter.drawLine(_plotArea.bottomLeft(), _plotArea.bottomRight());
|
|
||||||
|
|
||||||
// draw y-ticks & labels
|
|
||||||
double dh = double(height)/_mindB;
|
|
||||||
double x = _plotArea.topLeft().x();
|
|
||||||
double y = _plotArea.topLeft().y();
|
|
||||||
double ddB = _mindB/(_numYTicks-1);
|
|
||||||
QFontMetrics fm(_axisFont); QRect bb; double db=0;
|
|
||||||
for (size_t i=0; i<_numYTicks; i++, db+=ddB) {
|
|
||||||
QString label = QString("%1").arg(db);
|
|
||||||
bb = fm.boundingRect(label);
|
|
||||||
y = _plotArea.topLeft().y() + db*dh;
|
|
||||||
bb.translate(x-8-bb.width(),y+fm.strikeOutPos());
|
|
||||||
painter.drawLine(x-5,y, x,y);
|
|
||||||
painter.drawText(bb, label);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Draw x ticks & labels (real spectrum)
|
|
||||||
if (_spectrum->isInputReal()) {
|
|
||||||
double dx = double(width)/(_numXTicks-1);
|
|
||||||
double maxF = std::min(_maxF, _spectrum->sampleRate()/2);
|
|
||||||
double df = maxF/(_numXTicks-1);
|
|
||||||
double x = _plotArea.bottomLeft().x();
|
|
||||||
double y = _plotArea.bottomLeft().y();
|
|
||||||
double f = 0;
|
|
||||||
for (size_t i=0; i<11; i++, f +=df, x += dx) {
|
|
||||||
QString label = QString("%1").arg(f);
|
|
||||||
bb = fm.boundingRect(label);
|
|
||||||
bb.translate(x-bb.width()/2,y+8+fm.overlinePos());
|
|
||||||
painter.drawLine(x,y, x,y+5);
|
|
||||||
painter.drawText(bb, label);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
double dx = double(width)/(_numXTicks-1);
|
|
||||||
double df = _spectrum->sampleRate()/(_numXTicks-1);
|
|
||||||
double x = _plotArea.bottomLeft().x();
|
|
||||||
double y = _plotArea.bottomLeft().y();
|
|
||||||
double f = -_spectrum->sampleRate()/2;
|
|
||||||
for (size_t i=0; i<_numXTicks; i++, f +=df, x += dx) {
|
|
||||||
QString label = QString("%1").arg(f);
|
|
||||||
bb = fm.boundingRect(label);
|
|
||||||
bb.translate(x-bb.width()/2,y+8+fm.overlinePos());
|
|
||||||
painter.drawLine(x,y, x,y+5);
|
|
||||||
painter.drawText(bb, label);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
painter.restore();
|
|
||||||
}
|
|
||||||
@ -1,74 +0,0 @@
|
|||||||
#ifndef __SDR_GUI_SPECTRUMVIEW_HH__
|
|
||||||
#define __SDR_GUI_SPECTRUMVIEW_HH__
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QPen>
|
|
||||||
|
|
||||||
#include "sdr.hh"
|
|
||||||
#include "spectrum.hh"
|
|
||||||
|
|
||||||
|
|
||||||
namespace sdr {
|
|
||||||
namespace gui {
|
|
||||||
|
|
||||||
/** A simple widget to display a PSD with live update. */
|
|
||||||
class SpectrumView: public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** @param rrate Specifies the (approx) refreshrate of the FFT plot. */
|
|
||||||
explicit SpectrumView(SpectrumProvider *spectrum, QWidget *parent=0);
|
|
||||||
|
|
||||||
inline size_t numXTicks() const { return _numXTicks; }
|
|
||||||
inline void setNumXTicks(size_t N) { _numXTicks=N; update(); }
|
|
||||||
|
|
||||||
inline size_t numYTicks() const { return _numYTicks; }
|
|
||||||
inline void setNumYTicks(size_t N) { _numYTicks = N; }
|
|
||||||
|
|
||||||
inline double mindB() const { return _mindB; }
|
|
||||||
inline void setMindB(double mindB) { _mindB = mindB; }
|
|
||||||
|
|
||||||
/// Destructor.
|
|
||||||
virtual ~SpectrumView();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void click(double f);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/** Handles mouse clicks. */
|
|
||||||
virtual void mouseReleaseEvent(QMouseEvent *evt);
|
|
||||||
|
|
||||||
/** Updates _plotArea on resize events. */
|
|
||||||
virtual void resizeEvent(QResizeEvent *evt);
|
|
||||||
/** Draws the spectrum. */
|
|
||||||
virtual void paintEvent(QPaintEvent *evt);
|
|
||||||
/** Draws the spectrum graph */
|
|
||||||
void _drawGraph(QPainter &painter);
|
|
||||||
/** Draw the axes, ticks and labels. */
|
|
||||||
void _drawAxis(QPainter &painter);
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/** Holds a weak reference to the spectrum recorder object. */
|
|
||||||
SpectrumProvider *_spectrum;
|
|
||||||
/// The font being used for axis labels
|
|
||||||
QFont _axisFont;
|
|
||||||
/// The plot area
|
|
||||||
QRect _plotArea;
|
|
||||||
/// Axis pen.
|
|
||||||
QPen _axisPen;
|
|
||||||
/// The pen used to draw the graph.
|
|
||||||
QPen _graphPen;
|
|
||||||
|
|
||||||
size_t _numXTicks;
|
|
||||||
size_t _numYTicks;
|
|
||||||
double _maxF;
|
|
||||||
/** Lower bound of the PSD plot. */
|
|
||||||
double _mindB;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __SDR_GUI_SPECTRUMVIEW_HH__
|
|
||||||
@ -1,212 +0,0 @@
|
|||||||
#include "waterfallview.hh"
|
|
||||||
#include <QPainter>
|
|
||||||
#include <QPaintEvent>
|
|
||||||
#include <QDebug>
|
|
||||||
|
|
||||||
using namespace sdr;
|
|
||||||
using namespace sdr::gui;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* ****************************************************************************************** *
|
|
||||||
* Implementation of ColorMap
|
|
||||||
* ****************************************************************************************** */
|
|
||||||
ColorMap::ColorMap(double min, double max)
|
|
||||||
: _min(min), _max(max)
|
|
||||||
{
|
|
||||||
// pass...
|
|
||||||
}
|
|
||||||
|
|
||||||
ColorMap::~ColorMap() {
|
|
||||||
// pass...
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ****************************************************************************************** *
|
|
||||||
* Implementation of GrayScaleColorMap
|
|
||||||
* ****************************************************************************************** */
|
|
||||||
GrayScaleColorMap::GrayScaleColorMap(double min, double max)
|
|
||||||
: ColorMap(min, max)
|
|
||||||
{
|
|
||||||
// pass...
|
|
||||||
}
|
|
||||||
|
|
||||||
GrayScaleColorMap::~GrayScaleColorMap() {
|
|
||||||
// pass...
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor
|
|
||||||
GrayScaleColorMap::map(const double &value) {
|
|
||||||
int h = 255*value;
|
|
||||||
return QColor(h,h,h);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ****************************************************************************************** *
|
|
||||||
* Implementation of LinearColorMap
|
|
||||||
* ****************************************************************************************** */
|
|
||||||
LinearColorMap::LinearColorMap(const QVector<QColor> &colors, double min, double max)
|
|
||||||
: ColorMap(min, max), _colors(colors)
|
|
||||||
{
|
|
||||||
// pass...
|
|
||||||
}
|
|
||||||
|
|
||||||
LinearColorMap::~LinearColorMap() {
|
|
||||||
// pass...
|
|
||||||
}
|
|
||||||
|
|
||||||
QColor
|
|
||||||
LinearColorMap::map(const double &value) {
|
|
||||||
// Calc indices
|
|
||||||
double upper = ceil(value*(_colors.size()-1));
|
|
||||||
double lower = floor(value*(_colors.size()-1));
|
|
||||||
int idx = int(lower);
|
|
||||||
if (lower == upper) { return _colors[idx]; }
|
|
||||||
double dv = upper-(value*(_colors.size()-1));
|
|
||||||
double dr = dv * (_colors[idx].red() - _colors[idx+1].red());
|
|
||||||
double dg = dv * (_colors[idx].green() - _colors[idx+1].green());
|
|
||||||
double db = dv * (_colors[idx].blue() - _colors[idx+1].blue());
|
|
||||||
return QColor(int(_colors[idx+1].red()+dr),
|
|
||||||
int(_colors[idx+1].green()+dg),
|
|
||||||
int(_colors[idx+1].blue()+db));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ****************************************************************************************** *
|
|
||||||
* Implementation of WaterFallView
|
|
||||||
* ****************************************************************************************** */
|
|
||||||
WaterFallView::WaterFallView(SpectrumProvider *spectrum, size_t hist, Direction dir, QWidget *parent)
|
|
||||||
: QWidget(parent), _spectrum(spectrum), _N(_spectrum->fftSize()), _M(hist), _dir(dir),
|
|
||||||
_waterfall(_N,_M)
|
|
||||||
{
|
|
||||||
switch (dir) {
|
|
||||||
case BOTTOM_UP:
|
|
||||||
case TOP_DOWN:
|
|
||||||
setMinimumHeight(hist);
|
|
||||||
break;
|
|
||||||
case LEFT_RIGHT:
|
|
||||||
case RIGHT_LEFT:
|
|
||||||
setMinimumWidth(hist);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill waterfall pixmap
|
|
||||||
_waterfall.fill(Qt::black);
|
|
||||||
// Create color map
|
|
||||||
//_colorMap = new GrayScaleColorMap(-120, 0);
|
|
||||||
QVector<QColor> colors; colors.reserve(4);
|
|
||||||
colors << Qt::black << Qt::red << Qt::yellow << Qt::white;
|
|
||||||
_colorMap = new LinearColorMap(colors, -60, 0);
|
|
||||||
|
|
||||||
// Get notified once a new spectrum is available:
|
|
||||||
QObject::connect(_spectrum, SIGNAL(spectrumUpdated()), this, SLOT(_onSpectrumUpdated()));
|
|
||||||
QObject::connect(_spectrum, SIGNAL(spectrumConfigured()), this, SLOT(_onSpectrumConfigure()));
|
|
||||||
}
|
|
||||||
|
|
||||||
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++) {
|
|
||||||
int idx = (_spectrum->fftSize()/2+i) % _spectrum->fftSize();
|
|
||||||
double value;
|
|
||||||
if ((TOP_DOWN == _dir) || (LEFT_RIGHT == _dir)) {
|
|
||||||
value = 10*log10(_spectrum->spectrum()[_spectrum->fftSize()-1-idx])-10*log10(_N);
|
|
||||||
} else {
|
|
||||||
value = 10*log10(_spectrum->spectrum()[idx])-10*log10(_N);
|
|
||||||
}
|
|
||||||
// Reset NaNs
|
|
||||||
if (value != value) { value = std::numeric_limits<double>::min(); }
|
|
||||||
painter.setPen((*_colorMap)(value));
|
|
||||||
painter.drawPoint(i, _M-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Trigger update
|
|
||||||
this->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
WaterFallView::_onSpectrumConfigure() {
|
|
||||||
// Update spectrum width
|
|
||||||
_N = _spectrum->fftSize();
|
|
||||||
// Replace WaterFall pixmap
|
|
||||||
_waterfall = QPixmap(_N, _M);
|
|
||||||
// Fill waterfall pixmap
|
|
||||||
_waterfall.fill(Qt::black);
|
|
||||||
|
|
||||||
// Trigger update
|
|
||||||
this->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
WaterFallView::mouseReleaseEvent(QMouseEvent *evt) {
|
|
||||||
// If event is accepted -> determine frequency
|
|
||||||
if ((evt->pos().x() < 0) || (evt->pos().x() > this->width())) { return; }
|
|
||||||
double f=0;
|
|
||||||
|
|
||||||
if ((BOTTOM_UP == _dir) || (TOP_DOWN == _dir)) {
|
|
||||||
double dfdx = _spectrum->sampleRate()/this->width();
|
|
||||||
f = -_spectrum->sampleRate()/2 + dfdx*evt->pos().x();
|
|
||||||
emit click(f);
|
|
||||||
} else {
|
|
||||||
double dfdx = _spectrum->sampleRate()/this->height();
|
|
||||||
f = -_spectrum->sampleRate()/2 + dfdx*evt->pos().y();
|
|
||||||
emit click(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Forward to default impl:
|
|
||||||
QWidget::mouseReleaseEvent(evt);
|
|
||||||
|
|
||||||
// redraw
|
|
||||||
this->update();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
WaterFallView::paintEvent(QPaintEvent *evt)
|
|
||||||
{
|
|
||||||
QWidget::paintEvent(evt);
|
|
||||||
|
|
||||||
QPainter painter(this);
|
|
||||||
|
|
||||||
painter.save();
|
|
||||||
painter.setRenderHints(QPainter::SmoothPixmapTransform|QPainter::Antialiasing);
|
|
||||||
// Assemble trafo
|
|
||||||
QTransform trafo;
|
|
||||||
switch (_dir) {
|
|
||||||
case BOTTOM_UP:
|
|
||||||
trafo.scale(this->width()/qreal(_N), this->height()/qreal(_M));
|
|
||||||
break;
|
|
||||||
case LEFT_RIGHT:
|
|
||||||
trafo.scale(this->width()/qreal(_M), this->height()/qreal(_N));
|
|
||||||
trafo.translate(_M,0);
|
|
||||||
trafo.rotate(90);
|
|
||||||
break;
|
|
||||||
case TOP_DOWN:
|
|
||||||
trafo.scale(this->width()/qreal(_N), this->height()/qreal(_M));
|
|
||||||
trafo.translate(_N,_M);
|
|
||||||
trafo.rotate(180);
|
|
||||||
break;
|
|
||||||
case RIGHT_LEFT:
|
|
||||||
trafo.scale(this->width()/qreal(_M), this->height()/qreal(_N));
|
|
||||||
trafo.translate(0,_N);
|
|
||||||
trafo.rotate(270);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
painter.setTransform(trafo);
|
|
||||||
QRect exposedRect = painter.matrix().inverted()
|
|
||||||
.mapRect(evt->rect())
|
|
||||||
.adjusted(-1, -1, 1, 1);
|
|
||||||
// the adjust is to account for half pixels along edges
|
|
||||||
painter.drawPixmap(exposedRect, _waterfall, exposedRect);
|
|
||||||
//painter.drawPixmap(0,0, _waterfall);
|
|
||||||
painter.restore();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,119 +0,0 @@
|
|||||||
#ifndef __SDR_GUI_WATERFALLVIEW_HH__
|
|
||||||
#define __SDR_GUI_WATERFALLVIEW_HH__
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QImage>
|
|
||||||
#include "spectrum.hh"
|
|
||||||
|
|
||||||
|
|
||||||
namespace sdr {
|
|
||||||
namespace gui {
|
|
||||||
|
|
||||||
/** Interface for all color maps. */
|
|
||||||
class ColorMap
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
/** Hidden constructor. */
|
|
||||||
ColorMap(double min, double max);
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** Destructor. */
|
|
||||||
virtual ~ColorMap();
|
|
||||||
|
|
||||||
/** Maps a value to a color. */
|
|
||||||
inline QColor operator()(const double &value) {
|
|
||||||
if (value > _max) { return this->map(1); }
|
|
||||||
if (value < _min) { return this->map(0); }
|
|
||||||
return this->map((value-_min)/(_max-_min));
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Maps a value on the interval [0,1] to a color.
|
|
||||||
* Needs to be implemented by all sub-classes. */
|
|
||||||
virtual QColor map(const double &value) = 0;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/** Minimum value. */
|
|
||||||
double _min;
|
|
||||||
/** Maximum value. */
|
|
||||||
double _max;
|
|
||||||
};
|
|
||||||
|
|
||||||
/** 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 [min, max]
|
|
||||||
* to a gray-scale. */
|
|
||||||
GrayScaleColorMap(double min, double max);
|
|
||||||
/** Destructor. */
|
|
||||||
virtual ~GrayScaleColorMap();
|
|
||||||
/** Implements the color mapping. */
|
|
||||||
virtual QColor map(const double &value);
|
|
||||||
};
|
|
||||||
|
|
||||||
/** A linear interpolating color map. */
|
|
||||||
class LinearColorMap: public ColorMap {
|
|
||||||
public:
|
|
||||||
LinearColorMap(const QVector<QColor> &colors, double min, double max);
|
|
||||||
/** Destructor. */
|
|
||||||
virtual ~LinearColorMap();
|
|
||||||
virtual QColor map(const double &value);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QVector<QColor> _colors;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/** A simple waterfall display of the spectrogram. */
|
|
||||||
class WaterFallView : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
typedef enum {
|
|
||||||
BOTTOM_UP, TOP_DOWN, LEFT_RIGHT, RIGHT_LEFT
|
|
||||||
} Direction;
|
|
||||||
|
|
||||||
public:
|
|
||||||
/** Constructor.
|
|
||||||
* @param spectrum Specifies the spectrum sink.
|
|
||||||
* @param hist Specifies the number of PSDs to display.
|
|
||||||
* @param parent The parent widget. */
|
|
||||||
explicit WaterFallView(SpectrumProvider *spectrum, size_t hist=100, Direction dir=BOTTOM_UP, QWidget *parent = 0);
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void click(double f);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/** Handles mouse clicks. */
|
|
||||||
virtual void mouseReleaseEvent(QMouseEvent *evt);
|
|
||||||
|
|
||||||
/** Draws the scaled waterfall spectrogram. */
|
|
||||||
virtual void paintEvent(QPaintEvent *evt);
|
|
||||||
|
|
||||||
protected slots:
|
|
||||||
/** Gets called once a new PSD is available. */
|
|
||||||
void _onSpectrumUpdated();
|
|
||||||
/** Gets called once the spectrum provider gets reconfigured. */
|
|
||||||
void _onSpectrumConfigure();
|
|
||||||
|
|
||||||
protected:
|
|
||||||
/** The spectrum sink. */
|
|
||||||
SpectrumProvider *_spectrum;
|
|
||||||
/** The size of the spectrum. */
|
|
||||||
size_t _N;
|
|
||||||
/** "Height of the spectrum. */
|
|
||||||
size_t _M;
|
|
||||||
/** Specifies the direction of the waterfall. */
|
|
||||||
Direction _dir;
|
|
||||||
/** The waterfall spectrogram. */
|
|
||||||
QPixmap _waterfall;
|
|
||||||
/** The color map to be used. */
|
|
||||||
ColorMap *_colorMap;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // WATERFALLVIEW_HH
|
|
||||||
Loading…
Reference in New Issue