You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
5.2KB

  1. //***********************************************************************************************
  2. //Impromptu Modular: Modules for VCV Rack by Marc Boulé
  3. //***********************************************************************************************
  4. #include "dsp/digital.hpp"
  5. using namespace rack;
  6. namespace rack_plugin_ImpromptuModular {
  7. // General constants
  8. enum RunModeIds {MODE_FWD, MODE_REV, MODE_PPG, MODE_BRN, MODE_RND, MODE_FW2, MODE_FW3, MODE_FW4, NUM_MODES};
  9. static const std::string modeLabels[NUM_MODES]={"FWD","REV","PPG","BRN","RND","FW2","FW3","FW4"};
  10. static const int NUM_GATES = 12;
  11. static const uint32_t advGateHitMask[NUM_GATES] =
  12. {0x00003F, 0x0F0F0F, 0x000FFF, 0x0F0F00, 0x03FFFF, 0xFFFFFF, 0x00000F, 0x03F03F, 0x000F00, 0x03F000, 0x0F0000, 0};
  13. // 25% TRI 50% T23 75% FUL TR1 DUO TR2 D2 TR3 TRIG
  14. enum AttributeBitMasks {ATT_MSK_GATE1 = 0x01, ATT_MSK_GATE1P = 0x02, ATT_MSK_GATE2 = 0x04, ATT_MSK_SLIDE = 0x08, ATT_MSK_TIED = 0x10};// 5 bits
  15. static const int ATT_MSK_GATE1MODE = 0x01E0;// 4 bits
  16. static const int gate1ModeShift = 5;
  17. static const int ATT_MSK_GATE2MODE = 0x1E00;// 4 bits
  18. static const int gate2ModeShift = 9;
  19. // Inline methods
  20. inline bool getGate1a(int attribute) {return (attribute & ATT_MSK_GATE1) != 0;}
  21. inline bool getGate1Pa(int attribute) {return (attribute & ATT_MSK_GATE1P) != 0;}
  22. inline bool getGate2a(int attribute) {return (attribute & ATT_MSK_GATE2) != 0;}
  23. inline bool getSlideA(int attribute) {return (attribute & ATT_MSK_SLIDE) != 0;}
  24. inline bool getTiedA(int attribute) {return (attribute & ATT_MSK_TIED) != 0;}
  25. inline int getGate1aMode(int attribute) {return (attribute & ATT_MSK_GATE1MODE) >> gate1ModeShift;}
  26. inline int getGate2aMode(int attribute) {return (attribute & ATT_MSK_GATE2MODE) >> gate2ModeShift;}
  27. inline void setGate1a(int *attribute, bool gate1State) {(*attribute) &= ~ATT_MSK_GATE1; if (gate1State) (*attribute) |= ATT_MSK_GATE1;}
  28. inline void setGate1Pa(int *attribute, bool gate1PState) {(*attribute) &= ~ATT_MSK_GATE1P; if (gate1PState) (*attribute) |= ATT_MSK_GATE1P;}
  29. inline void setGate2a(int *attribute, bool gate2State) {(*attribute) &= ~ATT_MSK_GATE2; if (gate2State) (*attribute) |= ATT_MSK_GATE2;}
  30. inline void setSlideA(int *attribute, bool slideState) {(*attribute) &= ~ATT_MSK_SLIDE; if (slideState) (*attribute) |= ATT_MSK_SLIDE;}
  31. inline void setTiedA(int *attribute, bool tiedState) {(*attribute) &= ~ATT_MSK_TIED; if (tiedState) (*attribute) |= ATT_MSK_TIED;}
  32. inline void toggleGate1a(int *attribute) {(*attribute) ^= ATT_MSK_GATE1;}
  33. inline void toggleGate1Pa(int *attribute) {(*attribute) ^= ATT_MSK_GATE1P;}
  34. inline void toggleGate2a(int *attribute) {(*attribute) ^= ATT_MSK_GATE2;}
  35. inline void toggleSlideA(int *attribute) {(*attribute) ^= ATT_MSK_SLIDE;}
  36. inline void toggleTiedA(int *attribute) {(*attribute) ^= ATT_MSK_TIED;}
  37. inline int ppsToIndex(int pulsesPerStep) {// map 1,4,6,12,24, to 0,1,2,3,4
  38. if (pulsesPerStep == 1) return 0;
  39. if (pulsesPerStep == 4) return 1;
  40. if (pulsesPerStep == 6) return 2;
  41. if (pulsesPerStep == 12) return 3;
  42. return 4;
  43. }
  44. inline int indexToPps(int index) {// inverse map of ppsToIndex()
  45. index = clamp(index, 0, 4);
  46. if (index == 0) return 1;
  47. if (index == 1) return 4;
  48. if (index == 2) return 6;
  49. if (index == 3) return 12;
  50. return 24;
  51. }
  52. inline bool calcGate(int gateCode, SchmittTrigger clockTrigger, unsigned long clockStep, float sampleRate) {
  53. if (gateCode < 2)
  54. return gateCode == 1;
  55. if (gateCode == 2)
  56. return clockTrigger.isHigh();
  57. return clockStep < (unsigned long) (sampleRate * 0.001f);
  58. }
  59. inline int getAdvGate(int ppqnCount, int pulsesPerStep, int gateMode) {
  60. if (gateMode == 11)
  61. return ppqnCount == 0 ? 3 : 0;
  62. uint32_t shiftAmt = ppqnCount * (24 / pulsesPerStep);
  63. return (int)((advGateHitMask[gateMode] >> shiftAmt) & (uint32_t)0x1);
  64. }
  65. inline int calcGate1Code(int attribute, int ppqnCount, int pulsesPerStep, float randKnob) {
  66. // -1 = gate off for whole step, 0 = gate off for current ppqn, 1 = gate on, 2 = clock high, 3 = trigger
  67. if (ppqnCount == 0 && getGate1Pa(attribute) && !(randomUniform() < randKnob))// randomUniform is [0.0, 1.0), see include/util/common.hpp
  68. return -1;// must do this first in this method since it will kill rest of step if prob turns off the step
  69. if (!getGate1a(attribute))
  70. return 0;
  71. if (pulsesPerStep == 1)
  72. return 2;// clock high
  73. return getAdvGate(ppqnCount, pulsesPerStep, getGate1aMode(attribute));
  74. }
  75. inline int calcGate2Code(int attribute, int ppqnCount, int pulsesPerStep) {
  76. // 0 = gate off, 1 = clock high, 2 = trigger, 3 = gate on
  77. if (!getGate2a(attribute))
  78. return 0;
  79. if (pulsesPerStep == 1)
  80. return 2;// clock high
  81. return getAdvGate(ppqnCount, pulsesPerStep, getGate2aMode(attribute));
  82. }
  83. inline int gateModeToKeyLightIndex(int attribute, bool isGate1) {// keyLight index now matches gate modes, so no mapping table needed anymore
  84. return isGate1 ? getGate1aMode(attribute) : getGate2aMode(attribute);
  85. }
  86. // Other methods (code in PhraseSeqUtil.cpp)
  87. int moveIndex(int index, int indexNext, int numSteps);
  88. bool moveIndexRunMode(int* index, int numSteps, int runMode, int* history);
  89. int keyIndexToGateMode(int keyIndex, int pulsesPerStep);
  90. } // namespace rack_plugin_ImpromptuModular