From dd7607fa234cb33e916be6cdef7705fc090d8255 Mon Sep 17 00:00:00 2001 From: hemmer <915048+hemmer@users.noreply.github.com> Date: Sat, 12 Jun 2021 22:40:17 +0100 Subject: [PATCH] Tuning/calibration of Kickall sliders etc --- plugin.json | 4 ++- src/ChoppingKinky.cpp | 8 ++--- src/Common.hpp | 4 +-- src/Kickall.cpp | 70 +++++++++++++++++++++++-------------------- 4 files changed, 46 insertions(+), 40 deletions(-) diff --git a/plugin.json b/plugin.json index b84e5e5..6aedfd6 100644 --- a/plugin.json +++ b/plugin.json @@ -117,6 +117,7 @@ "slug": "ChoppingKinky", "name": "ChoppingKinky", "description": "Voltage controllable, dual channel wavefolder", + "modularGridUrl": "https://www.modulargrid.net/e/befaco-chopping-kinky", "tags": [ "Dual", "Hardware clone", @@ -127,7 +128,8 @@ { "slug": "Kickall", "name": "Kickall", - "description": "", + "description": "Bassdrum module, with pitch and volume envelopes", + "modularGridUrl": "https://www.modulargrid.net/e/befaco-kickall", "tags": [ "Drum", "Hardware clone", diff --git a/src/ChoppingKinky.cpp b/src/ChoppingKinky.cpp index fa3ef6b..5871c30 100644 --- a/src/ChoppingKinky.cpp +++ b/src/ChoppingKinky.cpp @@ -56,10 +56,10 @@ struct ChoppingKinky : Module { ChoppingKinky() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); - configParam(FOLD_A_PARAM, 0.f, 2.f, 0.f, ""); - configParam(FOLD_B_PARAM, 0.f, 2.f, 0.f, ""); - configParam(CV_A_PARAM, -1.f, 1.f, 0.f, ""); - configParam(CV_B_PARAM, -1.f, 1.f, 0.f, ""); + configParam(FOLD_A_PARAM, 0.f, 2.f, 0.f, "Gain/shape control for channel A"); + configParam(FOLD_B_PARAM, 0.f, 2.f, 0.f, "Gain/shape control for channel B"); + configParam(CV_A_PARAM, -1.f, 1.f, 0.f, "Channel A CV control attenuverter"); + configParam(CV_B_PARAM, -1.f, 1.f, 0.f, "Channel A CV control attenuverter"); cacheWaveshaperResponses(); diff --git a/src/Common.hpp b/src/Common.hpp index 8f00570..645a8e0 100644 --- a/src/Common.hpp +++ b/src/Common.hpp @@ -89,11 +89,11 @@ struct ADEnvelope { env = std::pow(envLinear, decayShape); } - if (env >= 1.0f) { + if (envLinear >= 1.0f) { stage = STAGE_DECAY; env = envLinear = 1.0f; } - else if (env <= 0.0f) { + else if (envLinear <= 0.0f) { stage = STAGE_OFF; env = envLinear = 0.0f; } diff --git a/src/Kickall.cpp b/src/Kickall.cpp index 6b570d7..8861305 100644 --- a/src/Kickall.cpp +++ b/src/Kickall.cpp @@ -30,42 +30,46 @@ struct Kickall : Module { NUM_LIGHTS }; + static constexpr float FREQ_A0 = 27.5f; + static constexpr float FREQ_B2 = 123.471f; + static constexpr float minVolumeDecay = 0.075f; + static constexpr float maxVolumeDecay = 4.f; + static constexpr float minPitchDecay = 0.0075f; + static constexpr float maxPitchDecay = 1.f; + static constexpr float bendRange = 10000; + float phase = 0.f; + ADEnvelope volume; + ADEnvelope pitch; + + dsp::SchmittTrigger trigger; + + static const int UPSAMPLE = 8; + chowdsp::Oversampling oversampler; + float shaperBuf[UPSAMPLE]; + Kickall() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); // TODO: review this mapping, using displayBase multiplier seems more normal configParam(TUNE_PARAM, FREQ_A0, FREQ_B2, 0.5 * (FREQ_A0 + FREQ_B2), "Tune", "Hz"); configParam(TRIGG_BUTTON_PARAM, 0.f, 1.f, 0.f, "Manual trigger"); - configParam(SHAPE_PARAM, 0.f, 1.f, 0.f, ""); - configParam(DECAY_PARAM, 0.01f, 1.f, 0.01f, "VCA Envelope decay time"); - configParam(TIME_PARAM, 0.0079f, 0.076f, 0.0079f, "Pitch envelope decay time", "ms", 0.0f, 1000.f); + configParam(SHAPE_PARAM, 0.f, 1.f, 0.f, "Wave shape"); + configParam(DECAY_PARAM, 0.f, 1.f, 0.01f, "VCA Envelope decay time"); + configParam(TIME_PARAM, 0.f, 1.0f, 0.f, "Pitch envelope decay time"); configParam(BEND_PARAM, 0.f, 1.f, 0.f, "Pitch envelope attenuator"); - volume.attackTime = 0.00165; + volume.attackTime = 0.01; + volume.decayShape = 3.0; pitch.attackTime = 0.00165; + pitch.decayShape = 3.0; // calculate up/downsampling rates onSampleRateChange(); } - void onSampleRateChange() override { - // SampleRateConverter needs integer value - int sampleRate = APP->engine->getSampleRate(); - oversampler.reset(sampleRate); + void onSampleRateChange() override { + oversampler.reset(APP->engine->getSampleRate()); } - float bendRange = 600; - float phase = 0.f; - ADEnvelope volume; - ADEnvelope pitch; - - dsp::SchmittTrigger trigger; - - static constexpr float FREQ_A0 = 27.5f; - static constexpr float FREQ_B2 = 123.471f; - - static const int UPSAMPLE = 8; - chowdsp::Oversampling oversampler; - float shaperBuf[UPSAMPLE]; void process(const ProcessArgs& args) override { @@ -75,26 +79,26 @@ struct Kickall : Module { pitch.stage = ADEnvelope::STAGE_ATTACK; } - float vcaGain = clamp(inputs[VOLUME_INPUT].getNormalVoltage(10.f) / 10.f, 0.f, 1.0f); + const float vcaGain = clamp(inputs[VOLUME_INPUT].getNormalVoltage(10.f) / 10.f, 0.f, 1.0f); // pitch envelope - float bend = params[BEND_PARAM].getValue(); - pitch.decayTime = params[TIME_PARAM].getValue(); + const float bend = bendRange * std::pow(params[BEND_PARAM].getValue(), 3.0); + pitch.decayTime = rescale(params[TIME_PARAM].getValue(), 0.f, 1.0f, minPitchDecay, maxPitchDecay); pitch.process(args.sampleTime); - // volume envelope TODO: calibrate CV/slider interaction - volume.decayTime = clamp(params[DECAY_PARAM].getValue() + inputs[DECAY_INPUT].getVoltage() * 0.1f, 0.01, 1.0); + // volume envelope + const float volumeDecay = minVolumeDecay * std::pow(2.f, params[DECAY_PARAM].getValue() * std::log2(maxVolumeDecay / minVolumeDecay)); + volume.decayTime = clamp(volumeDecay + inputs[DECAY_INPUT].getVoltage() * 0.1f, 0.01, 10.0); volume.process(args.sampleTime); float freq = params[TUNE_PARAM].getValue(); - freq *= std::pow(2, inputs[TUNE_INPUT].getVoltage()); + freq *= std::pow(2.f, inputs[TUNE_INPUT].getVoltage()); + + const float kickFrequency = std::max(10.0f, freq + bend * pitch.env); + const float phaseInc = clamp(args.sampleTime * kickFrequency / UPSAMPLE, 1e-6, 0.35f); - const float kickFrequency = std::max(10.0f, freq + bendRange * bend * pitch.env); - const float phaseInc = args.sampleTime * kickFrequency / UPSAMPLE; - float shape = clamp(inputs[SHAPE_INPUT].getVoltage() / 2.f + params[SHAPE_PARAM].getValue() * 5.0f, 0.0f, 10.0f); - shape = clamp(shape, 0.f, 5.0f) * 0.2f; - shape *= 0.99f; + const float shape = clamp(inputs[SHAPE_INPUT].getVoltage() / 10.f + params[SHAPE_PARAM].getValue(), 0.0f, 1.0f) * 0.99f; const float shapeB = (1.0f - shape) / (1.0f + shape); const float shapeA = (4.0f * shape) / ((1.0f - shape) * (1.0f + shape)); @@ -107,7 +111,7 @@ struct Kickall : Module { inputBuf[i] = inputBuf[i] * (shapeA + shapeB) / ((std::abs(inputBuf[i]) * shapeA) + shapeB); } - float out = volume.env * oversampler.downsample() * 5.0f * vcaGain; + const float out = volume.env * oversampler.downsample() * 5.0f * vcaGain; outputs[OUT_OUTPUT].setVoltage(out); lights[ENV_LIGHT].setBrightness(volume.env);