peak trace: limit min/max freq.
This commit is contained in:
@@ -63,6 +63,7 @@ void Measurements::findPeaks(const std::vector<float>& spectrumDB, int maxN,
|
|||||||
|
|
||||||
void Measurements::update(const std::vector<float>& spectrumDB,
|
void Measurements::update(const std::vector<float>& spectrumDB,
|
||||||
double sampleRate, bool isIQ, int fftSize) {
|
double sampleRate, bool isIQ, int fftSize) {
|
||||||
|
lastSampleRate_ = sampleRate;
|
||||||
// Always track global peak (for the readout label).
|
// Always track global peak (for the readout label).
|
||||||
if (!spectrumDB.empty()) {
|
if (!spectrumDB.empty()) {
|
||||||
auto it = std::max_element(spectrumDB.begin(), spectrumDB.end());
|
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_.dB = *it;
|
||||||
globalPeak_.freq = binToFreq(bin, sampleRate, isIQ, fftSize);
|
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;
|
constexpr int kMaxHistory = 4096;
|
||||||
if (static_cast<int>(peakHistBins_.size()) < kMaxHistory)
|
if (static_cast<int>(peakHistBins_.size()) < kMaxHistory)
|
||||||
peakHistBins_.resize(kMaxHistory, -1);
|
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;
|
peakHistIdx_ = (peakHistIdx_ + 1) % kMaxHistory;
|
||||||
peakHistBins_[peakHistIdx_] = bin;
|
peakHistBins_[peakHistIdx_] = traceBin;
|
||||||
if (peakHistLen_ < kMaxHistory) ++peakHistLen_;
|
if (peakHistLen_ < kMaxHistory) ++peakHistLen_;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -222,6 +241,21 @@ void Measurements::drawWaterfall(const SpectrumDisplay& specDisplay,
|
|||||||
|
|
||||||
void Measurements::drawPanel() {
|
void Measurements::drawPanel() {
|
||||||
ImGui::Checkbox("Peak trace", &showPeakTrace);
|
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;
|
if (!enabled) return;
|
||||||
|
|
||||||
ImGui::SetNextItemWidth(-1);
|
ImGui::SetNextItemWidth(-1);
|
||||||
|
|||||||
@@ -46,11 +46,14 @@ public:
|
|||||||
bool showOnSpectrum = true; // draw markers on spectrum
|
bool showOnSpectrum = true; // draw markers on spectrum
|
||||||
bool showOnWaterfall = false; // draw vertical lines on waterfall
|
bool showOnWaterfall = false; // draw vertical lines on waterfall
|
||||||
bool showPeakTrace = false; // draw peak history curve 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:
|
private:
|
||||||
PeakInfo globalPeak_; // always-tracked highest peak
|
PeakInfo globalPeak_; // always-tracked highest peak
|
||||||
std::vector<PeakInfo> peaks_;
|
std::vector<PeakInfo> peaks_;
|
||||||
|
|
||||||
|
double lastSampleRate_ = 48000.0;
|
||||||
// Peak history for waterfall trace (circular buffer, newest at peakHistIdx_)
|
// Peak history for waterfall trace (circular buffer, newest at peakHistIdx_)
|
||||||
std::vector<int> peakHistBins_; // bin index per waterfall line
|
std::vector<int> peakHistBins_; // bin index per waterfall line
|
||||||
int peakHistIdx_ = 0;
|
int peakHistIdx_ = 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user