diff --git a/core/src/imgui/imgui_custom.cpp b/core/src/imgui/imgui_custom.cpp new file mode 100644 index 00000000..99ad6921 --- /dev/null +++ b/core/src/imgui/imgui_custom.cpp @@ -0,0 +1,57 @@ +#include "imgui_custom.h" +#include "imgui.h" + +#ifndef IMGUI_DEFINE_MATH_OPERATORS +#define IMGUI_DEFINE_MATH_OPERATORS +#endif +#include "imgui_internal.h" + +namespace ImGui{ + void VolumeBar(float volumeL, float volumeR, float *holdL, float *holdR, const ImVec2& size_arg){ + ImGuiWindow* window = GetCurrentWindow(); + if (window->SkipItems) + return; + + ImGuiContext& g = *GImGui; + const ImGuiStyle& style = g.Style; + + ImVec2 pos = window->DC.CursorPos; + ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), g.FontSize + style.FramePadding.y * 2.0f); + ImRect bb(pos, pos + size); + ItemSize(size, style.FramePadding.y); + if (!ItemAdd(bb, 0)) + return; + + float fractionU = ImSaturate(1.0f+20*std::log10(volumeL)/60.0f); + float fractionD = ImSaturate(1.0f+20*std::log10(volumeR)/60.0f); + + *holdL = std::max(*holdL-0.005f,fractionU); + *holdR = std::max(*holdR-0.005f,fractionD); + + //Background + ImRect upbb(bb.Min, ImVec2(bb.Max.x, ImLerp(bb.Min.y, bb.Max.y, 0.4f))); + RenderRectFilledRangeH(window->DrawList, upbb, 0xff005500, 0.0f, 0.6f, 0.0f); + RenderRectFilledRangeH(window->DrawList, upbb, 0xff005555, 0.6f, 0.85f, 0.0f); + RenderRectFilledRangeH(window->DrawList, upbb, 0xff000055, 0.85f, 1.0f, 0.0f); + + ImRect dwbb(ImVec2(bb.Min.x, ImLerp(bb.Min.y, bb.Max.y, 0.6f)), bb.Max); + RenderRectFilledRangeH(window->DrawList, dwbb, 0xff005500, 0.00f, 0.6f, 0.0f); + RenderRectFilledRangeH(window->DrawList, dwbb, 0xff005555, 0.60f, 0.85f, 0.0f); + RenderRectFilledRangeH(window->DrawList, dwbb, 0xff000055, 0.85f, 1.0f, 0.0f); + + //Bar + RenderRectFilledRangeH(window->DrawList, upbb, 0xff00ff00, 0.00f, 0.60f*ImSaturate(fractionU/0.6f), 0.0f); + RenderRectFilledRangeH(window->DrawList, upbb, 0xff00ffff, 0.60f, 0.60f+0.25f*ImSaturate((fractionU-0.6f)/0.25f), 0.0f); + RenderRectFilledRangeH(window->DrawList, upbb, 0xff0000ff, 0.85f, 0.85f+0.15f*ImSaturate((fractionU-0.85f)/0.15f), 0.0f); + + RenderRectFilledRangeH(window->DrawList, dwbb, 0xff00ff00, 0.00f, 0.60f*ImSaturate(fractionD/0.6f), 0.0f); + RenderRectFilledRangeH(window->DrawList, dwbb, 0xff00ffff, 0.60f, 0.60f+0.25f*ImSaturate((fractionD-0.6f)/0.25f), 0.0f); + RenderRectFilledRangeH(window->DrawList, dwbb, 0xff0000ff, 0.85f, 0.85f+0.15f*ImSaturate((fractionD-0.85f)/0.15f), 0.0f); + + //Holders + RenderRectFilledRangeH(window->DrawList, upbb, GetColorU32(ImGuiCol_SliderGrab), *holdL, *holdL+0.01f, 0.0f); + + RenderRectFilledRangeH(window->DrawList, dwbb, GetColorU32(ImGuiCol_SliderGrab), *holdR, *holdR+0.01f, 0.0f); + + } +} diff --git a/core/src/imgui/imgui_custom.h b/core/src/imgui/imgui_custom.h new file mode 100644 index 00000000..47d4bb34 --- /dev/null +++ b/core/src/imgui/imgui_custom.h @@ -0,0 +1,6 @@ +#pragma once +#include "imgui.h" + +namespace ImGui{ + IMGUI_API void VolumeBar(float volumeL, float volumeR, float *holdL, float *holdR, const ImVec2& size_arg); +}; diff --git a/recorder/src/main.cpp b/recorder/src/main.cpp index efff67b7..26c05a4c 100644 --- a/recorder/src/main.cpp +++ b/recorder/src/main.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -58,6 +59,9 @@ public: selectedStreamId = 0; lastNameList = ""; + volumeHold = {0}; + currentVolumePeak = {0}; + config.aquire(); if (!config.conf.contains(name)) { config.conf[name]["recMode"] = 1; @@ -144,6 +148,12 @@ private: ImGui::PopStyleColor(); } + { + std::lock_guard lck(_this->volumeMtx); + ImGui::VolumeBar(_this->currentVolumePeak.l, _this->currentVolumePeak.r, &_this->volumeHold.l, &_this->volumeHold.r, ImVec2(-1.0f, 0.0f)); + _this->volumePeakShouldReset = true; + } + // TODO: Change VFO ref in signal path // TODO: Add VFO record ImGui::Columns(2, CONCAT("RecordModeColumns##_", _this->name), false); @@ -191,6 +201,7 @@ private: sigpath::signalPath.unbindIQStream(_this->iqStream); _this->writer->close(); delete _this->writer; + _this->currentVolumePeak = {0}; _this->recording = false; } uint64_t seconds = _this->samplesWritten / (uint64_t)_this->sampleRate; @@ -238,6 +249,7 @@ private: sigpath::sinkManager.unbindStream(_this->selectedStreamName, _this->audioStream); _this->writer->close(); delete _this->writer; + _this->currentVolumePeak = {0}; _this->recording = false; } uint64_t seconds = _this->samplesWritten / (uint64_t)_this->sampleRate; @@ -253,6 +265,23 @@ private: while (true) { int count = _this->audioStream->read(); if (count < 0) { break; } + + { + std::lock_guard lck(_this->volumeMtx); + if (_this->volumePeakShouldReset) { + _this->currentVolumePeak.l = 0.0f; + _this->currentVolumePeak.r = 0.0f; + _this->volumePeakShouldReset = false; + } + + for (int i = 0; i < count; i++) { + _this->currentVolumePeak.l = std::max(_this->currentVolumePeak.l, + std::abs(_this->audioStream->readBuf[i].l)); + _this->currentVolumePeak.r = std::max(_this->currentVolumePeak.r, + std::abs(_this->audioStream->readBuf[i].r)); + } + } + for (int i = 0; i < count; i++) { sampleBuf[(i * 2) + 0] = _this->audioStream->readBuf[i].l * 0x7FFF; sampleBuf[(i * 2) + 1] = _this->audioStream->readBuf[i].r * 0x7FFF; @@ -269,6 +298,23 @@ private: while (true) { int count = _this->iqStream->read(); if (count < 0) { break; } + + { + std::lock_guard lck(_this->volumeMtx); + if (_this->volumePeakShouldReset) { + _this->currentVolumePeak.l = 0.0f; + _this->currentVolumePeak.r = 0.0f; + _this->volumePeakShouldReset = false; + } + + for (int i = 0; i < count; i++) { + _this->currentVolumePeak.l = std::max(_this->currentVolumePeak.l, + std::abs(_this->iqStream->readBuf[i].q)); + _this->currentVolumePeak.r = std::max(_this->currentVolumePeak.r, + std::abs(_this->iqStream->readBuf[i].i)); + } + } + for (int i = 0; i < count; i++) { sampleBuf[(i * 2) + 0] = _this->iqStream->readBuf[i].q * 0x7FFF; sampleBuf[(i * 2) + 1] = _this->iqStream->readBuf[i].i * 0x7FFF; @@ -284,6 +330,10 @@ private: bool enabled = true; char path[4096]; bool pathValid = true; + std::mutex volumeMtx; + dsp::stereo_t currentVolumePeak; + dsp::stereo_t volumeHold; + bool volumePeakShouldReset; dsp::stream* audioStream; dsp::stream* iqStream; WavWriter* writer;