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.

826 lines
27KB

  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 nCHANNELS 6
  7. #define nSTEPS 32
  8. #define nPROG 16
  9. typedef struct
  10. {
  11. bool bPending;
  12. int prog;
  13. }PHRASE_CHANGE_STRUCT;
  14. //-----------------------------------------------------
  15. // Module Definition
  16. //
  17. //-----------------------------------------------------
  18. struct SEQ_6x32x16 : Module
  19. {
  20. #define NO_COPY -1
  21. enum ParamIds
  22. {
  23. PARAM_CPY_NEXT,
  24. PARAM_RAND = PARAM_CPY_NEXT + nCHANNELS,
  25. PARAM_PAUSE = PARAM_RAND + nCHANNELS,
  26. PARAM_BILEVEL = PARAM_PAUSE + nCHANNELS,
  27. PARAM_LVL1_KNOB = PARAM_BILEVEL + nCHANNELS,
  28. PARAM_LVL2_KNOB = PARAM_LVL1_KNOB + nCHANNELS,
  29. PARAM_LVL3_KNOB = PARAM_LVL2_KNOB + nCHANNELS,
  30. PARAM_LVL4_KNOB = PARAM_LVL3_KNOB + nCHANNELS,
  31. PARAM_LVL5_KNOB = PARAM_LVL4_KNOB + nCHANNELS,
  32. nPARAMS = PARAM_LVL5_KNOB + nCHANNELS
  33. };
  34. enum InputIds
  35. {
  36. IN_GLOBAL_CLK_RESET,
  37. IN_GLOBAL_PAT_CHANGE,
  38. IN_CLK,
  39. IN_PAT_TRIG = IN_CLK + nCHANNELS,
  40. IN_GLOBAL_TRIG_MUTE = IN_PAT_TRIG + nCHANNELS,
  41. nINPUTS
  42. };
  43. enum OutputIds
  44. {
  45. OUT_TRIG,
  46. OUT_LEVEL = OUT_TRIG + nCHANNELS,
  47. OUT_BEAT1 = OUT_LEVEL + nCHANNELS,
  48. nOUTPUTS = OUT_BEAT1 + nCHANNELS
  49. };
  50. bool m_bInitialized = false;
  51. CLog lg;
  52. bool m_bPauseState[ nCHANNELS ] = {};
  53. bool m_bBiLevelState[ nCHANNELS ] = {};
  54. SinglePatternClocked32 *m_pPatternDisplay[ nCHANNELS ] = {};
  55. int m_Pattern[ nCHANNELS ][ nPROG ][ nSTEPS ];
  56. int m_MaxPat[ nCHANNELS ][ nPROG ] = {};
  57. PatternSelectStrip *m_pProgramDisplay[ nCHANNELS ] = {};
  58. int m_CurrentProg[ nCHANNELS ] = {};
  59. int m_MaxProg[ nCHANNELS ] = {};
  60. PHRASE_CHANGE_STRUCT m_ProgPending[ nCHANNELS ] = {};
  61. SchmittTrigger m_SchTrigClock[ nCHANNELS ];
  62. SchmittTrigger m_SchTrigProg[ nCHANNELS ];
  63. SchmittTrigger m_SchTrigGlobalClkReset;
  64. SchmittTrigger m_SchTrigGlobalProg;
  65. bool m_bTrig[ nCHANNELS ] = {};
  66. PulseGenerator m_gatePulse[ nCHANNELS ];
  67. PulseGenerator m_gateBeatPulse[ nCHANNELS ];
  68. // swing
  69. //int m_SwingLen[ nCHANNELS ] = {0};
  70. //int m_SwingCount[ nCHANNELS ] = {0};
  71. int m_ClockTick[ nCHANNELS ] = {0};
  72. int m_CopySrc = NO_COPY;
  73. // trig mute
  74. bool m_bTrigMute = false;
  75. MyLEDButton *m_pButtonTrigMute = NULL;
  76. // buttons
  77. MyLEDButton *m_pButtonPause[ nCHANNELS ] = {};
  78. MyLEDButton *m_pButtonCopy[ nCHANNELS ] = {};
  79. MyLEDButton *m_pButtonBiLevel[ nCHANNELS ] = {};
  80. MyLEDButton *m_pButtonRand[ nCHANNELS ] = {};
  81. MyLEDButton *m_pButtonAutoPat[ nCHANNELS ] = {};
  82. MyLEDButton *m_pButtonHoldCV[ nCHANNELS ] = {};
  83. MyLEDButton *m_pButtonClear[ nCHANNELS ] = {};
  84. bool m_bAutoPatChange[ nCHANNELS ] = {};
  85. bool m_bHoldCVState[ nCHANNELS ] = {};
  86. float m_fCVRanges[ 3 ] = { 15.0f, 10.0f, 5.0f};
  87. int m_RangeSelect = 0;
  88. char m_strRange[ 10 ] = {0};
  89. float flast[ nCHANNELS ];
  90. // Contructor
  91. SEQ_6x32x16() : Module(nPARAMS, nINPUTS, nOUTPUTS, 0){}
  92. // Overrides
  93. void step() override;
  94. json_t* toJson() override;
  95. void fromJson(json_t *rootJ) override;
  96. void onRandomize() override;
  97. void onReset() override;
  98. void JsonParams( bool bTo, json_t *root);
  99. void CpyNext( int ch );
  100. void Rand( int ch );
  101. void ChangeProg( int ch, int prog, bool force );
  102. void SetPendingProg( int ch, int prog );
  103. void Copy( int kb, bool bOn );
  104. };
  105. //-----------------------------------------------------
  106. // MyLEDButton_TrigMute
  107. //-----------------------------------------------------
  108. void MyLEDButton_TrigMute( void *pClass, int id, bool bOn )
  109. {
  110. SEQ_6x32x16 *mymodule;
  111. mymodule = (SEQ_6x32x16*)pClass;
  112. mymodule->m_bTrigMute = bOn;
  113. }
  114. //-----------------------------------------------------
  115. // MyLEDButton_AutoPat
  116. //-----------------------------------------------------
  117. void MyLEDButton_AutoPat( void *pClass, int id, bool bOn )
  118. {
  119. SEQ_6x32x16 *mymodule;
  120. mymodule = (SEQ_6x32x16*)pClass;
  121. mymodule->m_bAutoPatChange[ id ] = bOn;
  122. }
  123. //-----------------------------------------------------
  124. // MyLEDButton_Pause
  125. //-----------------------------------------------------
  126. void MyLEDButton_Pause( void *pClass, int id, bool bOn )
  127. {
  128. SEQ_6x32x16 *mymodule;
  129. mymodule = (SEQ_6x32x16*)pClass;
  130. mymodule->m_bPauseState[ id ] = bOn;
  131. }
  132. //-----------------------------------------------------
  133. // MyLEDButton_HoldCV
  134. //-----------------------------------------------------
  135. void MyLEDButton_HoldCV( void *pClass, int id, bool bOn )
  136. {
  137. SEQ_6x32x16 *mymodule;
  138. mymodule = (SEQ_6x32x16*)pClass;
  139. mymodule->m_bHoldCVState[ id ] = bOn;
  140. }
  141. //-----------------------------------------------------
  142. // MyLEDButton_BiLevel
  143. //-----------------------------------------------------
  144. void MyLEDButton_BiLevel( void *pClass, int id, bool bOn )
  145. {
  146. SEQ_6x32x16 *mymodule;
  147. mymodule = (SEQ_6x32x16*)pClass;
  148. mymodule->m_bBiLevelState[ id ] = bOn;
  149. }
  150. //-----------------------------------------------------
  151. // MyLEDButton_CpyNxt
  152. //-----------------------------------------------------
  153. void MyLEDButton_CpyNxt( void *pClass, int id, bool bOn )
  154. {
  155. SEQ_6x32x16 *mymodule;
  156. mymodule = (SEQ_6x32x16*)pClass;
  157. mymodule->Copy( id, bOn );
  158. }
  159. //-----------------------------------------------------
  160. // MyLEDButton_Rand
  161. //-----------------------------------------------------
  162. void MyLEDButton_Rand( void *pClass, int id, bool bOn )
  163. {
  164. SEQ_6x32x16 *mymodule;
  165. mymodule = (SEQ_6x32x16*)pClass;
  166. mymodule->Rand( id );
  167. }
  168. //-----------------------------------------------------
  169. // MyLEDButton_Rand
  170. //-----------------------------------------------------
  171. void MyLEDButton_Clear( void *pClass, int id, bool bOn )
  172. {
  173. SEQ_6x32x16 *mymodule;
  174. mymodule = (SEQ_6x32x16*)pClass;
  175. for( int i = 0; i < nSTEPS; i++ )
  176. {
  177. mymodule->m_Pattern[ id ][ mymodule->m_CurrentProg[ id ] ][ i ] = 0;
  178. }
  179. mymodule->m_pPatternDisplay[ id ]->SetPatAll( mymodule->m_Pattern[ id ][ mymodule->m_CurrentProg[ id ] ] );
  180. }
  181. //-----------------------------------------------------
  182. // Procedure: PatternChangeCallback
  183. //
  184. //-----------------------------------------------------
  185. void SEQ_6x32x16_PatternChangeCallback ( void *pClass, int ch, int pat, int level, int maxpat )
  186. {
  187. SEQ_6x32x16 *mymodule = (SEQ_6x32x16 *)pClass;
  188. if( !mymodule || !mymodule->m_bInitialized )
  189. return;
  190. mymodule->m_MaxPat[ ch ][ mymodule->m_CurrentProg[ ch ] ] = maxpat;
  191. mymodule->m_Pattern[ ch ][ mymodule->m_CurrentProg[ ch ] ] [ pat ] = level;
  192. }
  193. //-----------------------------------------------------
  194. // Procedure: ProgramChangeCallback
  195. //
  196. //-----------------------------------------------------
  197. void SEQ_6x32x16_ProgramChangeCallback ( void *pClass, int ch, int pat, int max )
  198. {
  199. SEQ_6x32x16 *mymodule = (SEQ_6x32x16 *)pClass;
  200. if( !mymodule || !mymodule->m_bInitialized )
  201. return;
  202. if( mymodule->m_MaxProg[ ch ] != max )
  203. {
  204. mymodule->m_MaxProg[ ch ] = max;
  205. }
  206. else if( mymodule->m_CurrentProg[ ch ] == pat && mymodule->m_bPauseState[ ch ] && mymodule->m_CopySrc != NO_COPY )
  207. {
  208. mymodule->ChangeProg( ch, pat, true );
  209. }
  210. else if( mymodule->m_CurrentProg[ ch ] != pat )
  211. {
  212. if( !mymodule->m_bPauseState[ ch ] && mymodule->inputs[ SEQ_6x32x16::IN_CLK + ch ].active )
  213. mymodule->SetPendingProg( ch, pat );
  214. else
  215. mymodule->ChangeProg( ch, pat, false );
  216. }
  217. }
  218. //-----------------------------------------------------
  219. // Procedure: Widget
  220. //
  221. //-----------------------------------------------------
  222. struct SEQ_6x32x16_Widget : ModuleWidget
  223. {
  224. Menu *createContextMenu() override;
  225. SEQ_6x32x16_Widget( SEQ_6x32x16 *module );
  226. };
  227. SEQ_6x32x16_Widget::SEQ_6x32x16_Widget( SEQ_6x32x16 *module ) : ModuleWidget(module)
  228. {
  229. int x, y, x2, y2;
  230. ParamWidget *pWidget = NULL;
  231. box.size = Vec( 15*41, 380);
  232. {
  233. SVGPanel *panel = new SVGPanel();
  234. panel->box.size = box.size;
  235. panel->setBackground(SVG::load(assetPlugin(plugin, "res/SEQ_6x32x16.svg")));
  236. addChild(panel);
  237. }
  238. //module->lg.Open("SEQ_6x32x16.txt");
  239. x = 7;
  240. y = 22;
  241. // global inputs
  242. addInput(Port::create<MyPortInSmall>( Vec( 204, 357 ), Port::INPUT, module, SEQ_6x32x16::IN_GLOBAL_CLK_RESET ) );
  243. addInput(Port::create<MyPortInSmall>( Vec( 90, 357 ), Port::INPUT, module, SEQ_6x32x16::IN_GLOBAL_PAT_CHANGE ) );
  244. // trig mute
  245. module->m_pButtonTrigMute = new MyLEDButton( 491, 3, 15, 15, 13.0, DWRGB( 180, 180, 180 ), DWRGB( 255, 0, 0 ), MyLEDButton::TYPE_SWITCH, 0, module, MyLEDButton_TrigMute );
  246. addChild( module->m_pButtonTrigMute );
  247. addInput(Port::create<MyPortInSmall>( Vec( 466, 1 ), Port::INPUT, module, SEQ_6x32x16::IN_GLOBAL_TRIG_MUTE ) );
  248. for( int ch = 0; ch < nCHANNELS; ch++ )
  249. {
  250. // inputs
  251. addInput(Port::create<MyPortInSmall>( Vec( x + 6, y + 7 ), Port::INPUT, module, SEQ_6x32x16::IN_CLK + ch ) );
  252. addInput(Port::create<MyPortInSmall>( Vec( x + 64, y + 31 ), Port::INPUT, module, SEQ_6x32x16::IN_PAT_TRIG + ch ) );
  253. // pattern display
  254. module->m_pPatternDisplay[ ch ] = new SinglePatternClocked32( x + 39, y + 2, 13, 13, 5, 2, 7, DWRGB( 255, 128, 64 ), DWRGB( 18, 9, 0 ), DWRGB( 180, 75, 180 ), DWRGB( 80, 45, 80 ), nSTEPS, ch, module, SEQ_6x32x16_PatternChangeCallback );
  255. addChild( module->m_pPatternDisplay[ ch ] );
  256. // program display
  257. module->m_pProgramDisplay[ ch ] = new PatternSelectStrip( x + 106, y + 31, 9, 7, DWRGB( 180, 180, 0 ), DWRGB( 90, 90, 64 ), DWRGB( 0, 180, 200 ), DWRGB( 0, 90, 90 ), nPROG, ch, module, SEQ_6x32x16_ProgramChangeCallback );
  258. addChild( module->m_pProgramDisplay[ ch ] );
  259. // add knobs
  260. y2 = y + 34;
  261. //pWidget = ParamWidget::create<Knob_Green1_15>( Vec( x + 374, y2 ), module, SEQ_6x32x16::PARAM_SWING_KNOB + ch, 0.0, 0.6, 0.0 );
  262. // removed for now
  263. if( pWidget )
  264. {
  265. addParam( pWidget );
  266. pWidget->visible = false;
  267. }
  268. x2 = x + 447;
  269. addParam(ParamWidget::create<Knob_Green1_15>( Vec( x2, y2 ), module, SEQ_6x32x16::PARAM_LVL1_KNOB + ch, 0.0, 1.0, 0.25 ) ); x2 += 19;
  270. addParam(ParamWidget::create<Knob_Green1_15>( Vec( x2, y2 ), module, SEQ_6x32x16::PARAM_LVL2_KNOB + ch, 0.0, 1.0, 0.33 ) ); x2 += 19;
  271. addParam(ParamWidget::create<Knob_Green1_15>( Vec( x2, y2 ), module, SEQ_6x32x16::PARAM_LVL3_KNOB + ch, 0.0, 1.0, 0.50 ) ); x2 += 19;
  272. addParam(ParamWidget::create<Knob_Green1_15>( Vec( x2, y2 ), module, SEQ_6x32x16::PARAM_LVL4_KNOB + ch, 0.0, 1.0, 0.75 ) ); x2 += 19;
  273. addParam(ParamWidget::create<Knob_Green1_15>( Vec( x2, y2 ), module, SEQ_6x32x16::PARAM_LVL5_KNOB + ch, 0.0, 1.0, 0.9 ) );
  274. // add buttons
  275. module->m_pButtonAutoPat[ ch ] = new MyLEDButton( x + 55, y + 35, 9, 9, 6.0, DWRGB( 180, 180, 180 ), DWRGB( 0, 255, 0 ), MyLEDButton::TYPE_SWITCH, ch, module, MyLEDButton_AutoPat );
  276. addChild( module->m_pButtonAutoPat[ ch ] );
  277. module->m_pButtonPause[ ch ] = new MyLEDButton( x + 26, y + 10, 11, 11, 8.0, DWRGB( 180, 180, 180 ), DWRGB( 255, 0, 0 ), MyLEDButton::TYPE_SWITCH, ch, module, MyLEDButton_Pause );
  278. addChild( module->m_pButtonPause[ ch ] );
  279. y2 = y + 33;
  280. module->m_pButtonCopy[ ch ] = new MyLEDButton( x + 290, y2, 11, 11, 8.0, DWRGB( 180, 180, 180 ), DWRGB( 0, 244, 244 ), MyLEDButton::TYPE_SWITCH, ch, module, MyLEDButton_CpyNxt );
  281. addChild( module->m_pButtonCopy[ ch ] );
  282. module->m_pButtonRand[ ch ] = new MyLEDButton( x + 315, y2, 11, 11, 8.0, DWRGB( 180, 180, 180 ), DWRGB( 0, 244, 244 ), MyLEDButton::TYPE_MOMENTARY, ch, module, MyLEDButton_Rand );
  283. addChild( module->m_pButtonRand[ ch ] );
  284. module->m_pButtonClear[ ch ] = new MyLEDButton( x + 340, y2, 11, 11, 8.0, DWRGB( 180, 180, 180 ), DWRGB( 0, 244, 244 ), MyLEDButton::TYPE_MOMENTARY, ch, module, MyLEDButton_Clear );
  285. addChild( module->m_pButtonClear[ ch ] );
  286. module->m_pButtonHoldCV[ ch ] = new MyLEDButton( x + 405, y2, 11, 11, 8.0, DWRGB( 180, 180, 180 ), DWRGB( 0, 244, 244 ), MyLEDButton::TYPE_SWITCH, ch, module, MyLEDButton_HoldCV );
  287. addChild( module->m_pButtonHoldCV[ ch ] );
  288. module->m_pButtonBiLevel[ ch ] = new MyLEDButton( x + 425, y2, 11, 11, 8.0, DWRGB( 180, 180, 180 ), DWRGB( 0, 244, 244 ), MyLEDButton::TYPE_SWITCH, ch, module, MyLEDButton_BiLevel );
  289. addChild( module->m_pButtonBiLevel[ ch ] );
  290. // add outputs
  291. addOutput(Port::create<MyPortOutSmall>( Vec( x + 580, y + 7 ), Port::OUTPUT, module, SEQ_6x32x16::OUT_TRIG + ch ) );
  292. addOutput(Port::create<MyPortOutSmall>( Vec( x + 544, y + 33 ), Port::OUTPUT, module, SEQ_6x32x16::OUT_LEVEL + ch ) );
  293. addOutput(Port::create<MyPortOutSmall>( Vec( x + 37, y + 31 ), Port::OUTPUT, module, SEQ_6x32x16::OUT_BEAT1 + ch ) );
  294. y += 56;
  295. }
  296. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  297. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0)));
  298. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  299. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365)));
  300. module->m_bInitialized = true;
  301. module->onReset();
  302. }
  303. //-----------------------------------------------------
  304. // Procedure: JsonParams
  305. //
  306. //-----------------------------------------------------
  307. void SEQ_6x32x16::JsonParams( bool bTo, json_t *root)
  308. {
  309. JsonDataBool ( bTo, "m_bPauseState", root, &m_bPauseState[ 0 ], nCHANNELS );
  310. JsonDataBool ( bTo, "m_bBiLevelState", root, &m_bBiLevelState[ 0 ], nCHANNELS );
  311. JsonDataInt ( bTo, "m_Pattern", root, &m_Pattern[ 0 ][ 0 ][ 0 ], nCHANNELS * nSTEPS * nPROG );
  312. JsonDataInt ( bTo, "m_MaxPat", root, &m_MaxPat[ 0 ][ 0 ], nCHANNELS * nPROG );
  313. JsonDataInt ( bTo, "m_CurrentProg", root, &m_CurrentProg[ 0 ], nCHANNELS );
  314. JsonDataInt ( bTo, "m_MaxProg", root, &m_MaxProg[ 0 ], nCHANNELS );
  315. JsonDataBool ( bTo, "m_bAutoPatChange", root, &m_bAutoPatChange[ 0 ], nCHANNELS );
  316. JsonDataBool ( bTo, "m_bHoldCVState", root, &m_bHoldCVState[ 0 ], nCHANNELS );
  317. JsonDataInt ( bTo, "m_RangeSelect", root, &m_RangeSelect, 1 );
  318. JsonDataBool ( bTo, "m_bTrigMute", root, &m_bTrigMute, 1 );
  319. }
  320. //-----------------------------------------------------
  321. // Procedure: toJson
  322. //
  323. //-----------------------------------------------------
  324. json_t *SEQ_6x32x16::toJson()
  325. {
  326. json_t *root = json_object();
  327. if( !root )
  328. return NULL;
  329. JsonParams( TOJSON, root );
  330. return root;
  331. }
  332. //-----------------------------------------------------
  333. // Procedure: fromJson
  334. //
  335. //-----------------------------------------------------
  336. void SEQ_6x32x16::fromJson( json_t *root )
  337. {
  338. JsonParams( FROMJSON, root );
  339. for( int ch = 0; ch < nCHANNELS; ch++ )
  340. {
  341. m_pButtonAutoPat[ ch ]->Set( m_bAutoPatChange[ ch ] );
  342. m_pButtonPause[ ch ]->Set( m_bPauseState[ ch ] );
  343. m_pButtonBiLevel[ ch ]->Set( m_bBiLevelState[ ch ] );
  344. m_pButtonHoldCV[ ch ]->Set( m_bHoldCVState[ ch ] );
  345. m_pPatternDisplay[ ch ]->SetPatAll( m_Pattern[ ch ][ m_CurrentProg[ ch ] ] );
  346. m_pPatternDisplay[ ch ]->SetMax( m_MaxPat[ ch ][ m_CurrentProg[ ch ] ] );
  347. m_pProgramDisplay[ ch ]->SetPat( m_CurrentProg[ ch ], false );
  348. m_pProgramDisplay[ ch ]->SetMax( m_MaxProg[ ch ] );
  349. }
  350. if( m_bTrigMute )
  351. m_pButtonTrigMute->Set( m_bTrigMute );
  352. sprintf( m_strRange, "%.1fV", m_fCVRanges[ m_RangeSelect ] );
  353. }
  354. //-----------------------------------------------------
  355. // Procedure: reset
  356. //
  357. //-----------------------------------------------------
  358. void SEQ_6x32x16::onReset()
  359. {
  360. if( !m_bInitialized )
  361. return;
  362. for( int ch = 0; ch < nCHANNELS; ch++ )
  363. {
  364. m_pButtonPause[ ch ]->Set( false );
  365. m_pButtonBiLevel[ ch ]->Set( false );
  366. }
  367. memset( m_bPauseState, 0, sizeof(m_bPauseState) );
  368. memset( m_bBiLevelState, 0, sizeof(m_bBiLevelState) );
  369. memset( m_Pattern, 0, sizeof(m_Pattern) );
  370. memset( m_CurrentProg, 0, sizeof(m_CurrentProg) );
  371. for( int ch = 0; ch < nCHANNELS; ch++ )
  372. {
  373. for( int prog = 0; prog < nCHANNELS; prog++ )
  374. m_MaxPat[ ch ][ prog ] = nSTEPS - 1;
  375. m_MaxProg[ ch ] = nPROG - 1;
  376. m_pPatternDisplay[ ch ]->SetPatAll( m_Pattern[ ch ][ 0 ] );
  377. m_pPatternDisplay[ ch ]->SetMax( m_MaxPat[ ch ][ 0 ] );
  378. m_pProgramDisplay[ ch ]->SetPat( 0, false );
  379. m_pProgramDisplay[ ch ]->SetMax( m_MaxProg[ ch ] );
  380. m_pPatternDisplay[ ch ]->SetPatAll( m_Pattern[ ch ][ m_CurrentProg[ ch ] ] );
  381. ChangeProg( ch, 0, true );
  382. }
  383. }
  384. //-----------------------------------------------------
  385. // Procedure: randomize
  386. //
  387. //-----------------------------------------------------
  388. void SEQ_6x32x16::onRandomize()
  389. {
  390. for( int ch = 0; ch < nCHANNELS; ch++ )
  391. {
  392. for( int p = 0; p < nPROG; p++ )
  393. {
  394. for( int i = 0; i < nSTEPS; i++ )
  395. {
  396. m_Pattern[ ch ][ p ][ i ] = (int)(randomUniform() * 5.0 );
  397. }
  398. }
  399. m_pPatternDisplay[ ch ]->SetPatAll( m_Pattern[ ch ][ m_CurrentProg[ ch ] ] );
  400. }
  401. }
  402. //-----------------------------------------------------
  403. // Procedure: Rand
  404. //
  405. //-----------------------------------------------------
  406. void SEQ_6x32x16::Rand( int ch )
  407. {
  408. for( int i = 0; i < nSTEPS; i++ )
  409. {
  410. if( i <= m_MaxPat[ ch ][ m_CurrentProg[ ch ] ] && randomUniform() > 0.5f )
  411. m_Pattern[ ch ][ m_CurrentProg[ ch ] ][ i ] = (int)(randomUniform() * 5.0 );
  412. else
  413. m_Pattern[ ch ][ m_CurrentProg[ ch ] ][ i ] = 0;
  414. }
  415. m_pPatternDisplay[ ch ]->SetPatAll( m_Pattern[ ch ][ m_CurrentProg[ ch ] ] );
  416. }
  417. //-----------------------------------------------------
  418. // Procedure: CpyNext
  419. //
  420. //-----------------------------------------------------
  421. void SEQ_6x32x16::CpyNext( int ch )
  422. {
  423. int next;
  424. next = m_CurrentProg[ ch ] + 1;
  425. if( next >= nPROG )
  426. return;
  427. memcpy( m_Pattern[ ch ][ next ], m_Pattern[ ch ][ m_CurrentProg[ ch ] ], sizeof(int) * nSTEPS );
  428. if(m_bPauseState[ ch ] || !inputs[ SEQ_6x32x16::IN_CLK + ch ].active )
  429. ChangeProg( ch, next, false );
  430. }
  431. //-----------------------------------------------------
  432. // Procedure: Copy
  433. //
  434. //-----------------------------------------------------
  435. void SEQ_6x32x16::Copy( int ch, bool bOn )
  436. {
  437. if( !m_bPauseState[ ch ] || !bOn || m_CopySrc != NO_COPY )
  438. {
  439. if( m_CopySrc != NO_COPY )
  440. m_pButtonCopy[ m_CopySrc ]->Set( false );
  441. m_CopySrc = NO_COPY;
  442. m_pButtonCopy[ ch ]->Set( false );
  443. }
  444. else if( bOn )
  445. {
  446. m_CopySrc = ch;
  447. }
  448. }
  449. //-----------------------------------------------------
  450. // Procedure: ChangProg
  451. //
  452. //-----------------------------------------------------
  453. void SEQ_6x32x16::ChangeProg( int ch, int prog, bool bforce )
  454. {
  455. if( ch < 0 || ch >= nCHANNELS )
  456. return;
  457. if( !bforce && prog == m_CurrentProg[ ch ] )
  458. return;
  459. if( prog < 0 )
  460. prog = nPROG - 1;
  461. else if( prog >= nPROG )
  462. prog = 0;
  463. if( m_CopySrc != NO_COPY )
  464. {
  465. if( m_bPauseState[ ch ] )
  466. {
  467. memcpy( m_Pattern[ ch ][ prog ], m_Pattern[ m_CopySrc ][ m_CurrentProg[ m_CopySrc ] ], sizeof(int) * nSTEPS );
  468. m_pButtonCopy[ m_CopySrc ]->Set( false );
  469. m_MaxPat[ ch ][ prog ] = m_MaxPat[ m_CopySrc ][ m_CurrentProg[ m_CopySrc ] ];
  470. m_CopySrc = NO_COPY;
  471. }
  472. }
  473. m_CurrentProg[ ch ] = prog;
  474. m_pPatternDisplay[ ch ]->SetPatAll( m_Pattern[ ch ][ prog ] );
  475. m_pPatternDisplay[ ch ]->SetMax( m_MaxPat[ ch ][ prog ] );
  476. m_pProgramDisplay[ ch ]->SetPat( prog, false );
  477. }
  478. //-----------------------------------------------------
  479. // Procedure: SetPendingProg
  480. //
  481. //-----------------------------------------------------
  482. void SEQ_6x32x16::SetPendingProg( int ch, int progIn )
  483. {
  484. int prog;
  485. if( progIn < 0 || progIn >= nPROG )
  486. prog = ( m_CurrentProg[ ch ] + 1 ) & 0xF;
  487. else
  488. prog = progIn;
  489. if( prog > m_MaxProg[ ch ] )
  490. prog = 0;
  491. m_ProgPending[ ch ].bPending = true;
  492. m_ProgPending[ ch ].prog = prog;
  493. m_pProgramDisplay[ ch ]->SetPat( m_CurrentProg[ ch ], false );
  494. m_pProgramDisplay[ ch ]->SetPat( prog, true );
  495. }
  496. //-----------------------------------------------------
  497. // Procedure: step
  498. //
  499. //-----------------------------------------------------
  500. void SEQ_6x32x16::step()
  501. {
  502. int ch, level, useclock;
  503. bool bClk, bClkTrig, bClockAtZero = false, bGlobalClk = false, bGlobalProg = false, bTrigOut, bPatTrig[ nCHANNELS ] = {};
  504. float fout = 0.0;
  505. if( !m_bInitialized )
  506. return;
  507. if( inputs[ IN_GLOBAL_TRIG_MUTE ].active )
  508. {
  509. if( inputs[ IN_GLOBAL_TRIG_MUTE ].value >= 0.00001 )
  510. {
  511. m_bTrigMute = true;
  512. m_pButtonTrigMute->Set( true );
  513. }
  514. else if( inputs[ IN_GLOBAL_TRIG_MUTE ].value < 0.00001 )
  515. {
  516. m_bTrigMute = false;
  517. m_pButtonTrigMute->Set( false );
  518. }
  519. }
  520. if( inputs[ IN_GLOBAL_CLK_RESET ].active )
  521. bGlobalClk = m_SchTrigGlobalClkReset.process( inputs[ IN_GLOBAL_CLK_RESET ].value );
  522. if( inputs[ IN_GLOBAL_PAT_CHANGE ].active )
  523. bGlobalProg= m_SchTrigGlobalProg.process( inputs[ IN_GLOBAL_PAT_CHANGE ].value );
  524. // get trigs
  525. for( ch = 0; ch < nCHANNELS; ch++ )
  526. bPatTrig[ ch ] = m_SchTrigClock[ ch ].process( inputs[ IN_CLK + ch ].normalize( 0.0f ) );
  527. for( ch = 0; ch < nCHANNELS; ch++ )
  528. {
  529. bClkTrig = false;
  530. bClk = false;
  531. bTrigOut = false;
  532. bClockAtZero = false;
  533. useclock = ch;
  534. // if no keyboard clock active then use kb 0's clock
  535. if( !inputs[ IN_CLK + ch ].active && inputs[ IN_CLK + 0 ].active )
  536. useclock = 0;
  537. if( inputs[ IN_CLK + useclock ].active )
  538. {
  539. // time the clock tick
  540. if( bGlobalClk )
  541. {
  542. m_pPatternDisplay[ ch ]->ClockReset();
  543. bClkTrig = true;
  544. bClockAtZero = true;
  545. bClk = true;
  546. }
  547. // clock
  548. if( bPatTrig[ useclock ] && !bGlobalClk )
  549. bClkTrig = true;
  550. bClk = bClkTrig;
  551. // clock the pattern
  552. if( !m_bPauseState[ ch ] )
  553. {
  554. if( bGlobalProg || m_SchTrigProg[ ch ].process( inputs[ IN_PAT_TRIG + ch ].value ) )
  555. SetPendingProg( ch, -1 );
  556. // clock in
  557. if( bClk )
  558. {
  559. if( !bGlobalClk )
  560. bClockAtZero = m_pPatternDisplay[ ch ]->ClockInc();
  561. bTrigOut = ( m_Pattern[ ch ][ m_CurrentProg[ ch ] ][ m_pPatternDisplay[ ch ]->m_PatClk ] );
  562. }
  563. }
  564. }
  565. // no clock input
  566. else
  567. {
  568. // resolve any left over phrase triggers
  569. if( m_ProgPending[ ch ].bPending )
  570. {
  571. m_ProgPending[ ch ].bPending = false;
  572. ChangeProg( ch, m_ProgPending[ ch ].prog, true );
  573. }
  574. continue;
  575. }
  576. // auto inc pattern
  577. if( m_bAutoPatChange[ ch ] && bClockAtZero )
  578. {
  579. SetPendingProg( ch, -1 );
  580. m_ProgPending[ ch ].bPending = false;
  581. ChangeProg( ch, m_ProgPending[ ch ].prog, true );
  582. bTrigOut = ( m_Pattern[ ch ][ m_CurrentProg[ ch ] ][ m_pPatternDisplay[ ch ]->m_PatClk ] );
  583. }
  584. // resolve pattern change
  585. else if( m_ProgPending[ ch ].bPending && bClockAtZero )
  586. {
  587. m_ProgPending[ ch ].bPending = false;
  588. ChangeProg( ch, m_ProgPending[ ch ].prog, false );
  589. bTrigOut = ( m_Pattern[ ch ][ m_CurrentProg[ ch ] ][ m_pPatternDisplay[ ch ]->m_PatClk ] );
  590. }
  591. // trigger the beat 0 output
  592. if( bClockAtZero )
  593. m_gateBeatPulse[ ch ].trigger(1e-3);
  594. outputs[ OUT_BEAT1 + ch ].value = m_gateBeatPulse[ ch ].process( 1.0 / engineGetSampleRate() ) ? CV_MAX : 0.0;
  595. // trigger out
  596. if( bTrigOut )
  597. {
  598. m_gatePulse[ ch ].trigger(1e-3);
  599. }
  600. if( !m_bTrigMute )
  601. outputs[ OUT_TRIG + ch ].value = m_gatePulse[ ch ].process( 1.0 / engineGetSampleRate() ) ? CV_MAX : 0.0;
  602. else
  603. outputs[ OUT_TRIG + ch ].value = 0.0f;
  604. level = m_Pattern[ ch ][ m_CurrentProg[ ch ] ][ m_pPatternDisplay[ ch ]->m_PatClk ];
  605. // get actual level from knobs
  606. switch( level )
  607. {
  608. case 1:
  609. fout = params[ PARAM_LVL1_KNOB + ch ].value;
  610. break;
  611. case 2:
  612. fout = params[ PARAM_LVL2_KNOB + ch ].value;
  613. break;
  614. case 3:
  615. fout = params[ PARAM_LVL3_KNOB + ch ].value;
  616. break;
  617. case 4:
  618. fout = params[ PARAM_LVL4_KNOB + ch ].value;
  619. break;
  620. case 5:
  621. fout = params[ PARAM_LVL5_KNOB + ch ].value;
  622. break;
  623. default:
  624. if( m_bHoldCVState[ ch ] )
  625. continue;
  626. else
  627. fout = 0.0f;
  628. }
  629. // bidirectional convert to -1.0 to 1.0
  630. if( m_bBiLevelState[ ch ] )
  631. fout = ( fout * 2 ) - 1.0;
  632. if( m_bTrigMute )
  633. outputs[ OUT_LEVEL + ch ].value = flast[ ch ];
  634. else
  635. {
  636. flast[ ch ] = m_fCVRanges[ m_RangeSelect ] * fout;
  637. outputs[ OUT_LEVEL + ch ].value = flast[ ch ];
  638. }
  639. }
  640. }
  641. //-----------------------------------------------------
  642. // Procedure: SEQ_6x32x16_CVRange
  643. //
  644. //-----------------------------------------------------
  645. struct SEQ_6x32x16_CVRange : MenuItem
  646. {
  647. SEQ_6x32x16 *module;
  648. void onAction(EventAction &e) override
  649. {
  650. module->m_RangeSelect++;
  651. if( module->m_RangeSelect > 2 )
  652. module->m_RangeSelect = 0;
  653. sprintf( module->m_strRange, "%.1fV", module->m_fCVRanges[ module->m_RangeSelect ] );
  654. }
  655. void step() override
  656. {
  657. rightText = module->m_strRange;
  658. }
  659. };
  660. //-----------------------------------------------------
  661. // Procedure: createContextMenu
  662. //
  663. //-----------------------------------------------------
  664. Menu *SEQ_6x32x16_Widget::createContextMenu()
  665. {
  666. Menu *menu = ModuleWidget::createContextMenu();
  667. SEQ_6x32x16 *mod = dynamic_cast<SEQ_6x32x16*>(module);
  668. assert(mod);
  669. menu->addChild(construct<MenuLabel>());
  670. menu->addChild(construct<MenuLabel>(&MenuLabel::text, "---- CV Output Level ----"));
  671. menu->addChild(construct<SEQ_6x32x16_CVRange>( &MenuItem::text, "VRange (15, 10, 5):", &SEQ_6x32x16_CVRange::module, mod ) );
  672. return menu;
  673. }
  674. } // namespace rack_plugin_mscHack
  675. using namespace rack_plugin_mscHack;
  676. RACK_PLUGIN_MODEL_INIT(mscHack, SEQ_6x32x16) {
  677. Model *modelSEQ_6x32x16 = Model::create<SEQ_6x32x16, SEQ_6x32x16_Widget>( "mscHack", "Seq_6ch_32step", "SEQ 6 x 32", SEQUENCER_TAG, MULTIPLE_TAG );
  678. return modelSEQ_6x32x16;
  679. }