mirror of
https://github.com/AlexandreRouma/SDRPlusPlus.git
synced 2024-12-26 02:48:31 +01:00
Added new deemphasis mode + new image widget
This commit is contained in:
parent
5483268f8f
commit
f1a231b791
66
core/src/gui/widgets/image.cpp
Normal file
66
core/src/gui/widgets/image.cpp
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
#include <gui/widgets/image.h>
|
||||||
|
|
||||||
|
namespace ImGui {
|
||||||
|
ImageDisplay::ImageDisplay(int width, int height, GLenum format) {
|
||||||
|
_width = width;
|
||||||
|
_height = height;
|
||||||
|
_format = format;
|
||||||
|
buffer = malloc(_width * _height * 4);
|
||||||
|
activeBuffer = malloc(_width * _height * 4);
|
||||||
|
memset(buffer, 0, _width * _height * 4);
|
||||||
|
memset(activeBuffer, 0, _width * _height * 4);
|
||||||
|
|
||||||
|
glGenTextures(1, &textureId);
|
||||||
|
}
|
||||||
|
|
||||||
|
ImageDisplay::~ImageDisplay() {
|
||||||
|
free(buffer);
|
||||||
|
free(activeBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageDisplay::draw(const ImVec2& size_arg) {
|
||||||
|
std::lock_guard<std::mutex> lck(bufferMtx);
|
||||||
|
|
||||||
|
ImGuiWindow* window = GetCurrentWindow();
|
||||||
|
ImGuiStyle& style = GetStyle();
|
||||||
|
float pad = style.FramePadding.y;
|
||||||
|
ImVec2 min = window->DC.CursorPos;
|
||||||
|
|
||||||
|
// Calculate scale
|
||||||
|
float width = CalcItemWidth();
|
||||||
|
float height = roundf((width / (float)_width) * (float)_height);
|
||||||
|
|
||||||
|
ImVec2 size = CalcItemSize(size_arg, CalcItemWidth(), height);
|
||||||
|
ImRect bb(min, ImVec2(min.x+size.x, min.y+size.y));
|
||||||
|
float lineHeight = size.y;
|
||||||
|
|
||||||
|
ItemSize(size, style.FramePadding.y);
|
||||||
|
if (!ItemAdd(bb, 0)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newData) {
|
||||||
|
newData = false;
|
||||||
|
updateTexture();
|
||||||
|
}
|
||||||
|
|
||||||
|
window->DrawList->AddImage((void*)(intptr_t)textureId, min, ImVec2(min.x + width, min.y + height));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageDisplay::swap() {
|
||||||
|
std::lock_guard<std::mutex> lck(bufferMtx);
|
||||||
|
void* tmp = activeBuffer;
|
||||||
|
activeBuffer = buffer;
|
||||||
|
buffer = tmp;
|
||||||
|
newData = true;
|
||||||
|
memset(buffer, 0, _width * _height * 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ImageDisplay::updateTexture() {
|
||||||
|
glBindTexture(GL_TEXTURE_2D, textureId);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||||
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||||
|
glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
|
||||||
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, _width, _height, 0, GL_RGBA, GL_UNSIGNED_BYTE, activeBuffer);
|
||||||
|
}
|
||||||
|
}
|
34
core/src/gui/widgets/image.h
Normal file
34
core/src/gui/widgets/image.h
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <imgui.h>
|
||||||
|
#include <imgui_internal.h>
|
||||||
|
#include <dsp/stream.h>
|
||||||
|
#include <mutex>
|
||||||
|
#include <GL/glew.h>
|
||||||
|
|
||||||
|
namespace ImGui {
|
||||||
|
class ImageDisplay {
|
||||||
|
public:
|
||||||
|
ImageDisplay(int width, int height, GLenum format);
|
||||||
|
~ImageDisplay();
|
||||||
|
void draw(const ImVec2& size_arg = ImVec2(0, 0));
|
||||||
|
void swap();
|
||||||
|
|
||||||
|
void* buffer;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateTexture();
|
||||||
|
|
||||||
|
std::mutex bufferMtx;
|
||||||
|
void* activeBuffer;
|
||||||
|
|
||||||
|
int _width;
|
||||||
|
int _height;
|
||||||
|
GLenum _format;
|
||||||
|
|
||||||
|
GLuint textureId;
|
||||||
|
|
||||||
|
bool newData = false;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
119
core/src/utils/optionlist.h
Normal file
119
core/src/utils/optionlist.h
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
template <class K, class T>
|
||||||
|
class OptionList {
|
||||||
|
public:
|
||||||
|
void define(K key, std::string name, T value) {
|
||||||
|
if (keyExists(key)) { throw std::runtime_error("Key already exists"); }
|
||||||
|
if (nameExists(name)) { throw std::runtime_error("Name already exists"); }
|
||||||
|
if (valueExists(value)) { throw std::runtime_error("Value already exists"); }
|
||||||
|
keys.push_back(key);
|
||||||
|
names.push_back(name);
|
||||||
|
values.push_back(value);
|
||||||
|
updateText();
|
||||||
|
}
|
||||||
|
|
||||||
|
void define(std::string name, T value) {
|
||||||
|
define(name, name, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void undefined(int id) {
|
||||||
|
keys.erase(id);
|
||||||
|
names.erase(id);
|
||||||
|
values.erase(id);
|
||||||
|
updateText();
|
||||||
|
}
|
||||||
|
|
||||||
|
void undefineKey(K key) {
|
||||||
|
undefined(keyId(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
void undefineName(std::string name) {
|
||||||
|
undefined(nameId(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
void undefineValue(T value) {
|
||||||
|
undefined(valueId(value));
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
keys.clear();
|
||||||
|
names.clear();
|
||||||
|
values.clear();
|
||||||
|
updateText();
|
||||||
|
}
|
||||||
|
|
||||||
|
int size() {
|
||||||
|
return keys.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool keyExists(K key) {
|
||||||
|
if (std::find(keys.begin(), keys.end(), key) != keys.end()) { return true; }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nameExists(std::string name) {
|
||||||
|
if (std::find(names.begin(), names.end(), name) != names.end()) { return true; }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool valueExists(T value) {
|
||||||
|
if (std::find(values.begin(), values.end(), value) != values.end()) { return true; }
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int keyId(K key) {
|
||||||
|
auto it = std::find(keys.begin(), keys.end(), key);
|
||||||
|
if (it == keys.end()) { throw std::runtime_error("Key doesn't exists"); }
|
||||||
|
return std::distance(keys.begin(), it);
|
||||||
|
}
|
||||||
|
|
||||||
|
int nameId(std::string name) {
|
||||||
|
auto it = std::find(names.begin(), names.end(), name);
|
||||||
|
if (it == names.end()) { throw std::runtime_error("Name doesn't exists"); }
|
||||||
|
return std::distance(names.begin(), it);
|
||||||
|
}
|
||||||
|
|
||||||
|
int valueId(T value) {
|
||||||
|
auto it = std::find(values.begin(), values.end(), value);
|
||||||
|
if (it == values.end()) { throw std::runtime_error("Value doesn't exists"); }
|
||||||
|
return std::distance(values.begin(), it);
|
||||||
|
}
|
||||||
|
|
||||||
|
K key(int id) {
|
||||||
|
return keys[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name(int id) {
|
||||||
|
return names[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
T value(int id) {
|
||||||
|
return values[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
T operator [](int& id) {
|
||||||
|
return value(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* txt = NULL;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateText() {
|
||||||
|
_txt.clear();
|
||||||
|
for (auto& name : names) {
|
||||||
|
_txt += name;
|
||||||
|
_txt += '\0';
|
||||||
|
}
|
||||||
|
txt = _txt.c_str();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> keys;
|
||||||
|
std::vector<std::string> names;
|
||||||
|
std::vector<T> values;
|
||||||
|
std::string _txt;
|
||||||
|
|
||||||
|
};
|
@ -6,6 +6,7 @@
|
|||||||
#include <utils/event.h>
|
#include <utils/event.h>
|
||||||
|
|
||||||
enum DeemphasisMode {
|
enum DeemphasisMode {
|
||||||
|
DEEMP_MODE_22US,
|
||||||
DEEMP_MODE_50US,
|
DEEMP_MODE_50US,
|
||||||
DEEMP_MODE_75US,
|
DEEMP_MODE_75US,
|
||||||
DEEMP_MODE_NONE,
|
DEEMP_MODE_NONE,
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
#include <dsp/chain.h>
|
#include <dsp/chain.h>
|
||||||
#include <dsp/noise_reduction.h>
|
#include <dsp/noise_reduction.h>
|
||||||
#include <core.h>
|
#include <core.h>
|
||||||
|
#include <utils/optionlist.h>
|
||||||
#include "radio_interface.h"
|
#include "radio_interface.h"
|
||||||
#include "demod.h"
|
#include "demod.h"
|
||||||
|
|
||||||
@ -15,18 +16,23 @@ ConfigManager config;
|
|||||||
|
|
||||||
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
#define CONCAT(a, b) ((std::string(a) + b).c_str())
|
||||||
|
|
||||||
const double DeemphasisModes[] {
|
std::map<DeemphasisMode, double> deempTaus = {
|
||||||
50e-6,
|
{DEEMP_MODE_22US, 22e-6},
|
||||||
75e-6
|
{DEEMP_MODE_50US, 50e-6},
|
||||||
|
{DEEMP_MODE_75US, 75e-6}
|
||||||
};
|
};
|
||||||
|
|
||||||
const char* DeemhasisModesTxt = "50µs\00075µs\000None\000";
|
|
||||||
|
|
||||||
class RadioModule : public ModuleManager::Instance {
|
class RadioModule : public ModuleManager::Instance {
|
||||||
public:
|
public:
|
||||||
RadioModule(std::string name) {
|
RadioModule(std::string name) {
|
||||||
this->name = name;
|
this->name = name;
|
||||||
|
|
||||||
|
// Intialize option lists
|
||||||
|
deempModes.define("None", DEEMP_MODE_NONE);
|
||||||
|
deempModes.define("22us", DEEMP_MODE_22US);
|
||||||
|
deempModes.define("50us", DEEMP_MODE_50US);
|
||||||
|
deempModes.define("75us", DEEMP_MODE_75US);
|
||||||
|
|
||||||
// Initialize the config if it doesn't exist
|
// Initialize the config if it doesn't exist
|
||||||
bool created = false;
|
bool created = false;
|
||||||
config.acquire();
|
config.acquire();
|
||||||
@ -243,8 +249,8 @@ private:
|
|||||||
if (_this->deempAllowed) {
|
if (_this->deempAllowed) {
|
||||||
ImGui::LeftLabel("De-emphasis");
|
ImGui::LeftLabel("De-emphasis");
|
||||||
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
ImGui::SetNextItemWidth(menuWidth - ImGui::GetCursorPosX());
|
||||||
if (ImGui::Combo(("##_radio_wfm_deemp_" + _this->name).c_str(), &_this->deempMode, DeemhasisModesTxt)) {
|
if (ImGui::Combo(("##_radio_wfm_deemp_" + _this->name).c_str(), &_this->deempId, _this->deempModes.txt)) {
|
||||||
_this->setDeemphasisMode(_this->deempMode);
|
_this->setDeemphasisMode(_this->deempModes[_this->deempId]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -336,7 +342,7 @@ private:
|
|||||||
snapInterval = selectedDemod->getDefaultSnapInterval();
|
snapInterval = selectedDemod->getDefaultSnapInterval();
|
||||||
squelchLevel = MIN_SQUELCH;
|
squelchLevel = MIN_SQUELCH;
|
||||||
deempAllowed = selectedDemod->getDeempAllowed();
|
deempAllowed = selectedDemod->getDeempAllowed();
|
||||||
deempMode = selectedDemod->getDefaultDeemphasisMode();
|
deempId = deempModes.valueId((DeemphasisMode)selectedDemod->getDefaultDeemphasisMode());
|
||||||
squelchEnabled = false;
|
squelchEnabled = false;
|
||||||
postProcEnabled = selectedDemod->getPostProcEnabled();
|
postProcEnabled = selectedDemod->getPostProcEnabled();
|
||||||
FMIFNRAllowed = selectedDemod->getFMIFNRAllowed();
|
FMIFNRAllowed = selectedDemod->getFMIFNRAllowed();
|
||||||
@ -359,7 +365,15 @@ private:
|
|||||||
squelchEnabled = config.conf[name][selectedDemod->getName()]["squelchEnabled"];
|
squelchEnabled = config.conf[name][selectedDemod->getName()]["squelchEnabled"];
|
||||||
}
|
}
|
||||||
if (config.conf[name][selectedDemod->getName()].contains("deempMode")) {
|
if (config.conf[name][selectedDemod->getName()].contains("deempMode")) {
|
||||||
deempMode = config.conf[name][selectedDemod->getName()]["deempMode"];
|
// Upgrade to the text key
|
||||||
|
if (!config.conf[name][selectedDemod->getName()]["deempMode"].is_string()) {
|
||||||
|
config.conf[name][selectedDemod->getName()]["deempMode"] = deempModes.key(deempId);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string deempOpt = config.conf[name][selectedDemod->getName()]["deempMode"];
|
||||||
|
if (deempModes.keyExists(deempOpt)) {
|
||||||
|
deempId = deempModes.keyId(deempOpt);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (config.conf[name][selectedDemod->getName()].contains("FMIFNREnabled")) {
|
if (config.conf[name][selectedDemod->getName()].contains("FMIFNREnabled")) {
|
||||||
FMIFNREnabled = config.conf[name][selectedDemod->getName()]["FMIFNREnabled"];
|
FMIFNREnabled = config.conf[name][selectedDemod->getName()]["FMIFNREnabled"];
|
||||||
@ -374,7 +388,6 @@ private:
|
|||||||
nbLevel = config.conf[name][selectedDemod->getName()]["noiseBlankerLevel"];
|
nbLevel = config.conf[name][selectedDemod->getName()]["noiseBlankerLevel"];
|
||||||
}
|
}
|
||||||
config.release();
|
config.release();
|
||||||
deempMode = std::clamp<int>(deempMode, 0, _DEEMP_MODE_COUNT-1);
|
|
||||||
|
|
||||||
// Configure VFO
|
// Configure VFO
|
||||||
if (vfo) {
|
if (vfo) {
|
||||||
@ -411,7 +424,7 @@ private:
|
|||||||
afChain.enable(&resamp);
|
afChain.enable(&resamp);
|
||||||
|
|
||||||
// Configure deemphasis
|
// Configure deemphasis
|
||||||
setDeemphasisMode(deempMode);
|
setDeemphasisMode(deempModes[deempId]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Disable everyting if post processing is disabled
|
// Disable everyting if post processing is disabled
|
||||||
@ -475,18 +488,16 @@ private:
|
|||||||
afChain.start();
|
afChain.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDeemphasisMode(int mode) {
|
void setDeemphasisMode(DeemphasisMode mode) {
|
||||||
deempMode = std::clamp<int>(mode, 0, _DEEMP_MODE_COUNT-1);
|
deempId = deempModes.valueId(mode);
|
||||||
if (!postProcEnabled || !selectedDemod) { return; }
|
if (!postProcEnabled || !selectedDemod) { return; }
|
||||||
bool deempEnabled = (deempMode != DEEMP_MODE_NONE);
|
bool deempEnabled = (mode != DEEMP_MODE_NONE);
|
||||||
if (deempEnabled) {
|
if (deempEnabled) { deemp.block.setTau(deempTaus[mode]); }
|
||||||
deemp.block.setTau(DeemphasisModes[deempMode]);
|
|
||||||
}
|
|
||||||
afChain.setState(&deemp, deempEnabled);
|
afChain.setState(&deemp, deempEnabled);
|
||||||
|
|
||||||
// Save config
|
// Save config
|
||||||
config.acquire();
|
config.acquire();
|
||||||
config.conf[name][selectedDemod->getName()]["deempMode"] = deempMode;
|
config.conf[name][selectedDemod->getName()]["deempMode"] = deempModes.key(deempId);
|
||||||
config.release(true);
|
config.release(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -643,6 +654,8 @@ private:
|
|||||||
std::array<demod::Demodulator*, _RADIO_DEMOD_COUNT> demods;
|
std::array<demod::Demodulator*, _RADIO_DEMOD_COUNT> demods;
|
||||||
demod::Demodulator* selectedDemod = NULL;
|
demod::Demodulator* selectedDemod = NULL;
|
||||||
|
|
||||||
|
OptionList<std::string, DeemphasisMode> deempModes;
|
||||||
|
|
||||||
double audioSampleRate = 48000.0;
|
double audioSampleRate = 48000.0;
|
||||||
float minBandwidth;
|
float minBandwidth;
|
||||||
float maxBandwidth;
|
float maxBandwidth;
|
||||||
@ -655,7 +668,7 @@ private:
|
|||||||
bool squelchEnabled = false;
|
bool squelchEnabled = false;
|
||||||
float squelchLevel;
|
float squelchLevel;
|
||||||
|
|
||||||
int deempMode = DEEMP_MODE_NONE;
|
int deempId = 0;
|
||||||
bool deempAllowed;
|
bool deempAllowed;
|
||||||
|
|
||||||
bool FMIFNRAllowed;
|
bool FMIFNRAllowed;
|
||||||
|
Loading…
Reference in New Issue
Block a user