Start of ZamAudio modules, WIP/Experimental

This commit is contained in:
falkTX 2022-07-26 16:54:54 +01:00
parent 65244f1979
commit 9be8413054
17 changed files with 8739 additions and 1 deletions

View 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");
// --------------------------------------------------------------------------------------------------------------------

View 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;

View 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);
}
};