mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2024-12-25 02:18:30 +01:00
push before merge
This commit is contained in:
parent
dd4ec22b39
commit
f217804838
99
core/src/dsp/measure.h
Normal file
99
core/src/dsp/measure.h
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <dsp/block.h>
|
||||||
|
#include <fftw3.h>
|
||||||
|
#include <volk/volk.h>
|
||||||
|
#include <spdlog/spdlog.h>
|
||||||
|
#include <dsp/types.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
namespace dsp {
|
||||||
|
class VolumeMeasure : public generic_block<VolumeMeasure> {
|
||||||
|
public:
|
||||||
|
VolumeMeasure() {}
|
||||||
|
|
||||||
|
VolumeMeasure(stream<stereo_t>* in) { init(in); }
|
||||||
|
|
||||||
|
~VolumeMeasure() {
|
||||||
|
generic_block<VolumeMeasure>::stop();
|
||||||
|
delete[] leftBuf;
|
||||||
|
delete[] rightBuf;
|
||||||
|
}
|
||||||
|
|
||||||
|
void init(stream<stereo_t>* in) {
|
||||||
|
_in = in;
|
||||||
|
leftBuf = new float[STREAM_BUFFER_SIZE];
|
||||||
|
rightBuf = new float[STREAM_BUFFER_SIZE];
|
||||||
|
generic_block<VolumeMeasure>::registerInput(_in);
|
||||||
|
generic_block<VolumeMeasure>::registerOutput(&out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setInput(stream<stereo_t>* in) {
|
||||||
|
std::lock_guard<std::mutex> lck(generic_block<VolumeMeasure>::ctrlMtx);
|
||||||
|
generic_block<VolumeMeasure>::tempStop();
|
||||||
|
generic_block<VolumeMeasure>::unregisterInput(_in);
|
||||||
|
_in = in;
|
||||||
|
generic_block<VolumeMeasure>::registerInput(_in);
|
||||||
|
generic_block<VolumeMeasure>::tempStart();
|
||||||
|
}
|
||||||
|
|
||||||
|
int run() {
|
||||||
|
count = _in->read();
|
||||||
|
if (count < 0) { return -1; }
|
||||||
|
|
||||||
|
memcpy(out.writeBuf, _in->readBuf, count * sizeof(stereo_t));
|
||||||
|
volk_32fc_deinterleave_32f_x2(leftBuf, rightBuf, (lv_32fc_t*)_in->readBuf, count);
|
||||||
|
|
||||||
|
_in->flush();
|
||||||
|
if (!out.swap(count)) { return -1; }
|
||||||
|
|
||||||
|
// Get peak from last value
|
||||||
|
float time = (float)count / sampleRate;
|
||||||
|
peak.l -= peakFall * time;
|
||||||
|
peak.r -= peakFall * time;
|
||||||
|
stereo_t _peak;
|
||||||
|
_peak.l = powf(10, peak.l / 10.0f);
|
||||||
|
_peak.r = powf(10, peak.r / 10.0f);
|
||||||
|
|
||||||
|
stereo_t _average;
|
||||||
|
|
||||||
|
// Calculate average
|
||||||
|
volk_32f_s32f_power_32f(leftBuf, leftBuf, 2, count);
|
||||||
|
volk_32f_s32f_power_32f(rightBuf, rightBuf, 2, count);
|
||||||
|
volk_32f_sqrt_32f(leftBuf, leftBuf, count);
|
||||||
|
volk_32f_sqrt_32f(rightBuf, rightBuf, count);
|
||||||
|
volk_32f_accumulator_s32f(&_average.l, leftBuf, count);
|
||||||
|
volk_32f_accumulator_s32f(&_average.r, rightBuf, count);
|
||||||
|
_average.l /= (float)count;
|
||||||
|
_average.r /= (float)count;
|
||||||
|
|
||||||
|
// Calculate peak
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
if (leftBuf[i] > _peak.l) { _peak.l = leftBuf[i]; }
|
||||||
|
if (rightBuf[i] > _peak.r) { _peak.r = rightBuf[i]; }
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assign
|
||||||
|
peak.l = 10.0f * log10f(_peak.l);
|
||||||
|
peak.r = 10.0f * log10f(_peak.r);
|
||||||
|
average.l = (average.l * (1.0f - avgFilt)) + (10.0f * log10f(_average.l) * avgFilt);
|
||||||
|
average.r = (average.r * (1.0f - avgFilt)) + (10.0f * log10f(_average.r) * avgFilt);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream<stereo_t> out;
|
||||||
|
|
||||||
|
stereo_t peak = {0, 0};
|
||||||
|
stereo_t average = {0, 0};
|
||||||
|
|
||||||
|
private:
|
||||||
|
int count;
|
||||||
|
float peakFall = 10.0f; // dB/S
|
||||||
|
float avgFilt = 0.2f; // IIR filter coef
|
||||||
|
float sampleRate = 48000;
|
||||||
|
stream<stereo_t>* _in;
|
||||||
|
|
||||||
|
float* leftBuf;
|
||||||
|
float* rightBuf;
|
||||||
|
};
|
||||||
|
}
|
53
core/src/gui/widgets/volume_meter.cpp
Normal file
53
core/src/gui/widgets/volume_meter.cpp
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#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 VolumeMeter(float avg, float peak, float val_min, float val_max, const ImVec2& size_arg) {
|
||||||
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
ImGuiStyle& style = GImGui->Style;
|
||||||
|
|
||||||
|
avg = std::clamp<float>(avg, val_min, val_max);
|
||||||
|
peak = std::clamp<float>(peak, val_min, val_max);
|
||||||
|
|
||||||
|
float pad = style.FramePadding.y;
|
||||||
|
|
||||||
|
ImVec2 min = window->DC.CursorPos;
|
||||||
|
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), (GImGui->FontSize / 2) + style.FramePadding.y);
|
||||||
|
ImRect bb(min, min + size);
|
||||||
|
|
||||||
|
float lineHeight = size.y;
|
||||||
|
|
||||||
|
ItemSize(size, style.FramePadding.y);
|
||||||
|
if (!ItemAdd(bb, 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float zeroDb = roundf(((-val_min) / (val_max - val_min)) * size.x);
|
||||||
|
|
||||||
|
window->DrawList->AddRectFilled(min, min + ImVec2(zeroDb, lineHeight), IM_COL32( 0, 255, 0, 127 ));
|
||||||
|
window->DrawList->AddRectFilled(min + ImVec2(zeroDb, 0), min + ImVec2(size.x, lineHeight), IM_COL32( 255, 0, 0, 127 ));
|
||||||
|
|
||||||
|
float end = roundf(((avg - val_min) / (val_max - val_min)) * size.x);
|
||||||
|
float endP = roundf(((peak - val_min) / (val_max - val_min)) * size.x);
|
||||||
|
|
||||||
|
if (avg <= 0) {
|
||||||
|
window->DrawList->AddRectFilled(min, min + ImVec2(end, lineHeight), IM_COL32( 0, 255, 0, 255 ));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
window->DrawList->AddRectFilled(min, min + ImVec2(zeroDb, lineHeight), IM_COL32( 0, 255, 0, 255 ));
|
||||||
|
window->DrawList->AddRectFilled(min + ImVec2(zeroDb, 0), min + ImVec2(end, lineHeight), IM_COL32( 255, 0, 0, 255 ));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (peak <= 0) {
|
||||||
|
window->DrawList->AddLine(min + ImVec2(endP, -1), min + ImVec2(endP, lineHeight - 1), IM_COL32( 127, 255, 127, 255 ));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
window->DrawList->AddLine(min + ImVec2(endP, -1), min + ImVec2(endP, lineHeight - 1), IM_COL32( 255, 127, 127, 255 ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
6
core/src/gui/widgets/volume_meter.h
Normal file
6
core/src/gui/widgets/volume_meter.h
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <imgui/imgui.h>
|
||||||
|
|
||||||
|
namespace ImGui {
|
||||||
|
void VolumeMeter(float avg, float peak, float val_min, float val_max, const ImVec2& size_arg = ImVec2(0, 0));
|
||||||
|
}
|
@ -13,7 +13,6 @@
|
|||||||
#include <gui/style.h>
|
#include <gui/style.h>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
#include <options.h>
|
#include <options.h>
|
||||||
|
|
||||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||||
|
|
||||||
SDRPP_MOD_INFO {
|
SDRPP_MOD_INFO {
|
||||||
|
Loading…
Reference in New Issue
Block a user