Added SNR meter

This commit is contained in:
Ryzerth 2021-04-30 04:28:08 +02:00
parent 3e79d4dfad
commit 96f83ee55c
5 changed files with 123 additions and 4 deletions

View File

@ -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();
}

View 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);
}
}
}

View File

@ -0,0 +1,6 @@
#pragma once
#include <imgui/imgui.h>
namespace ImGui {
void SNRMeter(float val, const ImVec2& size_arg = ImVec2(0, 0));
}

View File

@ -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();
}

View File

@ -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;