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.

425 lines
18KB

  1. //***********************************************************************************************
  2. //Impromptu Modular: Modules for VCV Rack by Marc Boulé
  3. //***********************************************************************************************
  4. #ifndef FOUNDRY_SEQUENCER_KERNEL_HPP
  5. #define FOUNDRY_SEQUENCER_KERNEL_HPP
  6. #include "ImpromptuModular.hpp"
  7. namespace rack_plugin_ImpromptuModular {
  8. class StepAttributes {
  9. unsigned long attributes;
  10. public:
  11. static const unsigned long ATT_MSK_GATE = 0x01000000, gateShift = 24;
  12. static const unsigned long ATT_MSK_GATEP = 0x02000000;
  13. static const unsigned long ATT_MSK_SLIDE = 0x04000000;
  14. static const unsigned long ATT_MSK_TIED = 0x08000000;
  15. static const unsigned long ATT_MSK_GATETYPE = 0xF0000000, gateTypeShift = 28;
  16. static const unsigned long ATT_MSK_VELOCITY = 0x000000FF, velocityShift = 0;
  17. static const unsigned long ATT_MSK_GATEP_VAL = 0x0000FF00, gatePValShift = 8;
  18. static const unsigned long ATT_MSK_SLIDE_VAL = 0x00FF0000, slideValShift = 16;
  19. static const int INIT_VELOCITY = 100;
  20. static const int MAX_VELOCITY = 200;
  21. static const int INIT_PROB = 50;// range is 0 to 100
  22. static const int INIT_SLIDE = 10;// range is 0 to 100
  23. static const unsigned long ATT_MSK_INITSTATE = ((ATT_MSK_GATE) | (INIT_VELOCITY << velocityShift) | (INIT_PROB << gatePValShift) | (INIT_SLIDE << slideValShift));
  24. inline void clear() {attributes = 0ul;}
  25. inline void init() {attributes = ATT_MSK_INITSTATE;}
  26. inline void randomize() {attributes = ( (randomu32() & (ATT_MSK_GATE | ATT_MSK_GATEP | ATT_MSK_SLIDE /*| ATT_MSK_TIED*/)) | ((randomu32() % 101) << gatePValShift) | ((randomu32() % 101) << slideValShift) | (randomu32() % (MAX_VELOCITY + 1)) ) ;}
  27. inline bool getGate() {return (attributes & ATT_MSK_GATE) != 0;}
  28. inline int getGateType() {return (int)((attributes & ATT_MSK_GATETYPE) >> gateTypeShift);}
  29. inline bool getTied() {return (attributes & ATT_MSK_TIED) != 0;}
  30. inline bool getGateP() {return (attributes & ATT_MSK_GATEP) != 0;}
  31. inline int getGatePVal() {return (int)((attributes & ATT_MSK_GATEP_VAL) >> gatePValShift);}
  32. inline bool getSlide() {return (attributes & ATT_MSK_SLIDE) != 0;}
  33. inline int getSlideVal() {return (int)((attributes & ATT_MSK_SLIDE_VAL) >> slideValShift);}
  34. inline int getVelocityVal() {return (int)((attributes & ATT_MSK_VELOCITY) >> velocityShift);}
  35. inline unsigned long getAttribute() {return attributes;}
  36. inline void setGate(bool gate1State) {attributes &= ~ATT_MSK_GATE; if (gate1State) attributes |= ATT_MSK_GATE;}
  37. inline void setGateType(int gateType) {attributes &= ~ATT_MSK_GATETYPE; attributes |= (((unsigned long)gateType) << gateTypeShift);}
  38. inline void setTied(bool tiedState) {
  39. attributes &= ~ATT_MSK_TIED;
  40. if (tiedState) {
  41. attributes |= ATT_MSK_TIED;
  42. attributes &= ~(ATT_MSK_GATE | ATT_MSK_GATEP | ATT_MSK_SLIDE);// clear other attributes if tied
  43. }
  44. }
  45. inline void setGateP(bool GatePState) {attributes &= ~ATT_MSK_GATEP; if (GatePState) attributes |= ATT_MSK_GATEP;}
  46. inline void setGatePVal(int gatePval) {attributes &= ~ATT_MSK_GATEP_VAL; attributes |= (((unsigned long)gatePval) << gatePValShift);}
  47. inline void setSlide(bool slideState) {attributes &= ~ATT_MSK_SLIDE; if (slideState) attributes |= ATT_MSK_SLIDE;}
  48. inline void setSlideVal(int slideVal) {attributes &= ~ATT_MSK_SLIDE_VAL; attributes |= (((unsigned long)slideVal) << slideValShift);}
  49. inline void setVelocityVal(int _velocity) {attributes &= ~ATT_MSK_VELOCITY; attributes |= (((unsigned long)_velocity) << velocityShift);}
  50. inline void setAttribute(unsigned long _attributes) {attributes = _attributes;}
  51. };// class StepAttributes
  52. //*****************************************************************************
  53. class Phrase {
  54. // a phrase is a sequence number and a number of repetitions; it is used to make a song
  55. unsigned long phrase;
  56. public:
  57. static const unsigned long PHR_MSK_SEQNUM = 0x00FF;
  58. static const unsigned long PHR_MSK_REPS = 0xFF00, repShift = 8;// a rep is 0 to 99
  59. inline void init() {phrase = (1 << repShift);}
  60. inline void randomize(int maxSeqs) {phrase = ((randomu32() % maxSeqs) | ((randomu32() % 4 + 1) << repShift));}
  61. inline int getSeqNum() {return (int)(phrase & PHR_MSK_SEQNUM);}
  62. inline int getReps() {return (int)((phrase & PHR_MSK_REPS) >> repShift);}
  63. inline unsigned long getPhraseJson() {return phrase - (1 << repShift);}// compression trick (store 0 instead of 1)
  64. inline void setSeqNum(int seqn) {phrase &= ~PHR_MSK_SEQNUM; phrase |= ((unsigned long)seqn);}
  65. inline void setReps(int _reps) {phrase &= ~PHR_MSK_REPS; phrase |= (((unsigned long)_reps) << repShift);}
  66. inline void setPhraseJson(unsigned long _phrase) {phrase = (_phrase + (1 << repShift));}// compression trick (store 0 instead of 1)
  67. };// class Phrase
  68. //*****************************************************************************
  69. class SeqAttributes {
  70. unsigned long attributes;
  71. public:
  72. static const unsigned long SEQ_MSK_LENGTH = 0x000000FF;// number of steps in each sequence, min value is 1
  73. static const unsigned long SEQ_MSK_RUNMODE = 0x0000FF00, runModeShift = 8;
  74. static const unsigned long SEQ_MSK_TRANSPOSE = 0x007F0000, transposeShift = 16;
  75. static const unsigned long SEQ_MSK_TRANSIGN = 0x00800000;// manually implement sign bit
  76. static const unsigned long SEQ_MSK_ROTATE = 0x7F000000, rotateShift = 24;
  77. static const unsigned long SEQ_MSK_ROTSIGN = 0x80000000;// manually implement sign bit (+ is right, - is left)
  78. inline void init(int length, int runMode) {attributes = ((length) | (((unsigned long)runMode) << runModeShift));}
  79. inline void randomize(int maxSteps, int numModes) {attributes = ( (1 + (randomu32() % maxSteps)) | (((unsigned long)(randomu32() % numModes) << runModeShift)) );}
  80. inline int getLength() {return (int)(attributes & SEQ_MSK_LENGTH);}
  81. inline int getRunMode() {return (int)((attributes & SEQ_MSK_RUNMODE) >> runModeShift);}
  82. inline int getTranspose() {
  83. int ret = (int)((attributes & SEQ_MSK_TRANSPOSE) >> transposeShift);
  84. if ( (attributes & SEQ_MSK_TRANSIGN) != 0)// if negative
  85. ret *= -1;
  86. return ret;
  87. }
  88. inline int getRotate() {
  89. int ret = (int)((attributes & SEQ_MSK_ROTATE) >> rotateShift);
  90. if ( (attributes & SEQ_MSK_ROTSIGN) != 0)// if negative
  91. ret *= -1;
  92. return ret;
  93. }
  94. inline unsigned long getSeqAttrib() {return attributes;}
  95. inline void setLength(int length) {attributes &= ~SEQ_MSK_LENGTH; attributes |= ((unsigned long)length);}
  96. inline void setRunMode(int runMode) {attributes &= ~SEQ_MSK_RUNMODE; attributes |= (((unsigned long)runMode) << runModeShift);}
  97. inline void setTranspose(int transp) {
  98. attributes &= ~ (SEQ_MSK_TRANSPOSE | SEQ_MSK_TRANSIGN);
  99. attributes |= (((unsigned long)abs(transp)) << transposeShift);
  100. if (transp < 0)
  101. attributes |= SEQ_MSK_TRANSIGN;
  102. }
  103. inline void setRotate(int rotn) {
  104. attributes &= ~ (SEQ_MSK_ROTATE | SEQ_MSK_ROTSIGN);
  105. attributes |= (((unsigned long)abs(rotn)) << rotateShift);
  106. if (rotn < 0)
  107. attributes |= SEQ_MSK_ROTSIGN;
  108. }
  109. inline void setSeqAttrib(unsigned long _attributes) {attributes = _attributes;}
  110. };// class SeqAttributes
  111. //*****************************************************************************
  112. // SequencerKernel
  113. //*****************************************************************************
  114. struct SeqCPbuffer;
  115. struct SongCPbuffer;
  116. class SequencerKernel {
  117. public:
  118. // Sequencer kernel dimensions
  119. static const int MAX_STEPS = 32;// must be a power of two (some multi select loops have bitwise "& (MAX_STEPS - 1)")
  120. static const int MAX_SEQS = 64;
  121. static const int MAX_PHRASES = 99;// maximum value is 99 (index value is 0 to 98; disp will be 1 to 99)
  122. // Run modes
  123. enum RunModeIds {MODE_FWD, MODE_REV, MODE_PPG, MODE_PEN, MODE_BRN, MODE_RND, MODE_TKA, NUM_MODES};
  124. static const std::string modeLabels[NUM_MODES];
  125. private:
  126. // Gate types
  127. static const int NUM_GATES = 12;
  128. static const uint64_t advGateHitMaskLow[NUM_GATES];
  129. static const uint64_t advGateHitMaskHigh[NUM_GATES];
  130. static constexpr float INIT_CV = 0.0f;
  131. int id;
  132. std::string ids;
  133. // Need to save
  134. int pulsesPerStep;// stored range is [1:49] so must ALWAYS read thgouth getPulsesPerStep(). Must do this because of knob
  135. int delay;
  136. int runModeSong;
  137. int songBeginIndex;
  138. int songEndIndex;
  139. Phrase phrases[MAX_PHRASES];// This is the song (series of phases; a phrase is a sequence number and a repetition value)
  140. SeqAttributes sequences[MAX_SEQS];
  141. float cv[MAX_SEQS][MAX_STEPS];// [-3.0 : 3.917].
  142. StepAttributes attributes[MAX_SEQS][MAX_STEPS];
  143. char dirty[MAX_SEQS];
  144. // No need to save
  145. int stepIndexRun;
  146. unsigned long stepIndexRunHistory;
  147. int phraseIndexRun;
  148. unsigned long phraseIndexRunHistory;
  149. int ppqnCount;
  150. int ppqnLeftToSkip;// used in clock delay
  151. int gateCode;// -1 = Killed for all pulses of step, 0 = Low for current pulse of step, 1 = High for current pulse of step, 2 = Clk high pulse, 3 = 1ms trig
  152. unsigned long slideStepsRemain;// 0 when no slide under way, downward step counter when sliding
  153. float slideCVdelta;// no need to initialize, this is only used when slideStepsRemain is not 0
  154. SequencerKernel *masterKernel;// nullprt for track 0, used for grouped run modes (tracks B,C,D follow A when random, for example)
  155. bool* holdTiedNotesPtr;
  156. unsigned long clockPeriod;// counts number of step() calls upward from last clock (reset after clock processed)
  157. bool moveStepIndexRunIgnore;
  158. public:
  159. void construct(int _id, SequencerKernel *_masterKernel, bool* _holdTiedNotesPtr); // don't want regaular constructor mechanism
  160. inline int getRunModeSong() {return runModeSong;}
  161. inline int getRunModeSeq(int seqn) {return sequences[seqn].getRunMode();}
  162. inline int getBegin() {return songBeginIndex;}
  163. inline int getEnd() {return songEndIndex;}
  164. inline int getLength(int seqn) {return sequences[seqn].getLength();}
  165. inline int getPhraseSeq(int phrn) {return phrases[phrn].getSeqNum();}
  166. inline int getPhraseReps(int phrn) {return phrases[phrn].getReps();}
  167. inline int getPulsesPerStep() {return (pulsesPerStep > 2 ? ((pulsesPerStep - 1) << 1) : pulsesPerStep);}
  168. inline int getDelay() {return delay;}
  169. inline int getTransposeOffset(int seqn) {return sequences[seqn].getTranspose();}
  170. inline int getRotateOffset(int seqn) {return sequences[seqn].getRotate();}
  171. inline int getStepIndexRun() {return stepIndexRun;}
  172. inline int getPhraseIndexRun() {return phraseIndexRun;}
  173. inline float getCV(int seqn, int stepn) {return cv[seqn][stepn];}
  174. inline float getCVRun() {return cv[phrases[phraseIndexRun].getSeqNum()][stepIndexRun];}
  175. inline StepAttributes getAttribute(int seqn, int stepn) {return attributes[seqn][stepn];}
  176. inline StepAttributes getAttributeRun() {return attributes[phrases[phraseIndexRun].getSeqNum()][stepIndexRun];}
  177. inline bool getGate(int seqn, int stepn) {return attributes[seqn][stepn].getGate();}
  178. inline bool getGateP(int seqn, int stepn) {return attributes[seqn][stepn].getGateP();}
  179. inline bool getSlide(int seqn, int stepn) {return attributes[seqn][stepn].getSlide();}
  180. inline bool getTied(int seqn, int stepn) {return attributes[seqn][stepn].getTied();}
  181. inline int getGatePVal(int seqn, int stepn) {return attributes[seqn][stepn].getGatePVal();}
  182. inline int getSlideVal(int seqn, int stepn) {return attributes[seqn][stepn].getSlideVal();}
  183. inline int getVelocityVal(int seqn, int stepn) {return attributes[seqn][stepn].getVelocityVal();}
  184. inline int getVelocityValRun() {return getAttributeRun().getVelocityVal();}
  185. inline int getGateType(int seqn, int stepn) {return attributes[seqn][stepn].getGateType();}
  186. inline void setPhraseIndexRun(int _phraseIndexRun) {phraseIndexRun = _phraseIndexRun;}
  187. inline void setPulsesPerStep(int _pps) {pulsesPerStep = _pps;}
  188. inline void setDelay(int _delay) {delay = _delay;}
  189. inline void setLength(int seqn, int _length) {sequences[seqn].setLength(_length);}
  190. inline void setPhraseReps(int phrn, int _reps) {phrases[phrn].setReps(_reps);}
  191. inline void setPhraseSeqNum(int phrn, int _seqn) {phrases[phrn].setSeqNum(_seqn);}
  192. inline void setBegin(int phrn) {songBeginIndex = phrn; songEndIndex = max(phrn, songEndIndex);}
  193. inline void setEnd(int phrn) {songEndIndex = phrn; songBeginIndex = min(phrn, songBeginIndex);}
  194. inline void setRunModeSong(int _runMode) {runModeSong = _runMode;}
  195. inline void setRunModeSeq(int seqn, int _runMode) {sequences[seqn].setRunMode(_runMode);}
  196. void setGate(int seqn, int stepn, bool newGate, int count);
  197. void setGateP(int seqn, int stepn, bool newGateP, int count);
  198. void setSlide(int seqn, int stepn, bool newSlide, int count);
  199. void setTied(int seqn, int stepn, bool newTied, int count);
  200. void setGatePVal(int seqn, int stepn, int gatePval, int count);
  201. void setSlideVal(int seqn, int stepn, int slideVal, int count);
  202. void setVelocityVal(int seqn, int stepn, int velocity, int count);
  203. void setGateType(int seqn, int stepn, int gateType, int count);
  204. void setMoveStepIndexRunIgnore() {moveStepIndexRunIgnore = true;}
  205. inline int modRunModeSong(int delta) {
  206. runModeSong = clamp(runModeSong += delta, 0, NUM_MODES - 1);
  207. return runModeSong;
  208. }
  209. inline int modRunModeSeq(int seqn, int delta) {
  210. int rVal = sequences[seqn].getRunMode();
  211. rVal = clamp(rVal + delta, 0, NUM_MODES - 1);
  212. sequences[seqn].setRunMode(rVal);
  213. return rVal;
  214. }
  215. inline int modLength(int seqn, int delta) {
  216. int lVal = sequences[seqn].getLength();
  217. lVal = clamp(lVal + delta, 1, MAX_STEPS);
  218. sequences[seqn].setLength(lVal);
  219. return lVal;
  220. }
  221. inline int modPhraseSeqNum(int phrn, int delta) {
  222. int seqn = phrases[phrn].getSeqNum();
  223. seqn = moveIndex(seqn, seqn + delta, MAX_SEQS);
  224. phrases[phrn].setSeqNum(seqn);
  225. return seqn;
  226. }
  227. inline int modPhraseReps(int phrn, int delta) {
  228. int rVal = phrases[phrn].getReps();
  229. rVal = clamp(rVal + delta, 0, 99);
  230. phrases[phrn].setReps(rVal);
  231. return rVal;
  232. }
  233. inline int modPulsesPerStep(int delta) {
  234. pulsesPerStep += delta;
  235. if (pulsesPerStep < 1) pulsesPerStep = 1;
  236. if (pulsesPerStep > 49) pulsesPerStep = 49;
  237. return pulsesPerStep;
  238. }
  239. inline int modDelay(int delta) {
  240. delay = clamp(delay + delta, 0, 99);
  241. return delay;
  242. }
  243. inline int modGatePVal(int seqn, int stepn, int delta, int count) {
  244. int pVal = getGatePVal(seqn, stepn);
  245. pVal = clamp(pVal + delta, 0, 100);
  246. setGatePVal(seqn, stepn, pVal, count);
  247. return pVal;
  248. }
  249. inline int modSlideVal(int seqn, int stepn, int delta, int count) {
  250. int sVal = getSlideVal(seqn, stepn);
  251. sVal = clamp(sVal + delta, 0, 100);
  252. setSlideVal(seqn, stepn, sVal, count);
  253. return sVal;
  254. }
  255. inline int modVelocityVal(int seqn, int stepn, int delta, int upperLimit, int count) {
  256. int vVal = getVelocityVal(seqn, stepn);
  257. vVal = clamp(vVal + delta, 0, upperLimit);
  258. setVelocityVal(seqn, stepn, vVal, count);
  259. return vVal;
  260. }
  261. inline void decSlideStepsRemain() {if (slideStepsRemain > 0ul) slideStepsRemain--;}
  262. inline bool toggleGate(int seqn, int stepn, int count) {
  263. bool newGate = !attributes[seqn][stepn].getGate();
  264. setGate(seqn, stepn, newGate, count);
  265. return newGate;
  266. }
  267. inline bool toggleGateP(int seqn, int stepn, int count) {
  268. bool newGateP = !attributes[seqn][stepn].getGateP();
  269. setGateP(seqn, stepn, newGateP, count);
  270. return newGateP;
  271. }
  272. inline bool toggleSlide(int seqn, int stepn, int count) {
  273. bool newSlide = !attributes[seqn][stepn].getSlide();
  274. setSlide(seqn, stepn, newSlide, count);
  275. return newSlide;
  276. }
  277. inline bool toggleTied(int seqn, int stepn, int count) {
  278. bool newTied = !attributes[seqn][stepn].getTied();
  279. setTied(seqn, stepn, newTied, count);
  280. return newTied;
  281. }
  282. float applyNewOctave(int seqn, int stepn, int newOct, int count);
  283. float applyNewKey(int seqn, int stepn, int newKeyIndex, int count);
  284. void writeCV(int seqn, int stepn, float newCV, int count);
  285. inline float calcSlideOffset() {return (slideStepsRemain > 0ul ? (slideCVdelta * (float)slideStepsRemain) : 0.0f);}
  286. inline bool calcGate(Trigger clockTrigger, float sampleRate) {
  287. if (ppqnLeftToSkip != 0)
  288. return false;
  289. if (gateCode < 2)
  290. return gateCode == 1;
  291. if (gateCode == 2)
  292. return clockTrigger.isHigh();
  293. return clockPeriod < (unsigned long) (sampleRate * 0.01f);
  294. }
  295. inline void initPulsesPerStep() {pulsesPerStep = 1;}
  296. inline void initDelay() {delay = 0;}
  297. void initSequence(int seqn);
  298. void initSong();
  299. void randomizeSequence(int seqn);
  300. void randomizeSong();
  301. void copySequence(SeqCPbuffer* seqCPbuf, int seqn, int startCP, int countCP);
  302. void pasteSequence(SeqCPbuffer* seqCPbuf, int seqn, int startCP);
  303. void copySong(SongCPbuffer* songCPbuf, int startCP, int countCP);
  304. void pasteSong(SongCPbuffer* songCPbuf, int startCP);
  305. void reset();
  306. void randomize(int seqn);
  307. void toJson(json_t *rootJ);
  308. void fromJson(json_t *rootJ);
  309. void initRun();
  310. bool clockStep();
  311. inline void step() {
  312. clockPeriod++;
  313. }
  314. int keyIndexToGateTypeEx(int keyIndex);
  315. void transposeSeq(int seqn, int delta);
  316. void unTransposeSeq(int seqn) {
  317. transposeSeq(seqn, getTransposeOffset(seqn) * -1);
  318. }
  319. void rotateSeq(int seqn, int delta);
  320. void unRotateSeq(int seqn) {
  321. rotateSeq(seqn, getRotateOffset(seqn) * -1);
  322. }
  323. private:
  324. void rotateSeqByOne(int seqn, bool directionRight);
  325. inline void propagateCVtoTied(int seqn, int stepn) {
  326. for (int i = stepn + 1; i < MAX_STEPS && attributes[seqn][i].getTied(); i++)
  327. cv[seqn][i] = cv[seqn][i - 1];
  328. }
  329. void activateTiedStep(int seqn, int stepn);
  330. void deactivateTiedStep(int seqn, int stepn);
  331. void calcGateCodeEx();
  332. bool moveStepIndexRun(bool init);
  333. void moveSongIndexBackward(bool init, bool rollover);
  334. void moveSongIndexForeward(bool init, bool rollover);
  335. int tempPhraseIndexes[MAX_PHRASES];// used only in next method
  336. void moveSongIndexRandom(bool init, uint32_t randomValue);
  337. void moveSongIndexBrownian(bool init, uint32_t randomValue);
  338. void movePhraseIndexRun(bool init);
  339. };// class SequencerKernel
  340. struct SeqCPbuffer {
  341. float cvCPbuffer[SequencerKernel::MAX_STEPS];// copy paste buffer for CVs
  342. StepAttributes attribCPbuffer[SequencerKernel::MAX_STEPS];
  343. SeqAttributes seqAttribCPbuffer;
  344. int storedLength;// number of steps that contain actual cp data
  345. SeqCPbuffer() {reset();}
  346. void reset();
  347. };// struct SeqCPbuffer
  348. struct SongCPbuffer {
  349. Phrase phraseCPbuffer[SequencerKernel::MAX_PHRASES];
  350. int beginIndex;
  351. int endIndex;
  352. int runModeSong;
  353. int storedLength;// number of steps that contain actual cp data
  354. SongCPbuffer() {reset();}
  355. void reset();
  356. };// song SeqCPbuffer
  357. } // namespace rack_plugin_ImpromptuModular
  358. #endif