Spectrum overlap fixes. Spectrum time and power zomming. Implements #779

pull/788/head
f4exb 2021-02-19 13:42:05 +01:00
rodzic 076a4f6306
commit 043a76faf8
4 zmienionych plików z 184 dodań i 27 usunięć

Wyświetl plik

@ -33,6 +33,8 @@
MESSAGE_CLASS_DEFINITION(GLSpectrum::MsgReportSampleRate, Message)
MESSAGE_CLASS_DEFINITION(GLSpectrum::MsgReportWaterfallShare, Message)
MESSAGE_CLASS_DEFINITION(GLSpectrum::MsgReportFFTOverlap, Message)
MESSAGE_CLASS_DEFINITION(GLSpectrum::MsgReportPowerScale, Message)
const float GLSpectrum::m_maxFrequencyZoom = 10.0f;
@ -1315,20 +1317,20 @@ void GLSpectrum::applyChanges()
m_waterfallHeight = 0;
}
if (!m_invertedWaterfall)
{
waterfallTop = m_topMargin;
frequencyScaleTop = waterfallTop + m_waterfallHeight + 1;
histogramTop = waterfallTop + m_waterfallHeight + m_frequencyScaleHeight + 1;
m_histogramHeight = height() - m_topMargin - m_waterfallHeight - m_frequencyScaleHeight - m_bottomMargin;
}
else
if (m_invertedWaterfall)
{
histogramTop = m_topMargin;
m_histogramHeight = height() - m_topMargin - m_waterfallHeight - m_frequencyScaleHeight - m_bottomMargin;
waterfallTop = histogramTop + m_histogramHeight + m_frequencyScaleHeight + 1;
frequencyScaleTop = histogramTop + m_histogramHeight + 1;
}
else
{
waterfallTop = m_topMargin;
frequencyScaleTop = waterfallTop + m_waterfallHeight + 1;
histogramTop = waterfallTop + m_waterfallHeight + m_frequencyScaleHeight + 1;
m_histogramHeight = height() - m_topMargin - m_waterfallHeight - m_frequencyScaleHeight - m_bottomMargin;
}
m_timeScale.setSize(m_waterfallHeight);
@ -1336,7 +1338,10 @@ void GLSpectrum::applyChanges()
{
float scaleDiv = ((float)m_sampleRate / (float)m_timingRate) * (m_ssbSpectrum ? 2 : 1);
float halfFFTSize = m_fftSize / 2;
scaleDiv *= halfFFTSize / (halfFFTSize - m_fftOverlap);
if (halfFFTSize > m_fftOverlap) {
scaleDiv *= halfFFTSize / (halfFFTSize - m_fftOverlap);
}
if (!m_invertedWaterfall) {
m_timeScale.setRange(m_timingRate > 1 ? Unit::TimeHMS : Unit::Time, (m_waterfallHeight * m_fftSize) / scaleDiv, 0);
@ -1437,7 +1442,10 @@ void GLSpectrum::applyChanges()
{
float scaleDiv = ((float)m_sampleRate / (float)m_timingRate) * (m_ssbSpectrum ? 2 : 1);
float halfFFTSize = m_fftSize / 2;
scaleDiv *= halfFFTSize / (halfFFTSize - m_fftOverlap);
if (halfFFTSize > m_fftOverlap) {
scaleDiv *= halfFFTSize / (halfFFTSize - m_fftOverlap);
}
if (!m_invertedWaterfall) {
m_timeScale.setRange(m_timingRate > 1 ? Unit::TimeHMS : Unit::Time, (m_waterfallHeight * m_fftSize) / scaleDiv, 0);
@ -2278,7 +2286,7 @@ void GLSpectrum::wheelEvent(QWheelEvent *event)
}
}
void GLSpectrum::frequencyZoom(QWheelEvent *event)
void GLSpectrum::zoom(QWheelEvent *event)
{
#if QT_VERSION >= QT_VERSION_CHECK(5, 14, 0)
const QPointF& p = event->position();
@ -2286,30 +2294,63 @@ void GLSpectrum::frequencyZoom(QWheelEvent *event)
const QPointF& p = event->pos();
#endif
if (event->delta() > 0) // zoom in
float pwx = (p.x() - m_leftMargin) / (width() - m_leftMargin - m_rightMargin); // x position in window
if ((pwx >= 0.0f) && (pwx <= 1.0f))
{
if (m_frequencyZoomFactor < m_maxFrequencyZoom) {
m_frequencyZoomFactor += 0.5f;
} else {
return;
if (event->delta() > 0) // zoom in
{
if (m_frequencyZoomFactor < m_maxFrequencyZoom) {
m_frequencyZoomFactor += 0.5f;
} else {
return;
}
}
else
{
if (m_frequencyZoomFactor > 1.0f) {
m_frequencyZoomFactor -= 0.5f;
} else {
return;
}
}
frequencyZoom(pwx);
}
else
{
if (m_frequencyZoomFactor > 1.0f) {
m_frequencyZoomFactor -= 0.5f;
} else {
return;
float pwyh, pwyw;
if (m_invertedWaterfall) // histo on top
{
pwyh = (p.y() - m_topMargin) / m_histogramHeight;
pwyw = (p.y() - m_topMargin - m_histogramHeight - m_frequencyScaleHeight) / m_waterfallHeight;
}
else // waterfall on top
{
pwyw = (p.y() - m_topMargin) / m_waterfallHeight;
pwyh = (p.y() - m_topMargin - m_waterfallHeight - m_frequencyScaleHeight) / m_histogramHeight;
}
//qDebug("GLSpectrum::zoom: pwyh: %f pwyw: %f", pwyh, pwyw);
if ((pwyw >= 0.0f) && (pwyw <= 1.0f)) {
timeZoom(event->delta() > 0);
}
if ((pwyh >= 0.0f) && (pwyh <= 1.0f) && !m_linear) {
powerZoom(pwyh, event->delta() > 0);
}
}
}
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;
void GLSpectrum::frequencyZoom(float 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;
qDebug("GLSpectrum::spectrumZoom: pw: %f p: %f z: %f", pw, m_frequencyZoomPos, m_frequencyZoomFactor);
qDebug("GLSpectrum::frequencyZoom: pw: %f p: %f z: %f", pw, m_frequencyZoomPos, m_frequencyZoomFactor);
updateFFTLimits();
}
@ -2331,6 +2372,47 @@ void GLSpectrum::frequencyPan(QMouseEvent *event)
updateFFTLimits();
}
void GLSpectrum::timeZoom(bool zoomInElseOut)
{
if ((m_fftOverlap == 0) && !zoomInElseOut) {
return;
}
if (zoomInElseOut && (m_fftOverlap == m_fftSize/2 - 1)) {
return;
}
m_fftOverlap = m_fftOverlap + (zoomInElseOut ? 1 : -1);
m_changesPending = true;
if (m_messageQueueToGUI)
{
MsgReportFFTOverlap *msg = new MsgReportFFTOverlap(m_fftOverlap);
m_messageQueueToGUI->push(msg);
}
}
void GLSpectrum::powerZoom(float pw, bool zoomInElseOut)
{
m_powerRange = m_powerRange + (zoomInElseOut ? -2 : 2);
if (pw > 2.0/3.0) { // bottom
m_referenceLevel = m_referenceLevel + (zoomInElseOut ? -2 : 2);
} else if (pw > 1.0/3.0) { // middle
m_referenceLevel = m_referenceLevel + (zoomInElseOut ? -1 : 1);
} // top
m_powerRange = m_powerRange < 1 ? 1 : m_powerRange > 100 ? 100 : m_powerRange;
m_referenceLevel = m_referenceLevel < -110 ? -110 : m_referenceLevel > 0 ? 0 : m_referenceLevel;
m_changesPending = true;
if (m_messageQueueToGUI)
{
MsgReportPowerScale *msg = new MsgReportPowerScale(m_referenceLevel, m_powerRange);
m_messageQueueToGUI->push(msg);
}
}
void GLSpectrum::resetFrequencyZoom()
{
m_frequencyZoomFactor = 1.0f;
@ -2421,7 +2503,7 @@ void GLSpectrum::channelMarkerMove(QWheelEvent *event, int mul)
}
}
frequencyZoom(event);
zoom(event);
}
void GLSpectrum::enterEvent(QEvent* event)

Wyświetl plik

@ -75,6 +75,39 @@ public:
Real m_waterfallShare;
};
class MsgReportFFTOverlap : public Message {
MESSAGE_CLASS_DECLARATION
public:
MsgReportFFTOverlap(int overlap) :
Message(),
m_overlap(overlap)
{}
int getOverlap() const { return m_overlap; }
private:
int m_overlap;
};
class MsgReportPowerScale : public Message {
MESSAGE_CLASS_DECLARATION
public:
MsgReportPowerScale(int refLevel, int range) :
Message(),
m_refLevel(refLevel),
m_range(range)
{}
Real getRefLevel() const { return m_refLevel; }
Real getRange() const { return m_range; }
private:
Real m_refLevel;
Real m_range;
};
GLSpectrum(QWidget* parent = nullptr);
virtual ~GLSpectrum();
@ -349,8 +382,11 @@ private:
void mouseReleaseEvent(QMouseEvent* event);
void wheelEvent(QWheelEvent*);
void channelMarkerMove(QWheelEvent*, int mul);
void frequencyZoom(QWheelEvent*);
void zoom(QWheelEvent*);
void frequencyZoom(float pw);
void frequencyPan(QMouseEvent*);
void timeZoom(bool zoomInElseOut);
void powerZoom(float pw, bool zoomInElseOut);
void resetFrequencyZoom();
void updateFFTLimits();
void setFrequencyScale();

