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.

1158 lines
33KB

  1. #include "mscHack.hpp"
  2. //#include "mscHack_Controls.hpp"
  3. #include "dsp/digital.hpp"
  4. //#include "CLog.h"
  5. #include "window.hpp"
  6. namespace rack_plugin_mscHack {
  7. #define nKEYBOARDS 3
  8. #define nKEYS 37
  9. #define nOCTAVESEL 5
  10. #define nPATTERNS 16
  11. #define nPHRASE_SAVES 8
  12. #define SEMI ( 1.0f / 12.0f )
  13. typedef struct
  14. {
  15. float fsemi;
  16. }KEYBOARD_KEY_STRUCT;
  17. typedef struct
  18. {
  19. int note;
  20. bool bTrigOff;
  21. int pad[ 6 ];
  22. }PATTERN_STRUCT;
  23. typedef struct
  24. {
  25. bool bPending;
  26. int phrase;
  27. }PHRASE_CHANGE_STRUCT;
  28. //-----------------------------------------------------
  29. // Module Definition
  30. //
  31. //-----------------------------------------------------
  32. struct Seq_Triad2 : Module
  33. {
  34. #define NO_COPY -1
  35. enum ParamIds
  36. {
  37. PARAM_PAUSE,
  38. PARAM_OCTAVES = PARAM_PAUSE + ( nKEYBOARDS ),
  39. PARAM_GLIDE = PARAM_OCTAVES + (nOCTAVESEL * nKEYBOARDS),
  40. PARAM_TRIGOFF = PARAM_GLIDE + ( nKEYBOARDS ),
  41. nPARAMS = PARAM_TRIGOFF + ( nKEYBOARDS )
  42. };
  43. enum InputIds
  44. {
  45. IN_PATTERN_TRIG,
  46. IN_VOCT_OFF = IN_PATTERN_TRIG + ( nKEYBOARDS ),
  47. IN_PROG_CHANGE = IN_VOCT_OFF + ( nKEYBOARDS ),
  48. IN_CLOCK_RESET = IN_PROG_CHANGE + ( nKEYBOARDS ),
  49. IN_GLOBAL_PAT_CLK,
  50. IN_GLOBAL_TRIG_MUTE,
  51. IN_CHANNEL_TRIG_MUTE,
  52. nINPUTS = IN_CHANNEL_TRIG_MUTE + ( nKEYBOARDS )
  53. };
  54. enum OutputIds
  55. {
  56. OUT_TRIG,
  57. OUT_VOCTS = OUT_TRIG + nKEYBOARDS,
  58. nOUTPUTS = OUT_VOCTS + nKEYBOARDS
  59. };
  60. CLog lg;
  61. bool m_bInitialized = false;
  62. // octaves
  63. int m_Octave[ nKEYBOARDS ] = {};
  64. float m_fCvStartOut[ nKEYBOARDS ] = {};
  65. float m_fCvEndOut[ nKEYBOARDS ] = {};
  66. // patterns
  67. int m_CurrentPattern[ nKEYBOARDS ] = {};
  68. PATTERN_STRUCT m_PatternNotes[ nKEYBOARDS ][ nPHRASE_SAVES ][ nPATTERNS ] = {};
  69. SchmittTrigger m_SchTrigPatternSelectInput[ nKEYBOARDS ];
  70. PatternSelectStrip *m_pPatternSelect[ nKEYBOARDS ] = {};
  71. int m_CopySrc = NO_COPY;
  72. // phrase save
  73. int m_CurrentPhrase[ nKEYBOARDS ] = {};
  74. PHRASE_CHANGE_STRUCT m_PhrasePending[ nKEYBOARDS ] = {};
  75. SchmittTrigger m_SchTrigPhraseSelect[ nKEYBOARDS ] = {};
  76. int m_PhrasesUsed[ nKEYBOARDS ] = {0};
  77. PatternSelectStrip *m_pPhraseSelect[ nKEYBOARDS ] = {};
  78. // number of steps
  79. int m_nSteps[ nKEYBOARDS ][ nPHRASE_SAVES ] = {};
  80. // pause button
  81. bool m_bPause[ nKEYBOARDS ] = {};
  82. // trig mute
  83. bool m_bTrigMute = false;
  84. MyLEDButton *m_pButtonTrigMute = NULL;
  85. // channel trig mute
  86. bool m_bChTrigMute[ nKEYBOARDS ] = {};
  87. MyLEDButton *m_pButtonChTrigMute[ nKEYBOARDS ] = {};
  88. // triggers
  89. bool m_bTrig[ nKEYBOARDS ] = {};
  90. PulseGenerator m_gatePulse[ nKEYBOARDS ];
  91. // global triggers
  92. SchmittTrigger m_SchTrigGlobalClkReset;
  93. SchmittTrigger m_SchTrigGlobalPatChange;
  94. bool m_GlobalClkResetPending = false;
  95. // glide
  96. float m_fglideInc[ nKEYBOARDS ] = {};
  97. int m_glideCount[ nKEYBOARDS ] = {};
  98. float m_fglide[ nKEYBOARDS ] = {};
  99. float m_fLastNotePlayed[ nKEYBOARDS ];
  100. bool m_bWasLastNotePlayed[ nKEYBOARDS ] = {};
  101. Keyboard_3Oct_Widget *pKeyboardWidget[ nKEYBOARDS ];
  102. float m_fKeyNotes[ 37 ];
  103. float m_VoctOffsetIn[ nKEYBOARDS ] = {};
  104. // buttons
  105. MyLEDButtonStrip *m_pButtonOctaveSelect[ nKEYBOARDS ] = {};
  106. MyLEDButton *m_pButtonPause[ nKEYBOARDS ] = {};
  107. MyLEDButton *m_pButtonTrig[ nKEYBOARDS ] = {};
  108. MyLEDButton *m_pButtonCopy[ nKEYBOARDS ] = {};
  109. float flast[ nKEYBOARDS ] = {};
  110. // Constructor
  111. Seq_Triad2() : Module( nPARAMS, nINPUTS, nOUTPUTS, 0 )
  112. {
  113. int i;
  114. for( i = 0; i < 37; i++ )
  115. m_fKeyNotes[ i ] = (float)i * SEMI;
  116. }
  117. // Overrides
  118. void step() override;
  119. json_t* toJson() override;
  120. void fromJson(json_t *rootJ) override;
  121. void onRandomize() override;
  122. void onReset() override;
  123. void SetPhraseSteps( int kb, int nSteps );
  124. void SetSteps( int kb, int steps );
  125. void SetKey( int kb );
  126. void SetOut( int kb );
  127. void ChangePattern( int kb, int index, bool bForce, bool bPlay );
  128. void ChangePhrase( int kb, int index, bool bForce );
  129. void SetPendingPhrase( int kb, int phrase );
  130. void Copy( int kb, bool bOn );
  131. };
  132. //-----------------------------------------------------
  133. // Seq_Triad2_OctSelect
  134. //-----------------------------------------------------
  135. void Seq_Triad2_OctSelect( void *pClass, int id, int nbutton, bool bOn )
  136. {
  137. Seq_Triad2 *mymodule;
  138. mymodule = (Seq_Triad2*)pClass;
  139. mymodule->m_Octave[ id ] = nbutton;
  140. mymodule->SetOut( id );
  141. }
  142. //-----------------------------------------------------
  143. // Seq_Triad2_Pause
  144. //-----------------------------------------------------
  145. void Seq_Triad2_Pause( void *pClass, int id, bool bOn )
  146. {
  147. Seq_Triad2 *mymodule;
  148. mymodule = (Seq_Triad2*)pClass;
  149. mymodule->m_bPause[ id ] = !mymodule->m_bPause[ id ];
  150. }
  151. //-----------------------------------------------------
  152. // Seq_Triad2_TrigMute
  153. //-----------------------------------------------------
  154. void Seq_Triad2_TrigMute( void *pClass, int id, bool bOn )
  155. {
  156. Seq_Triad2 *mymodule;
  157. mymodule = (Seq_Triad2*)pClass;
  158. mymodule->m_bTrigMute = bOn;
  159. }
  160. //-----------------------------------------------------
  161. // Seq_Triad2_ChTrigMute
  162. //-----------------------------------------------------
  163. void Seq_Triad2_ChTrigMute( void *pClass, int id, bool bOn )
  164. {
  165. Seq_Triad2 *mymodule;
  166. mymodule = (Seq_Triad2*)pClass;
  167. mymodule->m_bChTrigMute[ id ] = bOn;
  168. }
  169. //-----------------------------------------------------
  170. // Seq_Triad2_Trig
  171. //-----------------------------------------------------
  172. void Seq_Triad2_Trig( void *pClass, int id, bool bOn )
  173. {
  174. Seq_Triad2 *mymodule;
  175. mymodule = (Seq_Triad2*)pClass;
  176. mymodule->m_PatternNotes[ id ][ mymodule->m_CurrentPhrase[ id ] ][ mymodule->m_CurrentPattern[ id ] ].bTrigOff = bOn;//!mymodule->m_PatternNotes[ id ][ mymodule->m_CurrentPhrase[ id ] ][ mymodule->m_CurrentPattern[ id ] ].bTrigOff;
  177. }
  178. //-----------------------------------------------------
  179. // Procedure: Widget
  180. //
  181. //-----------------------------------------------------
  182. void Seq_Triad2_Widget_NoteChangeCallback ( void *pClass, int kb, int notepressed, int *pnotes, bool bOn, int button )
  183. {
  184. bool bCtrl = false;
  185. Seq_Triad2 *mymodule = (Seq_Triad2 *)pClass;
  186. if( !pClass )
  187. return;
  188. // don't allow program unless paused
  189. if( button == 1 && !mymodule->m_bPause[ kb ] )
  190. return;
  191. // right click advance step
  192. if( button == 1 )
  193. {
  194. if( windowIsModPressed() )
  195. bCtrl = true;
  196. mymodule->ChangePattern( kb, mymodule->m_CurrentPattern[ kb ] + 1, true, false );
  197. if( mymodule->m_CurrentPattern[ kb ] == 0 )
  198. mymodule->ChangePhrase( kb, mymodule->m_CurrentPhrase[ kb ] + 1, true );
  199. // hit control to set trig off
  200. if( bCtrl )
  201. mymodule->m_PatternNotes[ kb ][ mymodule->m_CurrentPhrase[ kb ] ][ mymodule->m_CurrentPattern[ kb ] ].bTrigOff = true;
  202. else
  203. mymodule->m_PatternNotes[ kb ][ mymodule->m_CurrentPhrase[ kb ] ][ mymodule->m_CurrentPattern[ kb ] ].bTrigOff = false;
  204. mymodule->m_pButtonTrig[ kb ]->Set( bCtrl );
  205. mymodule->m_PatternNotes[ kb ][ mymodule->m_CurrentPhrase[ kb ] ][ mymodule->m_CurrentPattern[ kb ] ].note = notepressed;
  206. mymodule->SetKey( kb );
  207. }
  208. else
  209. mymodule->m_PatternNotes[ kb ][ mymodule->m_CurrentPhrase[ kb ] ][ mymodule->m_CurrentPattern[ kb ] ].note = notepressed;
  210. mymodule->SetOut( kb );
  211. }
  212. //-----------------------------------------------------
  213. // Procedure: PatternChangeCallback
  214. //
  215. //-----------------------------------------------------
  216. void Seq_Triad2_Widget_PatternChangeCallback ( void *pClass, int kb, int pat, int max )
  217. {
  218. Seq_Triad2 *mymodule = (Seq_Triad2 *)pClass;
  219. if( !mymodule || !mymodule->m_bInitialized )
  220. return;
  221. if( mymodule->m_CurrentPattern[ kb ] != pat )
  222. mymodule->ChangePattern( kb, pat, false, true );
  223. else if( mymodule->m_nSteps[ kb ][ mymodule->m_CurrentPhrase[ kb ] ] != max )
  224. mymodule->SetSteps( kb, max );
  225. }
  226. //-----------------------------------------------------
  227. // Procedure: PhraseChangeCallback
  228. //
  229. //-----------------------------------------------------
  230. void Seq_Triad2_Widget_PhraseChangeCallback ( void *pClass, int kb, int pat, int max )
  231. {
  232. Seq_Triad2 *mymodule = (Seq_Triad2 *)pClass;
  233. if( !mymodule || !mymodule->m_bInitialized )
  234. return;
  235. if( mymodule->m_PhrasesUsed[ kb ] != max )
  236. {
  237. mymodule->SetPhraseSteps( kb, max );
  238. }
  239. else if( mymodule->m_CurrentPhrase[ kb ] == pat && mymodule->m_bPause[ kb ] && mymodule->m_CopySrc != NO_COPY )
  240. {
  241. mymodule->ChangePhrase( kb, pat, true );
  242. }
  243. else if( mymodule->m_CurrentPhrase[ kb ] != pat )
  244. {
  245. if( !mymodule->m_bPause[ kb ] && mymodule->inputs[ Seq_Triad2::IN_PATTERN_TRIG + kb ].active )
  246. mymodule->SetPendingPhrase( kb, pat );
  247. else
  248. mymodule->ChangePhrase( kb, pat, false );
  249. }
  250. }
  251. //-----------------------------------------------------
  252. // MyLEDButton_Copy
  253. //-----------------------------------------------------
  254. void MyLEDButton_Copy( void *pClass, int id, bool bOn )
  255. {
  256. Seq_Triad2 *mymodule;
  257. mymodule = (Seq_Triad2*)pClass;
  258. mymodule->Copy( id, bOn );
  259. }
  260. //-----------------------------------------------------
  261. // Procedure: Widget
  262. //
  263. //-----------------------------------------------------
  264. struct Seq_Triad2_Widget : ModuleWidget {
  265. Seq_Triad2_Widget( Seq_Triad2 *module );
  266. };
  267. Seq_Triad2_Widget::Seq_Triad2_Widget( Seq_Triad2 *module ) : ModuleWidget(module)
  268. {
  269. int kb, x, x2, y, y2;
  270. box.size = Vec( 15*25, 380);
  271. {
  272. SVGPanel *panel = new SVGPanel();
  273. panel->box.size = box.size;
  274. panel->setBackground(SVG::load(assetPlugin(plugin, "res/TriadSequencer2.svg")));
  275. addChild(panel);
  276. }
  277. //module->lg.Open("TriadSequencer2.txt");
  278. //----------------------------------------------------
  279. // Keyboard Keys
  280. y = 21;
  281. x = 11;
  282. for( kb = 0; kb < nKEYBOARDS; kb++ )
  283. {
  284. // channel trig mute
  285. module->m_pButtonChTrigMute[ kb ] = new MyLEDButton( x + 310, y + 3, 15, 15, 13.0, DWRGB( 180, 180, 180 ), DWRGB( 255, 0, 0 ), MyLEDButton::TYPE_SWITCH, kb, module, Seq_Triad2_ChTrigMute );
  286. addChild( module->m_pButtonChTrigMute[ kb ] );
  287. addInput(Port::create<MyPortInSmall>( Vec( x + 285, y + 1 ), Port::INPUT, module, Seq_Triad2::IN_CHANNEL_TRIG_MUTE + kb ) );
  288. // pause button
  289. module->m_pButtonPause[ kb ] = new MyLEDButton( x + 60, y + 4, 11, 11, 8.0, DWRGB( 180, 180, 180 ), DWRGB( 255, 0, 0 ), MyLEDButton::TYPE_SWITCH, kb, module, Seq_Triad2_Pause );
  290. addChild( module->m_pButtonPause[ kb ] );
  291. // trig button
  292. module->m_pButtonTrig[ kb ] = new MyLEDButton( x + 260, y + 5, 11, 11, 8.0, DWRGB( 180, 180, 180 ), DWRGB( 255, 0, 0 ), MyLEDButton::TYPE_SWITCH, kb, module, Seq_Triad2_Trig );
  293. addChild( module->m_pButtonTrig[ kb ] );
  294. // glide knob
  295. addParam( ParamWidget::create<Knob_Yellow1_15>( Vec( x + 235, y + 86 ), module, Seq_Triad2::PARAM_GLIDE + kb, 0.0, 1.0, 0.0 ) );
  296. module->m_pButtonCopy[ kb ] = new MyLEDButton( x + 194, y + 89, 11, 11, 8.0, DWRGB( 180, 180, 180 ), DWRGB( 0, 244, 244 ), MyLEDButton::TYPE_SWITCH, kb, module, MyLEDButton_Copy );
  297. addChild( module->m_pButtonCopy[ kb ] );
  298. x2 = x + 274;
  299. // octave select
  300. module->m_pButtonOctaveSelect[ kb ] = new MyLEDButtonStrip( x2, y + 90, 11, 11, 3, 8.0, nOCTAVESEL, false, DWRGB( 180, 180, 180 ), DWRGB( 0, 255, 255 ), MyLEDButtonStrip::TYPE_EXCLUSIVE, kb, module, Seq_Triad2_OctSelect );
  301. addChild( module->m_pButtonOctaveSelect[ kb ] );
  302. // keyboard widget
  303. module->pKeyboardWidget[ kb ] = new Keyboard_3Oct_Widget( x + 39, y + 19, 1, kb, DWRGB( 255, 128, 64 ), module, Seq_Triad2_Widget_NoteChangeCallback, &module->lg );
  304. addChild( module->pKeyboardWidget[ kb ] );
  305. // pattern selects
  306. module->m_pPatternSelect[ kb ] = new PatternSelectStrip( x + 79, y + 1, 9, 7, DWRGB( 255, 128, 64 ), DWRGB( 128, 64, 0 ), DWRGB( 255, 0, 128 ), DWRGB( 128, 0, 64 ), nPATTERNS, kb, module, Seq_Triad2_Widget_PatternChangeCallback );
  307. addChild( module->m_pPatternSelect[ kb ] );
  308. // phrase selects
  309. module->m_pPhraseSelect[ kb ] = new PatternSelectStrip( x + 79, y + 86, 9, 7, DWRGB( 255, 255, 0 ), DWRGB( 128, 128, 64 ), DWRGB( 0, 255, 255 ), DWRGB( 0, 128, 128 ), nPHRASE_SAVES, kb, module, Seq_Triad2_Widget_PhraseChangeCallback );
  310. addChild( module->m_pPhraseSelect[ kb ] );
  311. x2 = x + 9;
  312. y2 = y + 4;
  313. // prog change trigger
  314. addInput(Port::create<MyPortInSmall>( Vec( x2, y2 ), Port::INPUT, module, Seq_Triad2::IN_PATTERN_TRIG + kb ) ); y2 += 40;
  315. // VOCT offset input
  316. addInput(Port::create<MyPortInSmall>( Vec( x2, y2 ), Port::INPUT, module, Seq_Triad2::IN_VOCT_OFF + kb ) ); y2 += 40;
  317. // prog change trigger
  318. addInput(Port::create<MyPortInSmall>( Vec( x2, y2 ), Port::INPUT, module, Seq_Triad2::IN_PROG_CHANGE + kb ) );
  319. // outputs
  320. x2 = x + 330;
  321. addOutput(Port::create<MyPortOutSmall>( Vec( x2, y + 27 ), Port::OUTPUT, module, Seq_Triad2::OUT_VOCTS + kb ) );
  322. addOutput(Port::create<MyPortOutSmall>( Vec( x2, y + 68 ), Port::OUTPUT, module, Seq_Triad2::OUT_TRIG + kb ) );
  323. y += 111;
  324. }
  325. // trig mute
  326. module->m_pButtonTrigMute = new MyLEDButton( x + 310, 3, 15, 15, 13.0, DWRGB( 180, 180, 180 ), DWRGB( 255, 0, 0 ), MyLEDButton::TYPE_SWITCH, 0, module, Seq_Triad2_TrigMute );
  327. addChild( module->m_pButtonTrigMute );
  328. addInput(Port::create<MyPortInSmall>( Vec( x + 285, 1 ), Port::INPUT, module, Seq_Triad2::IN_GLOBAL_TRIG_MUTE ) );
  329. // reset inputs
  330. y2 = 357;
  331. addInput(Port::create<MyPortInSmall>( Vec( x + 89, y2 ), Port::INPUT, module, Seq_Triad2::IN_CLOCK_RESET ) );
  332. addInput(Port::create<MyPortInSmall>( Vec( x + 166, y2 ), Port::INPUT, module, Seq_Triad2::IN_GLOBAL_PAT_CLK ) );
  333. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  334. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0)));
  335. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  336. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365)));
  337. module->m_bInitialized = true;
  338. module->onReset();
  339. }
  340. //-----------------------------------------------------
  341. // Procedure: reset
  342. //
  343. //-----------------------------------------------------
  344. void Seq_Triad2::onReset()
  345. {
  346. if( !m_bInitialized )
  347. return;
  348. for( int kb = 0; kb < nKEYBOARDS; kb++ )
  349. m_pButtonOctaveSelect[ kb ]->Set( 0, true );
  350. memset( m_fCvStartOut, 0, sizeof(m_fCvStartOut) );
  351. memset( m_fCvEndOut, 0, sizeof(m_fCvEndOut) );
  352. memset( m_PatternNotes, 0, sizeof(m_PatternNotes) );
  353. for( int kb = 0; kb < nKEYBOARDS; kb++ )
  354. {
  355. for( int pat = 0; pat < nPHRASE_SAVES; pat++ )
  356. m_nSteps[ kb ][ pat ] = 3;
  357. SetPhraseSteps( kb, 3 );
  358. ChangePattern( kb, 0, true, true );
  359. ChangePhrase( kb, 0, true );
  360. }
  361. }
  362. //-----------------------------------------------------
  363. // Procedure: randomize
  364. //
  365. //-----------------------------------------------------
  366. const int keyscalenotes[ 7 ] = { 0, 2, 4, 5, 7, 9, 11};
  367. const int keyscalenotes_minor[ 7 ] = { 0, 2, 3, 5, 7, 9, 11};
  368. void Seq_Triad2::onRandomize()
  369. {
  370. int kb, pat, phrase, basekey, note;
  371. for( int kb = 0; kb < nKEYBOARDS; kb++ )
  372. m_pButtonOctaveSelect[ kb ]->Set( 0, true );
  373. memset( m_fCvStartOut, 0, sizeof(m_fCvStartOut) );
  374. memset( m_fCvEndOut, 0, sizeof(m_fCvEndOut) );
  375. memset( m_PatternNotes, 0, sizeof(m_PatternNotes) );
  376. basekey = (int)(randomUniform() * 24.0);
  377. for( kb = 0; kb < nKEYBOARDS; kb++ )
  378. {
  379. m_Octave[ kb ] = (int)( randomUniform() * 4.0 );
  380. for( pat = 0; pat < nPATTERNS; pat++ )
  381. {
  382. for( phrase = 0; phrase < nPHRASE_SAVES; phrase++ )
  383. {
  384. if( randomUniform() > 0.7 )
  385. note = keyscalenotes_minor[ (int)(randomUniform() * 7.0 ) ];
  386. else
  387. note = keyscalenotes[ (int)(randomUniform() * 7.0 ) ];
  388. m_PatternNotes[ kb ][ phrase ][ pat ].bTrigOff = ( randomUniform() < 0.10 );
  389. m_PatternNotes[ kb ][ phrase ][ pat ].note = basekey + note;
  390. }
  391. }
  392. ChangePattern( kb, 0, true, true );
  393. }
  394. }
  395. //-----------------------------------------------------
  396. // Procedure: SetPhraseSteps
  397. //
  398. //-----------------------------------------------------
  399. void Seq_Triad2::SetPhraseSteps( int kb, int nSteps )
  400. {
  401. if( nSteps < 0 || nSteps >= nPHRASE_SAVES )
  402. nSteps = 0;
  403. m_PhrasesUsed[ kb ] = nSteps;
  404. }
  405. //-----------------------------------------------------
  406. // Procedure: SetSteps
  407. //
  408. //-----------------------------------------------------
  409. void Seq_Triad2::SetSteps( int kb, int nSteps )
  410. {
  411. if( nSteps < 0 || nSteps >= nPATTERNS )
  412. nSteps = 0;
  413. m_nSteps[ kb ][ m_CurrentPhrase[ kb ] ] = nSteps;
  414. }
  415. //-----------------------------------------------------
  416. // Procedure: Copy
  417. //
  418. //-----------------------------------------------------
  419. void Seq_Triad2::Copy( int kb, bool bOn )
  420. {
  421. if( kb < 0 || kb >= nKEYBOARDS )
  422. return;
  423. if( !m_bPause[ kb ] || !bOn || m_CopySrc != NO_COPY )
  424. {
  425. if( m_CopySrc != NO_COPY )
  426. m_pButtonCopy[ m_CopySrc ]->Set( false );
  427. m_CopySrc = NO_COPY;
  428. m_pButtonCopy[ kb ]->Set( false );
  429. }
  430. else if( bOn )
  431. {
  432. m_CopySrc = kb;
  433. }
  434. }
  435. //-----------------------------------------------------
  436. // Procedure: SetOut
  437. //
  438. //-----------------------------------------------------
  439. void Seq_Triad2::SetOut( int kb )
  440. {
  441. int note;
  442. float foct;
  443. if( kb < 0 || kb >= nKEYBOARDS )
  444. return;
  445. // end glide note (current pattern note)
  446. foct = (float)m_Octave[ kb ];
  447. note = m_PatternNotes[ kb ][ m_CurrentPhrase[ kb ] ][ m_CurrentPattern[ kb ] ].note;
  448. if( note > 36 || note < 0 )
  449. note = 0;
  450. m_fCvEndOut[ kb ] = foct + m_fKeyNotes[ note ] + m_VoctOffsetIn[ kb ];
  451. // start glide note (last pattern note)
  452. if( m_bWasLastNotePlayed[ kb ] )
  453. {
  454. m_fCvStartOut[ kb ] = m_fLastNotePlayed[ kb ] + m_VoctOffsetIn[ kb ];
  455. }
  456. else
  457. {
  458. m_bWasLastNotePlayed[ kb ] = true;
  459. m_fCvStartOut[ kb ] = m_fCvEndOut[ kb ] + m_VoctOffsetIn[ kb ];
  460. }
  461. m_fLastNotePlayed[ kb ] = m_fCvEndOut[ kb ] + m_VoctOffsetIn[ kb ];
  462. // glide time ( max glide = 0.5 seconds )
  463. m_glideCount[ kb ] = 1 + (int)( ( params[ PARAM_GLIDE + kb ].value * 0.5 ) * engineGetSampleRate());
  464. m_fglideInc[ kb ] = 1.0 / (float)m_glideCount[ kb ];
  465. m_fglide[ kb ] = 1.0;
  466. // always trig on pause
  467. if( m_bPause[ kb ] )
  468. m_bTrig[ kb ] = true;
  469. else if( !m_PatternNotes[ kb ][ m_CurrentPhrase[ kb ] ][ m_CurrentPattern[ kb ] ].bTrigOff )
  470. m_bTrig[ kb ] = true;
  471. else
  472. m_bTrig[ kb ] = false;
  473. }
  474. //-----------------------------------------------------
  475. // Procedure: SetKey
  476. //
  477. //-----------------------------------------------------
  478. void Seq_Triad2::SetKey( int kb )
  479. {
  480. pKeyboardWidget[ kb ]->setkey( &m_PatternNotes[ kb ][ m_CurrentPhrase[ kb ] ][ m_CurrentPattern[ kb ] ].note );
  481. }
  482. //-----------------------------------------------------
  483. // Procedure: SetPendingPhrase
  484. //
  485. //-----------------------------------------------------
  486. void Seq_Triad2::SetPendingPhrase( int kb, int phraseIn )
  487. {
  488. int phrase;
  489. if( phraseIn < 0 || phraseIn >= nPHRASE_SAVES )
  490. phrase = ( m_CurrentPhrase[ kb ] + 1 ) & 0x7;
  491. else
  492. phrase = phraseIn;
  493. if( phrase > m_PhrasesUsed[ kb ] )
  494. phrase = 0;
  495. m_PhrasePending[ kb ].bPending = true;
  496. m_PhrasePending[ kb ].phrase = phrase;
  497. m_pPhraseSelect[ kb ]->SetPat( m_CurrentPhrase[ kb ], false );
  498. m_pPhraseSelect[ kb ]->SetPat( phrase, true );
  499. }
  500. //-----------------------------------------------------
  501. // Procedure: ChangePhrase
  502. //
  503. //-----------------------------------------------------
  504. void Seq_Triad2::ChangePhrase( int kb, int index, bool bForce )
  505. {
  506. if( kb < 0 || kb >= nKEYBOARDS )
  507. return;
  508. if( !bForce && index == m_CurrentPhrase[ kb ] )
  509. return;
  510. if( index < 0 )
  511. index = nPHRASE_SAVES - 1;
  512. else if( index >= nPHRASE_SAVES )
  513. index = 0;
  514. if( m_CopySrc != NO_COPY )
  515. {
  516. // do not copy if we are not paused
  517. if( m_bPause[ kb ] )
  518. {
  519. memcpy( m_PatternNotes[ kb ][ index ], m_PatternNotes[ m_CopySrc ][ m_CurrentPhrase[ m_CopySrc ] ], sizeof(PATTERN_STRUCT) * nPATTERNS );
  520. m_pButtonCopy[ m_CopySrc ]->Set( false );
  521. m_nSteps[ kb ][ index ] = m_nSteps[ m_CopySrc ][ m_CurrentPhrase[ m_CopySrc ] ];
  522. m_CopySrc = NO_COPY;
  523. }
  524. }
  525. m_CurrentPhrase[ kb ] = index;
  526. m_pPhraseSelect[ kb ]->SetPat( index, false );
  527. m_pPhraseSelect[ kb ]->SetMax( m_PhrasesUsed[ kb ] );
  528. m_pPatternSelect[ kb ]->SetMax( m_nSteps[ kb ][ index ] );
  529. // set keyboard key
  530. SetKey( kb );
  531. m_pButtonTrig[ kb ]->Set( m_PatternNotes[ kb ][ m_CurrentPhrase[ kb ] ][ m_CurrentPattern[ kb ] ].bTrigOff );
  532. // change octave light
  533. m_pButtonOctaveSelect[ kb ]->Set( m_Octave[ kb ], true );
  534. // set output note
  535. SetOut( kb );
  536. }
  537. //-----------------------------------------------------
  538. // Procedure: ChangePattern
  539. //
  540. //-----------------------------------------------------
  541. void Seq_Triad2::ChangePattern( int kb, int index, bool bForce, bool bPlay )
  542. {
  543. if( kb < 0 || kb >= nKEYBOARDS )
  544. return;
  545. if( !bForce && index == m_CurrentPattern[ kb ] )
  546. return;
  547. if( index < 0 )
  548. index = nPATTERNS - 1;
  549. else if( index >= nPATTERNS )
  550. index = 0;
  551. // update octave offset immediately when not running
  552. m_VoctOffsetIn[ kb ] = inputs[ IN_VOCT_OFF + kb ].normalize( 0.0 );
  553. m_CurrentPattern[ kb ] = index;
  554. m_pPatternSelect[ kb ]->SetPat( index, false );
  555. // set keyboard key
  556. SetKey( kb );
  557. m_pButtonTrig[ kb ]->Set( m_PatternNotes[ kb ][ m_CurrentPhrase[ kb ] ][ m_CurrentPattern[ kb ] ].bTrigOff );
  558. // change octave light
  559. m_pButtonOctaveSelect[ kb ]->Set( m_Octave[ kb ], true );
  560. // set outputted note
  561. if( bPlay )
  562. SetOut( kb );
  563. }
  564. //-----------------------------------------------------
  565. // Procedure:
  566. //
  567. //-----------------------------------------------------
  568. json_t *Seq_Triad2::toJson()
  569. {
  570. int *pint;
  571. bool *pbool;
  572. json_t *gatesJ;
  573. json_t *rootJ = json_object();
  574. // pauses
  575. pbool = &m_bPause[ 0 ];
  576. gatesJ = json_array();
  577. for (int i = 0; i < nKEYBOARDS; i++)
  578. {
  579. json_t *gateJ = json_integer( (int)pbool[ i ] );
  580. json_array_append_new( gatesJ, gateJ );
  581. }
  582. json_object_set_new( rootJ, "m_bPause", gatesJ );
  583. // number of steps
  584. pint = (int*)&m_nSteps[ 0 ][ 0 ];
  585. gatesJ = json_array();
  586. for (int i = 0; i < nKEYBOARDS * nPHRASE_SAVES; i++)
  587. {
  588. json_t *gateJ = json_integer( pint[ i ] );
  589. json_array_append_new( gatesJ, gateJ );
  590. }
  591. json_object_set_new( rootJ, "m_nSteps", gatesJ );
  592. // octaves
  593. pint = (int*)&m_Octave[ 0 ];
  594. gatesJ = json_array();
  595. for (int i = 0; i < nKEYBOARDS; i++)
  596. {
  597. json_t *gateJ = json_integer( pint[ i ] );
  598. json_array_append_new( gatesJ, gateJ );
  599. }
  600. json_object_set_new( rootJ, "m_Octave", gatesJ );
  601. // phrase select
  602. pint = (int*)&m_CurrentPhrase[ 0 ];
  603. gatesJ = json_array();
  604. for (int i = 0; i < nKEYBOARDS; i++)
  605. {
  606. json_t *gateJ = json_integer( pint[ i ] );
  607. json_array_append_new( gatesJ, gateJ );
  608. }
  609. json_object_set_new( rootJ, "m_CurrentPhrase", gatesJ );
  610. // patterns
  611. pint = (int*)&m_PatternNotes[ 0 ][ 0 ][ 0 ];
  612. gatesJ = json_array();
  613. for (int i = 0; i < (nPHRASE_SAVES * nPATTERNS * nKEYBOARDS * 8); i++)
  614. {
  615. json_t *gateJ = json_integer( pint[ i ] );
  616. json_array_append_new( gatesJ, gateJ );
  617. }
  618. json_object_set_new( rootJ, "m_PatternNotes", gatesJ );
  619. // phrase used
  620. pint = (int*)&m_PhrasesUsed[ 0 ];
  621. gatesJ = json_array();
  622. for (int i = 0; i < nKEYBOARDS; i++)
  623. {
  624. json_t *gateJ = json_integer( pint[ i ] );
  625. json_array_append_new( gatesJ, gateJ );
  626. }
  627. json_object_set_new( rootJ, "m_PhrasesUsed", gatesJ );
  628. // current pattern
  629. pint = (int*)&m_CurrentPattern[ 0 ];
  630. gatesJ = json_array();
  631. for (int i = 0; i < nKEYBOARDS; i++)
  632. {
  633. json_t *gateJ = json_integer( pint[ i ] );
  634. json_array_append_new( gatesJ, gateJ );
  635. }
  636. json_object_set_new( rootJ, "m_CurrentPattern", gatesJ );
  637. // trig mute
  638. gatesJ = json_array();
  639. json_t *gateJ = json_boolean( m_bTrigMute );
  640. json_array_append_new( gatesJ, gateJ );
  641. json_object_set_new( rootJ, "m_bTrigMute", gatesJ );
  642. // channel trig mute
  643. pbool = &m_bChTrigMute[ 0 ];
  644. gatesJ = json_array();
  645. for (int i = 0; i < nKEYBOARDS; i++)
  646. {
  647. json_t *gateJ = json_integer( pbool[ i ] );
  648. json_array_append_new( gatesJ, gateJ );
  649. }
  650. json_object_set_new( rootJ, "m_bChTrigMute", gatesJ );
  651. return rootJ;
  652. }
  653. //-----------------------------------------------------
  654. // Procedure: fromJson
  655. //
  656. //-----------------------------------------------------
  657. void Seq_Triad2::fromJson(json_t *rootJ)
  658. {
  659. bool *pbool;
  660. int *pint;
  661. int i;
  662. json_t *StepsJ;
  663. // pauses
  664. pbool = &m_bPause[ 0 ];
  665. StepsJ = json_object_get( rootJ, "m_bPause" );
  666. if (StepsJ)
  667. {
  668. for ( i = 0; i < nKEYBOARDS; i++)
  669. {
  670. json_t *gateJ = json_array_get(StepsJ, i);
  671. if (gateJ)
  672. pbool[ i ] = json_integer_value( gateJ );
  673. }
  674. }
  675. // number of steps
  676. pint = (int*)&m_nSteps[ 0 ][ 0 ];
  677. StepsJ = json_object_get( rootJ, "m_nSteps" );
  678. if (StepsJ)
  679. {
  680. for ( i = 0; i < nKEYBOARDS * nPHRASE_SAVES; i++)
  681. {
  682. json_t *gateJ = json_array_get(StepsJ, i);
  683. if (gateJ)
  684. pint[ i ] = json_integer_value( gateJ );
  685. }
  686. }
  687. // octaves
  688. pint = (int*)&m_Octave[ 0 ];
  689. StepsJ = json_object_get( rootJ, "m_Octave" );
  690. if (StepsJ)
  691. {
  692. for ( i = 0; i < nKEYBOARDS; i++)
  693. {
  694. json_t *gateJ = json_array_get(StepsJ, i);
  695. if (gateJ)
  696. pint[ i ] = json_integer_value( gateJ );
  697. }
  698. }
  699. // phrase select
  700. pint = (int*)&m_CurrentPhrase[ 0 ];
  701. StepsJ = json_object_get( rootJ, "m_CurrentPhrase" );
  702. if (StepsJ)
  703. {
  704. for ( i = 0; i < nKEYBOARDS; i++)
  705. {
  706. json_t *gateJ = json_array_get(StepsJ, i);
  707. if (gateJ)
  708. pint[ i ] = json_integer_value( gateJ );
  709. }
  710. }
  711. // all patterns and phrases
  712. pint = (int*)&m_PatternNotes[ 0 ][ 0 ][ 0 ];
  713. StepsJ = json_object_get( rootJ, "m_PatternNotes" );
  714. if (StepsJ)
  715. {
  716. for ( i = 0; i < (nPHRASE_SAVES * nPATTERNS * nKEYBOARDS * 8); i++)
  717. {
  718. json_t *gateJ = json_array_get(StepsJ, i);
  719. if (gateJ)
  720. pint[ i ] = json_integer_value( gateJ );
  721. }
  722. }
  723. // phrase steps
  724. pint = (int*)&m_PhrasesUsed[ 0 ];
  725. StepsJ = json_object_get( rootJ, "m_PhrasesUsed" );
  726. if (StepsJ)
  727. {
  728. for ( i = 0; i < nKEYBOARDS; i++)
  729. {
  730. json_t *gateJ = json_array_get(StepsJ, i);
  731. if (gateJ)
  732. pint[ i ] = json_integer_value( gateJ );
  733. }
  734. }
  735. // current pattern
  736. pint = (int*)&m_CurrentPattern[ 0 ];
  737. StepsJ = json_object_get( rootJ, "m_CurrentPattern" );
  738. if (StepsJ)
  739. {
  740. for ( i = 0; i < nKEYBOARDS; i++)
  741. {
  742. json_t *gateJ = json_array_get(StepsJ, i);
  743. if (gateJ)
  744. pint[ i ] = json_integer_value( gateJ );
  745. }
  746. }
  747. for( i = 0; i < nKEYBOARDS; i++ )
  748. {
  749. m_pPhraseSelect[ i ]->SetMax( m_PhrasesUsed[ i ] );
  750. m_pPhraseSelect[ i ]->SetPat( m_CurrentPhrase[ i ], false );
  751. m_pPatternSelect[ i ]->SetMax( m_nSteps[ i ][ m_CurrentPhrase[ i ] ] );
  752. m_pPatternSelect[ i ]->SetPat( m_CurrentPattern[ i ], false );
  753. m_pButtonPause[ i ]->Set( m_bPause[ i ] );
  754. SetPhraseSteps( i, m_PhrasesUsed[ i ] );
  755. ChangePhrase( i, m_CurrentPhrase[ i ], true );
  756. ChangePattern( i, m_CurrentPattern[ i ], true, false );
  757. }
  758. // pauses
  759. StepsJ = json_object_get( rootJ, "m_bTrigMute" );
  760. if (StepsJ)
  761. {
  762. json_t *gateJ = json_array_get( StepsJ, 0 );
  763. if (gateJ)
  764. m_bTrigMute = json_boolean_value( gateJ );
  765. }
  766. if( m_bTrigMute )
  767. m_pButtonTrigMute->Set( m_bTrigMute );
  768. // channel trig mute
  769. pbool = &m_bChTrigMute[ 0 ];
  770. StepsJ = json_object_get( rootJ, "m_bChTrigMute" );
  771. if (StepsJ)
  772. {
  773. for ( i = 0; i < nKEYBOARDS; i++)
  774. {
  775. json_t *gateJ = json_array_get(StepsJ, i);
  776. if (gateJ)
  777. pbool[ i ] = json_integer_value( gateJ );
  778. }
  779. }
  780. for( i = 0; i < nKEYBOARDS; i++ )
  781. {
  782. if( m_bChTrigMute[ i ] )
  783. m_pButtonChTrigMute[ i ]->Set( m_bChTrigMute[ i ] );
  784. }
  785. }
  786. //-----------------------------------------------------
  787. // Procedure: step
  788. //
  789. //-----------------------------------------------------
  790. #define LIGHT_LAMBDA ( 0.065f )
  791. void Seq_Triad2::step()
  792. {
  793. int kb, useclock;
  794. bool bGlobalPatChange = false, bGlobalClkTriggered = false, PatTrig[ nKEYBOARDS ] = {};
  795. float trigout = 0.0f;
  796. if( !m_bInitialized )
  797. return;
  798. if( inputs[ IN_GLOBAL_TRIG_MUTE ].active )
  799. {
  800. if( inputs[ IN_GLOBAL_TRIG_MUTE ].value >= 0.00001 )
  801. {
  802. m_bTrigMute = true;
  803. m_pButtonTrigMute->Set( true );
  804. }
  805. else if( inputs[ IN_GLOBAL_TRIG_MUTE ].value < 0.00001 )
  806. {
  807. m_bTrigMute = false;
  808. m_pButtonTrigMute->Set( false );
  809. }
  810. }
  811. // global phrase change trigger
  812. if( inputs[ IN_GLOBAL_PAT_CLK ].active )
  813. {
  814. if( m_SchTrigGlobalPatChange.process( inputs[ IN_GLOBAL_PAT_CLK ].value ) )
  815. bGlobalPatChange = true;
  816. }
  817. // global clock reset
  818. if( inputs[ IN_CLOCK_RESET ].active )
  819. {
  820. if( m_SchTrigGlobalClkReset.process( inputs[ IN_CLOCK_RESET ].value ) )
  821. m_GlobalClkResetPending = true;
  822. }
  823. // get trigs
  824. for( kb = 0; kb < nKEYBOARDS; kb++ )
  825. PatTrig[ kb ] = m_SchTrigPatternSelectInput[ kb ].process( inputs[ IN_PATTERN_TRIG + kb ].value );
  826. // process triggered phrase changes
  827. for( kb = 0; kb < nKEYBOARDS; kb++ )
  828. {
  829. useclock = kb;
  830. if( inputs[ IN_CHANNEL_TRIG_MUTE + kb ].active )
  831. {
  832. if( inputs[ IN_CHANNEL_TRIG_MUTE + kb ].value >= 0.00001 )
  833. {
  834. m_bChTrigMute[ kb ] = true;
  835. m_pButtonChTrigMute[ kb ]->Set( true );
  836. }
  837. else if( inputs[ IN_CHANNEL_TRIG_MUTE + kb ].value < 0.00001 )
  838. {
  839. m_bChTrigMute[ kb ] = false;
  840. m_pButtonChTrigMute[ kb ]->Set( false );
  841. }
  842. }
  843. // if no keyboard clock active then use kb 0's clock
  844. if( !inputs[ IN_PATTERN_TRIG + kb ].active && inputs[ IN_PATTERN_TRIG + 0 ].active )
  845. useclock = 0;
  846. // phrase change trigger
  847. if( bGlobalPatChange && !m_bPause[ kb ] && inputs[ IN_PATTERN_TRIG + useclock ].active )
  848. {
  849. SetPendingPhrase( kb, -1 );
  850. }
  851. else if( inputs[ IN_PROG_CHANGE + kb ].active && !m_bPause[ kb ] && inputs[ IN_PATTERN_TRIG + useclock ].active )
  852. {
  853. if( m_SchTrigPhraseSelect[ kb ].process( inputs[ IN_PROG_CHANGE + kb ].value ) )
  854. SetPendingPhrase( kb, -1 );
  855. }
  856. // pat change trigger - ignore if already pending
  857. if( inputs[ IN_PATTERN_TRIG + useclock ].active && !m_bPause[ kb ] )
  858. {
  859. if( PatTrig[ useclock ] )
  860. {
  861. if( m_GlobalClkResetPending )
  862. {
  863. bGlobalClkTriggered = true;
  864. m_CurrentPattern[ kb ] = -1;
  865. }
  866. else if( m_CurrentPattern[ kb ] >= ( m_nSteps[ kb ][ m_CurrentPhrase[ kb ] ] ) )
  867. {
  868. m_CurrentPattern[ kb ] = (nPATTERNS - 1);
  869. }
  870. ChangePattern( kb, m_CurrentPattern[ kb ] + 1, true, true );
  871. if( m_CurrentPattern[ kb ] == 0 )
  872. {
  873. if( m_PhrasePending[ kb ].bPending )
  874. {
  875. m_PhrasePending[ kb ].bPending = false;
  876. ChangePhrase( kb, m_PhrasePending[ kb ].phrase, false );
  877. }
  878. }
  879. }
  880. }
  881. else
  882. {
  883. // resolve any left over phrase triggers
  884. if( m_PhrasePending[ kb ].bPending )
  885. {
  886. m_PhrasePending[ kb ].bPending = false;
  887. ChangePhrase( kb, m_PhrasePending[ kb ].phrase, false );
  888. }
  889. }
  890. if( m_bTrig[ kb ] )
  891. {
  892. m_bTrig[ kb ] = false;
  893. m_gatePulse[ kb ].trigger( 0.050f );
  894. }
  895. trigout = m_gatePulse[ kb ].process( 1.0 / engineGetSampleRate() ) ? CV_MAX : 0.0;
  896. if( !m_bTrigMute && !m_bChTrigMute[ kb ] )
  897. outputs[ OUT_TRIG + kb ].value = trigout;
  898. else
  899. outputs[ OUT_TRIG + kb ].value = 0.0f;
  900. if( --m_glideCount[ kb ] > 0 )
  901. m_fglide[ kb ] -= m_fglideInc[ kb ];
  902. else
  903. m_fglide[ kb ] = 0.0;
  904. if( m_bTrigMute || m_bChTrigMute[ kb ] )
  905. outputs[ OUT_VOCTS + kb ].value = flast[ kb ];
  906. else
  907. {
  908. flast[ kb ] = ( m_fCvStartOut[ kb ] * m_fglide[ kb ] ) + ( m_fCvEndOut[ kb ] * ( 1.0 - m_fglide[ kb ] ) );
  909. outputs[ OUT_VOCTS + kb ].value = flast[ kb ];
  910. }
  911. }
  912. if( bGlobalClkTriggered )
  913. m_GlobalClkResetPending = false;
  914. }
  915. } // namespace rack_plugin_mscHack
  916. using namespace rack_plugin_mscHack;
  917. RACK_PLUGIN_MODEL_INIT(mscHack, Seq_Triad2) {
  918. Model *modelSeq_Triad2 = Model::create<Seq_Triad2, Seq_Triad2_Widget>( "mscHack", "TriadSeq2", "SEQ Triad 2", SEQUENCER_TAG, MULTIPLE_TAG );
  919. return modelSeq_Triad2;
  920. }