better Hz/db formatting
This commit is contained in:
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cmath>
|
||||||
#include <complex>
|
#include <complex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -85,6 +87,28 @@ inline const char* inputFormatName(InputFormat f) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ── Formatting helpers ───────────────────────────────────────────────────────
|
||||||
|
|
||||||
|
// Format frequency into buf with fixed-width numeric field per unit range.
|
||||||
|
inline int fmtFreq(char* buf, size_t sz, double freq) {
|
||||||
|
if (std::abs(freq) >= 1e6)
|
||||||
|
return std::snprintf(buf, sz, "% 10.6f MHz", freq / 1e6);
|
||||||
|
else if (std::abs(freq) >= 1e3)
|
||||||
|
return std::snprintf(buf, sz, "% 7.3f kHz", freq / 1e3);
|
||||||
|
else
|
||||||
|
return std::snprintf(buf, sz, "% 7.1f Hz", freq);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format "label: freq, dB" into buf for sidebar display (fixed-width freq + dB).
|
||||||
|
inline int fmtFreqDB(char* buf, size_t sz, const char* label, double freq, float dB) {
|
||||||
|
if (std::abs(freq) >= 1e6)
|
||||||
|
return std::snprintf(buf, sz, "%s: % 10.6f MHz %6.1f dB", label, freq / 1e6, dB);
|
||||||
|
else if (std::abs(freq) >= 1e3)
|
||||||
|
return std::snprintf(buf, sz, "%s: % 7.3f kHz %6.1f dB", label, freq / 1e3, dB);
|
||||||
|
else
|
||||||
|
return std::snprintf(buf, sz, "%s: % 7.1f Hz %6.1f dB", label, freq, dB);
|
||||||
|
}
|
||||||
|
|
||||||
// ── Spectrum data ────────────────────────────────────────────────────────────
|
// ── Spectrum data ────────────────────────────────────────────────────────────
|
||||||
|
|
||||||
struct SpectrumLine {
|
struct SpectrumLine {
|
||||||
|
|||||||
@@ -460,13 +460,7 @@ void Application::render() {
|
|||||||
|
|
||||||
// Frequency label at top of waterfall
|
// Frequency label at top of waterfall
|
||||||
char freqLabel[48];
|
char freqLabel[48];
|
||||||
double hf = cursors_.hover.freq;
|
fmtFreq(freqLabel, sizeof(freqLabel), cursors_.hover.freq);
|
||||||
if (std::abs(hf) >= 1e6)
|
|
||||||
std::snprintf(freqLabel, sizeof(freqLabel), "%.6f MHz", hf / 1e6);
|
|
||||||
else if (std::abs(hf) >= 1e3)
|
|
||||||
std::snprintf(freqLabel, sizeof(freqLabel), "%.3f kHz", hf / 1e3);
|
|
||||||
else
|
|
||||||
std::snprintf(freqLabel, sizeof(freqLabel), "%.1f Hz", hf);
|
|
||||||
|
|
||||||
ImVec2 tSz = ImGui::CalcTextSize(freqLabel);
|
ImVec2 tSz = ImGui::CalcTextSize(freqLabel);
|
||||||
float lx = std::min(hx + 4, wfPosX_ + wfSizeX_ - tSz.x - 4);
|
float lx = std::min(hx + 4, wfPosX_ + wfSizeX_ - tSz.x - 4);
|
||||||
@@ -572,7 +566,8 @@ void Application::renderControlPanel() {
|
|||||||
if (ImGui::CollapsingHeader("FFT", ImGuiTreeNodeFlags_DefaultOpen)) {
|
if (ImGui::CollapsingHeader("FFT", ImGuiTreeNodeFlags_DefaultOpen)) {
|
||||||
const char* sizeNames[] = {"256", "512", "1024", "2048", "4096",
|
const char* sizeNames[] = {"256", "512", "1024", "2048", "4096",
|
||||||
"8192", "16384", "32768", "65536"};
|
"8192", "16384", "32768", "65536"};
|
||||||
ImGui::SetNextItemWidth(-1);
|
float halfW = (ImGui::GetContentRegionAvail().x - ImGui::GetStyle().ItemSpacing.x) * 0.5f;
|
||||||
|
ImGui::SetNextItemWidth(halfW);
|
||||||
if (ImGui::Combo("##fftsize", &fftSizeIdx_, sizeNames, kNumFFTSizes)) {
|
if (ImGui::Combo("##fftsize", &fftSizeIdx_, sizeNames, kNumFFTSizes)) {
|
||||||
settings_.fftSize = kFFTSizes[fftSizeIdx_];
|
settings_.fftSize = kFFTSizes[fftSizeIdx_];
|
||||||
updateAnalyzerSettings();
|
updateAnalyzerSettings();
|
||||||
@@ -580,9 +575,10 @@ void Application::renderControlPanel() {
|
|||||||
}
|
}
|
||||||
if (ImGui::IsItemHovered()) ImGui::SetTooltip("FFT Size");
|
if (ImGui::IsItemHovered()) ImGui::SetTooltip("FFT Size");
|
||||||
|
|
||||||
|
ImGui::SameLine();
|
||||||
const char* winNames[] = {"Rectangular", "Hann", "Hamming", "Blackman",
|
const char* winNames[] = {"Rectangular", "Hann", "Hamming", "Blackman",
|
||||||
"Blackman-Harris", "Kaiser", "Flat Top"};
|
"Blackman-Harris", "Kaiser", "Flat Top"};
|
||||||
ImGui::SetNextItemWidth(-1);
|
ImGui::SetNextItemWidth(halfW);
|
||||||
if (ImGui::Combo("##window", &windowIdx_, winNames,
|
if (ImGui::Combo("##window", &windowIdx_, winNames,
|
||||||
static_cast<int>(WindowType::Count))) {
|
static_cast<int>(WindowType::Count))) {
|
||||||
settings_.window = static_cast<WindowType>(windowIdx_);
|
settings_.window = static_cast<WindowType>(windowIdx_);
|
||||||
@@ -621,7 +617,7 @@ void Application::renderControlPanel() {
|
|||||||
ImVec2 rMax = ImGui::GetItemRectMax();
|
ImVec2 rMax = ImGui::GetItemRectMax();
|
||||||
float tx = rMin.x + ((rMax.x - rMin.x) - textSize.x) * 0.5f;
|
float tx = rMin.x + ((rMax.x - rMin.x) - textSize.x) * 0.5f;
|
||||||
float ty = rMin.y + ((rMax.y - rMin.y) - textSize.y) * 0.5f;
|
float ty = rMin.y + ((rMax.y - rMin.y) - textSize.y) * 0.5f;
|
||||||
ImGui::GetForegroundDrawList()->AddText({tx, ty}, IM_COL32(255, 255, 255, 220), overlayText);
|
ImGui::GetWindowDrawList()->AddText({tx, ty}, IM_COL32(255, 255, 255, 220), overlayText);
|
||||||
if (ImGui::IsItemHovered()) ImGui::SetTooltip("Overlap");
|
if (ImGui::IsItemHovered()) ImGui::SetTooltip("Overlap");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -635,6 +631,7 @@ void Application::renderControlPanel() {
|
|||||||
if (ImGui::IsItemHovered()) ImGui::SetTooltip("dB Range (min / max)");
|
if (ImGui::IsItemHovered()) ImGui::SetTooltip("dB Range (min / max)");
|
||||||
|
|
||||||
ImGui::Checkbox("Peak Hold", &specDisplay_.peakHoldEnable);
|
ImGui::Checkbox("Peak Hold", &specDisplay_.peakHoldEnable);
|
||||||
|
if (ImGui::IsItemHovered()) ImGui::SetTooltip("Draws a \"maximum\" line in the spectrogram");
|
||||||
if (specDisplay_.peakHoldEnable) {
|
if (specDisplay_.peakHoldEnable) {
|
||||||
ImGui::SameLine();
|
ImGui::SameLine();
|
||||||
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x
|
ImGui::SetNextItemWidth(ImGui::GetContentRegionAvail().x
|
||||||
@@ -669,6 +666,7 @@ void Application::renderControlPanel() {
|
|||||||
viewLo_ = 0.0f;
|
viewLo_ = 0.0f;
|
||||||
viewHi_ = 0.5f;
|
viewHi_ = 0.5f;
|
||||||
}
|
}
|
||||||
|
if (ImGui::IsItemHovered()) ImGui::SetTooltip("Reset to 2x zoom");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -829,12 +827,11 @@ void Application::renderControlPanel() {
|
|||||||
int pkCh2 = std::clamp(waterfallChannel_, 0, analyzer_.numSpectra() - 1);
|
int pkCh2 = std::clamp(waterfallChannel_, 0, analyzer_.numSpectra() - 1);
|
||||||
auto [peakBin, peakDB] = analyzer_.findPeak(pkCh2);
|
auto [peakBin, peakDB] = analyzer_.findPeak(pkCh2);
|
||||||
double peakFreq = analyzer_.binToFreq(peakBin);
|
double peakFreq = analyzer_.binToFreq(peakBin);
|
||||||
if (std::abs(peakFreq) >= 1e6)
|
{
|
||||||
ImGui::TextDisabled("Peak: %.6f MHz, %.1f dB", peakFreq / 1e6, peakDB);
|
char peakBuf[128];
|
||||||
else if (std::abs(peakFreq) >= 1e3)
|
fmtFreqDB(peakBuf, sizeof(peakBuf), "Peak", peakFreq, peakDB);
|
||||||
ImGui::TextDisabled("Peak: %.3f kHz, %.1f dB", peakFreq / 1e3, peakDB);
|
ImGui::TextDisabled("%s", peakBuf);
|
||||||
else
|
}
|
||||||
ImGui::TextDisabled("Peak: %.1f Hz, %.1f dB", peakFreq, peakDB);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Application::renderSpectrumPanel() {
|
void Application::renderSpectrumPanel() {
|
||||||
|
|||||||
@@ -78,12 +78,7 @@ void Cursors::draw(const SpectrumDisplay& specDisplay,
|
|||||||
|
|
||||||
// Format a cursor label string.
|
// Format a cursor label string.
|
||||||
auto formatLabel = [](char* buf, size_t sz, const char* label, double freq, float dB) {
|
auto formatLabel = [](char* buf, size_t sz, const char* label, double freq, float dB) {
|
||||||
if (std::abs(freq) >= 1e6)
|
fmtFreqDB(buf, sz, label, freq, dB);
|
||||||
std::snprintf(buf, sz, "%s: %.6f MHz %.1f dB", label, freq / 1e6, dB);
|
|
||||||
else if (std::abs(freq) >= 1e3)
|
|
||||||
std::snprintf(buf, sz, "%s: %.3f kHz %.1f dB", label, freq / 1e3, dB);
|
|
||||||
else
|
|
||||||
std::snprintf(buf, sz, "%s: %.1f Hz %.1f dB", label, freq, dB);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
float aDB = avgDBA(), bDB = avgDBB();
|
float aDB = avgDBA(), bDB = avgDBB();
|
||||||
@@ -124,12 +119,7 @@ void Cursors::draw(const SpectrumDisplay& specDisplay,
|
|||||||
double dFreq = cursorB.freq - cursorA.freq;
|
double dFreq = cursorB.freq - cursorA.freq;
|
||||||
float dDB = bDB - aDB;
|
float dDB = bDB - aDB;
|
||||||
char val1[48], val2[48];
|
char val1[48], val2[48];
|
||||||
if (std::abs(dFreq) >= 1e6)
|
fmtFreq(val1, sizeof(val1), dFreq);
|
||||||
std::snprintf(val1, sizeof(val1), "%.6f MHz", dFreq / 1e6);
|
|
||||||
else if (std::abs(dFreq) >= 1e3)
|
|
||||||
std::snprintf(val1, sizeof(val1), "%.3f kHz", dFreq / 1e3);
|
|
||||||
else
|
|
||||||
std::snprintf(val1, sizeof(val1), "%.1f Hz", dFreq);
|
|
||||||
std::snprintf(val2, sizeof(val2), "%.1f dB", dDB);
|
std::snprintf(val2, sizeof(val2), "%.1f dB", dDB);
|
||||||
|
|
||||||
ImVec2 labelSz = ImGui::CalcTextSize("dF = ");
|
ImVec2 labelSz = ImGui::CalcTextSize("dF = ");
|
||||||
@@ -138,7 +128,7 @@ void Cursors::draw(const SpectrumDisplay& specDisplay,
|
|||||||
float valW = std::max(v1Sz.x, v2Sz.x);
|
float valW = std::max(v1Sz.x, v2Sz.x);
|
||||||
float lineH = labelSz.y;
|
float lineH = labelSz.y;
|
||||||
float totalW = labelSz.x + valW;
|
float totalW = labelSz.x + valW;
|
||||||
float tx = posX + sizeX - totalW - 8;
|
float tx = posX + sizeX - totalW - 158;
|
||||||
float ty = posY + 4;
|
float ty = posY + 4;
|
||||||
ImU32 col = IM_COL32(255, 200, 100, 255);
|
ImU32 col = IM_COL32(255, 200, 100, 255);
|
||||||
float eqX = tx + labelSz.x; // values start here (right of '= ')
|
float eqX = tx + labelSz.x; // values start here (right of '= ')
|
||||||
@@ -158,12 +148,9 @@ void Cursors::drawPanel() {
|
|||||||
ImGui::TextDisabled("%s: --", label);
|
ImGui::TextDisabled("%s: --", label);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (std::abs(c.freq) >= 1e6)
|
char buf[128];
|
||||||
ImGui::Text("%s: %.6f MHz, %.1f dB", label, c.freq / 1e6, dispDB);
|
fmtFreqDB(buf, sizeof(buf), label, c.freq, dispDB);
|
||||||
else if (std::abs(c.freq) >= 1e3)
|
ImGui::Text("%s", buf);
|
||||||
ImGui::Text("%s: %.3f kHz, %.1f dB", label, c.freq / 1e3, dispDB);
|
|
||||||
else
|
|
||||||
ImGui::Text("%s: %.1f Hz, %.1f dB", label, c.freq, dispDB);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
float aDB = avgDBA(), bDB = avgDBB();
|
float aDB = avgDBA(), bDB = avgDBB();
|
||||||
@@ -173,21 +160,9 @@ void Cursors::drawPanel() {
|
|||||||
if (cursorA.active && cursorB.active) {
|
if (cursorA.active && cursorB.active) {
|
||||||
double dF = cursorB.freq - cursorA.freq;
|
double dF = cursorB.freq - cursorA.freq;
|
||||||
float dA = bDB - aDB;
|
float dA = bDB - aDB;
|
||||||
if (std::abs(dF) >= 1e6)
|
char dbuf[128];
|
||||||
ImGui::Text("D: %.6f MHz, %.1f dB", dF / 1e6, dA);
|
fmtFreqDB(dbuf, sizeof(dbuf), "D", dF, dA);
|
||||||
else if (std::abs(dF) >= 1e3)
|
ImGui::Text("%s", dbuf);
|
||||||
ImGui::Text("D: %.3f kHz, %.1f dB", dF / 1e3, dA);
|
|
||||||
else
|
|
||||||
ImGui::Text("D: %.1f Hz, %.1f dB", dF, dA);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hover.active) {
|
|
||||||
if (std::abs(hover.freq) >= 1e6)
|
|
||||||
ImGui::TextDisabled("%.6f MHz, %.1f dB", hover.freq / 1e6, hover.dB);
|
|
||||||
else if (std::abs(hover.freq) >= 1e3)
|
|
||||||
ImGui::TextDisabled("%.3f kHz, %.1f dB", hover.freq / 1e3, hover.dB);
|
|
||||||
else
|
|
||||||
ImGui::TextDisabled("%.1f Hz, %.1f dB", hover.freq, hover.dB);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Averaging slider (logarithmic scale)
|
// Averaging slider (logarithmic scale)
|
||||||
|
|||||||
@@ -186,12 +186,11 @@ void Measurements::drawPanel() {
|
|||||||
ImU32 col = (i == 0) ? IM_COL32(255, 80, 80, 255)
|
ImU32 col = (i == 0) ? IM_COL32(255, 80, 80, 255)
|
||||||
: IM_COL32(255, 140, 60, 255);
|
: IM_COL32(255, 140, 60, 255);
|
||||||
ImGui::PushStyleColor(ImGuiCol_Text, col);
|
ImGui::PushStyleColor(ImGuiCol_Text, col);
|
||||||
if (std::abs(p.freq) >= 1e6)
|
char plabel[4];
|
||||||
ImGui::Text("P%d: %.6f MHz, %.1f dB", i + 1, p.freq / 1e6, p.dB);
|
std::snprintf(plabel, sizeof(plabel), "P%d", i + 1);
|
||||||
else if (std::abs(p.freq) >= 1e3)
|
char pbuf[128];
|
||||||
ImGui::Text("P%d: %.3f kHz, %.1f dB", i + 1, p.freq / 1e3, p.dB);
|
fmtFreqDB(pbuf, sizeof(pbuf), plabel, p.freq, p.dB);
|
||||||
else
|
ImGui::Text("%s", pbuf);
|
||||||
ImGui::Text("P%d: %.1f Hz, %.1f dB", i + 1, p.freq, p.dB);
|
|
||||||
ImGui::PopStyleColor();
|
ImGui::PopStyleColor();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user