spectrogram decimation

This commit is contained in:
2026-04-09 10:20:28 +02:00
parent 793df68ba1
commit 6846c853c0
6 changed files with 23 additions and 7 deletions

View File

@@ -702,6 +702,7 @@ void Application::loadConfig() {
cursors_.snapToPeaks = config_.getBool("snap_to_peaks", cursors_.snapToPeaks);
measurements_.traceMinFreq = config_.getFloat("trace_min_freq", measurements_.traceMinFreq);
measurements_.traceMaxFreq = config_.getFloat("trace_max_freq", measurements_.traceMaxFreq);
ui_.specMinPixPerBin = config_.getInt("spec_min_pix_per_bin", ui_.specMinPixPerBin);
// Clamp
controlPanel_.fftSizeIdx = std::clamp(controlPanel_.fftSizeIdx, 0, ControlPanel::kNumFFTSizes - 1);
@@ -766,6 +767,7 @@ void Application::saveConfig() const {
cfg.setBool("snap_to_peaks", cursors_.snapToPeaks);
cfg.setFloat("trace_min_freq", measurements_.traceMinFreq);
cfg.setFloat("trace_max_freq", measurements_.traceMaxFreq);
cfg.setInt("spec_min_pix_per_bin", ui_.specMinPixPerBin);
int devIdx = audio_.deviceIdx();
if (devIdx >= 0 && devIdx < static_cast<int>(devices.size()))

View File

@@ -178,6 +178,15 @@ void ControlPanel::render(AudioEngine& audio, UIState& ui,
}
if (ImGui::IsItemHovered()) ImGui::SetTooltip("Reset to 2x zoom");
}
{
ImGui::AlignTextToFramePadding();
ImGui::Text("Decim:");
ImGui::SameLine();
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x);
ImGui::SliderInt("##decimation", &ui.specMinPixPerBin, 1, 8, "%d px/bin");
if (ImGui::IsItemHovered()) ImGui::SetTooltip("Spectrum frequency decimation (peak-detect)");
}
}
// ── Channels ──

View File

@@ -86,7 +86,7 @@ void DisplayPanel::renderSpectrum(AudioEngine& audio, UIState& ui,
specDisplay.draw(allSpectraScratch_, stylesScratch_, ui.minDB, ui.maxDB,
settings.sampleRate, settings.isIQ, ui.freqScale,
specPosX, specPosY, specSizeX, specSizeY,
ui.viewLo, ui.viewHi);
ui.viewLo, ui.viewHi, ui.specMinPixPerBin);
cursors.draw(specDisplay, specPosX, specPosY, specSizeX, specSizeY,
settings.sampleRate, settings.isIQ, ui.freqScale, ui.minDB, ui.maxDB,

View File

@@ -60,9 +60,11 @@ static void buildPolyline(const std::vector<float>& spectrumDB,
bool isIQ, FreqScale freqScale,
float posX, float posY, float sizeX, float sizeY,
float viewLo, float viewHi,
std::vector<ImVec2>& outPoints) {
std::vector<ImVec2>& outPoints,
int minPixPerBin = 1) {
int bins = static_cast<int>(spectrumDB.size());
int displayPts = std::min(bins, static_cast<int>(sizeX));
int maxPts = std::max(1, static_cast<int>(sizeX) / std::max(1, minPixPerBin));
int displayPts = std::min(bins, maxPts);
if (displayPts < 2) displayPts = 2;
outPoints.resize(displayPts);
@@ -108,7 +110,8 @@ void SpectrumDisplay::draw(const std::vector<std::vector<float>>& spectra,
FreqScale freqScale,
float posX, float posY,
float sizeX, float sizeY,
float viewLo, float viewHi) const {
float viewLo, float viewHi,
int minPixPerBin) const {
if (spectra.empty() || spectra[0].empty() || sizeX <= 0 || sizeY <= 0) return;
ImDrawList* dl = ImGui::GetWindowDrawList();
@@ -178,7 +181,7 @@ void SpectrumDisplay::draw(const std::vector<std::vector<float>>& spectra,
if (spectra[ch].empty()) continue;
buildPolyline(spectra[ch], minDB, maxDB,
isIQ, freqScale, posX, posY, sizeX, sizeY,
viewLo, viewHi, allPoints[ch]);
viewLo, viewHi, allPoints[ch], minPixPerBin);
}
// Draw spectra: all fills first, then all lines on top.
@@ -237,7 +240,7 @@ void SpectrumDisplay::draw(const std::vector<std::vector<float>>& spectra,
ImU32 col = (st.lineColor & 0x00FFFFFF) | 0x90000000;
buildPolyline(peakHold_[ch], minDB, maxDB,
isIQ, freqScale, posX, posY, sizeX, sizeY,
viewLo, viewHi, phPoints);
viewLo, viewHi, phPoints, minPixPerBin);
if (phPoints.size() >= 2)
dl->AddPolyline(phPoints.data(), static_cast<int>(phPoints.size()),
col, ImDrawFlags_None, 1.0f);

View File

@@ -22,7 +22,8 @@ public:
double sampleRate, bool isIQ,
FreqScale freqScale,
float posX, float posY, float sizeX, float sizeY,
float viewLo = 0.0f, float viewHi = 1.0f) const;
float viewLo = 0.0f, float viewHi = 1.0f,
int minPixPerBin = 1) const;
// Convenience: single-channel draw (backward compat).
void draw(const std::vector<float>& spectrumDB,

View File

@@ -17,6 +17,7 @@ struct UIState {
int waterfallChannel = 0;
bool waterfallMultiCh = true;
int specMinPixPerBin = 1; // min screen pixels per spectrum bin (1 = no decimation)
std::array<bool, kMaxChannels> channelEnabled = {true,true,true,true,true,true,true,true};
// Complementary pairs: colors at indices 0+1, 2+3, 4+5, 6+7 sum to white.
std::array<ImVec4, kMaxChannels> channelColors = {{