Browse Source

Add ImguiSimpleGain example, WIP

Signed-off-by: falkTX <falktx@falktx.com>
pull/272/head
falkTX 4 years ago
parent
commit
1682712841
Signed by: falkTX <falktx@falktx.com> GPG Key ID: CDBAA37ABC74FBA0
10 changed files with 1151 additions and 0 deletions
  1. +41
    -0
      examples/ImguiSimpleGain/CParamSmooth.hpp
  2. +145
    -0
      examples/ImguiSimpleGain/DistrhoPluginInfo.h
  3. +35
    -0
      examples/ImguiSimpleGain/ImGuiSrc.cpp
  4. +316
    -0
      examples/ImguiSimpleGain/ImGuiUI.cpp
  5. +56
    -0
      examples/ImguiSimpleGain/ImGuiUI.hpp
  6. +51
    -0
      examples/ImguiSimpleGain/Makefile
  7. +161
    -0
      examples/ImguiSimpleGain/PluginSimpleGain.cpp
  8. +161
    -0
      examples/ImguiSimpleGain/PluginSimpleGain.hpp
  9. +130
    -0
      examples/ImguiSimpleGain/UISimpleGain.cpp
  10. +55
    -0
      examples/ImguiSimpleGain/UISimpleGain.hpp

+ 41
- 0
examples/ImguiSimpleGain/CParamSmooth.hpp View File

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

+ 145
- 0
examples/ImguiSimpleGain/DistrhoPluginInfo.h View File

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

+ 35
- 0
examples/ImguiSimpleGain/ImGuiSrc.cpp View File

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

+ 316
- 0
examples/ImguiSimpleGain/ImGuiUI.cpp View File

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

+ 56
- 0
examples/ImguiSimpleGain/ImGuiUI.hpp View File

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

+ 51
- 0
examples/ImguiSimpleGain/Makefile View File

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

# --------------------------------------------------------------

+ 161
- 0
examples/ImguiSimpleGain/PluginSimpleGain.cpp View File

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

+ 161
- 0
examples/ImguiSimpleGain/PluginSimpleGain.hpp View File

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

+ 130
- 0
examples/ImguiSimpleGain/UISimpleGain.cpp View File

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

+ 55
- 0
examples/ImguiSimpleGain/UISimpleGain.hpp View File

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

Loading…
Cancel
Save