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.

930 lines
28KB

  1. #include "mscHack.hpp"
  2. //#include "mscHack_Controls.hpp"
  3. #include "dsp/digital.hpp"
  4. //#include "CLog.h"
  5. namespace rack_plugin_mscHack {
  6. #define MAX_ARP_PATTERNS 16
  7. #define MAX_ARP_NOTES 7
  8. #define SUBSTEP_PER_NOTE 3
  9. #define SEMI ( 1.0f / 12.0f )
  10. #define TRIG_OFF_TICKS 10
  11. #define ARP_OFF 0
  12. #define ARP_ON 1
  13. #define ARP_REST 2
  14. typedef struct
  15. {
  16. int notesused;
  17. int notes [ MAX_ARP_NOTES ];
  18. int onoffsel[ MAX_ARP_NOTES ][ SUBSTEP_PER_NOTE ];
  19. int lensel [ MAX_ARP_NOTES ][ SUBSTEP_PER_NOTE ];
  20. int lenmod [ MAX_ARP_NOTES ][ SUBSTEP_PER_NOTE ];
  21. int legato [ MAX_ARP_NOTES ];
  22. int glide [ MAX_ARP_NOTES ];
  23. int mode;
  24. int oct;
  25. }ARP_PATTERN_STRUCT;
  26. typedef struct
  27. {
  28. bool bPending;
  29. int pat;
  30. }ARP_PHRASE_CHANGE_STRUCT;
  31. //------------------------------------------------------
  32. // sliding window average
  33. /*#define AVG_ARRAY_LEN 4
  34. #define AVG_AND (AVG_ARRAY_LEN - 1)
  35. typedef struct
  36. {
  37. int count;
  38. int avg[ AVG_ARRAY_LEN ];
  39. int tot;
  40. }SLIDING_AVG_STRUCT;*/
  41. typedef struct
  42. {
  43. // track in clk bpm
  44. //SLIDING_AVG_STRUCT Avg;
  45. int tickcount;
  46. float ftickspersec;
  47. float fbpm;
  48. // track sync tick
  49. float fsynclen;
  50. float fsynccount;
  51. bool bClockReset;
  52. int IgnoreClockCount;
  53. }MAIN_SYNC_CLOCK;
  54. typedef struct
  55. {
  56. // timing
  57. bool bTrig;
  58. int pat;
  59. int used;
  60. int step;
  61. int virtstep;
  62. ARP_PHRASE_CHANGE_STRUCT pending;
  63. // track current arp trig
  64. int nextcount;
  65. bool bNextTrig;
  66. // glide
  67. float fglideInc;
  68. int glideCount;
  69. float fglide;
  70. float fLastNotePlayed;
  71. bool bWasLastNotePlayed;
  72. // voct out
  73. float fCvStartOut = 0;
  74. float fCvEndOut = 0;
  75. }PAT_STEP_STRUCT;
  76. //-----------------------------------------------------
  77. // Module Definition
  78. //
  79. //-----------------------------------------------------
  80. struct ARP700 : Module
  81. {
  82. enum ParamIds
  83. {
  84. nPARAMS
  85. };
  86. enum InputIds
  87. {
  88. IN_CLOCK_TRIG,
  89. IN_VOCT_OFF,
  90. IN_PROG_CHANGE,
  91. IN_CLOCK_RESET,
  92. nINPUTS
  93. };
  94. enum OutputIds
  95. {
  96. OUT_TRIG,
  97. OUT_VOCTS,
  98. nOUTPUTS
  99. };
  100. enum NoteStates
  101. {
  102. STATE_NOTE_OFF,
  103. STATE_NOTE_ON,
  104. STATE_NOTE_REST,
  105. STATE_TRIG_OFF
  106. };
  107. CLog lg;
  108. bool m_bInitialized = false;
  109. // Contructor
  110. ARP700() : Module(nPARAMS, nINPUTS, nOUTPUTS, 0){}
  111. // pattern
  112. ARP_PATTERN_STRUCT m_PatternSave[ MAX_ARP_PATTERNS ] = {};
  113. PAT_STEP_STRUCT m_PatCtrl = {};
  114. SchmittTrigger m_SchTrigPatternChange;
  115. PatternSelectStrip *m_pPatternSelect = NULL;
  116. bool m_bCopySrc = false;
  117. // pattern buttons
  118. MyLEDButtonStrip *m_pButtonOnOff [ MAX_ARP_NOTES ][ SUBSTEP_PER_NOTE ] = {};
  119. MyLEDButtonStrip *m_pButtonLen [ MAX_ARP_NOTES ][ SUBSTEP_PER_NOTE ] = {};
  120. MyLEDButtonStrip *m_pButtonLenMod[ MAX_ARP_NOTES ][ SUBSTEP_PER_NOTE ] = {};
  121. MyLEDButton *m_pButtonGlide [ MAX_ARP_NOTES ] = {};
  122. MyLEDButton *m_pButtonTrig [ MAX_ARP_NOTES ] = {};
  123. MyLEDButtonStrip *m_plastbut = NULL;
  124. MyLEDButton *m_pButtonCopy= NULL;
  125. // clock
  126. SchmittTrigger m_SchTrigClk;
  127. MAIN_SYNC_CLOCK m_Clock;
  128. // global triggers
  129. SchmittTrigger m_SchTrigGlobalClkReset;
  130. bool m_GlobalClkResetPending = false;
  131. // keyboard
  132. Keyboard_3Oct_Widget *pKeyboardWidget = NULL;
  133. float m_fKeyNotes[ 37 ];
  134. float m_VoctOffsetIn = 0;
  135. // octave
  136. MyLEDButtonStrip *m_pButtonOctaveSelect = NULL;
  137. // pause
  138. bool m_bPauseState = false;
  139. MyLEDButton *m_pButtonPause;
  140. // mode
  141. MyLEDButtonStrip *m_pButtonMode = 0;
  142. // Overrides
  143. void step() override;
  144. void JsonParams( bool bTo, json_t *root);
  145. json_t* toJson() override;
  146. void fromJson(json_t *rootJ) override;
  147. void onRandomize() override;
  148. void onReset() override;
  149. void SetPatternSteps( int nSteps );
  150. void SetOut( void );
  151. void ChangePattern( int index, bool bForce );
  152. void SetPendingPattern( int phrase );
  153. void ArpStep( bool bReset );
  154. void Copy( bool bOn );
  155. };
  156. //-----------------------------------------------------
  157. // Procedure: ARP700_ModeSelect
  158. //-----------------------------------------------------
  159. void ARP700_ModeSelect( void *pClass, int id, int nbutton, bool bOn )
  160. {
  161. ARP700 *mymodule;
  162. mymodule = (ARP700*)pClass;
  163. mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].mode = nbutton;
  164. }
  165. //-----------------------------------------------------
  166. // Procedure: ARP700_NoteOnOff
  167. //-----------------------------------------------------
  168. void ARP700_NoteOnOff( void *pClass, int id, int nbutton, bool bOn )
  169. {
  170. int note, param;
  171. ARP700 *mymodule;
  172. mymodule = (ARP700*)pClass;
  173. note = id / SUBSTEP_PER_NOTE;
  174. param = id - ( SUBSTEP_PER_NOTE * note );
  175. mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].onoffsel[ note ][ param ] = nbutton;
  176. }
  177. //-----------------------------------------------------
  178. // Procedure: ARP700_NoteLenSelect
  179. //-----------------------------------------------------
  180. void ARP700_NoteLenSelect( void *pClass, int id, int nbutton, bool bOn )
  181. {
  182. int note, param;
  183. ARP700 *mymodule;
  184. mymodule = (ARP700*)pClass;
  185. note = id / SUBSTEP_PER_NOTE;
  186. param = id - ( SUBSTEP_PER_NOTE * note );
  187. mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].lensel[ note ][ param ] = nbutton;
  188. }
  189. //-----------------------------------------------------
  190. // Procedure: ARP700_OctSelect
  191. //-----------------------------------------------------
  192. void ARP700_OctSelect( void *pClass, int id, int nbutton, bool bOn )
  193. {
  194. ARP700 *mymodule;
  195. mymodule = (ARP700*)pClass;
  196. mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].oct = nbutton;
  197. }
  198. //-----------------------------------------------------
  199. // Procedure: ARP700_mod
  200. //-----------------------------------------------------
  201. void ARP700_mod( void *pClass, int id, int nbutton, bool bOn )
  202. {
  203. int note, param;
  204. ARP700 *mymodule;
  205. mymodule = (ARP700*)pClass;
  206. note = id / SUBSTEP_PER_NOTE;
  207. param = id - ( SUBSTEP_PER_NOTE * note );
  208. mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].lenmod[ note ][ param ] = nbutton;
  209. }
  210. //-----------------------------------------------------
  211. // Procedure: ARP700_Pause
  212. //-----------------------------------------------------
  213. void ARP700_Pause( void *pClass, int id, bool bOn )
  214. {
  215. ARP700 *mymodule;
  216. mymodule = (ARP700*)pClass;
  217. mymodule->m_bPauseState = bOn;
  218. }
  219. //-----------------------------------------------------
  220. // Procedure: ARP700_Copy
  221. //-----------------------------------------------------
  222. void ARP700_Copy( void *pClass, int id, bool bOn )
  223. {
  224. ARP700 *mymodule;
  225. mymodule = (ARP700*)pClass;
  226. mymodule->Copy( bOn );
  227. }
  228. //-----------------------------------------------------
  229. // Procedure: ARP700_Glide
  230. //-----------------------------------------------------
  231. void ARP700_Glide( void *pClass, int id, bool bOn )
  232. {
  233. ARP700 *mymodule;
  234. mymodule = (ARP700*)pClass;
  235. mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].glide[ id ] = bOn;
  236. //mymodule->lg.f("Glide[ %d ] = %d\n", id, bOn );
  237. }
  238. //-----------------------------------------------------
  239. // Procedure: ARP700_Trig
  240. //-----------------------------------------------------
  241. void ARP700_Trig( void *pClass, int id, bool bOn )
  242. {
  243. ARP700 *mymodule;
  244. mymodule = (ARP700*)pClass;
  245. mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].legato[ id ] = bOn;
  246. //mymodule->lg.f("Legato[ %d ] = %d\n", id, bOn );
  247. }
  248. //-----------------------------------------------------
  249. // Procedure: NoteChangeCallback
  250. //
  251. //-----------------------------------------------------
  252. void ARP700_Widget_NoteChangeCallback ( void *pClass, int kb, int notepressed, int *pnotes, bool bOn, int button )
  253. {
  254. ARP700 *mymodule = (ARP700 *)pClass;
  255. if( !pClass )
  256. return;
  257. memcpy( mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].notes, pnotes, sizeof( int ) * MAX_ARP_NOTES );
  258. mymodule->m_PatternSave[ mymodule->m_PatCtrl.pat ].notesused = mymodule->pKeyboardWidget->m_nKeysOn;
  259. }
  260. //-----------------------------------------------------
  261. // Procedure: PatternChangeCallback
  262. //
  263. //-----------------------------------------------------
  264. void ARP700_Widget_PatternChangeCallback ( void *pClass, int kb, int pat, int max )
  265. {
  266. ARP700 *mymodule = (ARP700 *)pClass;
  267. if( !mymodule || !mymodule->m_bInitialized )
  268. return;
  269. if( mymodule->m_PatCtrl.pat != pat )
  270. {
  271. if( !mymodule->m_bPauseState && mymodule->inputs[ ARP700::IN_CLOCK_TRIG ].active )
  272. mymodule->SetPendingPattern( pat );
  273. else
  274. mymodule->ChangePattern( pat, false );
  275. }
  276. else if( mymodule->m_PatCtrl.used != max )
  277. mymodule->SetPatternSteps( max );
  278. }
  279. //-----------------------------------------------------
  280. // Procedure: Widget
  281. //
  282. //-----------------------------------------------------
  283. struct ARP700_Widget : ModuleWidget {
  284. ARP700_Widget( ARP700 *module );
  285. };
  286. ARP700_Widget::ARP700_Widget( ARP700 *module ) : ModuleWidget(module)
  287. {
  288. int x, y, note, param;
  289. box.size = Vec( 15*27, 380);
  290. {
  291. SVGPanel *panel = new SVGPanel();
  292. panel->box.size = box.size;
  293. panel->setBackground(SVG::load(assetPlugin(plugin, "res/ARP700.svg")));
  294. addChild(panel);
  295. }
  296. for( int i = 0; i < 37; i++ )
  297. module->m_fKeyNotes[ i ] = (float)i * SEMI;
  298. //module->lg.Open("ARP700.txt");
  299. // pause button
  300. module->m_pButtonPause = new MyLEDButton( 75, 22, 11, 11, 8.0, DWRGB( 180, 180, 180 ), DWRGB( 255, 0, 0 ), MyLEDButton::TYPE_SWITCH, 0, module, ARP700_Pause );
  301. addChild( module->m_pButtonPause );
  302. // copy button
  303. module->m_pButtonCopy = new MyLEDButton( 307, 22, 11, 11, 8.0, DWRGB( 180, 180, 180 ), DWRGB( 0, 255, 255 ), MyLEDButton::TYPE_SWITCH, 0, module, ARP700_Copy );
  304. addChild( module->m_pButtonCopy );
  305. // keyboard widget
  306. module->pKeyboardWidget = new Keyboard_3Oct_Widget( 75, 38, MAX_ARP_NOTES, 0, DWRGB( 255, 128, 64 ), module, ARP700_Widget_NoteChangeCallback, &module->lg );
  307. addChild( module->pKeyboardWidget );
  308. // octave select
  309. module->m_pButtonOctaveSelect = new MyLEDButtonStrip( 307, 104, 11, 11, 3, 8.0, 4, false, DWRGB( 180, 180, 180 ), DWRGB( 0, 255, 255 ), MyLEDButtonStrip::TYPE_EXCLUSIVE, 0, module, ARP700_OctSelect );
  310. addChild( module->m_pButtonOctaveSelect );
  311. // pattern selects
  312. module->m_pPatternSelect = new PatternSelectStrip( 75, 104, 9, 7, DWRGB( 200, 200, 200 ), DWRGB( 40, 40, 40 ), DWRGB( 112, 104, 102 ), DWRGB( 40, 40, 40 ), MAX_ARP_PATTERNS, 0, module, ARP700_Widget_PatternChangeCallback );
  313. addChild( module->m_pPatternSelect );
  314. x = 60;
  315. for( note = 0; note < MAX_ARP_NOTES; note++ )
  316. {
  317. for( param = 0; param < SUBSTEP_PER_NOTE; param++ )
  318. {
  319. y = 140;
  320. module->m_pButtonOnOff[ note ][ param ] = new MyLEDButtonStrip( x, y, 12, 12, 2, 10.0, 3, true, DWRGB( 180, 180, 180 ), DWRGB( 255, 0, 0 ), MyLEDButtonStrip::TYPE_EXCLUSIVE, (note * SUBSTEP_PER_NOTE ) + param, module, ARP700_NoteOnOff );
  321. addChild( module->m_pButtonOnOff[ note ][ param ] );
  322. module->m_pButtonOnOff[ note ][ param ]->SetLEDCol( 1, DWRGB( 0, 255, 0 ) );
  323. module->m_pButtonOnOff[ note ][ param ]->SetLEDCol( 2, DWRGB( 255, 255, 0 ) );
  324. y += 43;
  325. module->m_pButtonLen[ note ][ param ] = new MyLEDButtonStrip( x, y, 12, 12, 2, 10.0, 6, true, DWRGB( 180, 180, 180 ), DWRGB( 255, 128, 0 ), MyLEDButtonStrip::TYPE_EXCLUSIVE, (note * SUBSTEP_PER_NOTE ) + param, module, ARP700_NoteLenSelect );
  326. addChild( module->m_pButtonLen[ note ][ param ] );
  327. y += 89;
  328. module->m_pButtonLenMod[ note ][ param ] = new MyLEDButtonStrip( x, y, 12, 12, 2, 10.0, 3, true, DWRGB( 180, 180, 180 ), DWRGB( 255, 128, 0 ), MyLEDButtonStrip::TYPE_EXCLUSIVE_WOFF, (note * SUBSTEP_PER_NOTE ) + param, module, ARP700_mod );
  329. addChild( module->m_pButtonLenMod[ note ][ param ] );
  330. if( param == 1 )
  331. {
  332. y += 43;
  333. module->m_pButtonGlide[ note ] = new MyLEDButton( x, y, 12, 12, 10.0, DWRGB( 180, 180, 180 ), DWRGB( 0, 255, 255 ), MyLEDButton::TYPE_SWITCH, note, module, ARP700_Glide );
  334. addChild( module->m_pButtonGlide[ note ] );
  335. y += 16;
  336. module->m_pButtonTrig[ note ] = new MyLEDButton( x, y, 12, 12, 10.0, DWRGB( 180, 180, 180 ), DWRGB( 0, 255, 255 ), MyLEDButton::TYPE_SWITCH, note, module, ARP700_Trig );
  337. addChild( module->m_pButtonTrig[ note ] );
  338. }
  339. x += 14;
  340. }
  341. x += 5;
  342. }
  343. // clock trigger
  344. addInput(Port::create<MyPortInSmall>( Vec( 44, 21 ), Port::INPUT, module, ARP700::IN_CLOCK_TRIG ) );
  345. // VOCT offset input
  346. addInput(Port::create<MyPortInSmall>( Vec( 44, 52 ), Port::INPUT, module, ARP700::IN_VOCT_OFF ) );
  347. // prog change trigger
  348. addInput(Port::create<MyPortInSmall>( Vec( 44, 102 ), Port::INPUT, module, ARP700::IN_PROG_CHANGE ) );
  349. // outputs
  350. addOutput(Port::create<MyPortOutSmall>( Vec( 365, 38 ), Port::OUTPUT, module, ARP700::OUT_VOCTS ) );
  351. addOutput(Port::create<MyPortOutSmall>( Vec( 365, 79 ), Port::OUTPUT, module, ARP700::OUT_TRIG ) );
  352. // reset inputs
  353. addInput(Port::create<MyPortInSmall>( Vec( 14, 21 ), Port::INPUT, module, ARP700::IN_CLOCK_RESET ) );
  354. // mode buttons
  355. module->m_pButtonMode = new MyLEDButtonStrip( 154, 360, 12, 12, 7, 10.0, 7, false, DWRGB( 180, 180, 180 ), DWRGB( 255, 255, 0 ), MyLEDButtonStrip::TYPE_EXCLUSIVE, 0, module, ARP700_ModeSelect );
  356. addChild( module->m_pButtonMode );
  357. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  358. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0)));
  359. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  360. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365)));
  361. module->m_Clock.fsynclen = 2.0 * 48.0; // default to 120bpm
  362. module->m_Clock.IgnoreClockCount = 2;
  363. module->m_bInitialized = true;
  364. module->onReset();
  365. }
  366. //-----------------------------------------------------
  367. // Procedure: JsonParams
  368. //
  369. //-----------------------------------------------------
  370. void ARP700::JsonParams( bool bTo, json_t *root)
  371. {
  372. JsonDataBool ( bTo, "m_bPauseState", root, &m_bPauseState, 1 );
  373. JsonDataInt ( bTo, "m_CurrentPattern", root, &m_PatCtrl.pat, 1 );
  374. JsonDataInt ( bTo, "m_PatternSave", root, (int*)m_PatternSave, sizeof( m_PatternSave ) / 4 );
  375. JsonDataInt ( bTo, "m_PatternsUsed", root, &m_PatCtrl.used, 1 );
  376. }
  377. //-----------------------------------------------------
  378. // Procedure: toJson
  379. //
  380. //-----------------------------------------------------
  381. json_t *ARP700::toJson()
  382. {
  383. json_t *root = json_object();
  384. if( !root )
  385. return NULL;
  386. JsonParams( TOJSON, root );
  387. return root;
  388. }
  389. //-----------------------------------------------------
  390. // Procedure: fromJson
  391. //
  392. //-----------------------------------------------------
  393. void ARP700::fromJson( json_t *root )
  394. {
  395. JsonParams( FROMJSON, root );
  396. m_pButtonPause->Set( m_bPauseState );
  397. pKeyboardWidget->setkey( m_PatternSave[ m_PatCtrl.pat ].notes );
  398. ChangePattern( m_PatCtrl.pat, true );
  399. ArpStep( true );
  400. }
  401. //-----------------------------------------------------
  402. // Procedure: reset
  403. //
  404. //-----------------------------------------------------
  405. void ARP700::onReset()
  406. {
  407. int pat, note;
  408. if( !m_bInitialized )
  409. return;
  410. m_pButtonOctaveSelect->Set( 0, true );
  411. m_PatCtrl.fCvStartOut = 0;
  412. m_PatCtrl.fCvEndOut = 0;
  413. memset( m_PatternSave, 0, sizeof(m_PatternSave) );
  414. for( pat = 0; pat < MAX_ARP_PATTERNS; pat++ )
  415. {
  416. for( note = 0; note < MAX_ARP_NOTES; note++ )
  417. m_PatternSave[ pat ].notes[ note ] = -1;
  418. }
  419. SetPatternSteps( MAX_ARP_PATTERNS - 1 );
  420. ChangePattern( 0, true );
  421. }
  422. //-----------------------------------------------------
  423. // Procedure: randomize
  424. //
  425. //-----------------------------------------------------
  426. void ARP700::onRandomize()
  427. {
  428. }
  429. //-----------------------------------------------------
  430. // Procedure: SetPhraseSteps
  431. //
  432. //-----------------------------------------------------
  433. void ARP700::SetPatternSteps( int nSteps )
  434. {
  435. if( nSteps < 0 || nSteps >= MAX_ARP_PATTERNS )
  436. nSteps = 0;
  437. m_PatCtrl.used = nSteps;
  438. }
  439. //-----------------------------------------------------
  440. // Procedure: SetOut
  441. //
  442. //-----------------------------------------------------
  443. void ARP700::SetOut( void )
  444. {
  445. int note = 0, nstep, substep;
  446. float foct;
  447. m_VoctOffsetIn = inputs[ IN_VOCT_OFF ].normalize( 0.0 );
  448. nstep = m_PatCtrl.step / SUBSTEP_PER_NOTE;
  449. substep = m_PatCtrl.step - ( nstep * SUBSTEP_PER_NOTE );
  450. if( m_PatternSave[ m_PatCtrl.pat ].onoffsel[ nstep ][ substep ] == ARP_ON )
  451. {
  452. note = m_PatternSave[ m_PatCtrl.pat ].notes[ nstep ];
  453. pKeyboardWidget->setkeyhighlight( note );
  454. }
  455. else
  456. return;
  457. if( note > 36 || note < 0 )
  458. note = 0;
  459. foct = (float)m_PatternSave[ m_PatCtrl.pat ].oct;
  460. m_PatCtrl.fCvEndOut = foct + m_fKeyNotes[ note ] + m_VoctOffsetIn;
  461. // start glide note (last pattern note)
  462. if( m_PatCtrl.bWasLastNotePlayed )
  463. {
  464. m_PatCtrl.fCvStartOut = m_PatCtrl.fLastNotePlayed + m_VoctOffsetIn;
  465. }
  466. else
  467. {
  468. m_PatCtrl.bWasLastNotePlayed = true;
  469. m_PatCtrl.fCvStartOut = m_PatCtrl.fCvEndOut + m_VoctOffsetIn;
  470. }
  471. m_PatCtrl.fLastNotePlayed = m_PatCtrl.fCvEndOut + m_VoctOffsetIn;
  472. if( m_PatternSave[ m_PatCtrl.pat ].glide[ nstep ] )
  473. {
  474. // glide time
  475. m_PatCtrl.glideCount = 0.2 * engineGetSampleRate();
  476. m_PatCtrl.fglideInc = 1.0 / (float)m_PatCtrl.glideCount;
  477. m_PatCtrl.fglide = 1.0;
  478. }
  479. else
  480. {
  481. m_PatCtrl.fglide = 0.0;
  482. m_PatCtrl.glideCount = 0;
  483. }
  484. }
  485. //-----------------------------------------------------
  486. // Procedure: SetPendingPattern
  487. //
  488. //-----------------------------------------------------
  489. void ARP700::SetPendingPattern( int patin )
  490. {
  491. int pattern;
  492. if( patin < 0 || patin >= MAX_ARP_PATTERNS )
  493. pattern = ( m_PatCtrl.pat + 1 ) & 0x7;
  494. else
  495. pattern = patin;
  496. if( pattern > m_PatCtrl.used )
  497. pattern = 0;
  498. m_PatCtrl.pending.bPending = true;
  499. m_PatCtrl.pending.pat = pattern;
  500. m_pPatternSelect->SetPat( m_PatCtrl.pat, false );
  501. m_pPatternSelect->SetPat( pattern, true );
  502. }
  503. //-----------------------------------------------------
  504. // Procedure: Copy
  505. //
  506. //-----------------------------------------------------
  507. void ARP700::Copy( bool bOn )
  508. {
  509. if( !m_bPauseState || !bOn )
  510. {
  511. m_bCopySrc = false;
  512. m_pButtonCopy->Set( false );
  513. }
  514. else if( bOn )
  515. {
  516. m_bCopySrc = true;
  517. }
  518. }
  519. //-----------------------------------------------------
  520. // Procedure: ChangePattern
  521. //
  522. //-----------------------------------------------------
  523. void ARP700::ChangePattern( int index, bool bForce )
  524. {
  525. int note, param;
  526. if( !bForce && index == m_PatCtrl.pat )
  527. return;
  528. if( index < 0 )
  529. index = MAX_ARP_PATTERNS - 1;
  530. else if( index >= MAX_ARP_PATTERNS )
  531. index = 0;
  532. if( m_bCopySrc )
  533. {
  534. // do not copy if we are not paused
  535. if( m_bPauseState )
  536. {
  537. memcpy( &m_PatternSave[ index ], &m_PatternSave[ m_PatCtrl.pat ], sizeof(ARP_PATTERN_STRUCT) );
  538. m_pButtonCopy->Set( false );
  539. m_bCopySrc = false;
  540. }
  541. }
  542. m_PatCtrl.pat = index;
  543. for( note = 0; note < MAX_ARP_NOTES; note++ )
  544. {
  545. m_pButtonGlide[ note ]->Set( m_PatternSave[ m_PatCtrl.pat ].glide[ note ] );
  546. m_pButtonTrig[ note ]->Set( m_PatternSave[ m_PatCtrl.pat ].legato[ note ] );
  547. for( param = 0; param < SUBSTEP_PER_NOTE; param++ )
  548. {
  549. m_pButtonOnOff[ note ][ param ]->Set( m_PatternSave[ m_PatCtrl.pat ].onoffsel[ note ][ param ], true );
  550. m_pButtonLen[ note ][ param ]->Set( m_PatternSave[ m_PatCtrl.pat ].lensel[ note ][ param ], true );
  551. m_pButtonLenMod[ note ][ param ]->Set( m_PatternSave[ m_PatCtrl.pat ].lenmod[ note ][ param ], true );
  552. }
  553. }
  554. m_pButtonOctaveSelect->Set( m_PatternSave[ m_PatCtrl.pat ].oct, true );
  555. m_pButtonMode->Set( m_PatternSave[ m_PatCtrl.pat ].mode, true );
  556. m_pPatternSelect->SetPat( index, false );
  557. m_pPatternSelect->SetMax( m_PatCtrl.used );
  558. // set keyboard keys
  559. pKeyboardWidget->setkey( m_PatternSave[ m_PatCtrl.pat ].notes );
  560. }
  561. //-----------------------------------------------------
  562. // Procedure: IncStep
  563. //
  564. //-----------------------------------------------------
  565. #define BASE_TICK_16th 48 // for 16th note
  566. const float fbasenotelen[ 6 ] = { BASE_TICK_16th * 4, BASE_TICK_16th * 2, BASE_TICK_16th, BASE_TICK_16th / 2, BASE_TICK_16th / 4, BASE_TICK_16th / 8};
  567. const int patmode[ 7 ][ 42 ] =
  568. {
  569. { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
  570. { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1 },
  571. { 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 },
  572. { 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, -1 },
  573. { 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 },
  574. { 0, 20, 1, 19, 2, 18, 3, 17, 4, 16, 5, 15, 6, 14, 7, 13, 8, 12, 9, 11, 10, 10, 11, 9, 12, 8, 13, 7, 14, 6, 15, 5, 16, 4, 17, 3, 18, 2, 19, 1, 20, 0 },
  575. { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }
  576. };
  577. void ARP700::ArpStep( bool bReset )
  578. {
  579. int i, nstep, substep, modestp;
  580. if( !m_PatternSave[ m_PatCtrl.pat ].notesused )
  581. {
  582. m_PatCtrl.virtstep = -1;
  583. m_PatCtrl.bTrig = false;
  584. return;
  585. }
  586. else
  587. {
  588. if( bReset )
  589. m_PatCtrl.virtstep = -1;
  590. // find next used step
  591. for( i = 0; i <= ( SUBSTEP_PER_NOTE * MAX_ARP_NOTES * 2 ); i++ )
  592. {
  593. m_PatCtrl.virtstep++;
  594. if( m_PatCtrl.virtstep >= ( SUBSTEP_PER_NOTE * MAX_ARP_NOTES * 2 ) )
  595. m_PatCtrl.virtstep = 0;
  596. if( m_PatternSave[ m_PatCtrl.pat ].mode == 6 )
  597. modestp = (int)( randomUniform() * 20.0f );
  598. else
  599. modestp = patmode[ m_PatternSave[ m_PatCtrl.pat ].mode ][ m_PatCtrl.virtstep ];
  600. if( modestp != -1 )
  601. {
  602. nstep = modestp / SUBSTEP_PER_NOTE;
  603. substep = modestp - ( nstep * SUBSTEP_PER_NOTE );
  604. if( m_PatternSave[ m_PatCtrl.pat ].onoffsel[ nstep ][ substep ] != ARP_OFF )
  605. {
  606. m_PatCtrl.step = modestp;
  607. goto stepfound;
  608. }
  609. }
  610. else
  611. {
  612. m_PatCtrl.virtstep = -1;
  613. }
  614. }
  615. }
  616. // if we are here, no step was found
  617. m_PatCtrl.step = -1;
  618. m_PatCtrl.bTrig = false;
  619. return;
  620. stepfound:
  621. if( m_PatCtrl.step == 0 )
  622. {
  623. if( m_PatCtrl.pending.bPending )
  624. {
  625. m_PatCtrl.pending.bPending = false;
  626. ChangePattern( m_PatCtrl.pending.pat, true );
  627. }
  628. }
  629. nstep = m_PatCtrl.step / SUBSTEP_PER_NOTE;
  630. substep = m_PatCtrl.step - ( nstep * SUBSTEP_PER_NOTE );
  631. if( m_plastbut )
  632. m_plastbut->SetHiLightOn( -1 );
  633. m_pButtonLen[ nstep ][ substep ]->SetHiLightOn( m_PatternSave[ m_PatCtrl.pat ].lensel[ nstep ][ substep ] );
  634. m_plastbut = m_pButtonLen[ nstep ][ substep ];
  635. // next step length
  636. m_PatCtrl.nextcount = fbasenotelen[ m_PatternSave[ m_PatCtrl.pat ].lensel[ nstep ][ substep ] ];
  637. switch( m_PatternSave[ m_PatCtrl.pat ].lenmod[ nstep ][ substep ] )
  638. {
  639. case 1: // x2
  640. m_PatCtrl.nextcount *= 2;
  641. break;
  642. case 2: // dotted
  643. m_PatCtrl.nextcount += m_PatCtrl.nextcount / 2;
  644. break;
  645. case 3: // triplet
  646. m_PatCtrl.nextcount = m_PatCtrl.nextcount / 3;
  647. break;
  648. }
  649. // if this is note on return true
  650. if( m_PatternSave[ m_PatCtrl.pat ].onoffsel[ nstep ][ substep ] == ARP_ON )
  651. {
  652. SetOut();
  653. if( m_PatternSave[ m_PatCtrl.pat ].legato[ nstep ] )
  654. m_PatCtrl.bTrig = false;
  655. else
  656. m_PatCtrl.bTrig = true;
  657. }
  658. }
  659. //-----------------------------------------------------
  660. // Procedure: step
  661. //
  662. //-----------------------------------------------------
  663. void ARP700::step()
  664. {
  665. bool bSyncTick = false, bResetClk = false;
  666. if( !m_bInitialized )
  667. return;
  668. if( !inputs[ IN_CLOCK_TRIG ].active )
  669. {
  670. outputs[ OUT_TRIG ].value = 0;
  671. m_Clock.tickcount = 0;
  672. m_Clock.fsynclen = 2.0 * 48.0; // default to 120bpm
  673. m_Clock.fsynccount = 0;
  674. m_Clock.IgnoreClockCount = 2;
  675. if( m_PatCtrl.pending.bPending )
  676. {
  677. m_PatCtrl.pending.bPending = false;
  678. ChangePattern( m_PatCtrl.pending.pat, false );
  679. }
  680. return;
  681. }
  682. // global clock reset
  683. m_Clock.bClockReset = ( m_SchTrigGlobalClkReset.process( inputs[ IN_CLOCK_RESET ].normalize( 0.0f ) ) );
  684. // pattern change trig
  685. if( !m_bPauseState && m_SchTrigPatternChange.process( inputs[ IN_PROG_CHANGE ].normalize( 0.0f ) ) )
  686. SetPendingPattern( -1 );
  687. // track clock period
  688. if( m_SchTrigClk.process( inputs[ IN_CLOCK_TRIG ].normalize( 0.0f ) ) || m_Clock.bClockReset )
  689. {
  690. if( m_Clock.bClockReset )
  691. {
  692. m_Clock.tickcount = 0;
  693. //ArpStep( true );
  694. m_Clock.bClockReset = false;
  695. m_Clock.IgnoreClockCount = 2;
  696. bResetClk = true;
  697. }
  698. if( m_Clock.tickcount && --m_Clock.IgnoreClockCount <= 0 )
  699. {
  700. m_Clock.IgnoreClockCount = 0;
  701. m_Clock.fsynclen = (float)( engineGetSampleRate() / (float)m_Clock.tickcount ) * 48.0;
  702. }
  703. m_Clock.fsynccount = 0;
  704. bSyncTick = true;
  705. m_Clock.tickcount = 0;
  706. }
  707. else
  708. {
  709. // keep track of sync tick (16th / 12 )
  710. m_Clock.fsynccount += m_Clock.fsynclen;
  711. if( m_Clock.fsynccount >= engineGetSampleRate() )
  712. {
  713. m_Clock.fsynccount = m_Clock.fsynccount - engineGetSampleRate();
  714. bSyncTick = true;
  715. }
  716. }
  717. m_Clock.tickcount++;
  718. if( m_bPauseState )
  719. {
  720. m_PatCtrl.bTrig = false;
  721. if( m_PatCtrl.pending.bPending )
  722. {
  723. m_PatCtrl.pending.bPending = false;
  724. ChangePattern( m_PatCtrl.pending.pat, false );
  725. }
  726. }
  727. else if( bSyncTick )
  728. {
  729. if( bResetClk )
  730. m_PatCtrl.nextcount = 0;
  731. else
  732. m_PatCtrl.nextcount--;
  733. // cut off note one tick early so they don't legato
  734. if( m_PatCtrl.nextcount == 1 )
  735. m_PatCtrl.bTrig = false;
  736. else if( m_PatCtrl.nextcount <= 0 )
  737. ArpStep( bResetClk );
  738. }
  739. outputs[ OUT_TRIG ].value = m_PatCtrl.bTrig ? CV_MAX : 0.0;
  740. if( --m_PatCtrl.glideCount > 0 )
  741. m_PatCtrl.fglide -= m_PatCtrl.fglideInc;
  742. else
  743. m_PatCtrl.fglide = 0.0;
  744. outputs[ OUT_VOCTS ].value = ( m_PatCtrl.fCvStartOut * m_PatCtrl.fglide ) + ( m_PatCtrl.fCvEndOut * ( 1.0 - m_PatCtrl.fglide ) );
  745. }
  746. } // namespace rack_plugin_mscHack
  747. using namespace rack_plugin_mscHack;
  748. RACK_PLUGIN_MODEL_INIT(mscHack, ARP700) {
  749. Model *modelARP700 = Model::create<ARP700, ARP700_Widget>( "mscHack", "ARP700", "ARP 700", SEQUENCER_TAG );
  750. return modelARP700;
  751. }