From d2ca7e745e4fecc5bf4e2914932a52e5a81353fa Mon Sep 17 00:00:00 2001 From: ericek111 Date: Thu, 9 Apr 2026 11:37:39 +0200 Subject: [PATCH] fix the peak trace line running out of sync with the waterfall due to 793df68b --- src/ui/Application.cpp | 18 ++++++++++--- src/ui/Measurements.cpp | 58 +++++++++++++++++++++++------------------ src/ui/Measurements.h | 4 +++ 3 files changed, 50 insertions(+), 30 deletions(-) diff --git a/src/ui/Application.cpp b/src/ui/Application.cpp index b9caded..23143a4 100644 --- a/src/ui/Application.cpp +++ b/src/ui/Application.cpp @@ -316,6 +316,10 @@ void Application::processAudio() { // Push ALL new spectra to the waterfall so that the scroll rate // is determined by the audio sample rate, not the display refresh. + int curCh = std::clamp(ui_.waterfallChannel, 0, nSpec - 1); + const auto& traceHist = audio_.getWaterfallHistory(curCh); + int traceHistSz = static_cast(traceHist.size()); + if (ui_.waterfallMultiCh && nSpec > 1) { // For multi-channel: replay the last spectraThisFrame entries // from channel 0's history to get per-step data. Other @@ -353,16 +357,22 @@ void Application::processAudio() { } } waterfall_.pushLineMulti(wfSpectra, wfInfo, ui_.minDB, ui_.maxDB); + + // Push peak trace entry synchronized with each waterfall line. + int tIdx = std::max(0, traceHistSz - (histSz - si)); + measurements_.pushPeakTrace(traceHist[tIdx], + settings.sampleRate, settings.isIQ, settings.fftSize); } } else { - int wfCh = std::clamp(ui_.waterfallChannel, 0, nSpec - 1); - const auto& hist = audio_.getWaterfallHistory(wfCh); + const auto& hist = audio_.getWaterfallHistory(curCh); int histSz = static_cast(hist.size()); int start = std::max(0, histSz - spectraThisFrame); - for (int si = start; si < histSz; ++si) + for (int si = start; si < histSz; ++si) { waterfall_.pushLine(hist[si], ui_.minDB, ui_.maxDB); + measurements_.pushPeakTrace(hist[si], + settings.sampleRate, settings.isIQ, settings.fftSize); + } } - int curCh = std::clamp(ui_.waterfallChannel, 0, nSpec - 1); cursors_.update(audio_.getSpectrum(curCh), settings.sampleRate, settings.isIQ, settings.fftSize); measurements_.update(audio_.getSpectrum(curCh), diff --git a/src/ui/Measurements.cpp b/src/ui/Measurements.cpp index 497cf3a..3f563ba 100644 --- a/src/ui/Measurements.cpp +++ b/src/ui/Measurements.cpp @@ -61,6 +61,38 @@ void Measurements::findPeaks(const std::vector& spectrumDB, int maxN, } } +void Measurements::pushPeakTrace(const std::vector& spectrumDB, + double sampleRate, bool isIQ, int fftSize) { + if (spectrumDB.empty()) return; + + constexpr int kMaxHistory = 4096; + if (static_cast(peakHistBins_.size()) < kMaxHistory) + peakHistBins_.resize(kMaxHistory, -1); + + auto it = std::max_element(spectrumDB.begin(), spectrumDB.end()); + int traceBin = static_cast(std::distance(spectrumDB.begin(), it)); + + // Optionally restrict to a frequency range. + int bins = static_cast(spectrumDB.size()); + if (traceMinFreq > 0.0f || traceMaxFreq > 0.0f) { + double fMin = isIQ ? -sampleRate / 2.0 : 0.0; + double fMax = isIQ ? sampleRate / 2.0 : sampleRate / 2.0; + int loB = 0, hiB = bins - 1; + if (traceMinFreq > 0.0f) + loB = std::max(0, static_cast((traceMinFreq - fMin) / (fMax - fMin) * bins)); + if (traceMaxFreq > 0.0f) + hiB = std::min(bins - 1, static_cast((traceMaxFreq - fMin) / (fMax - fMin) * bins)); + if (loB <= hiB) { + auto rangeIt = std::max_element(spectrumDB.begin() + loB, spectrumDB.begin() + hiB + 1); + traceBin = static_cast(std::distance(spectrumDB.begin(), rangeIt)); + } + } + + peakHistIdx_ = (peakHistIdx_ + 1) % kMaxHistory; + peakHistBins_[peakHistIdx_] = traceBin; + if (peakHistLen_ < kMaxHistory) ++peakHistLen_; +} + void Measurements::update(const std::vector& spectrumDB, double sampleRate, bool isIQ, int fftSize) { lastSampleRate_ = sampleRate; @@ -71,32 +103,6 @@ void Measurements::update(const std::vector& spectrumDB, globalPeak_.bin = bin; globalPeak_.dB = *it; globalPeak_.freq = binToFreq(bin, sampleRate, isIQ, fftSize); - - // Push into peak history circular buffer (with optional freq range filter) - constexpr int kMaxHistory = 4096; - if (static_cast(peakHistBins_.size()) < kMaxHistory) - peakHistBins_.resize(kMaxHistory, -1); - - // Find peak within the trace frequency range - int traceBin = bin; - int bins = static_cast(spectrumDB.size()); - if (traceMinFreq > 0.0f || traceMaxFreq > 0.0f) { - double fMin = isIQ ? -sampleRate / 2.0 : 0.0; - double fMax = isIQ ? sampleRate / 2.0 : sampleRate / 2.0; - int loB = 0, hiB = bins - 1; - if (traceMinFreq > 0.0f) - loB = std::max(0, static_cast((traceMinFreq - fMin) / (fMax - fMin) * bins)); - if (traceMaxFreq > 0.0f) - hiB = std::min(bins - 1, static_cast((traceMaxFreq - fMin) / (fMax - fMin) * bins)); - if (loB <= hiB) { - auto rangeIt = std::max_element(spectrumDB.begin() + loB, spectrumDB.begin() + hiB + 1); - traceBin = static_cast(std::distance(spectrumDB.begin(), rangeIt)); - } - } - - peakHistIdx_ = (peakHistIdx_ + 1) % kMaxHistory; - peakHistBins_[peakHistIdx_] = traceBin; - if (peakHistLen_ < kMaxHistory) ++peakHistLen_; } if (!enabled) { peaks_.clear(); return; } diff --git a/src/ui/Measurements.h b/src/ui/Measurements.h index 7e6eab1..5da442c 100644 --- a/src/ui/Measurements.h +++ b/src/ui/Measurements.h @@ -18,6 +18,10 @@ public: void update(const std::vector& spectrumDB, double sampleRate, bool isIQ, int fftSize); + // Push a single peak trace entry for this spectrum (call once per waterfall line). + void pushPeakTrace(const std::vector& spectrumDB, + double sampleRate, bool isIQ, int fftSize); + // Draw markers on the spectrum display area. void draw(const SpectrumDisplay& specDisplay, float posX, float posY, float sizeX, float sizeY,