Signed-off-by: falkTX <falktx@falktx.com>pull/272/head
@@ -0,0 +1,41 @@ | |||||
/** | |||||
* One-pole LPF for smooth parameter changes | |||||
* | |||||
* https://www.musicdsp.org/en/latest/Filters/257-1-pole-lpf-for-smooth-parameter-changes.html | |||||
*/ | |||||
#ifndef C_PARAM_SMOOTH_H | |||||
#define C_PARAM_SMOOTH_H | |||||
#include <math.h> | |||||
#define TWO_PI 6.283185307179586476925286766559f | |||||
class CParamSmooth { | |||||
public: | |||||
CParamSmooth(float smoothingTimeMs, float samplingRate) | |||||
: t(smoothingTimeMs) | |||||
{ | |||||
setSampleRate(samplingRate); | |||||
} | |||||
~CParamSmooth() { } | |||||
void setSampleRate(float samplingRate) { | |||||
if (samplingRate != fs) { | |||||
fs = samplingRate; | |||||
a = exp(-TWO_PI / (t * 0.001f * samplingRate)); | |||||
b = 1.0f - a; | |||||
z = 0.0f; | |||||
} | |||||
} | |||||
inline float process(float in) { | |||||
return z = (in * b) + (z * a); | |||||
} | |||||
private: | |||||
float a, b, t, z; | |||||
double fs = 0.0; | |||||
}; | |||||
#endif // #ifndef C_PARAM_SMOOTH_H |
@@ -0,0 +1,145 @@ | |||||
/* | |||||
* Simple Gain audio effect for DISTRHO Plugin Framework (DPF) | |||||
* SPDX-License-Identifier: MIT | |||||
* | |||||
* Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru> | |||||
* Copyright (C) 2021 Filipe Coelho <falktx@falktx.com> | |||||
* | |||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||||
* or without fee is hereby granted, provided that the above copyright notice and this | |||||
* permission notice appear in all copies. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |||||
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |||||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||||
*/ | |||||
/** | |||||
The plugin name.@n | |||||
This is used to identify your plugin before a Plugin instance can be created. | |||||
@note This macro is required. | |||||
*/ | |||||
#define DISTRHO_PLUGIN_NAME "ImguiSimpleGain" | |||||
/** | |||||
Number of audio inputs the plugin has. | |||||
@note This macro is required. | |||||
*/ | |||||
#define DISTRHO_PLUGIN_NUM_INPUTS 2 | |||||
/** | |||||
Number of audio outputs the plugin has. | |||||
@note This macro is required. | |||||
*/ | |||||
#define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | |||||
/** | |||||
The plugin URI when exporting in LV2 format. | |||||
@note This macro is required. | |||||
*/ | |||||
#define DISTRHO_PLUGIN_URI "http://distrho.sf.net/examples/imguisimplegain" | |||||
/** | |||||
Wherever the plugin has a custom %UI. | |||||
@see DISTRHO_UI_USE_NANOVG | |||||
@see UI | |||||
*/ | |||||
#define DISTRHO_PLUGIN_HAS_UI 1 | |||||
/** | |||||
Wherever the plugin processing is realtime-safe.@n | |||||
TODO - list rtsafe requirements | |||||
*/ | |||||
#define DISTRHO_PLUGIN_IS_RT_SAFE 1 | |||||
/** | |||||
Wherever the plugin is a synth.@n | |||||
@ref DISTRHO_PLUGIN_WANT_MIDI_INPUT is automatically enabled when this is too. | |||||
@see DISTRHO_PLUGIN_WANT_MIDI_INPUT | |||||
*/ | |||||
#define DISTRHO_PLUGIN_IS_SYNTH 0 | |||||
/** | |||||
Enable direct access between the %UI and plugin code. | |||||
@see UI::getPluginInstancePointer() | |||||
@note DO NOT USE THIS UNLESS STRICTLY NECESSARY!! | |||||
Try to avoid it at all costs! | |||||
*/ | |||||
#define DISTRHO_PLUGIN_WANT_DIRECT_ACCESS 0 | |||||
/** | |||||
Wherever the plugin introduces latency during audio or midi processing. | |||||
@see Plugin::setLatency(uint32_t) | |||||
*/ | |||||
#define DISTRHO_PLUGIN_WANT_LATENCY 0 | |||||
/** | |||||
Wherever the plugin wants MIDI input.@n | |||||
This is automatically enabled if @ref DISTRHO_PLUGIN_IS_SYNTH is true. | |||||
*/ | |||||
#define DISTRHO_PLUGIN_WANT_MIDI_INPUT 0 | |||||
/** | |||||
Wherever the plugin wants MIDI output. | |||||
@see Plugin::writeMidiEvent(const MidiEvent&) | |||||
*/ | |||||
#define DISTRHO_PLUGIN_WANT_MIDI_OUTPUT 0 | |||||
/** | |||||
Wherever the plugin provides its own internal programs. | |||||
@see Plugin::initProgramName(uint32_t, String&) | |||||
@see Plugin::loadProgram(uint32_t) | |||||
*/ | |||||
#define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | |||||
/** | |||||
Wherever the plugin uses internal non-parameter data. | |||||
@see Plugin::initState(uint32_t, String&, String&) | |||||
@see Plugin::setState(const char*, const char*) | |||||
*/ | |||||
#define DISTRHO_PLUGIN_WANT_STATE 0 | |||||
/** | |||||
Wherever the plugin wants time position information from the host. | |||||
@see Plugin::getTimePosition() | |||||
*/ | |||||
#define DISTRHO_PLUGIN_WANT_TIMEPOS 0 | |||||
/** | |||||
Wherever the %UI uses NanoVG for drawing instead of the default raw OpenGL calls.@n | |||||
When enabled your %UI instance will subclass @ref NanoWidget instead of @ref Widget. | |||||
*/ | |||||
#define DISTRHO_UI_USE_NANOVG 0 | |||||
/** | |||||
The %UI URI when exporting in LV2 format.@n | |||||
By default this is set to @ref DISTRHO_PLUGIN_URI with "#UI" as suffix. | |||||
*/ | |||||
#define DISTRHO_UI_URI DISTRHO_PLUGIN_URI "#UI" | |||||
/** | |||||
Wherever the %UI uses a custom toolkit implementation based on OpenGL.@n | |||||
When enabled, the macros @ref DISTRHO_UI_CUSTOM_INCLUDE_PATH and @ref DISTRHO_UI_CUSTOM_WIDGET_TYPE are required. | |||||
*/ | |||||
#define DISTRHO_UI_USE_CUSTOM 1 | |||||
/** | |||||
The include path to the header file used by the custom toolkit implementation. | |||||
This path must be relative to dpf/distrho/DistrhoUI.hpp | |||||
@see DISTRHO_UI_USE_CUSTOM | |||||
*/ | |||||
#define DISTRHO_UI_CUSTOM_INCLUDE_PATH "ImGuiUI.hpp" | |||||
/** | |||||
The top-level-widget typedef to use for the custom toolkit. | |||||
This widget class MUST be a subclass of DGL TopLevelWindow class. | |||||
It is recommended that you keep this widget class inside the DGL namespace, | |||||
and define widget type as e.g. DGL_NAMESPACE::MyCustomTopLevelWidget. | |||||
@see DISTRHO_UI_USE_CUSTOM | |||||
*/ | |||||
#define DISTRHO_UI_CUSTOM_WIDGET_TYPE DGL_NAMESPACE::ImGuiUI | |||||
#define DISTRHO_UI_USER_RESIZABLE 1 |
@@ -0,0 +1,35 @@ | |||||
/* | |||||
* DISTRHO Plugin Framework (DPF) | |||||
* Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru> | |||||
* | |||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||||
* or without fee is hereby granted, provided that the above copyright notice and this | |||||
* permission notice appear in all copies. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |||||
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |||||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||||
*/ | |||||
#include <imgui.h> | |||||
#if !defined(IMGUI_GL2) && !defined(IMGUI_GL3) | |||||
# define IMGUI_GL2 1 | |||||
#endif | |||||
#if defined(IMGUI_GL2) | |||||
# include <imgui_impl_opengl2.h> | |||||
#elif defined(IMGUI_GL3) | |||||
# include <imgui_impl_opengl3.h> | |||||
#endif | |||||
#include <imgui.cpp> | |||||
#include <imgui_draw.cpp> | |||||
#include <imgui_tables.cpp> | |||||
#include <imgui_widgets.cpp> | |||||
#if defined(IMGUI_GL2) | |||||
#include <imgui_impl_opengl2.cpp> | |||||
#elif defined(IMGUI_GL3) | |||||
#include <imgui_impl_opengl3.cpp> | |||||
#endif |
@@ -0,0 +1,316 @@ | |||||
/* | |||||
* DISTRHO Plugin Framework (DPF) | |||||
* Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru> | |||||
* | |||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||||
* or without fee is hereby granted, provided that the above copyright notice and this | |||||
* permission notice appear in all copies. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |||||
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |||||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||||
*/ | |||||
#include "Application.hpp" | |||||
#include <GL/glew.h> | |||||
#include "ImGuiUI.hpp" | |||||
#include <imgui.h> | |||||
#if !defined(IMGUI_GL2) && !defined(IMGUI_GL3) | |||||
# define IMGUI_GL2 1 | |||||
#endif | |||||
#if defined(IMGUI_GL2) | |||||
# include <imgui_impl_opengl2.h> | |||||
#elif defined(IMGUI_GL3) | |||||
# include <imgui_impl_opengl3.h> | |||||
#endif | |||||
#include <chrono> | |||||
#include <cmath> | |||||
START_NAMESPACE_DGL | |||||
struct ImGuiUI::Impl | |||||
{ | |||||
explicit Impl(ImGuiUI* self); | |||||
~Impl(); | |||||
void setupGL(); | |||||
void cleanupGL(); | |||||
// perhaps DPF will implement this in the future | |||||
float getScaleFactor() const { return 1.0f; } | |||||
static int mouseButtonToImGui(int button); | |||||
ImGuiUI* fSelf = nullptr; | |||||
ImGuiContext* fContext = nullptr; | |||||
Color fBackgroundColor{0.25f, 0.25f, 0.25f}; | |||||
int fRepaintIntervalMs = 15; | |||||
using Clock = std::chrono::steady_clock; | |||||
Clock::time_point fLastRepainted; | |||||
bool fWasEverPainted = false; | |||||
}; | |||||
ImGuiUI::ImGuiUI(Window& windowToMapTo) | |||||
: TopLevelWidget(windowToMapTo), | |||||
fImpl(new ImGuiUI::Impl(this)) | |||||
{ | |||||
getApp().addIdleCallback(this); | |||||
} | |||||
ImGuiUI::~ImGuiUI() | |||||
{ | |||||
delete fImpl; | |||||
} | |||||
void ImGuiUI::setBackgroundColor(Color color) | |||||
{ | |||||
fImpl->fBackgroundColor = color; | |||||
} | |||||
void ImGuiUI::setRepaintInterval(int intervalMs) | |||||
{ | |||||
fImpl->fRepaintIntervalMs = intervalMs; | |||||
} | |||||
void ImGuiUI::onDisplay() | |||||
{ | |||||
ImGui::SetCurrentContext(fImpl->fContext); | |||||
#if defined(IMGUI_GL2) | |||||
ImGui_ImplOpenGL2_NewFrame(); | |||||
#elif defined(IMGUI_GL3) | |||||
ImGui_ImplOpenGL3_NewFrame(); | |||||
#endif | |||||
ImGui::NewFrame(); | |||||
onImGuiDisplay(); | |||||
ImGui::Render(); | |||||
ImGuiIO &io = ImGui::GetIO(); | |||||
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); | |||||
Color backgroundColor = fImpl->fBackgroundColor; | |||||
glClearColor( | |||||
backgroundColor.red, backgroundColor.green, | |||||
backgroundColor.blue, backgroundColor.alpha); | |||||
glClear(GL_COLOR_BUFFER_BIT); | |||||
glLoadIdentity(); | |||||
#if defined(IMGUI_GL2) | |||||
ImGui_ImplOpenGL2_RenderDrawData(ImGui::GetDrawData()); | |||||
#elif defined(IMGUI_GL3) | |||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData()); | |||||
#endif | |||||
fImpl->fLastRepainted = Impl::Clock::now(); | |||||
fImpl->fWasEverPainted = true; | |||||
} | |||||
bool ImGuiUI::onKeyboard(const KeyboardEvent& event) | |||||
{ | |||||
ImGui::SetCurrentContext(fImpl->fContext); | |||||
ImGuiIO &io = ImGui::GetIO(); | |||||
if (event.press) | |||||
io.AddInputCharacter(event.key); | |||||
int imGuiKey = event.key; | |||||
if (imGuiKey >= 0 && imGuiKey < 128) | |||||
{ | |||||
if (imGuiKey >= 'a' && imGuiKey <= 'z') | |||||
imGuiKey = imGuiKey - 'a' + 'A'; | |||||
io.KeysDown[imGuiKey] = event.press; | |||||
} | |||||
return io.WantCaptureKeyboard; | |||||
} | |||||
bool ImGuiUI::onSpecial(const SpecialEvent& event) | |||||
{ | |||||
ImGui::SetCurrentContext(fImpl->fContext); | |||||
ImGuiIO &io = ImGui::GetIO(); | |||||
int imGuiKey = IM_ARRAYSIZE(io.KeysDown) - event.key; | |||||
io.KeysDown[imGuiKey] = event.press; | |||||
switch (event.key) | |||||
{ | |||||
case kKeyShift: | |||||
io.KeyShift = event.press; | |||||
break; | |||||
case kKeyControl: | |||||
io.KeyCtrl = event.press; | |||||
break; | |||||
case kKeyAlt: | |||||
io.KeyAlt = event.press; | |||||
break; | |||||
case kKeySuper: | |||||
io.KeySuper = event.press; | |||||
break; | |||||
default: | |||||
break; | |||||
} | |||||
return io.WantCaptureKeyboard; | |||||
} | |||||
bool ImGuiUI::onMouse(const MouseEvent& event) | |||||
{ | |||||
ImGui::SetCurrentContext(fImpl->fContext); | |||||
ImGuiIO &io = ImGui::GetIO(); | |||||
int imGuiButton = Impl::mouseButtonToImGui(event.button); | |||||
if (imGuiButton != -1) | |||||
io.MouseDown[imGuiButton] = event.press; | |||||
return io.WantCaptureMouse; | |||||
} | |||||
bool ImGuiUI::onMotion(const MotionEvent& event) | |||||
{ | |||||
ImGui::SetCurrentContext(fImpl->fContext); | |||||
ImGuiIO &io = ImGui::GetIO(); | |||||
const float scaleFactor = fImpl->getScaleFactor(); | |||||
io.MousePos.x = std::round(scaleFactor * event.pos.getX()); | |||||
io.MousePos.y = std::round(scaleFactor * event.pos.getY()); | |||||
return false; | |||||
} | |||||
bool ImGuiUI::onScroll(const ScrollEvent& event) | |||||
{ | |||||
ImGui::SetCurrentContext(fImpl->fContext); | |||||
ImGuiIO &io = ImGui::GetIO(); | |||||
io.MouseWheel += event.delta.getY(); | |||||
io.MouseWheelH += event.delta.getX(); | |||||
return io.WantCaptureMouse; | |||||
} | |||||
void ImGuiUI::onResize(const ResizeEvent& event) | |||||
{ | |||||
TopLevelWidget::onResize(event); | |||||
const uint width = event.size.getWidth(); | |||||
const uint height = event.size.getHeight(); | |||||
ImGui::SetCurrentContext(fImpl->fContext); | |||||
ImGuiIO &io = ImGui::GetIO(); | |||||
const float scaleFactor = fImpl->getScaleFactor(); | |||||
io.DisplaySize.x = std::round(scaleFactor * width); | |||||
io.DisplaySize.y = std::round(scaleFactor * height); | |||||
} | |||||
void ImGuiUI::idleCallback() | |||||
{ | |||||
bool shouldRepaint; | |||||
if (fImpl->fWasEverPainted) | |||||
{ | |||||
Impl::Clock::duration elapsed = | |||||
Impl::Clock::now() - fImpl->fLastRepainted; | |||||
std::chrono::milliseconds elapsedMs = | |||||
std::chrono::duration_cast<std::chrono::milliseconds>(elapsed); | |||||
shouldRepaint = elapsedMs.count() > fImpl->fRepaintIntervalMs; | |||||
} | |||||
else | |||||
{ | |||||
shouldRepaint = true; | |||||
} | |||||
if (shouldRepaint) | |||||
repaint(); | |||||
} | |||||
ImGuiUI::Impl::Impl(ImGuiUI* self) | |||||
: fSelf(self) | |||||
{ | |||||
setupGL(); | |||||
} | |||||
ImGuiUI::Impl::~Impl() | |||||
{ | |||||
cleanupGL(); | |||||
} | |||||
void ImGuiUI::Impl::setupGL() | |||||
{ | |||||
DISTRHO_SAFE_ASSERT_RETURN(glewInit() == 0,); | |||||
IMGUI_CHECKVERSION(); | |||||
fContext = ImGui::CreateContext(); | |||||
ImGui::SetCurrentContext(fContext); | |||||
ImGuiIO &io = ImGui::GetIO(); | |||||
const float scaleFactor = getScaleFactor(); | |||||
io.DisplaySize.x = std::round(scaleFactor * fSelf->getWidth()); | |||||
io.DisplaySize.y = std::round(scaleFactor * fSelf->getHeight()); | |||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; | |||||
io.IniFilename = nullptr; | |||||
io.KeyMap[ImGuiKey_Tab] = '\t'; | |||||
io.KeyMap[ImGuiKey_LeftArrow] = IM_ARRAYSIZE(io.KeysDown) - kKeyLeft; | |||||
io.KeyMap[ImGuiKey_RightArrow] = IM_ARRAYSIZE(io.KeysDown) - kKeyRight; | |||||
io.KeyMap[ImGuiKey_UpArrow] = IM_ARRAYSIZE(io.KeysDown) - kKeyUp; | |||||
io.KeyMap[ImGuiKey_DownArrow] = IM_ARRAYSIZE(io.KeysDown) - kKeyDown; | |||||
io.KeyMap[ImGuiKey_PageUp] = IM_ARRAYSIZE(io.KeysDown) - kKeyPageUp; | |||||
io.KeyMap[ImGuiKey_PageDown] = IM_ARRAYSIZE(io.KeysDown) - kKeyPageDown; | |||||
io.KeyMap[ImGuiKey_Home] = IM_ARRAYSIZE(io.KeysDown) - kKeyHome; | |||||
io.KeyMap[ImGuiKey_End] = IM_ARRAYSIZE(io.KeysDown) - kKeyEnd; | |||||
io.KeyMap[ImGuiKey_Insert] = IM_ARRAYSIZE(io.KeysDown) - kKeyInsert; | |||||
io.KeyMap[ImGuiKey_Delete] = 127; | |||||
io.KeyMap[ImGuiKey_Backspace] = '\b'; | |||||
io.KeyMap[ImGuiKey_Space] = ' '; | |||||
io.KeyMap[ImGuiKey_Enter] = '\r'; | |||||
io.KeyMap[ImGuiKey_Escape] = 27; | |||||
io.KeyMap[ImGuiKey_A] = 'A'; | |||||
io.KeyMap[ImGuiKey_C] = 'C'; | |||||
io.KeyMap[ImGuiKey_V] = 'V'; | |||||
io.KeyMap[ImGuiKey_X] = 'X'; | |||||
io.KeyMap[ImGuiKey_Y] = 'Y'; | |||||
io.KeyMap[ImGuiKey_Z] = 'Z'; | |||||
#if defined(IMGUI_GL2) | |||||
ImGui_ImplOpenGL2_Init(); | |||||
#elif defined(IMGUI_GL3) | |||||
ImGui_ImplOpenGL3_Init(); | |||||
#endif | |||||
} | |||||
void ImGuiUI::Impl::cleanupGL() | |||||
{ | |||||
ImGui::SetCurrentContext(fContext); | |||||
#if defined(IMGUI_GL2) | |||||
ImGui_ImplOpenGL2_Shutdown(); | |||||
#elif defined(IMGUI_GL3) | |||||
ImGui_ImplOpenGL3_Shutdown(); | |||||
#endif | |||||
ImGui::DestroyContext(fContext); | |||||
} | |||||
int ImGuiUI::Impl::mouseButtonToImGui(int button) | |||||
{ | |||||
switch (button) | |||||
{ | |||||
default: | |||||
return -1; | |||||
case 1: | |||||
return 0; | |||||
case 2: | |||||
return 2; | |||||
case 3: | |||||
return 1; | |||||
} | |||||
} | |||||
END_NAMESPACE_DGL |
@@ -0,0 +1,56 @@ | |||||
/* | |||||
* DISTRHO Plugin Framework (DPF) | |||||
* Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru> | |||||
* | |||||
* Permission to use, copy, modify, and/or distribute this software for any purpose with | |||||
* or without fee is hereby granted, provided that the above copyright notice and this | |||||
* permission notice appear in all copies. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |||||
* TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |||||
* NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |||||
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |||||
* IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |||||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |||||
*/ | |||||
#pragma once | |||||
#include "TopLevelWidget.hpp" | |||||
#include "Color.hpp" | |||||
#ifndef DGL_OPENGL | |||||
# error ImGUI is only available in OpenGL mode | |||||
#endif | |||||
START_NAMESPACE_DGL | |||||
/** | |||||
ImGui user interface class. | |||||
*/ | |||||
class ImGuiUI : public TopLevelWidget, | |||||
public IdleCallback { | |||||
public: | |||||
ImGuiUI(Window& windowToMapTo); | |||||
~ImGuiUI() override; | |||||
void setBackgroundColor(Color color); | |||||
void setRepaintInterval(int intervalMs); | |||||
protected: | |||||
virtual void onImGuiDisplay() = 0; | |||||
virtual void onDisplay() override; | |||||
virtual bool onKeyboard(const KeyboardEvent& event) override; | |||||
virtual bool onSpecial(const SpecialEvent& event) override; | |||||
virtual bool onMouse(const MouseEvent& event) override; | |||||
virtual bool onMotion(const MotionEvent& event) override; | |||||
virtual bool onScroll(const ScrollEvent& event) override; | |||||
virtual void onResize(const ResizeEvent& event) override; | |||||
virtual void idleCallback() override; | |||||
private: | |||||
struct Impl; | |||||
Impl* fImpl; | |||||
}; | |||||
END_NAMESPACE_DGL |
@@ -0,0 +1,51 @@ | |||||
#!/usr/bin/make -f | |||||
# Makefile for DISTRHO Plugins # | |||||
# ---------------------------- # | |||||
# Created by falkTX, Christopher Arndt, and Patrick Desaulniers | |||||
# | |||||
# -------------------------------------------------------------- | |||||
# Project name, used for binaries | |||||
NAME = d_ImguiSimpleGain | |||||
# -------------------------------------------------------------- | |||||
# Files to build | |||||
FILES_DSP = \ | |||||
PluginSimpleGain.cpp | |||||
FILES_UI = \ | |||||
UISimpleGain.cpp \ | |||||
ImGuiUI.cpp \ | |||||
ImGuiSrc.cpp | |||||
# -------------------------------------------------------------- | |||||
# Do some magic | |||||
include ../../Makefile.plugins.mk | |||||
BUILD_CXX_FLAGS += -I../../../imgui -I../../../imgui/backends | |||||
BUILD_CXX_FLAGS += $(shell $(PKG_CONFIG) glew --cflags) | |||||
LINK_FLAGS += $(shell $(PKG_CONFIG) glew --libs) | |||||
# -------------------------------------------------------------- | |||||
# Enable all selected plugin types | |||||
ifeq ($(HAVE_JACK),true) | |||||
ifeq ($(HAVE_OPENGL),true) | |||||
TARGETS += jack | |||||
endif | |||||
endif | |||||
ifeq ($(HAVE_OPENGL),true) | |||||
TARGETS += lv2_sep | |||||
else | |||||
TARGETS += lv2_dsp | |||||
endif | |||||
TARGETS += vst | |||||
all: $(TARGETS) | |||||
# -------------------------------------------------------------- |
@@ -0,0 +1,161 @@ | |||||
/* | |||||
* Simple Gain audio effect based on DISTRHO Plugin Framework (DPF) | |||||
* | |||||
* SPDX-License-Identifier: MIT | |||||
* | |||||
* Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru> | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
* of this software and associated documentation files (the "Software"), to | |||||
* deal in the Software without restriction, including without limitation the | |||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | |||||
* sell copies of the Software, and to permit persons to whom the Software is | |||||
* furnished to do so, subject to the following conditions: | |||||
* | |||||
* The above copyright notice and this permission notice shall be included in | |||||
* all copies or substantial portions of the Software. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |||||
* IN THE SOFTWARE. | |||||
*/ | |||||
#include "PluginSimpleGain.hpp" | |||||
START_NAMESPACE_DISTRHO | |||||
// ----------------------------------------------------------------------- | |||||
PluginSimpleGain::PluginSimpleGain() | |||||
: Plugin(paramCount, presetCount, 0) // paramCount param(s), presetCount program(s), 0 states | |||||
{ | |||||
smooth_gain = new CParamSmooth(20.0f, getSampleRate()); | |||||
for (unsigned p = 0; p < paramCount; ++p) { | |||||
Parameter param; | |||||
initParameter(p, param); | |||||
setParameterValue(p, param.ranges.def); | |||||
} | |||||
} | |||||
PluginSimpleGain::~PluginSimpleGain() { | |||||
delete smooth_gain; | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// Init | |||||
void PluginSimpleGain::initParameter(uint32_t index, Parameter& parameter) { | |||||
if (index >= paramCount) | |||||
return; | |||||
parameter.ranges.min = -90.0f; | |||||
parameter.ranges.max = 30.0f; | |||||
parameter.ranges.def = -0.0f; | |||||
parameter.unit = "db"; | |||||
parameter.hints = kParameterIsAutomable; | |||||
switch (index) { | |||||
case paramGain: | |||||
parameter.name = "Gain (dB)"; | |||||
parameter.shortName = "Gain"; | |||||
parameter.symbol = "gain"; | |||||
break; | |||||
} | |||||
} | |||||
/** | |||||
Set the name of the program @a index. | |||||
This function will be called once, shortly after the plugin is created. | |||||
*/ | |||||
void PluginSimpleGain::initProgramName(uint32_t index, String& programName) { | |||||
if (index < presetCount) { | |||||
programName = factoryPresets[index].name; | |||||
} | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// Internal data | |||||
/** | |||||
Optional callback to inform the plugin about a sample rate change. | |||||
*/ | |||||
void PluginSimpleGain::sampleRateChanged(double newSampleRate) { | |||||
fSampleRate = newSampleRate; | |||||
smooth_gain->setSampleRate(newSampleRate); | |||||
} | |||||
/** | |||||
Get the current value of a parameter. | |||||
*/ | |||||
float PluginSimpleGain::getParameterValue(uint32_t index) const { | |||||
return fParams[index]; | |||||
} | |||||
/** | |||||
Change a parameter value. | |||||
*/ | |||||
void PluginSimpleGain::setParameterValue(uint32_t index, float value) { | |||||
fParams[index] = value; | |||||
switch (index) { | |||||
case paramGain: | |||||
gain = DB_CO(CLAMP(fParams[paramGain], -90.0, 30.0)); | |||||
break; | |||||
} | |||||
} | |||||
/** | |||||
Load a program. | |||||
The host may call this function from any context, | |||||
including realtime processing. | |||||
*/ | |||||
void PluginSimpleGain::loadProgram(uint32_t index) { | |||||
if (index < presetCount) { | |||||
for (int i=0; i < paramCount; i++) { | |||||
setParameterValue(i, factoryPresets[index].params[i]); | |||||
} | |||||
} | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// Process | |||||
void PluginSimpleGain::activate() { | |||||
// plugin is activated | |||||
} | |||||
void PluginSimpleGain::run(const float** inputs, float** outputs, | |||||
uint32_t frames) { | |||||
// get the left and right audio inputs | |||||
const float* const inpL = inputs[0]; | |||||
const float* const inpR = inputs[1]; | |||||
// get the left and right audio outputs | |||||
float* const outL = outputs[0]; | |||||
float* const outR = outputs[1]; | |||||
// apply gain against all samples | |||||
for (uint32_t i=0; i < frames; ++i) { | |||||
float gainval = smooth_gain->process(gain); | |||||
outL[i] = inpL[i] * gainval; | |||||
outR[i] = inpR[i] * gainval; | |||||
} | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
Plugin* createPlugin() { | |||||
return new PluginSimpleGain(); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DISTRHO |
@@ -0,0 +1,161 @@ | |||||
/* | |||||
* Simple Gain audio effect based on DISTRHO Plugin Framework (DPF) | |||||
* | |||||
* SPDX-License-Identifier: MIT | |||||
* | |||||
* Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru> | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
* of this software and associated documentation files (the "Software"), to | |||||
* deal in the Software without restriction, including without limitation the | |||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | |||||
* sell copies of the Software, and to permit persons to whom the Software is | |||||
* furnished to do so, subject to the following conditions: | |||||
* | |||||
* The above copyright notice and this permission notice shall be included in | |||||
* all copies or substantial portions of the Software. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |||||
* IN THE SOFTWARE. | |||||
*/ | |||||
#ifndef PLUGIN_SIMPLEGAIN_H | |||||
#define PLUGIN_SIMPLEGAIN_H | |||||
#include "DistrhoPlugin.hpp" | |||||
#include "CParamSmooth.hpp" | |||||
START_NAMESPACE_DISTRHO | |||||
#ifndef MIN | |||||
#define MIN(a,b) ( (a) < (b) ? (a) : (b) ) | |||||
#endif | |||||
#ifndef MAX | |||||
#define MAX(a,b) ( (a) > (b) ? (a) : (b) ) | |||||
#endif | |||||
#ifndef CLAMP | |||||
#define CLAMP(v, min, max) (MIN((max), MAX((min), (v)))) | |||||
#endif | |||||
#ifndef DB_CO | |||||
#define DB_CO(g) ((g) > -90.0f ? powf(10.0f, (g) * 0.05f) : 0.0f) | |||||
#endif | |||||
// ----------------------------------------------------------------------- | |||||
class PluginSimpleGain : public Plugin { | |||||
public: | |||||
enum Parameters { | |||||
paramGain = 0, | |||||
paramCount | |||||
}; | |||||
PluginSimpleGain(); | |||||
~PluginSimpleGain(); | |||||
protected: | |||||
// ------------------------------------------------------------------- | |||||
// Information | |||||
const char* getLabel() const noexcept override { | |||||
return "SimpleGain"; | |||||
} | |||||
const char* getDescription() const override { | |||||
return "A simple audio volume gain plugin"; | |||||
} | |||||
const char* getMaker() const noexcept override { | |||||
return "example.com"; | |||||
} | |||||
const char* getHomePage() const override { | |||||
return "https://example.com/plugins/simplegain"; | |||||
} | |||||
const char* getLicense() const noexcept override { | |||||
return "https://spdx.org/licenses/MIT"; | |||||
} | |||||
uint32_t getVersion() const noexcept override { | |||||
return d_version(0, 1, 0); | |||||
} | |||||
// Go to: | |||||
// | |||||
// http://service.steinberg.de/databases/plugin.nsf/plugIn | |||||
// | |||||
// Get a proper plugin UID and fill it in here! | |||||
int64_t getUniqueId() const noexcept override { | |||||
return d_cconst('a', 'b', 'c', 'd'); | |||||
} | |||||
// ------------------------------------------------------------------- | |||||
// Init | |||||
void initParameter(uint32_t index, Parameter& parameter) override; | |||||
void initProgramName(uint32_t index, String& programName) override; | |||||
// ------------------------------------------------------------------- | |||||
// Internal data | |||||
float getParameterValue(uint32_t index) const override; | |||||
void setParameterValue(uint32_t index, float value) override; | |||||
void loadProgram(uint32_t index) override; | |||||
// ------------------------------------------------------------------- | |||||
// Optional | |||||
// Optional callback to inform the plugin about a sample rate change. | |||||
void sampleRateChanged(double newSampleRate) override; | |||||
// ------------------------------------------------------------------- | |||||
// Process | |||||
void activate() override; | |||||
void run(const float**, float** outputs, uint32_t frames) override; | |||||
// ------------------------------------------------------------------- | |||||
private: | |||||
float fParams[paramCount]; | |||||
double fSampleRate; | |||||
float gain; | |||||
CParamSmooth *smooth_gain; | |||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(PluginSimpleGain) | |||||
}; | |||||
struct Preset { | |||||
const char* name; | |||||
float params[PluginSimpleGain::paramCount]; | |||||
}; | |||||
const Preset factoryPresets[] = { | |||||
{ | |||||
"Unity Gain", | |||||
{0.0f} | |||||
} | |||||
//,{ | |||||
// "Another preset", // preset name | |||||
// {-14.0f, ...} // array of presetCount float param values | |||||
//} | |||||
}; | |||||
const uint presetCount = sizeof(factoryPresets) / sizeof(Preset); | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DISTRHO | |||||
#endif // #ifndef PLUGIN_SIMPLEGAIN_H |
@@ -0,0 +1,130 @@ | |||||
/* | |||||
* Simple Gain audio effect based on DISTRHO Plugin Framework (DPF) | |||||
* | |||||
* SPDX-License-Identifier: MIT | |||||
* | |||||
* Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru> | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
* of this software and associated documentation files (the "Software"), to | |||||
* deal in the Software without restriction, including without limitation the | |||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | |||||
* sell copies of the Software, and to permit persons to whom the Software is | |||||
* furnished to do so, subject to the following conditions: | |||||
* | |||||
* The above copyright notice and this permission notice shall be included in | |||||
* all copies or substantial portions of the Software. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |||||
* IN THE SOFTWARE. | |||||
*/ | |||||
#include "UISimpleGain.hpp" | |||||
#include <imgui.h> | |||||
// #include "Window.hpp" | |||||
START_NAMESPACE_DISTRHO | |||||
// ----------------------------------------------------------------------- | |||||
// Init / Deinit | |||||
UISimpleGain::UISimpleGain() | |||||
: UI(600, 400) | |||||
{ | |||||
setGeometryConstraints(600, 400, true); | |||||
} | |||||
UISimpleGain::~UISimpleGain() { | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// DSP/Plugin callbacks | |||||
/** | |||||
A parameter has changed on the plugin side. | |||||
This is called by the host to inform the UI about parameter changes. | |||||
*/ | |||||
void UISimpleGain::parameterChanged(uint32_t index, float value) { | |||||
params[index] = value; | |||||
switch (index) { | |||||
case PluginSimpleGain::paramGain: | |||||
// do something when Gain param is set, such as update a widget | |||||
break; | |||||
} | |||||
(void)value; | |||||
} | |||||
/** | |||||
A program has been loaded on the plugin side. | |||||
This is called by the host to inform the UI about program changes. | |||||
*/ | |||||
void UISimpleGain::programLoaded(uint32_t index) { | |||||
if (index < presetCount) { | |||||
for (int i=0; i < PluginSimpleGain::paramCount; i++) { | |||||
// set values for each parameter and update their widgets | |||||
parameterChanged(i, factoryPresets[index].params[i]); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
Optional callback to inform the UI about a sample rate change on the plugin side. | |||||
*/ | |||||
void UISimpleGain::sampleRateChanged(double newSampleRate) { | |||||
(void)newSampleRate; | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
// Widget callbacks | |||||
/** | |||||
A function called to draw the view contents. | |||||
*/ | |||||
void UISimpleGain::onImGuiDisplay() { | |||||
float width = getWidth(); | |||||
float height = getHeight(); | |||||
float margin = 20.0f; | |||||
ImGui::SetNextWindowPos(ImVec2(margin, margin)); | |||||
ImGui::SetNextWindowSize(ImVec2(width - 2 * margin, height - 2 * margin)); | |||||
if (ImGui::Begin("Simple gain")) { | |||||
static char aboutText[256] = | |||||
"This is a demo plugin made with ImGui.\n"; | |||||
ImGui::InputTextMultiline("About", aboutText, sizeof(aboutText)); | |||||
float& gain = params[PluginSimpleGain::paramGain]; | |||||
if (ImGui::SliderFloat("Gain (dB)", &gain, -90.0f, 30.0f)) | |||||
{ | |||||
if (ImGui::IsItemActivated()) | |||||
{ | |||||
editParameter(PluginSimpleGain::paramGain, true); | |||||
} | |||||
setParameterValue(PluginSimpleGain::paramGain, gain); | |||||
} | |||||
if (ImGui::IsItemDeactivated()) | |||||
{ | |||||
editParameter(PluginSimpleGain::paramGain, false); | |||||
} | |||||
} | |||||
ImGui::End(); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
UI* createUI() { | |||||
return new UISimpleGain(); | |||||
} | |||||
// ----------------------------------------------------------------------- | |||||
END_NAMESPACE_DISTRHO |
@@ -0,0 +1,55 @@ | |||||
/* | |||||
* Simple Gain audio effect based on DISTRHO Plugin Framework (DPF) | |||||
* | |||||
* SPDX-License-Identifier: MIT | |||||
* | |||||
* Copyright (C) 2021 Jean Pierre Cimalando <jp-dev@inbox.ru> | |||||
* | |||||
* Permission is hereby granted, free of charge, to any person obtaining a copy | |||||
* of this software and associated documentation files (the "Software"), to | |||||
* deal in the Software without restriction, including without limitation the | |||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | |||||
* sell copies of the Software, and to permit persons to whom the Software is | |||||
* furnished to do so, subject to the following conditions: | |||||
* | |||||
* The above copyright notice and this permission notice shall be included in | |||||
* all copies or substantial portions of the Software. | |||||
* | |||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | |||||
* IN THE SOFTWARE. | |||||
*/ | |||||
#ifndef UI_SIMPLEGAIN_H | |||||
#define UI_SIMPLEGAIN_H | |||||
#include "DistrhoUI.hpp" | |||||
#include "PluginSimpleGain.hpp" | |||||
START_NAMESPACE_DISTRHO | |||||
class UISimpleGain : public UI { | |||||
public: | |||||
UISimpleGain(); | |||||
~UISimpleGain(); | |||||
protected: | |||||
void parameterChanged(uint32_t, float value) override; | |||||
void programLoaded(uint32_t index) override; | |||||
void sampleRateChanged(double newSampleRate) override; | |||||
void onImGuiDisplay() override; | |||||
private: | |||||
float params[PluginSimpleGain::paramCount] {}; | |||||
DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(UISimpleGain) | |||||
}; | |||||
END_NAMESPACE_DISTRHO | |||||
#endif |