|
- //***********************************************************************************************
- //Impromptu Modular: Modules for VCV Rack by Marc Boulé
- //***********************************************************************************************
-
- #include "dsp/digital.hpp"
-
- using namespace rack;
-
- namespace rack_plugin_ImpromptuModular {
-
- // General constants
-
- enum RunModeIds {MODE_FWD, MODE_REV, MODE_PPG, MODE_BRN, MODE_RND, MODE_FW2, MODE_FW3, MODE_FW4, NUM_MODES};
- static const std::string modeLabels[NUM_MODES]={"FWD","REV","PPG","BRN","RND","FW2","FW3","FW4"};
-
- static const int NUM_GATES = 12;
- static const uint32_t advGateHitMask[NUM_GATES] =
- {0x00003F, 0x0F0F0F, 0x000FFF, 0x0F0F00, 0x03FFFF, 0xFFFFFF, 0x00000F, 0x03F03F, 0x000F00, 0x03F000, 0x0F0000, 0};
- // 25% TRI 50% T23 75% FUL TR1 DUO TR2 D2 TR3 TRIG
-
- enum AttributeBitMasks {ATT_MSK_GATE1 = 0x01, ATT_MSK_GATE1P = 0x02, ATT_MSK_GATE2 = 0x04, ATT_MSK_SLIDE = 0x08, ATT_MSK_TIED = 0x10};// 5 bits
- static const int ATT_MSK_GATE1MODE = 0x01E0;// 4 bits
- static const int gate1ModeShift = 5;
- static const int ATT_MSK_GATE2MODE = 0x1E00;// 4 bits
- static const int gate2ModeShift = 9;
-
-
-
- // Inline methods
- inline bool getGate1a(int attribute) {return (attribute & ATT_MSK_GATE1) != 0;}
- inline bool getGate1Pa(int attribute) {return (attribute & ATT_MSK_GATE1P) != 0;}
- inline bool getGate2a(int attribute) {return (attribute & ATT_MSK_GATE2) != 0;}
- inline bool getSlideA(int attribute) {return (attribute & ATT_MSK_SLIDE) != 0;}
- inline bool getTiedA(int attribute) {return (attribute & ATT_MSK_TIED) != 0;}
- inline int getGate1aMode(int attribute) {return (attribute & ATT_MSK_GATE1MODE) >> gate1ModeShift;}
- inline int getGate2aMode(int attribute) {return (attribute & ATT_MSK_GATE2MODE) >> gate2ModeShift;}
-
- inline void setGate1a(int *attribute, bool gate1State) {(*attribute) &= ~ATT_MSK_GATE1; if (gate1State) (*attribute) |= ATT_MSK_GATE1;}
- inline void setGate1Pa(int *attribute, bool gate1PState) {(*attribute) &= ~ATT_MSK_GATE1P; if (gate1PState) (*attribute) |= ATT_MSK_GATE1P;}
- inline void setGate2a(int *attribute, bool gate2State) {(*attribute) &= ~ATT_MSK_GATE2; if (gate2State) (*attribute) |= ATT_MSK_GATE2;}
- inline void setSlideA(int *attribute, bool slideState) {(*attribute) &= ~ATT_MSK_SLIDE; if (slideState) (*attribute) |= ATT_MSK_SLIDE;}
- inline void setTiedA(int *attribute, bool tiedState) {(*attribute) &= ~ATT_MSK_TIED; if (tiedState) (*attribute) |= ATT_MSK_TIED;}
-
- inline void toggleGate1a(int *attribute) {(*attribute) ^= ATT_MSK_GATE1;}
- inline void toggleGate1Pa(int *attribute) {(*attribute) ^= ATT_MSK_GATE1P;}
- inline void toggleGate2a(int *attribute) {(*attribute) ^= ATT_MSK_GATE2;}
- inline void toggleSlideA(int *attribute) {(*attribute) ^= ATT_MSK_SLIDE;}
- inline void toggleTiedA(int *attribute) {(*attribute) ^= ATT_MSK_TIED;}
-
-
- inline int ppsToIndex(int pulsesPerStep) {// map 1,4,6,12,24, to 0,1,2,3,4
- if (pulsesPerStep == 1) return 0;
- if (pulsesPerStep == 4) return 1;
- if (pulsesPerStep == 6) return 2;
- if (pulsesPerStep == 12) return 3;
- return 4;
- }
- inline int indexToPps(int index) {// inverse map of ppsToIndex()
- index = clamp(index, 0, 4);
- if (index == 0) return 1;
- if (index == 1) return 4;
- if (index == 2) return 6;
- if (index == 3) return 12;
- return 24;
- }
-
- inline bool calcGate(int gateCode, SchmittTrigger clockTrigger, unsigned long clockStep, float sampleRate) {
- if (gateCode < 2)
- return gateCode == 1;
- if (gateCode == 2)
- return clockTrigger.isHigh();
- return clockStep < (unsigned long) (sampleRate * 0.001f);
- }
-
- inline int getAdvGate(int ppqnCount, int pulsesPerStep, int gateMode) {
- if (gateMode == 11)
- return ppqnCount == 0 ? 3 : 0;
- uint32_t shiftAmt = ppqnCount * (24 / pulsesPerStep);
- return (int)((advGateHitMask[gateMode] >> shiftAmt) & (uint32_t)0x1);
- }
-
- inline int calcGate1Code(int attribute, int ppqnCount, int pulsesPerStep, float randKnob) {
- // -1 = gate off for whole step, 0 = gate off for current ppqn, 1 = gate on, 2 = clock high, 3 = trigger
- if (ppqnCount == 0 && getGate1Pa(attribute) && !(randomUniform() < randKnob))// randomUniform is [0.0, 1.0), see include/util/common.hpp
- return -1;// must do this first in this method since it will kill rest of step if prob turns off the step
- if (!getGate1a(attribute))
- return 0;
- if (pulsesPerStep == 1)
- return 2;// clock high
- return getAdvGate(ppqnCount, pulsesPerStep, getGate1aMode(attribute));
- }
- inline int calcGate2Code(int attribute, int ppqnCount, int pulsesPerStep) {
- // 0 = gate off, 1 = clock high, 2 = trigger, 3 = gate on
- if (!getGate2a(attribute))
- return 0;
- if (pulsesPerStep == 1)
- return 2;// clock high
- return getAdvGate(ppqnCount, pulsesPerStep, getGate2aMode(attribute));
- }
-
- inline int gateModeToKeyLightIndex(int attribute, bool isGate1) {// keyLight index now matches gate modes, so no mapping table needed anymore
- return isGate1 ? getGate1aMode(attribute) : getGate2aMode(attribute);
- }
-
-
-
- // Other methods (code in PhraseSeqUtil.cpp)
-
- int moveIndex(int index, int indexNext, int numSteps);
- bool moveIndexRunMode(int* index, int numSteps, int runMode, int* history);
- int keyIndexToGateMode(int keyIndex, int pulsesPerStep);
-
- } // namespace rack_plugin_ImpromptuModular
|