peak trace: limit min/max freq.

This commit is contained in:
2026-03-25 22:13:57 +01:00
parent 2f5f9c6e79
commit 2bf7ee45c8
2 changed files with 39 additions and 2 deletions

View File

@@ -63,6 +63,7 @@ void Measurements::findPeaks(const std::vector<float>& spectrumDB, int maxN,
void Measurements::update(const std::vector<float>& spectrumDB,
double sampleRate, bool isIQ, int fftSize) {
lastSampleRate_ = sampleRate;
// Always track global peak (for the readout label).
if (!spectrumDB.empty()) {
auto it = std::max_element(spectrumDB.begin(), spectrumDB.end());
@@ -71,12 +72,30 @@ void Measurements::update(const std::vector<float>& spectrumDB,
globalPeak_.dB = *it;
globalPeak_.freq = binToFreq(bin, sampleRate, isIQ, fftSize);
// Push into peak history circular buffer
// Push into peak history circular buffer (with optional freq range filter)
constexpr int kMaxHistory = 4096;
if (static_cast<int>(peakHistBins_.size()) < kMaxHistory)
peakHistBins_.resize(kMaxHistory, -1);
// Find peak within the trace frequency range
int traceBin = bin;
int bins = static_cast<int>(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<int>((traceMinFreq - fMin) / (fMax - fMin) * bins));
if (traceMaxFreq > 0.0f)
hiB = std::min(bins - 1, static_cast<int>((traceMaxFreq - fMin) / (fMax - fMin) * bins));
if (loB <= hiB) {
auto rangeIt = std::max_element(spectrumDB.begin() + loB, spectrumDB.begin() + hiB + 1);
traceBin = static_cast<int>(std::distance(spectrumDB.begin(), rangeIt));
}
}
peakHistIdx_ = (peakHistIdx_ + 1) % kMaxHistory;
peakHistBins_[peakHistIdx_] = bin;
peakHistBins_[peakHistIdx_] = traceBin;
if (peakHistLen_ < kMaxHistory) ++peakHistLen_;
}
@@ -222,6 +241,21 @@ void Measurements::drawWaterfall(const SpectrumDisplay& specDisplay,
void Measurements::drawPanel() {
ImGui::Checkbox("Peak trace", &showPeakTrace);
if (showPeakTrace) {
ImGui::SameLine();
float nyquistKHz = static_cast<float>(lastSampleRate_ / 2000.0);
float minKHz = traceMinFreq / 1000.0f;
float maxKHz = traceMaxFreq / 1000.0f;
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
if (ImGui::DragFloatRange2("##tracerange", &minKHz, &maxKHz, 0.01f,
0.0f, nyquistKHz,
minKHz > 0.0f ? "%.2f kHz" : "Min",
maxKHz > 0.0f ? "%.2f kHz" : "Max")) {
traceMinFreq = std::max(0.0f, minKHz * 1000.0f);
traceMaxFreq = std::max(0.0f, maxKHz * 1000.0f);
}
if (ImGui::IsItemHovered()) ImGui::SetTooltip("Peak trace frequency range (0 = no limit)");
}
if (!enabled) return;
ImGui::SetNextItemWidth(-1);

View File

@@ -46,11 +46,14 @@ public:
bool showOnSpectrum = true; // draw markers on spectrum
bool showOnWaterfall = false; // draw vertical lines on waterfall
bool showPeakTrace = false; // draw peak history curve on waterfall
float traceMinFreq = 0.0f; // min frequency for peak trace (Hz), 0 = no limit
float traceMaxFreq = 0.0f; // max frequency for peak trace (Hz), 0 = no limit
private:
PeakInfo globalPeak_; // always-tracked highest peak
std::vector<PeakInfo> peaks_;
double lastSampleRate_ = 48000.0;
// Peak history for waterfall trace (circular buffer, newest at peakHistIdx_)
std::vector<int> peakHistBins_; // bin index per waterfall line
int peakHistIdx_ = 0;