diff --git a/sdrbase/dsp/glspectruminterface.h b/sdrbase/dsp/glspectruminterface.h index c8cd56307..35f844bd5 100644 --- a/sdrbase/dsp/glspectruminterface.h +++ b/sdrbase/dsp/glspectruminterface.h @@ -26,7 +26,7 @@ class GLSpectrumInterface public: GLSpectrumInterface() {} virtual ~GLSpectrumInterface() {} - virtual void newSpectrum(const std::vector& spectrum, int fftSize) + virtual void newSpectrum(const Real* spectrum, int fftSize) { (void) spectrum; (void) fftSize; diff --git a/sdrbase/dsp/spectrumvis.cpp b/sdrbase/dsp/spectrumvis.cpp index 78762d7de..bbf818f87 100644 --- a/sdrbase/dsp/spectrumvis.cpp +++ b/sdrbase/dsp/spectrumvis.cpp @@ -44,6 +44,7 @@ MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgConfigureScalingFactor, Message) MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgConfigureWSpectrumOpenClose, Message) MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgConfigureWSpectrum, Message) MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgStartStop, Message) +MESSAGE_CLASS_DEFINITION(SpectrumVis::MsgFrequencyZooming, Message) const Real SpectrumVis::m_mult = (10.0f / log2(10.0f)); @@ -57,6 +58,8 @@ SpectrumVis::SpectrumVis(Real scalef) : m_psd(MAX_FFT_SIZE), m_fftBufferFill(0), m_needMoreSamples(false), + m_frequencyZoomFactor(1.0f), + m_frequencyZoomPos(0.5f), m_scalef(scalef), m_glSpectrum(nullptr), m_specMax(0.0f), @@ -121,6 +124,10 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length) Complex c; 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) { @@ -140,7 +147,7 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length) // send new data to visualisation 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 @@ -176,7 +183,7 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length) // send new data to visualisation 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 @@ -223,7 +230,7 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length) { // send new data to visualisation 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 @@ -269,7 +276,7 @@ void SpectrumVis::feed(const Complex *begin, unsigned int length) { // send new data to visualisation 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 @@ -374,7 +381,7 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV // send new data to visualisation 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 @@ -433,7 +440,7 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV // send new data to visualisation 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 @@ -512,7 +519,7 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV // send new data to visualisation 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 @@ -590,7 +597,7 @@ void SpectrumVis::feed(const SampleVector::const_iterator& cbegin, const SampleV // send new data to visualisation 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 @@ -694,7 +701,13 @@ bool SpectrumVis::handleMessage(const Message& message) { MsgStartStop& cmd = (MsgStartStop&) message; setRunning(cmd.getStartStop()); - + return true; + } + else if (MsgFrequencyZooming::match(message)) + { + MsgFrequencyZooming& cmd = (MsgFrequencyZooming&) message; + m_frequencyZoomFactor = cmd.getFrequencyZoomFactor(); + m_frequencyZoomPos = cmd.getFrequencyZoomPos(); return true; } else diff --git a/sdrbase/dsp/spectrumvis.h b/sdrbase/dsp/spectrumvis.h index 10cd73c0f..9b0ed80f1 100644 --- a/sdrbase/dsp/spectrumvis.h +++ b/sdrbase/dsp/spectrumvis.h @@ -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 { AvgModeNone, @@ -198,6 +220,9 @@ private: int m_fftBufferFill; bool m_needMoreSamples; + float m_frequencyZoomFactor; + float m_frequencyZoomPos; + Real m_scalef; GLSpectrumInterface* m_glSpectrum; WSSpectrum m_wsSpectrum; diff --git a/sdrgui/gui/glspectrum.cpp b/sdrgui/gui/glspectrum.cpp index ebf7b8d73..66e599732 100644 --- a/sdrgui/gui/glspectrum.cpp +++ b/sdrgui/gui/glspectrum.cpp @@ -25,6 +25,7 @@ #include #include #include +#include "dsp/spectrumvis.h" #include "gui/glspectrum.h" #include "util/messagequeue.h" @@ -33,10 +34,13 @@ MESSAGE_CLASS_DEFINITION(GLSpectrum::MsgReportSampleRate, Message) MESSAGE_CLASS_DEFINITION(GLSpectrum::MsgReportWaterfallShare, Message) +const float GLSpectrum::m_maxFrequencyZoom = 4.0f; + GLSpectrum::GLSpectrum(QWidget* parent) : QGLWidget(parent), m_cursorState(CSNormal), m_cursorChannel(0), + m_spectrumVis(nullptr), m_fpsPeriodMs(50), m_mouseInside(false), m_changesPending(true), @@ -159,6 +163,7 @@ GLSpectrum::GLSpectrum(QWidget* parent) : m_textOverlayFont = font(); // QFontDatabase::systemFont(QFontDatabase::FixedFont); m_textOverlayFont.setBold(true); // m_textOverlayFont.setPointSize(font().pointSize() - 1); + resetFrequencyZoom(); m_timer.setTimerType(Qt::PreciseTimer); connect(&m_timer, SIGNAL(timeout()), this, SLOT(tick())); @@ -408,7 +413,7 @@ void GLSpectrum::removeChannelMarker(ChannelMarker* channelMarker) m_mutex.unlock(); } -void GLSpectrum::newSpectrum(const std::vector& spectrum, int fftSize) +void GLSpectrum::newSpectrum(const Real *spectrum, int fftSize) { QMutexLocker mutexLocker(&m_mutex); @@ -435,7 +440,7 @@ void GLSpectrum::newSpectrum(const std::vector& spectrum, int fftSize) } } -void GLSpectrum::updateWaterfall(const std::vector& spectrum) +void GLSpectrum::updateWaterfall(const Real *spectrum) { if (m_waterfallBufferPos < m_waterfallBuffer->height()) { @@ -458,7 +463,7 @@ void GLSpectrum::updateWaterfall(const std::vector& spectrum) } } -void GLSpectrum::updateHistogram(const std::vector& spectrum) +void GLSpectrum::updateHistogram(const Real *spectrum) { quint8* b = m_histogram; int fftMulSize = 100 * m_fftSize; @@ -484,7 +489,7 @@ void GLSpectrum::updateHistogram(const std::vector& 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(m_decay >= 0) { // normal @@ -963,7 +968,7 @@ void GLSpectrum::paintGL() 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) { v = 0; @@ -2193,16 +2198,73 @@ void GLSpectrum::mouseReleaseEvent(QMouseEvent*) void GLSpectrum::wheelEvent(QWheelEvent *event) { - int mul; - if (event->modifiers() & Qt::ShiftModifier) { - mul = 100; + channelMarkerMove(event, 100); } else if (event->modifiers() & Qt::ControlModifier) { - mul = 10; + channelMarkerMove(event, 10); + } else if (event->modifiers() & Qt::AltModifier) { + frequencyZoom(event); } 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) { if ((m_channelMarkerStates[i]->m_channelMarker->getSourceOrSinkStream() != m_displaySourceOrSink) diff --git a/sdrgui/gui/glspectrum.h b/sdrgui/gui/glspectrum.h index 35782210b..a61292cbd 100644 --- a/sdrgui/gui/glspectrum.h +++ b/sdrgui/gui/glspectrum.h @@ -39,6 +39,7 @@ class QOpenGLShaderProgram; class MessageQueue; +class SpectrumVis; class SDRGUI_API GLSpectrum : public QGLWidget, public GLSpectrumInterface { Q_OBJECT @@ -103,7 +104,7 @@ public: void removeChannelMarker(ChannelMarker* channelMarker); void setMessageQueueToGUI(MessageQueue* messageQueue) { m_messageQueueToGUI = messageQueue; } - virtual void newSpectrum(const std::vector& spectrum, int fftSize); + virtual void newSpectrum(const Real* spectrum, int fftSize); void clearSpectrumHistogram(); Real getWaterfallShare() const { return m_waterfallShare; } @@ -115,6 +116,7 @@ public: m_displaySourceOrSink = sourceOrSink; m_displayStreamIndex = streamIndex; } + void setSpectrumVis(SpectrumVis *spectrumVis) { m_spectrumVis = spectrumVis; } private: struct ChannelMarkerState { @@ -235,6 +237,7 @@ private: CursorState m_cursorState; int m_cursorChannel; + SpectrumVis* m_spectrumVis; QTimer m_timer; int m_fpsPeriodMs; QMutex m_mutex; @@ -259,7 +262,7 @@ private: std::vector m_maxHold; bool m_displayMaxHold; - const std::vector *m_currentSpectrum; + const Real *m_currentSpectrum; bool m_displayCurrent; Real m_waterfallShare; @@ -305,6 +308,9 @@ private: bool m_displayChanged; bool m_displaySourceOrSink; int m_displayStreamIndex; + float m_frequencyZoomFactor; + float m_frequencyZoomPos; + static const float m_maxFrequencyZoom; GLShaderSimple m_glShaderSimple; GLShaderTextured m_glShaderLeftScale; @@ -321,10 +327,8 @@ private: MessageQueue *m_messageQueueToGUI; - static const int m_waterfallBufferHeight = 256; - - void updateWaterfall(const std::vector& spectrum); - void updateHistogram(const std::vector& spectrum); + void updateWaterfall(const Real *spectrum); + void updateHistogram(const Real *spectrum); void initializeGL(); void resizeGL(int width, int height); @@ -338,6 +342,10 @@ private: void mousePressEvent(QMouseEvent* event); void mouseReleaseEvent(QMouseEvent* event); void wheelEvent(QWheelEvent*); + void channelMarkerMove(QWheelEvent*, int mul); + void frequencyZoom(QWheelEvent*); + void resetFrequencyZoom(); + void updateFFTLimits(); void enterEvent(QEvent* event); void leaveEvent(QEvent* event); diff --git a/sdrgui/gui/glspectrumgui.cpp b/sdrgui/gui/glspectrumgui.cpp index b8c6bba0c..fdd5c3d71 100644 --- a/sdrgui/gui/glspectrumgui.cpp +++ b/sdrgui/gui/glspectrumgui.cpp @@ -77,6 +77,7 @@ void GLSpectrumGUI::setBuddies(SpectrumVis* spectrumVis, GLSpectrum* glSpectrum) { m_spectrumVis = spectrumVis; m_glSpectrum = glSpectrum; + m_glSpectrum->setSpectrumVis(spectrumVis); m_glSpectrum->setMessageQueueToGUI(&m_messageQueue); m_spectrumVis->setMessageQueueToGUI(&m_messageQueue); }