|
- #include "dsp/digital.hpp"
- #include "moDllz.hpp"
- /*
- * TwinGlider
- */
-
- namespace rack_plugin_moDllz {
-
- struct TwinGlider : Module {
- enum ParamIds {
- RISE_PARAM,
- FALL_PARAM=2,
- LINK_PARAM=4,
- RISEMODE_PARAM=6,
- FALLMODE_PARAM=8,
- TRIG_PARAM=10,
- SMPNGLIDE_PARAM=12,
- NUM_PARAMS=14
- };
- enum InputIds {
- RISE_INPUT,
- FALL_INPUT=2,
- GATE_INPUT=4,
- CLOCK_INPUT=6,
- IN_INPUT=8,
- NUM_INPUTS=10
- };
- enum OutputIds {
- TRIGRISE_OUTPUT,
- TRIG_OUTPUT=2,
- TRIGFALL_OUTPUT=4,
- GATERISE_OUTPUT=6,
- GATEFALL_OUTPUT=8,
- OUT_OUTPUT=10,
- NUM_OUTPUTS=12
- };
- enum LightIds {
- RISING_LIGHT,
- FALLING_LIGHT=2,
- NUM_LIGHTS=4
- };
-
- struct gliderObj{
- float out = 0.0f;
- float in = 0.0f;
- // float jump = 0.0f;
- int risemode = 0.0f;
- int fallmode = 0.0f;
- float riseval = 0.0f;
- float fallval = 0.0f;
- float prevriseval = 0.0f;
- float prevfallval = 0.0f;
- float riseramp = 0.0f;
- float fallramp = 0.0f;
- bool rising = false;
- bool falling = false;
- bool newgate = false;
- bool pulse = false;
- bool newin = false;
- bool trigR = false;
- bool trigF = false;
- int clocksafe = 0;
- // int frameTime = 0;
- PulseGenerator risePulse;
- PulseGenerator fallPulse;
-
- };
-
- gliderObj glider[2];
-
- const float threshold = 0.01f;
-
- // int testVal = 0;
-
- TwinGlider() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
- // ~TwinGlider() {
- // };
-
- void step() override;
- void onReset() override {
- for (int ix = 0; ix < 2 ; ix++){
- // gliding[ix] = false;
- outputs[OUT_OUTPUT + ix].value = inputs[IN_INPUT + ix].value;
- lights[RISING_LIGHT + ix].value = 0;
- lights[FALLING_LIGHT + ix].value = 0;
- outputs[GATERISE_OUTPUT + ix].value = 0;
- outputs[GATEFALL_OUTPUT + ix].value = 0;
- }
- }
- };
-
- ///////////////////////////////////////////
- ///////////////STEP //////////////////
- /////////////////////////////////////////////
-
- void TwinGlider::step() {
- for (int ix = 0; ix < 2; ix++){
- if (inputs[IN_INPUT + ix].active) {
- if (std::abs(glider[ix].in - inputs[IN_INPUT + ix].value) > threshold){
- glider[ix].newin = true;
- }
- if (params[SMPNGLIDE_PARAM + ix].value > 0.5f){
- bool allowin = false;
- if (inputs[CLOCK_INPUT + ix].active){
- // External clock
- if ((glider[ix].clocksafe > 8) && (inputs[CLOCK_INPUT + ix].value > 2.5f)){
- allowin = true;
- glider[ix].in = inputs[IN_INPUT + ix].value;
- glider[ix].clocksafe = 0;
- }else if ((glider[ix].clocksafe <10) && (inputs[CLOCK_INPUT + ix].value < 0.01f)) glider[ix].clocksafe ++;
- } else allowin = ((!glider[ix].rising) && (!glider[ix].falling));
- if (allowin) if (glider[ix].newin) glider[ix].in = inputs[IN_INPUT + ix].value;
- }
- else if (glider[ix].newin) glider[ix].in = inputs[IN_INPUT + ix].value;
- //Check for legato from Gate
- bool glideMe = false;
- if (inputs[GATE_INPUT + ix].active){
- if (inputs[GATE_INPUT + ix ].value < 0.5f) {
- glider[ix].newgate = true;
- glider[ix].out = glider[ix].in;
- }else if (glider[ix].newgate) {
- glider[ix].out = glider[ix].in ;
- glider[ix].newgate = false;
- }else glideMe= true;/// GLIDE !!!!!
- }else glideMe = true;//// GLIDE !!!!
-
- if (glideMe) {
- //////////////// GLIDE FUNCTION ////////////>>>>>>>>>>>>>>>>>>>>>
-
- glider[ix].risemode = static_cast<int> (params[RISEMODE_PARAM + ix].value);
- glider[ix].fallmode = static_cast<int> (params[FALLMODE_PARAM + ix].value);
- if (glider[ix].in > glider[ix].out){
- if (inputs[RISE_INPUT + ix].active)
- glider[ix].riseval = inputs[RISE_INPUT + ix].value / 10.0f * params[RISE_PARAM + ix].value;
- else glider[ix].riseval = params[RISE_PARAM + ix].value;
-
- if (glider[ix].riseval > 0.0f) {
- switch (glider[ix].risemode) {
- case 0: /// Hi Rate
- glider[ix].riseramp = 1.0f/(1.0f + glider[ix].riseval * 0.005f * engineGetSampleRate());
- break;
- case 1: /// Rate
- glider[ix].riseramp = 1.0f/(1.0f + glider[ix].riseval * 2.0f * engineGetSampleRate());
- break;
- case 2: /// Time
- if ((glider[ix].newin)||(glider[ix].riseval != glider[ix].prevriseval)){
- glider[ix].prevriseval = glider[ix].riseval;
- glider[ix].newin = false;
- glider[ix].riseramp = (glider[ix].in - glider[ix].out) * engineGetSampleTime() /(glider[ix].riseval * glider[ix].riseval * 10.0f);
- if (glider[ix].riseramp< 1e-6) glider[ix].riseramp = 1e-6;
- }
- break;
- default:
- break;
- }
- glider[ix].out += glider[ix].riseramp;
- glider[ix].rising = true;
- glider[ix].falling = false;
- if (glider[ix].out >= glider[ix].in) {///////REACH RISE
- glider[ix].out = glider[ix].in;
- glider[ix].rising = false;
- glider[ix].trigR = true;
- }
- } else {
- glider[ix].rising = false;
- glider[ix].out = glider[ix].in;
- glider[ix].trigR = true;
- }
-
- } else if (glider[ix].in < glider[ix].out){
- if (params[LINK_PARAM + ix].value > 0.5f) {
- glider[ix].fallmode = glider[ix].risemode;
- glider[ix].fallval = glider[ix].riseval;
- }else{
- if (inputs[FALL_INPUT + ix].active)
- glider[ix].fallval = inputs[FALL_INPUT + ix].value / 10.0f * params[FALL_PARAM + ix].value;
- else glider[ix].fallval = params[FALL_PARAM + ix].value;
- }
- if (glider[ix].fallval > 0.0f) {
- switch (glider[ix].fallmode) {
- case 0:
- glider[ix].fallramp = 1.0f/(1.0f + glider[ix].fallval * 0.005f * engineGetSampleRate());
- break;
- case 1:
- glider[ix].fallramp = 1.0f/(1.0f + glider[ix].fallval * 2.0f * engineGetSampleRate());
- break;
- case 2:
- if ((glider[ix].newin) || (glider[ix].fallval != glider[ix].prevfallval)){
- glider[ix].prevfallval = glider[ix].fallval;
- glider[ix].newin = false;
- glider[ix].fallramp = (glider[ix].out - glider[ix].in) * engineGetSampleTime() /(glider[ix].fallval * glider[ix].fallval * 10.0f);
- if (glider[ix].fallramp < 1e-6) glider[ix].fallramp= 1e-6;
- }
- break;
- default:
- break;
- }
- glider[ix].out -= glider[ix].fallramp;
- glider[ix].falling = true;
- glider[ix].rising = false;
- if (glider[ix].out <= glider[ix].in){////////REACH FALL
- glider[ix].out = glider[ix].in;
- glider[ix].falling = false;
- glider[ix].trigF = true;
- }
- }else{
- glider[ix].falling = false;
- glider[ix].out = glider[ix].in;
- glider[ix].trigF = true;
- }
- } else {
- glider[ix].rising = false;
- glider[ix].falling = false;
- glider[ix].out = glider[ix].in;
- }
- }else{
- glider[ix].rising = false;
- glider[ix].falling = false;
- glider[ix].out = glider[ix].in;
- }
-
- ///testVal = static_cast<int> (gliding[0] * 10^7);
-
-
- lights[RISING_LIGHT + ix].value = glider[ix].rising? 1.0 : 0.0f;
- lights[FALLING_LIGHT + ix].value = glider[ix].falling? 1.0 : 0.0f;
- outputs[GATERISE_OUTPUT + ix].value = glider[ix].rising? 10.0 : 0.0f;
- outputs[GATEFALL_OUTPUT + ix].value = glider[ix].falling? 10.0 : 0.0f;
-
- outputs[OUT_OUTPUT + ix].value = glider[ix].out;
-
- // //// do triggers and reset flags
- if (outputs[TRIGRISE_OUTPUT + ix].active||outputs[TRIG_OUTPUT + ix].active||outputs[TRIGFALL_OUTPUT + ix].active) {
- if (glider[ix].trigR) {
- glider[ix].risePulse.trigger(1e-3f);
- glider[ix].trigR = false;
- }
- if (glider[ix].trigF) {
- glider[ix].fallPulse.trigger(1e-3f);
- glider[ix].trigF = false;
- }
- //
- bool pulseR = glider[ix].risePulse.process(1.0f / engineGetSampleRate());
- outputs[TRIGRISE_OUTPUT + ix].value = pulseR ? 10.0 : 0.0;
-
- bool pulseF = glider[ix].fallPulse.process(1.0f / engineGetSampleRate());
- outputs[TRIGFALL_OUTPUT + ix].value = pulseF ? 10.0 : 0.0;
-
- outputs[TRIG_OUTPUT + ix].value = (pulseR || pulseF) ? 10.0 : 0.0;
- //
- }
- ///else {
- // trigR[ix] = false;
- // trigF[ix] = false;
- // }
-
-
- /// else from if input ACTIVE....
- }else{
- //disconnected in...reset Output if connected...
- // outputs[OUT_OUTPUT + ix].value = 0;
- outputs[GATERISE_OUTPUT + ix].value = 0.0f;
- outputs[GATEFALL_OUTPUT + ix].value = 0.0f;
- lights[RISING_LIGHT + ix].value = 0.0f;
- lights[FALLING_LIGHT + ix].value = 0.0f;
- glider[ix].out = 0.0f;
- glider[ix].in = 0.0f;
- // gliding[ix] = false;
- glider[ix].newgate = false;
- // allowin[ix] = true;
- }/// Closing if input ACTIVE
-
- } //for loop ix
-
- }//closing STEP
-
- /////////////////////////////////////////////
- ///// TEST DISPLAY //////
-
- //struct testDisplay : TransparentWidget {
- // testDisplay() {
- // font = Font::load(FONT_FILE);
- // }
- // float mdfontSize = 16.f;
- // std::shared_ptr<Font> font;
- // std::string displayedVal;
- // int *valP;
- // int val = 0;
- // void draw(NVGcontext* vg)
- // {
- // val = *valP;
- // displayedVal = std::to_string(val);
- // nvgFillColor(vg, nvgRGB(0xFF,0xFF,0x00));
- // nvgFontSize(vg, mdfontSize);
- // //nvgTextLetterSpacing(vg, 2.0f);
- // //nvgTextAlign(vg, NVG_ALIGN_CENTER);
- // nvgTextBox(vg, 0.0f, 20.0f, 165.0f, displayedVal.c_str(), NULL);
- //
- // }
- //
- //};
- ////////////////////////////////////////////
- ///////////////////////////////////////////
-
- struct TwinGliderWidget : ModuleWidget {
-
- TwinGliderWidget(TwinGlider *module): ModuleWidget(module){
- setPanel(SVG::load(assetPlugin(plugin, "res/TwinGlider.svg")));
-
- //Screws
- addChild(Widget::create<ScrewBlack>(Vec(0, 0)));
- addChild(Widget::create<ScrewBlack>(Vec(box.size.x - 15, 0)));
- addChild(Widget::create<ScrewBlack>(Vec(0, 365)));
- addChild(Widget::create<ScrewBlack>(Vec(box.size.x - 15, 365)));
-
- float Ystep = 30.0f ;
- float Ypos = 0.0f;
-
- for (int i=0; i<2; i++){
-
- Ypos = 25.0f + static_cast<float>(i* 173); //2nd panel offset
-
- // Gliding Leds
- addChild(ModuleLightWidget::create<TinyLight<RedLight>>(Vec(6.75, Ypos+1), module, TwinGlider::RISING_LIGHT + i));
- addChild(ModuleLightWidget::create<TinyLight<RedLight>>(Vec(154.75, Ypos+1), module, TwinGlider::FALLING_LIGHT + i));
- /// Glide Knobs
- addParam(ParamWidget::create<moDllzKnobM>(Vec(19, Ypos-4), module, TwinGlider::RISE_PARAM + i, 0.0, 1.0, 0.0));
- addParam(ParamWidget::create<moDllzKnobM>(Vec(102, Ypos-4), module, TwinGlider::FALL_PARAM + i, 0.0, 1.0, 0.0));
-
- Ypos += Ystep; //55
-
- // LINK SWITCH//CKSS
- addParam(ParamWidget::create<moDllzSwitchLedH>(Vec(73, Ypos-12), module, TwinGlider::LINK_PARAM + i, 0.0, 1.0, 1.0));
- /// Glides CVs
- addInput(Port::create<moDllzPort>(Vec(23, Ypos+5.5), Port::INPUT, module, TwinGlider::RISE_INPUT + i));
- addInput(Port::create<moDllzPort>(Vec(117.5, Ypos+5.5), Port::INPUT, module, TwinGlider::FALL_INPUT + i));
-
- Ypos += Ystep; //85
-
- /// Mode switches
- addParam(ParamWidget::create<moDllzSwitchT>(Vec(55, Ypos-7), module, TwinGlider::RISEMODE_PARAM + i, 0.0, 2.0, 2.0));
- addParam(ParamWidget::create<moDllzSwitchT>(Vec(100, Ypos-7), module, TwinGlider::FALLMODE_PARAM + i, 0.0, 2.0, 2.0));
-
- /// GATES OUT
- addOutput(Port::create<moDllzPort>(Vec(10.5, Ypos+14), Port::OUTPUT, module, TwinGlider::GATERISE_OUTPUT + i));
- addOutput(Port::create<moDllzPort>(Vec(130.5, Ypos+14), Port::OUTPUT, module, TwinGlider::GATEFALL_OUTPUT + i));
-
- Ypos += Ystep; //115
-
- /// TRIGGERS OUT
- addOutput(Port::create<moDllzPort>(Vec(43, Ypos-4.5), Port::OUTPUT, module, TwinGlider::TRIGRISE_OUTPUT + i));
- addOutput(Port::create<moDllzPort>(Vec(71, Ypos-4.5), Port::OUTPUT, module, TwinGlider::TRIG_OUTPUT + i));
- addOutput(Port::create<moDllzPort>(Vec(98, Ypos-4.5), Port::OUTPUT, module, TwinGlider::TRIGFALL_OUTPUT + i));
-
- Ypos += Ystep; //145
-
- // GATE IN
- addInput(Port::create<moDllzPort>(Vec(44, Ypos+7), Port::INPUT, module, TwinGlider::GATE_INPUT + i));
- // CLOCK IN
- addInput(Port::create<moDllzPort>(Vec(75, Ypos+7), Port::INPUT, module, TwinGlider::CLOCK_INPUT + i));
- // Sample&Glide SWITCH
- addParam(ParamWidget::create<moDllzSwitchLed>(Vec(108, Ypos+19), module, TwinGlider::SMPNGLIDE_PARAM + i, 0.0, 1.0, 0.0));
- // IN OUT
- addInput(Port::create<moDllzPort>(Vec(13.5, Ypos+6.5), Port::INPUT, module, TwinGlider::IN_INPUT + i));
- addOutput(Port::create<moDllzPort>(Vec(128.5, Ypos+6.5), Port::OUTPUT, module, TwinGlider::OUT_OUTPUT + i));
-
-
- }
- // {
- // testDisplay *mDisplay = new testDisplay();
- // mDisplay->box.pos = Vec(0.0f, 360.0f);
- // mDisplay->box.size = {165.0f, 20.0f};
- // mDisplay->valP = &(module->testVal);
- // addChild(mDisplay);
- // }
- }
- };
- //void TwinGliderWidget::step() {
- // ModuleWidget::step();
- //}
-
- // Specify the Module and ModuleWidget subclass, human-readable
- // manufacturer name for categorization, module slug (should never
- // change), human-readable module name, and any number of tags
- // (found in `include/tags.hpp`) separated by commas.
-
- } // namespace rack_plugin_moDllz
-
- using namespace rack_plugin_moDllz;
-
- RACK_PLUGIN_MODEL_INIT(moDllz, TwinGlider) {
- Model *modelTwinGlider = Model::create<TwinGlider, TwinGliderWidget>("moDllz", "TwinGlider", "TwinGlider Dual Portamento", SLEW_LIMITER_TAG, DUAL_TAG, ENVELOPE_FOLLOWER_TAG);
- return modelTwinGlider;
- }
|