Spectrum frequency zoom: UI implementation and messaging to spectrum vis

This commit is contained in:
f4exb 2021-02-15 13:49:51 +01:00
parent 166089a8bd
commit ab0a7f2e60
6 changed files with 135 additions and 26 deletions

View File

@ -26,7 +26,7 @@ class GLSpectrumInterface
public: public:
GLSpectrumInterface() {} GLSpectrumInterface() {}
virtual ~GLSpectrumInterface() {} virtual ~GLSpectrumInterface() {}
virtual void newSpectrum(const std::vector<Real>& spectrum, int fftSize) virtual void newSpectrum(const Real* spectrum, int fftSize)
{ {
(void) spectrum; (void) spectrum;
(void) fftSize; (void) fftSize;

View File

@ -44,6 +44,7 @@ MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgConfigureScalingFactor, Message)
MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgConfigureWSpectrumOpenClose, Message) MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgConfigureWSpectrumOpenClose, Message)
MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgConfigureWSpectrum, Message) MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgConfigureWSpectrum, Message)
MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgStartStop, Message) MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgStartStop, Message)
MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgFrequencyZooming, Message)
const Real SpectrumVis::m_mult = (10.0f / log2(10.0f)); const Real SpectrumVis::m_mult = (10.0f / log2(10.0f));
@ -57,6 +58,8 @@ SpectrumVis::SpectrumVis(Real scalef) :
m_psd(MAX_FFT_SIZE), m_psd(MAX_FFT_SIZE),
m_fftBufferFill(0), m_fftBufferFill(0),
m_needMoreSamples(false), m_needMoreSamples(false),
m_frequencyZoomFactor(1.0f),
m_frequencyZoomPos(0.5f),
m_scalef(scalef), m_scalef(scalef),
m_glSpectrum(nullptr), m_glSpectrum(nullptr),
m_specMax(0.0f), m_specMax(0.0f),
@ -121,6 +124,10 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length)
Complex c; Complex c;
Real v; Real v;
int fftMin = (m_frequencyZoomFactor == 1.0f) ?
0 : (m_frequencyZoomPos - (0.5f / m_frequencyZoomFactor)) * m_settings.m_fftSize;
int fftMax = (m_frequencyZoomFactor == 1.0f) ?
m_settings.m_fftSize : (m_frequencyZoomPos - (0.5f / m_frequencyZoomFactor)) * m_settings.m_fftSize;
if (m_settings.m_averagingMode == GLSpectrumSettings::AvgModeNone) if (m_settings.m_averagingMode == GLSpectrumSettings::AvgModeNone)
{ {
@ -140,7 +147,7 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length)
// send new data to visualisation // send new data to visualisation
if (m_glSpectrum) { if (m_glSpectrum) {
m_glSpectrum->newSpectrum(m_powerSpectrum, m_settings.m_fftSize); m_glSpectrum->newSpectrum(m_powerSpectrum.data(), m_settings.m_fftSize);
} }
// web socket spectrum connections // web socket spectrum connections
@ -176,7 +183,7 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length)
// send new data to visualisation // send new data to visualisation
if (m_glSpectrum) { if (m_glSpectrum) {
m_glSpectrum->newSpectrum(m_powerSpectrum, m_settings.m_fftSize); m_glSpectrum->newSpectrum(m_powerSpectrum.data(), m_settings.m_fftSize);
} }
// web socket spectrum connections // web socket spectrum connections
@ -223,7 +230,7 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length)
{ {
// send new data to visualisation // send new data to visualisation
if (m_glSpectrum) { if (m_glSpectrum) {
m_glSpectrum->newSpectrum(m_powerSpectrum, m_settings.m_fftSize); m_glSpectrum->newSpectrum(m_powerSpectrum.data(), m_settings.m_fftSize);
} }
// web socket spectrum connections // web socket spectrum connections
@ -269,7 +276,7 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length)
{ {
// send new data to visualisation // send new data to visualisation
if (m_glSpectrum) { if (m_glSpectrum) {
m_glSpectrum->newSpectrum(m_powerSpectrum, m_settings.m_fftSize); m_glSpectrum->newSpectrum(m_powerSpectrum.data(), m_settings.m_fftSize);
} }
// web socket spectrum connections // web socket spectrum connections
@ -374,7 +381,7 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV
// send new data to visualisation // send new data to visualisation
if (m_glSpectrum) { if (m_glSpectrum) {
m_glSpectrum->newSpectrum(m_powerSpectrum, m_settings.m_fftSize); m_glSpectrum->newSpectrum(m_powerSpectrum.data(), m_settings.m_fftSize);
} }
// web socket spectrum connections // web socket spectrum connections
@ -433,7 +440,7 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV
// send new data to visualisation // send new data to visualisation
if (m_glSpectrum) { if (m_glSpectrum) {
m_glSpectrum->newSpectrum(m_powerSpectrum, m_settings.m_fftSize); m_glSpectrum->newSpectrum(m_powerSpectrum.data(), m_settings.m_fftSize);
} }
// web socket spectrum connections // web socket spectrum connections
@ -512,7 +519,7 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV
// send new data to visualisation // send new data to visualisation
if (m_glSpectrum) { if (m_glSpectrum) {
m_glSpectrum->newSpectrum(m_powerSpectrum, m_settings.m_fftSize); m_glSpectrum->newSpectrum(m_powerSpectrum.data(), m_settings.m_fftSize);
} }
// web socket spectrum connections // web socket spectrum connections
@ -590,7 +597,7 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV
// send new data to visualisation // send new data to visualisation
if (m_glSpectrum) { if (m_glSpectrum) {
m_glSpectrum->newSpectrum(m_powerSpectrum, m_settings.m_fftSize); m_glSpectrum->newSpectrum(m_powerSpectrum.data(), m_settings.m_fftSize);
} }
// web socket spectrum connections // web socket spectrum connections
@ -694,7 +701,13 @@ bool SpectrumVis::handleMessage(const Message& message)
{ {
MsgStartStop& cmd = (MsgStartStop&) message; MsgStartStop& cmd = (MsgStartStop&) message;
setRunning(cmd.getStartStop()); setRunning(cmd.getStartStop());
return true;
}
else if (MsgFrequencyZooming::match(message))
{
MsgFrequencyZooming& cmd = (MsgFrequencyZooming&) message;
m_frequencyZoomFactor = cmd.getFrequencyZoomFactor();
m_frequencyZoomPos = cmd.getFrequencyZoomPos();
return true; return true;
} }
else else

View File

@ -107,6 +107,28 @@ public:
{} {}
}; };
class MsgFrequencyZooming : public Message {
MESSAGE_CLASS_DECLARATION
public:
float getFrequencyZoomFactor() const { return m_frequencyZoomFactor; }
float getFrequencyZoomPos() const { return m_frequencyZoomPos; }
static MsgFrequencyZooming* create(float frequencyZoomFactor, float frequencyZoomPos) {
return new MsgFrequencyZooming(frequencyZoomFactor, frequencyZoomPos);
}
private:
float m_frequencyZoomFactor;
float m_frequencyZoomPos;
MsgFrequencyZooming(float frequencyZoomFactor, float frequencyZoomPos) :
Message(),
m_frequencyZoomFactor(frequencyZoomFactor),
m_frequencyZoomPos(frequencyZoomPos)
{ }
};
enum AvgMode enum AvgMode
{ {
AvgModeNone, AvgModeNone,
@ -198,6 +220,9 @@ private:
int m_fftBufferFill; int m_fftBufferFill;
bool m_needMoreSamples; bool m_needMoreSamples;
float m_frequencyZoomFactor;
float m_frequencyZoomPos;
Real m_scalef; Real m_scalef;
GLSpectrumInterface* m_glSpectrum; GLSpectrumInterface* m_glSpectrum;
WSSpectrum m_wsSpectrum; WSSpectrum m_wsSpectrum;

View File

@ -25,6 +25,7 @@
#include <QOpenGLFunctions> #include <QOpenGLFunctions>
#include <QPainter> #include <QPainter>
#include <QFontDatabase> #include <QFontDatabase>
#include "dsp/spectrumvis.h"
#include "gui/glspectrum.h" #include "gui/glspectrum.h"
#include "util/messagequeue.h" #include "util/messagequeue.h"
@ -33,10 +34,13 @@
MESSAGE_CLASS_DEFINITION(GLSpectrum::MsgReportSampleRate, Message) MESSAGE_CLASS_DEFINITION(GLSpectrum::MsgReportSampleRate, Message)
MESSAGE_CLASS_DEFINITION(GLSpectrum::MsgReportWaterfallShare, Message) MESSAGE_CLASS_DEFINITION(GLSpectrum::MsgReportWaterfallShare, Message)
const float GLSpectrum::m_maxFrequencyZoom = 4.0f;
GLSpectrum::GLSpectrum(QWidget* parent) : GLSpectrum::GLSpectrum(QWidget* parent) :
QGLWidget(parent), QGLWidget(parent),
m_cursorState(CSNormal), m_cursorState(CSNormal),
m_cursorChannel(0), m_cursorChannel(0),
m_spectrumVis(nullptr),
m_fpsPeriodMs(50), m_fpsPeriodMs(50),
m_mouseInside(false), m_mouseInside(false),
m_changesPending(true), m_changesPending(true),
@ -159,6 +163,7 @@ GLSpectrum::GLSpectrum(QWidget* parent) :
m_textOverlayFont = font(); // QFontDatabase::systemFont(QFontDatabase::FixedFont); m_textOverlayFont = font(); // QFontDatabase::systemFont(QFontDatabase::FixedFont);
m_textOverlayFont.setBold(true); m_textOverlayFont.setBold(true);
// m_textOverlayFont.setPointSize(font().pointSize() - 1); // m_textOverlayFont.setPointSize(font().pointSize() - 1);
resetFrequencyZoom();
m_timer.setTimerType(Qt::PreciseTimer); m_timer.setTimerType(Qt::PreciseTimer);
connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick())); connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick()));
@ -408,7 +413,7 @@ void GLSpectrum::removeChannelMarker(ChannelMarker* channelMarker)
m_mutex.unlock(); m_mutex.unlock();
} }
void GLSpectrum::newSpectrum(const std::vector<Real>& spectrum, int fftSize) void GLSpectrum::newSpectrum(const Real *spectrum, int fftSize)
{ {
QMutexLocker mutexLocker(&m_mutex); QMutexLocker mutexLocker(&m_mutex);
@ -435,7 +440,7 @@ void GLSpectrum::newSpectrum(const std::vector<Real>& spectrum, int fftSize)
} }
} }
void GLSpectrum::updateWaterfall(const std::vector<Real>& spectrum) void GLSpectrum::updateWaterfall(const Real *spectrum)
{ {
if (m_waterfallBufferPos < m_waterfallBuffer->height()) if (m_waterfallBufferPos < m_waterfallBuffer->height())
{ {
@ -458,7 +463,7 @@ void GLSpectrum::updateWaterfall(const std::vector<Real>& spectrum)
} }
} }
void GLSpectrum::updateHistogram(const std::vector<Real>& spectrum) void GLSpectrum::updateHistogram(const Real *spectrum)
{ {
quint8* b = m_histogram; quint8* b = m_histogram;
int fftMulSize = 100 * m_fftSize; int fftMulSize = 100 * m_fftSize;
@ -484,7 +489,7 @@ void GLSpectrum::updateHistogram(const std::vector<Real>& spectrum)
} }
} }
m_currentSpectrum = &spectrum; // Store spectrum for current spectrum line display m_currentSpectrum = spectrum; // Store spectrum for current spectrum line display
#if 0 //def USE_SSE2 #if 0 //def USE_SSE2
if(m_decay >= 0) { // normal if(m_decay >= 0) { // normal
@ -963,7 +968,7 @@ void GLSpectrum::paintGL()
for (int i = 0; i < m_fftSize; i++) for (int i = 0; i < m_fftSize; i++)
{ {
Real v = (*m_currentSpectrum)[i] - m_referenceLevel; Real v = m_currentSpectrum[i] - m_referenceLevel;
if (v > 0) { if (v > 0) {
v = 0; v = 0;
@ -2193,16 +2198,73 @@ void GLSpectrum::mouseReleaseEvent(QMouseEvent*)
void GLSpectrum::wheelEvent(QWheelEvent *event) void GLSpectrum::wheelEvent(QWheelEvent *event)
{ {
int mul;
if (event->modifiers() & Qt::ShiftModifier) { if (event->modifiers() & Qt::ShiftModifier) {
mul = 100; channelMarkerMove(event, 100);
} else if (event->modifiers() & Qt::ControlModifier) { } else if (event->modifiers() & Qt::ControlModifier) {
mul = 10; channelMarkerMove(event, 10);
} else if (event->modifiers() & Qt::AltModifier) {
frequencyZoom(event);
} else { } else {
mul = 1; channelMarkerMove(event, 1);
}
}
void GLSpectrum::frequencyZoom(QWheelEvent *event)
{
const QPointF& p = event->position();
if (event->delta() > 0) // zoom in
{
if (m_frequencyZoomFactor < m_maxFrequencyZoom) {
m_frequencyZoomFactor += 0.5f;
}
}
else
{
if (m_frequencyZoomFactor > 1.0f) {
m_frequencyZoomFactor -= 0.5f;
}
} }
float pw = (p.x() - m_leftMargin) / (width() - m_leftMargin - m_rightMargin); // position in window
pw = pw < 0.0f ? 0.0f : pw > 1.0f ? 1.0 : pw;
m_frequencyZoomPos += (pw - 0.5f) * (1.0f / m_frequencyZoomFactor);
float lim = 0.5f / m_frequencyZoomFactor;
m_frequencyZoomPos = m_frequencyZoomPos < lim ? lim : m_frequencyZoomPos > 1 - lim ? 1 - lim : m_frequencyZoomPos;
updateFFTLimits();
qDebug("GLSpectrum::spectrumZoom: pw: %f p: %f z: %f", pw, m_frequencyZoomPos, m_frequencyZoomFactor);
}
void GLSpectrum::resetFrequencyZoom()
{
m_frequencyZoomFactor = 1.0f;
m_frequencyZoomPos = 0.5f;
updateFFTLimits();
}
void GLSpectrum::updateFFTLimits()
{
if (!m_spectrumVis) {
return;
}
SpectrumVis::MsgFrequencyZooming *msg = SpectrumVis::MsgFrequencyZooming::create(
m_frequencyZoomFactor, m_frequencyZoomPos
);
m_spectrumVis->getInputMessageQueue()->push(msg);
}
// void GLSpectrum::updateFFTLimits()
// {
// m_fftMin = m_frequencyZoomFactor == 1 ? 0 : (m_frequencyZoomPos - (0.5f / m_frequencyZoomFactor)) * m_fftSize;
// m_fftMax = m_frequencyZoomFactor == 1 ? m_fftSize : (m_frequencyZoomPos - (0.5f / m_frequencyZoomFactor)) * m_fftSize;
// }
void GLSpectrum::channelMarkerMove(QWheelEvent *event, int mul)
{
for (int i = 0; i < m_channelMarkerStates.size(); ++i) for (int i = 0; i < m_channelMarkerStates.size(); ++i)
{ {
if ((m_channelMarkerStates[i]->m_channelMarker->getSourceOrSinkStream() != m_displaySourceOrSink) if ((m_channelMarkerStates[i]->m_channelMarker->getSourceOrSinkStream() != m_displaySourceOrSink)

View File

@ -39,6 +39,7 @@
class QOpenGLShaderProgram; class QOpenGLShaderProgram;
class MessageQueue; class MessageQueue;
class SpectrumVis;
class SDRGUI_API GLSpectrum : public QGLWidget, public GLSpectrumInterface { class SDRGUI_API GLSpectrum : public QGLWidget, public GLSpectrumInterface {
Q_OBJECT Q_OBJECT
@ -103,7 +104,7 @@ public:
void removeChannelMarker(ChannelMarker* channelMarker); void removeChannelMarker(ChannelMarker* channelMarker);
void setMessageQueueToGUI(MessageQueue* messageQueue) { m_messageQueueToGUI = messageQueue; } void setMessageQueueToGUI(MessageQueue* messageQueue) { m_messageQueueToGUI = messageQueue; }
virtual void newSpectrum(const std::vector<Real>& spectrum, int fftSize); virtual void newSpectrum(const Real* spectrum, int fftSize);
void clearSpectrumHistogram(); void clearSpectrumHistogram();
Real getWaterfallShare() const { return m_waterfallShare; } Real getWaterfallShare() const { return m_waterfallShare; }
@ -115,6 +116,7 @@ public:
m_displaySourceOrSink = sourceOrSink; m_displaySourceOrSink = sourceOrSink;
m_displayStreamIndex = streamIndex; m_displayStreamIndex = streamIndex;
} }
void setSpectrumVis(SpectrumVis *spectrumVis) { m_spectrumVis = spectrumVis; }
private: private:
struct ChannelMarkerState { struct ChannelMarkerState {
@ -235,6 +237,7 @@ private:
CursorState m_cursorState; CursorState m_cursorState;
int m_cursorChannel; int m_cursorChannel;
SpectrumVis* m_spectrumVis;
QTimer m_timer; QTimer m_timer;
int m_fpsPeriodMs; int m_fpsPeriodMs;
QMutex m_mutex; QMutex m_mutex;
@ -259,7 +262,7 @@ private:
std::vector<Real> m_maxHold; std::vector<Real> m_maxHold;
bool m_displayMaxHold; bool m_displayMaxHold;
const std::vector<Real> *m_currentSpectrum; const Real *m_currentSpectrum;
bool m_displayCurrent; bool m_displayCurrent;
Real m_waterfallShare; Real m_waterfallShare;
@ -305,6 +308,9 @@ private:
bool m_displayChanged; bool m_displayChanged;
bool m_displaySourceOrSink; bool m_displaySourceOrSink;
int m_displayStreamIndex; int m_displayStreamIndex;
float m_frequencyZoomFactor;
float m_frequencyZoomPos;
static const float m_maxFrequencyZoom;
GLShaderSimple m_glShaderSimple; GLShaderSimple m_glShaderSimple;
GLShaderTextured m_glShaderLeftScale; GLShaderTextured m_glShaderLeftScale;
@ -321,10 +327,8 @@ private:
MessageQueue *m_messageQueueToGUI; MessageQueue *m_messageQueueToGUI;
static const int m_waterfallBufferHeight = 256; void updateWaterfall(const Real *spectrum);
void updateHistogram(const Real *spectrum);
void updateWaterfall(const std::vector<Real>& spectrum);
void updateHistogram(const std::vector<Real>& spectrum);
void initializeGL(); void initializeGL();
void resizeGL(int width, int height); void resizeGL(int width, int height);
@ -338,6 +342,10 @@ private:
void mousePressEvent(QMouseEvent* event); void mousePressEvent(QMouseEvent* event);
void mouseReleaseEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event);
void wheelEvent(QWheelEvent*); void wheelEvent(QWheelEvent*);
void channelMarkerMove(QWheelEvent*, int mul);
void frequencyZoom(QWheelEvent*);
void resetFrequencyZoom();
void updateFFTLimits();
void enterEvent(QEvent* event); void enterEvent(QEvent* event);
void leaveEvent(QEvent* event); void leaveEvent(QEvent* event);

View File

@ -77,6 +77,7 @@ void GLSpectrumGUI::setBuddies(SpectrumVis* spectrumVis, GLSpectrum* glSpectrum)
{ {
m_spectrumVis = spectrumVis; m_spectrumVis = spectrumVis;
m_glSpectrum = glSpectrum; m_glSpectrum = glSpectrum;
m_glSpectrum->setSpectrumVis(spectrumVis);
m_glSpectrum->setMessageQueueToGUI(&m_messageQueue); m_glSpectrum->setMessageQueueToGUI(&m_messageQueue);
m_spectrumVis->setMessageQueueToGUI(&m_messageQueue); m_spectrumVis->setMessageQueueToGUI(&m_messageQueue);
} }