mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2024-11-10 12:47:40 +01:00
Added SNR meter
This commit is contained in:
parent
3e79d4dfad
commit
96f83ee55c
@ -32,6 +32,7 @@
|
||||
#include <gui/dialogs/loading_screen.h>
|
||||
#include <options.h>
|
||||
#include <gui/colormaps.h>
|
||||
#include <gui/widgets/snr_meter.h>
|
||||
|
||||
int fftSize = 8192 * 8;
|
||||
|
||||
@ -103,6 +104,8 @@ bool centerTuning = false;
|
||||
dsp::stream<dsp::complex_t> dummyStream;
|
||||
bool demoWindow = false;
|
||||
|
||||
float testSNR = 50;
|
||||
|
||||
void windowInit() {
|
||||
LoadingScreen::show("Initializing UI");
|
||||
gui::waterfall.init();
|
||||
@ -515,6 +518,13 @@ void drawWindow() {
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
ImGui::SetCursorPosX(ImGui::GetWindowSize().x - 387);
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() + 5);
|
||||
ImGui::SetNextItemWidth(300);
|
||||
ImGui::SNRMeter((vfo != NULL) ? gui::waterfall.selectedVFOSNR : 0);
|
||||
|
||||
ImGui::SameLine();
|
||||
|
||||
// Logo button
|
||||
ImGui::SetCursorPosX(ImGui::GetWindowSize().x - 48);
|
||||
ImGui::SetCursorPosY(10);
|
||||
@ -604,6 +614,8 @@ void drawWindow() {
|
||||
firstMenuRender = true;
|
||||
}
|
||||
|
||||
ImGui::SliderFloat("Testing SNR meter", &testSNR, 0, 100);
|
||||
|
||||
ImGui::Spacing();
|
||||
}
|
||||
|
||||
|
43
core/src/gui/widgets/snr_meter.cpp
Normal file
43
core/src/gui/widgets/snr_meter.cpp
Normal file
@ -0,0 +1,43 @@
|
||||
#include <gui/widgets/volume_meter.h>
|
||||
#include <algorithm>
|
||||
|
||||
#ifndef IMGUI_DEFINE_MATH_OPERATORS
|
||||
#define IMGUI_DEFINE_MATH_OPERATORS
|
||||
#endif
|
||||
#include <imgui/imgui_internal.h>
|
||||
|
||||
namespace ImGui {
|
||||
void SNRMeter(float val, const ImVec2& size_arg = ImVec2(0, 0)) {
|
||||
ImGuiWindow* window = GetCurrentWindow();
|
||||
ImGuiStyle& style = GImGui->Style;
|
||||
|
||||
float pad = style.FramePadding.y;
|
||||
|
||||
ImVec2 min = window->DC.CursorPos;
|
||||
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), 26);
|
||||
ImRect bb(min, min + size);
|
||||
|
||||
float lineHeight = size.y;
|
||||
|
||||
ItemSize(size, style.FramePadding.y);
|
||||
if (!ItemAdd(bb, 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
val = std::clamp<float>(val, 0, 100);
|
||||
float ratio = size.x / 90;
|
||||
float it = size.x / 9;
|
||||
char buf[32];
|
||||
|
||||
window->DrawList->AddRectFilled(min + ImVec2(0, 1), min + ImVec2(roundf((float)val * ratio), 10), IM_COL32(0, 136, 255, 255));
|
||||
window->DrawList->AddLine(min, min + ImVec2(0, 9), IM_COL32(255, 255, 255, 255));
|
||||
window->DrawList->AddLine(min + ImVec2(0, 9), min + ImVec2(size.x + 1, 9), IM_COL32(255, 255, 255, 255));
|
||||
|
||||
for (int i = 0; i < 10; i++) {
|
||||
window->DrawList->AddLine(min + ImVec2(roundf((float)i * it), 9), min + ImVec2(roundf((float)i * it), 14), IM_COL32(255, 255, 255, 255));
|
||||
sprintf(buf, "%d", i * 10);
|
||||
ImVec2 sz = ImGui::CalcTextSize(buf);
|
||||
window->DrawList->AddText(min + ImVec2(roundf(((float)i * it) - (sz.x/2.0)) + 1, 16), IM_COL32(255, 255, 255, 255), buf);
|
||||
}
|
||||
}
|
||||
}
|
6
core/src/gui/widgets/snr_meter.h
Normal file
6
core/src/gui/widgets/snr_meter.h
Normal file
@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
#include <imgui/imgui.h>
|
||||
|
||||
namespace ImGui {
|
||||
void SNRMeter(float val, const ImVec2& size_arg = ImVec2(0, 0));
|
||||
}
|
@ -288,10 +288,6 @@ namespace ImGui {
|
||||
// Next, check if a VFO was selected
|
||||
if (!targetFound) {
|
||||
for (auto const& [name, _vfo] : vfos) {
|
||||
if (name == selectedVFO) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If another VFO is selected, select it and cancel out
|
||||
if (IS_IN_AREA(mousePos, _vfo->rectMin, _vfo->rectMax) || IS_IN_AREA(mousePos, _vfo->wfRectMin, _vfo->wfRectMax)) {
|
||||
selectedVFO = name;
|
||||
@ -436,6 +432,16 @@ namespace ImGui {
|
||||
printAndScale(_vfo->bandwidth, buf);
|
||||
ImGui::Text("Bandwidth: %sHz", buf);
|
||||
ImGui::Text("Bandwidth Locked: %s", _vfo->bandwidthLocked ? "Yes" : "No");
|
||||
|
||||
float strength, snr;
|
||||
if (calculateVFOSignalInfo(_vfo, strength, snr)) {
|
||||
ImGui::Text("Strength: %0.1fdBFS", strength);
|
||||
ImGui::Text("SNR: %0.1fdB", snr);
|
||||
}
|
||||
else {
|
||||
ImGui::Text("Strength: ---.-dBFS");
|
||||
ImGui::Text("SNR: ---.-dB");
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndTooltip();
|
||||
@ -445,6 +451,50 @@ namespace ImGui {
|
||||
}
|
||||
}
|
||||
|
||||
bool WaterFall::calculateVFOSignalInfo(WaterfallVFO* _vfo, float& strength, float& snr) {
|
||||
if (rawFFTs == NULL || fftLines <= 0) { return false; }
|
||||
|
||||
// Calculate FFT index data
|
||||
double vfoMinSizeFreq = _vfo->centerOffset - _vfo->bandwidth;
|
||||
double vfoMinFreq = _vfo->centerOffset - (_vfo->bandwidth/2.0);
|
||||
double vfoMaxFreq = _vfo->centerOffset + (_vfo->bandwidth/2.0);
|
||||
double vfoMaxSizeFreq = _vfo->centerOffset + _vfo->bandwidth;
|
||||
int vfoMinSideOffset = std::clamp<int>(((vfoMinSizeFreq / (wholeBandwidth/2.0)) * (double)(rawFFTSize/2)) + (rawFFTSize/2), 0, rawFFTSize);
|
||||
int vfoMinOffset = std::clamp<int>(((vfoMinFreq / (wholeBandwidth/2.0)) * (double)(rawFFTSize/2)) + (rawFFTSize/2), 0, rawFFTSize);
|
||||
int vfoMaxOffset = std::clamp<int>(((vfoMaxFreq / (wholeBandwidth/2.0)) * (double)(rawFFTSize/2)) + (rawFFTSize/2), 0, rawFFTSize);
|
||||
int vfoMaxSideOffset = std::clamp<int>(((vfoMaxSizeFreq / (wholeBandwidth/2.0)) * (double)(rawFFTSize/2)) + (rawFFTSize/2), 0, rawFFTSize);
|
||||
|
||||
float* fftLine = &rawFFTs[currentFFTLine * rawFFTSize];
|
||||
|
||||
double avg = 0;
|
||||
float max = -INFINITY;
|
||||
int avgCount = 0;
|
||||
|
||||
// Calculate Left average
|
||||
for (int i = vfoMinSideOffset; i < vfoMinOffset; i++) {
|
||||
avg += fftLine[i];
|
||||
avgCount++;
|
||||
}
|
||||
|
||||
// Calculate Right average
|
||||
for (int i = vfoMaxOffset + 1; i < vfoMaxSideOffset; i++) {
|
||||
avg += fftLine[i];
|
||||
avgCount++;
|
||||
}
|
||||
|
||||
avg /= (double)(avgCount);
|
||||
|
||||
// Calculate max
|
||||
for (int i = vfoMinOffset; i <= vfoMaxOffset; i++) {
|
||||
if (fftLine[i] > max) { max = fftLine[i]; }
|
||||
}
|
||||
|
||||
strength = max;
|
||||
snr = max - avg;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void WaterFall::setFastFFT(bool fastFFT) {
|
||||
std::lock_guard<std::mutex> lck(buf_mtx);
|
||||
_fastFFT = fastFFT;
|
||||
@ -748,6 +798,11 @@ namespace ImGui {
|
||||
doZoom(drawDataStart, drawDataSize, dataWidth, rawFFTs, latestFFT, _fastFFT);
|
||||
fftLines = 1;
|
||||
}
|
||||
|
||||
if (selectedVFO != "" && vfos.size() > 0) {
|
||||
float dummy;
|
||||
calculateVFOSignalInfo(vfos[selectedVFO], dummy, selectedVFOSNR);
|
||||
}
|
||||
|
||||
buf_mtx.unlock();
|
||||
}
|
||||
|
@ -133,6 +133,8 @@ namespace ImGui {
|
||||
bool mouseInFFT = false;
|
||||
bool mouseInWaterfall = false;
|
||||
|
||||
float selectedVFOSNR = NAN;
|
||||
|
||||
std::map<std::string, WaterfallVFO*> vfos;
|
||||
std::string selectedVFO = "";
|
||||
bool selectedVFOChanged = false;
|
||||
@ -162,6 +164,7 @@ namespace ImGui {
|
||||
void updateWaterfallFb();
|
||||
void updateWaterfallTexture();
|
||||
void updateAllVFOs();
|
||||
bool calculateVFOSignalInfo(WaterfallVFO* vfo, float& strength, float& snr);
|
||||
|
||||
bool waterfallUpdate = false;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user