Fix spectrum dBm range echo smoothing#2793
Conversation
There was a problem hiding this comment.
Pull request overview
This PR improves panadapter spectrum Y-scale stability when the dBm range changes by preventing brief “snap-back” artifacts from stale FFT frames and by allowing auto-floor animation to continue smoothly while waiting for radio echo/handshake confirmation.
Changes:
- Split pending dBm-range echo state between manual interactions vs. auto-noise-floor adjustments.
- Continue local auto-floor ref-level animation even while waiting for radio echo, and ignore/reissue stale auto-floor echoes when local state has moved on.
- Add a short post-release FFT “rebase” window that detects stale-range-encoded frames and remaps them to the pre-release range to avoid visible jumps.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.
| File | Description |
|---|---|
| src/gui/SpectrumWidget.h | Adds new state flags/counters to track echo source and post-release FFT rebasing parameters. |
| src/gui/SpectrumWidget.cpp | Implements auto-floor echo handling split + post-release stale FFT rebasing logic in updateSpectrum() and dBm drag release behavior. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| --m_holdFftUpdatesAfterDbmRelease; | ||
| const float oldRange = | ||
| m_dbmReleasePreviewOldMaxDbm - m_dbmReleasePreviewOldMinDbm; | ||
| const float newRange = | ||
| m_dbmReleasePreviewNewMaxDbm - m_dbmReleasePreviewNewMinDbm; | ||
| if (!m_bins.isEmpty() && m_bins.size() == binsDbm.size() | ||
| && oldRange > 0.0f && newRange > 0.0f) { |
| m_holdFftUpdatesAfterDbmRelease = | ||
| (std::abs(oldMinDbm - m_pendingMinDbm) > 0.05f | ||
| || std::abs(oldMaxDbm - m_pendingMaxDbm) > 0.05f) ? 10 : 0; |
| QVector<float> directErrors; | ||
| QVector<float> rebasedErrors; | ||
| const int step = qMax(1, binsDbm.size() / 256); | ||
| directErrors.reserve((binsDbm.size() + step - 1) / step); | ||
| rebasedErrors.reserve(directErrors.capacity()); | ||
| for (int i = 0; i < binsDbm.size(); i += step) { | ||
| const float directDbm = binsDbm[i]; | ||
| const float frac = (m_dbmReleasePreviewNewMaxDbm - directDbm) / newRange; | ||
| const float rebasedDbm = m_dbmReleasePreviewOldMaxDbm - frac * oldRange; | ||
| directErrors.append(std::abs(directDbm - m_bins[i])); | ||
| rebasedErrors.append(std::abs(rebasedDbm - m_bins[i])); | ||
| } | ||
| std::sort(directErrors.begin(), directErrors.end()); | ||
| std::sort(rebasedErrors.begin(), rebasedErrors.end()); | ||
| const float directMedian = directErrors[directErrors.size() / 2]; | ||
| const float rebasedMedian = rebasedErrors[rebasedErrors.size() / 2]; |
| m_holdFftUpdatesAfterDbmRelease = 0; | ||
| m_dbmReleasePreviewOldMinDbm = 0.0f; | ||
| m_dbmReleasePreviewOldMaxDbm = 0.0f; | ||
| m_dbmReleasePreviewNewMinDbm = 0.0f; | ||
| m_dbmReleasePreviewNewMaxDbm = 0.0f; |
9bc0806 to
4ea52c5
Compare
|
Updated the branch with a single amended commit that addresses the actionable Copilot review notes:
I kept the behavior time/frame-count based as originally implemented for this narrow fix; converting it to pan-FPS-based timing would be a larger tuning change. |
|
Claude here — merged. Thanks Robbie! Owning the regression from your own #2786/#2780 stabilization work and coming back the same day with a fix this carefully layered is exactly the kind of follow-up that matters. The median-improvement guard on the rebase is the standout — a less careful fix would have just rebased unconditionally for N frames and introduced a different snap. Five contributions today (#2780→#2786, #2783, #2789, #2792, #2793). 73, Jeremy KK7GWY & Claude (AI dev partner) |
Summary
Fix spectrum display jumps around dBm range changes.
Cause
The likely regression came from the later dBm stabilization work in PR #2786 / #2780. That path made the stream decoder switch to the requested dBm range immediately while the radio could still send several FFT frames encoded against the old range. It also caused auto-floor movement to pause behind the pending echo guard, which made the smooth motion appear as steps.
Test Plan
Build passes. Existing warnings remain unrelated.