Skip to content

Commit

Permalink
dockfft: zoom slider uses log scale with max 100000x
Browse files Browse the repository at this point in the history
Also, zoom and pan are constrained so no "empty space" is shown
at the sides of the plot.

Signed-off-by: Jeff Long <[email protected]>
  • Loading branch information
willcode committed Jul 2, 2023
1 parent 484917c commit 5f91743
Show file tree
Hide file tree
Showing 4 changed files with 37 additions and 48 deletions.
8 changes: 5 additions & 3 deletions src/qtgui/dockfft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,8 @@ void DockFft::setWaterfallRange(float min, float max)
void DockFft::setZoomLevel(float level)
{
ui->fftZoomSlider->blockSignals(true);
ui->fftZoomSlider->setValue((int) level);
float logZoom = 100.0f / 5.0f * log10f(level);
ui->fftZoomSlider->setValue(qRound(logZoom));
ui->zoomLevelLabel->setText(QString("%1x").arg((int) level));
ui->fftZoomSlider->blockSignals(false);
}
Expand Down Expand Up @@ -628,8 +629,9 @@ void DockFft::on_fftAvgSlider_valueChanged(int value)
/** FFT zoom level changed */
void DockFft::on_fftZoomSlider_valueChanged(int level)
{
ui->zoomLevelLabel->setText(QString("%1x").arg(level));
emit fftZoomChanged((float)level);
float linearZoom = powf(10.0f, (float)level * 5.0f / 100.0f);
ui->zoomLevelLabel->setText(QString("%1x").arg(qRound(linearZoom)));
emit fftZoomChanged(linearZoom);
}

void DockFft::on_wfModeBox_currentIndexChanged(int index)
Expand Down
2 changes: 1 addition & 1 deletion src/qtgui/dockfft.ui
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@
<string>Zoom level for frequency axis</string>
</property>
<property name="minimum">
<number>1</number>
<number>0</number>
</property>
<property name="maximum">
<number>100</number>
Expand Down
73 changes: 30 additions & 43 deletions src/qtgui/plotter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -910,53 +910,44 @@ void CPlotter::zoomStepX(float step, int x)
}

// calculate new range shown on FFT
double new_range = qBound(10.0, m_Span * (double)step, (double)m_SampleFreq * 10.0);

// Frequency where event occurred is kept fixed under mouse
double ratio = (double)x / (qreal)m_Size.width() / m_DPR;
qint64 fixed_hz = freqFromX(x);
double f_max = (double)fixed_hz + (1.0 - ratio) * new_range;
double f_min = f_max - new_range;

// ensure we don't go beyond the rangelimits
bool limit_hit = false;
double lolim = (double)(m_CenterFreq) - (double)m_SampleFreq / 2.0;
double hilim = (double)m_CenterFreq + (double)m_SampleFreq / 2.0;
if (f_min < lolim)
float new_span = std::min(
(float)m_Span * (float)step, (float)m_SampleFreq);

// Keep frequency under pointer the same and calculated the offset to the
// plot center.
float offset = (float)(freqFromX(x) - m_CenterFreq - m_FftCenter);
float new_FftCenter = (float)m_FftCenter + offset * (1.0f - step);

// Keep edges of plot in valid frequency range. The plot may need to be
// panned.
const float max_limit = (float)m_SampleFreq / 2.0f;
const float min_limit = - (float)m_SampleFreq / 2.0f;
float f_max = new_FftCenter + new_span / 2.0f;
float f_min = new_FftCenter - new_span / 2.0f;
if (f_min < min_limit)
{
f_min = lolim;
limit_hit = true;
f_min = min_limit;
f_max = f_min + new_span;
}
if (f_max > hilim)
if (f_max > max_limit)
{
f_max = hilim;
limit_hit = true;
f_max = max_limit;
f_min = f_max - new_span;
}

// the new span
quint32 new_span = qRound(f_max - f_min);
if( new_span & 1 )
// Make span into an even integer.
quint32 new_span_int = qRound(f_max - f_min);
if( new_span_int & 1 )
{
new_span++; // keep span even to avoid rounding in span/2
new_span_int--;
}

// find new FFT center frequency
qint64 new_FftCenter;
if( limit_hit ) // cannot keep fixed_hz fixed
{
new_FftCenter = qRound64((f_min + f_max) / 2.0) - m_CenterFreq;
}
else // calculate new FFT center frequency that really keeps fixed_hz fixed
{
qint64 wouldbe_hz = (m_CenterFreq + m_FftCenter - new_span / 2) + ratio * new_span;
new_FftCenter = m_FftCenter + (fixed_hz - wouldbe_hz);
}
setFftCenterFreq(new_FftCenter);
setFftCenterFreq(qRound64((f_max + f_min) / 2.0f));
setSpanFreq(new_span);

double factor = (double)m_SampleFreq / (double)m_Span;
emit newZoomLevel(factor);
qCDebug(plotter) << QString("Spectrum zoom: %1x").arg(factor, 0, 'f', 1);
double zoom = (double)m_SampleFreq / (double)m_Span;
emit newZoomLevel(zoom);
qCDebug(plotter) << QString("Spectrum zoom: %1x").arg(zoom, 0, 'f', 1);

m_MaxHoldValid = false;
m_MinHoldValid = false;
Expand All @@ -967,7 +958,7 @@ void CPlotter::zoomStepX(float step, int x)
void CPlotter::zoomOnXAxis(float level)
{
float current_level = (float)m_SampleFreq / (float)m_Span;
zoomStepX(current_level / level, xFromFreq(m_DemodCenterFreq));
zoomStepX(current_level / level, qRound((qreal)m_Size.width() * m_DPR / 2.0));
updateOverlay();
}

Expand Down Expand Up @@ -1892,7 +1883,7 @@ void CPlotter::setNewFftData(const float *fftData, int size)
double currentZoom = (double)m_SampleFreq / (double)m_Span;
double maxZoom = (double)m_fftDataSize / 4.0;
if (currentZoom > maxZoom)
zoomStepX(currentZoom / maxZoom, xFromFreq(m_CenterFreq + m_FftCenter));
zoomStepX(currentZoom / maxZoom, qRound((qreal)m_Size.width() * m_DPR / 2.0));
}

// For dBFS, define full scale as peak (not RMS). A 1.0 FS peak sine wave
Expand Down Expand Up @@ -2351,10 +2342,6 @@ int CPlotter::xFromFreq(qint64 freq)
+ (double)m_FftCenter
- (double)m_Span / 2.0;
int x = qRound(w * ((double)freq - startFreq) / (double)m_Span);
if (x < 0)
return 0;
if (x > (int)w)
return w;
return x;
}

Expand Down
2 changes: 1 addition & 1 deletion src/qtgui/plotter.h
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ class CPlotter : public QFrame
}

void setFftCenterFreq(qint64 f) {
qint64 limit = ((qint64)m_SampleFreq + m_Span) / 2 - 1;
qint64 limit = ((qint64)m_SampleFreq - m_Span) / 2 - 1;
m_FftCenter = qBound(-limit, f, limit);
}

Expand Down

0 comments on commit 5f91743

Please sign in to comment.