Wyświetl plik

@ -630,6 +630,29 @@ bool GLSpectrumGUI::handleMessage(const Message& message)
{
const GLSpectrum::MsgReportWaterfallShare& report = (const GLSpectrum::MsgReportWaterfallShare&) message;
m_settings.m_waterfallShare = report.getWaterfallShare();
return true;
}
else if (GLSpectrum::MsgReportFFTOverlap::match(message))
{
const GLSpectrum::MsgReportFFTOverlap& report = (const GLSpectrum::MsgReportFFTOverlap&) message;
m_settings.m_fftOverlap = report.getOverlap();
ui->fftOverlap->blockSignals(true);
ui->fftOverlap->setValue(m_settings.m_fftOverlap);
ui->fftOverlap->blockSignals(false);
return true;
}
else if (GLSpectrum::MsgReportPowerScale::match(message))
{
const GLSpectrum::MsgReportPowerScale& report = (const GLSpectrum::MsgReportPowerScale&) message;
m_settings.m_refLevel = report.getRefLevel();
m_settings.m_powerRange = report.getRange();
ui->refLevel->blockSignals(true);
ui->levelRange->blockSignals(true);
ui->refLevel->setValue(m_settings.m_refLevel);
ui->levelRange->setValue(m_settings.m_powerRange);
ui->levelRange->blockSignals(false);
ui->refLevel->blockSignals(false);
return true;
}
else if (SpectrumVis::MsgStartStop::match(message))
{

Wyświetl plik

@ -973,15 +973,31 @@ Any change in the spectrum settings is not reflected in the markers. You have to
<h4>Mouse scroll wheel</h4>
<h5>Channel moving</h5>
When the mouse is over the center line of a channel:
- scrolling will move the channel by +/- 10 Hz at each scroll up/down respectively
- combined with Ctrl it will move the channel by +/- 100 Hz
- combined with Shift it will move the channel by +/- 1 kHz
When the mouse is not over the center line of a channel it will zoom in/out along X (frequency) axis by a 0.5 step at each scroll up/down respectively between 1x (no zoom) and 10x. Note that in order to zoom on the center line of a channel you may move the mouse pointer in the top margin (center line moving is not active there but zooming is).
<h5>Frequency zooming</h5>
When zooming is active use Alt + left click to move the center frequency to the clicked point.
When the mouse is in the spectrum area but not over the center line of a channel it will zoom in/out along X (frequency) axis by a 0.5 step at each scroll up/down respectively between 1x (no zoom) and 10x. Note that in order to zoom on the center line of a channel you may move the mouse pointer in the top margin (center line moving is not active there but zooming is).
When frequency zooming is active use Alt + left click to move the center frequency to the clicked point.
<h5>Power zooming</h5>
When the mouse is inside the power scale (spectrum) the power range is decreased by 2 (zoom in) or increased by 2 (zoom in) at each wheel step forward or backward respectively. The behavior of the reference level depends on where in the scale is the mouse pointer:
- in the top third: the reference level is maintained thus the reference level at the top stays the same
- in the middle third: the reference level is decreased by 1 (zoom in) or increased by 1 (zoom out) at each wheel step forward or backward thus the level in the middle stays the same
- in the bottom third: the reference level is decreased by 2 (zoom in) or increased by 2 (zoom out) at each wheel step forward or backward thus the level at the bottom stays the same
<h5>Time zooming</h5>
When the mouse is inside the time scale (waterfall) the overlap is increased by 1 (zoom in) or decreased by 1 (zoom out) at each wheel step forward or backward respectively. Overlap is bounded by 0 and half of the FFT size minus one.
<h3>7. Status</h3>