Start of ZamAudio modules, WIP/Experimental
This commit is contained in:
parent
65244f1979
commit
9be8413054
17 changed files with 8739 additions and 1 deletions
195
plugins/ZamAudio/src/compressor.cpp
Normal file
195
plugins/ZamAudio/src/compressor.cpp
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* ZamComp mono compressor for Cardinal
|
||||
* Copyright (C) 2014-2019 Damien Zammit <damien@zamaudio.com>
|
||||
* Copyright (C) 2022 Filipe Coelho <falktx@falktx.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* For a full copy of the GNU General Public License see the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "plugin.hpp"
|
||||
#include "widgets.hpp"
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
struct ZamAudioCompModule : Module {
|
||||
enum ParamIds {
|
||||
PARAM_ATTACK,
|
||||
PARAM_RELEASE,
|
||||
PARAM_THRESHOLD,
|
||||
PARAM_RATIO,
|
||||
PARAM_KNEE,
|
||||
PARAM_SLEW,
|
||||
PARAM_MAKEUP,
|
||||
NUM_PARAMS
|
||||
};
|
||||
enum InputIds {
|
||||
AUDIO_INPUT,
|
||||
SIDECHAIN_INPUT,
|
||||
NUM_INPUTS
|
||||
};
|
||||
enum OutputIds {
|
||||
AUDIO_OUTPUT,
|
||||
NUM_OUTPUTS
|
||||
};
|
||||
enum LightIds {
|
||||
OUTLEVEL,
|
||||
GAINREDUCTION,
|
||||
NUM_LIGHTS
|
||||
};
|
||||
|
||||
float gainred,outlevel; //lights
|
||||
float oldL_yl, oldL_y1, oldL_yg; //temp
|
||||
|
||||
static inline float
|
||||
sanitize_denormal(float v) {
|
||||
if(!std::isnormal(v))
|
||||
return 0.f;
|
||||
return v;
|
||||
}
|
||||
|
||||
static inline float
|
||||
from_dB(float gdb) {
|
||||
return (expf(0.05f*gdb*logf(10.f)));
|
||||
}
|
||||
|
||||
static inline float
|
||||
to_dB(float g) {
|
||||
return (20.f*log10f(g));
|
||||
}
|
||||
|
||||
ZamAudioCompModule()
|
||||
{
|
||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
|
||||
|
||||
configParam(PARAM_ATTACK, 0.1f, 100.f, 10.f, "Attack", " ms");
|
||||
configParam(PARAM_RELEASE, 1.f, 500.f, 80.f, "Release", " ms");
|
||||
configParam(PARAM_THRESHOLD, -80.f, 0.f, 0.f, "Threshold", " db");
|
||||
configParam(PARAM_RATIO, 1.f, 20.f, 4.f, "Ratio");
|
||||
configParam(PARAM_KNEE, 0.f, 8.f, 0.f, "Knee", " dB");
|
||||
configParam(PARAM_SLEW, 1.f, 150.f, 1.f, "Slew");
|
||||
configParam(PARAM_MAKEUP, 0.f, 30.f, 0.f, "Makeup", " dB");
|
||||
configInput(AUDIO_INPUT, "Audio");
|
||||
configInput(SIDECHAIN_INPUT, "Sidechain");
|
||||
configOutput(AUDIO_OUTPUT, "Audio");
|
||||
configLight(OUTLEVEL, "Output Level");
|
||||
configLight(GAINREDUCTION, "Gain Reduction");
|
||||
|
||||
gainred = 0.0f;
|
||||
outlevel = -45.0f;
|
||||
oldL_yl = oldL_y1 = oldL_yg = 0.f;
|
||||
}
|
||||
|
||||
void process(const ProcessArgs& args) override
|
||||
{
|
||||
const float attack = params[PARAM_ATTACK].getValue();
|
||||
const float release = params[PARAM_RELEASE].getValue();
|
||||
const float thresdb = params[PARAM_THRESHOLD].getValue();
|
||||
const float ratio = params[PARAM_RATIO].getValue();
|
||||
const float knee = params[PARAM_KNEE].getValue();
|
||||
const float slewfactor = params[PARAM_SLEW].getValue();
|
||||
const float makeup = params[PARAM_MAKEUP].getValue();
|
||||
|
||||
const float srate = args.sampleRate;
|
||||
const float width = (6.f * knee) + 0.01;
|
||||
const float slewwidth = 1.8f;
|
||||
const float release_coeff = exp(-1000.f/(release * srate));
|
||||
|
||||
// const float gain = std::pow(params[0].getValue(), 2.f);
|
||||
|
||||
const float in0 = inputs[AUDIO_INPUT].getVoltageSum() * 0.1f;
|
||||
const float in = inputs[SIDECHAIN_INPUT].isConnected()
|
||||
? inputs[SIDECHAIN_INPUT].getVoltageSum() * 0.1f
|
||||
: in0;
|
||||
|
||||
const float Lxg = sanitize_denormal(in == 0.f ? -160.f : to_dB(fabsf(in)));
|
||||
|
||||
const float checkwidth = 2.f*fabsf(Lxg-thresdb);
|
||||
|
||||
bool attslew = false;
|
||||
float Lyg;
|
||||
if (2.f*(Lxg-thresdb) < -width) {
|
||||
Lyg = Lxg;
|
||||
} else if (checkwidth <= width) {
|
||||
Lyg = thresdb + (Lxg-thresdb)/ratio;
|
||||
Lyg = sanitize_denormal(Lyg);
|
||||
if (checkwidth <= slewwidth) {
|
||||
if (Lyg >= oldL_yg) {
|
||||
attslew = true;
|
||||
}
|
||||
}
|
||||
} else if (2.f*(Lxg-thresdb) > width) {
|
||||
Lyg = thresdb + (Lxg-thresdb)/ratio;
|
||||
Lyg = sanitize_denormal(Lyg);
|
||||
} else {
|
||||
Lyg = Lxg + (1.f/ratio-1.f)*(Lxg-thresdb+width/2.f)*(Lxg-thresdb+width/2.f)/(2.f*width);
|
||||
}
|
||||
|
||||
const float attack_coeff = attslew
|
||||
? exp(-1000.f/((attack + 2.0*(slewfactor - 1)) * srate))
|
||||
: exp(-1000.f/(attack * srate));
|
||||
// Don't slew on release
|
||||
|
||||
const float Lxl = Lxg - Lyg;
|
||||
|
||||
const float Lyl = sanitize_denormal(Lxl < oldL_yl ? release_coeff * oldL_yl + (1.f-release_coeff)*Lxl
|
||||
: Lxl > oldL_yl ? attack_coeff * oldL_yl+(1.f-attack_coeff)*Lxl : Lxl);
|
||||
|
||||
const float Lgain = from_dB(-Lyl);
|
||||
|
||||
const float out = in0 * Lgain * from_dB(makeup);
|
||||
outputs[AUDIO_OUTPUT].setVoltage(out * 10.0f);
|
||||
|
||||
oldL_yl = Lyl;
|
||||
oldL_yg = Lyg;
|
||||
|
||||
gainred = Lyl;
|
||||
// const float max = (fabsf(out) > max) ? fabsf(outputs[0][i]) : sanitize_denormal(max);
|
||||
// outlevel = (max == 0.f) ? -45.f : to_dB(max); // relative to - thresdb;
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
struct ZamAudioCompModuleWidget : ZamAudioModuleWidget {
|
||||
typedef FundamentalBlackKnob<36> BigKnob;
|
||||
|
||||
ZamAudioCompModule* const module;
|
||||
|
||||
ZamAudioCompModuleWidget(ZamAudioCompModule* const m)
|
||||
: ZamAudioModuleWidget(),
|
||||
module(m)
|
||||
{
|
||||
setModule(module);
|
||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/ZamComp.svg")));
|
||||
|
||||
addInput(createInput<PJ301MPort>(Vec(32, 280), m, ZamAudioCompModule::AUDIO_INPUT));
|
||||
addInput(createInput<PJ301MPort>(Vec(32, 310), m, ZamAudioCompModule::SIDECHAIN_INPUT));
|
||||
addOutput(createOutput<PJ301MPort>(Vec(100, 310), m, ZamAudioCompModule::AUDIO_OUTPUT));
|
||||
|
||||
const float scale = 0.8f;
|
||||
addParam(createParamCentered<BigKnob>(Vec(45.75f * scale, 121.25f * scale), m, ZamAudioCompModule::PARAM_ATTACK));
|
||||
addParam(createParamCentered<BigKnob>(Vec(127.75f * scale, 121.25f * scale), m, ZamAudioCompModule::PARAM_RELEASE));
|
||||
|
||||
addParam(createParamCentered<BigKnob>(Vec(48.25f * scale, 208.f * scale), m, ZamAudioCompModule::PARAM_THRESHOLD));
|
||||
addParam(createParamCentered<BigKnob>(Vec(130.75f * scale, 208.f * scale), m, ZamAudioCompModule::PARAM_RATIO));
|
||||
|
||||
addParam(createParamCentered<BigKnob>(Vec(48.25f * scale, 305.f * scale), m, ZamAudioCompModule::PARAM_KNEE));
|
||||
addParam(createParamCentered<BigKnob>(Vec(130.75f * scale, 305.f * scale), m, ZamAudioCompModule::PARAM_SLEW));
|
||||
}
|
||||
};
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
Model* modelZamComp = createModel<ZamAudioCompModule, ZamAudioCompModuleWidget>("ZamComp");
|
||||
|
||||
// --------------------------------------------------------------------------------------------------------------------
|
||||
27
plugins/ZamAudio/src/plugin.hpp
Normal file
27
plugins/ZamAudio/src/plugin.hpp
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* ZamAudio plugins For Cardinal
|
||||
* Copyright (C) 2014-2019 Damien Zammit <damien@zamaudio.com>
|
||||
* Copyright (C) 2022 Filipe Coelho <falktx@falktx.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* For a full copy of the GNU General Public License see the LICENSE file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "rack.hpp"
|
||||
|
||||
using namespace rack;
|
||||
|
||||
extern Plugin* pluginInstance;
|
||||
|
||||
extern Model* modelZamComp;
|
||||
52
plugins/ZamAudio/src/widgets.hpp
Normal file
52
plugins/ZamAudio/src/widgets.hpp
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* ZamAudio plugins For Cardinal
|
||||
* Copyright (C) 2014-2019 Damien Zammit <damien@zamaudio.com>
|
||||
* Copyright (C) 2022 Filipe Coelho <falktx@falktx.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License as
|
||||
* published by the Free Software Foundation; either version 2 of
|
||||
* the License, or (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* For a full copy of the GNU General Public License see the LICENSE file.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "plugin.hpp"
|
||||
|
||||
struct ZamAudioModuleWidget : ModuleWidget {
|
||||
};
|
||||
|
||||
template<int size>
|
||||
struct FundamentalBlackKnob : RoundKnob {
|
||||
static constexpr const float kSize = size;
|
||||
static constexpr const float kHalfSize = size * 0.5f;
|
||||
float scale;
|
||||
|
||||
FundamentalBlackKnob() {
|
||||
if (size <= 22) {
|
||||
setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/knob-marker-small.svg")));
|
||||
bg->setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/knob-small.svg")));
|
||||
} else {
|
||||
setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/knob-marker.svg")));
|
||||
bg->setSvg(Svg::load(asset::plugin(pluginInstance, "res/components/knob.svg")));
|
||||
}
|
||||
|
||||
scale = size / sw->box.size.x;
|
||||
box.size = Vec(size, size);
|
||||
bg->box.size = Vec(size, size);
|
||||
}
|
||||
|
||||
void draw(const DrawArgs& args) override {
|
||||
nvgSave(args.vg);
|
||||
nvgScale(args.vg, scale, scale);
|
||||
RoundKnob::draw(args);
|
||||
nvgRestore(args.vg);
|
||||
}
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue