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.

701 lines
21KB

  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 4
  7. #define MID_INDEX 12
  8. #define CLOCK_DIVS 25
  9. const int multdisplayval[ CLOCK_DIVS ] = { 32, 24, 16, 12, 9, 8, 7, 6, 5, 4, 3, 2, 1, 2, 3, 4, 5, 6, 7, 8, 9, 12, 16, 24, 32 };
  10. //-----------------------------------------------------
  11. // Module Definition
  12. //
  13. //-----------------------------------------------------
  14. struct MasterClockx4 : Module
  15. {
  16. enum ParamIds
  17. {
  18. PARAM_BPM,
  19. PARAM_MULT,
  20. PARAM_HUMANIZE = PARAM_MULT + nCHANNELS,
  21. nPARAMS
  22. };
  23. enum InputIds
  24. {
  25. INPUT_EXT_SYNC,
  26. INPUT_CHAIN = INPUT_EXT_SYNC + nCHANNELS,
  27. nINPUTS
  28. };
  29. enum OutputIds
  30. {
  31. OUTPUT_CLK,
  32. OUTPUT_TRIG = OUTPUT_CLK + ( nCHANNELS * 4 ),
  33. OUTPUT_CHAIN = OUTPUT_TRIG + ( nCHANNELS * 4 ),
  34. nOUTPUTS
  35. };
  36. bool m_bInitialized = false;
  37. CLog lg;
  38. float m_fBPM = 120;
  39. MyLED7DigitDisplay *m_pDigitDisplayMult[ nCHANNELS ] = {};
  40. MyLED7DigitDisplay *m_pDigitDisplayBPM = NULL;
  41. MyLEDButton *m_pButtonGlobalStop = NULL;
  42. MyLEDButton *m_pButtonGlobalTrig = NULL;
  43. MyLEDButton *m_pButtonStop[ nCHANNELS ] = {};
  44. MyLEDButton *m_pButtonTrig[ nCHANNELS ] = {};
  45. MyLEDButton *m_pButtonTimeX2[ nCHANNELS ] = {};
  46. bool m_bGlobalSync = false;
  47. bool m_bStopState[ nCHANNELS ] = {};
  48. bool m_bGlobalStopState = false;
  49. bool m_bChannelSyncPending[ nCHANNELS ] = {};
  50. bool m_bTimeX2[ nCHANNELS ] = {};
  51. int m_ChannelDivBeatCount[ nCHANNELS ] = {};
  52. float m_fChannelBeatsPers[ nCHANNELS ] = {};
  53. float m_fChannelClockCount[ nCHANNELS ] = {};
  54. int m_ChannelMultSelect[ nCHANNELS ] = {};
  55. float m_fHumanize = 0;
  56. float m_bWasChained = false;
  57. float m_fBeatsPers;
  58. float m_fMainClockCount;
  59. PulseGenerator m_PulseClock[ nCHANNELS ];
  60. PulseGenerator m_PulseSync[ nCHANNELS ];
  61. SchmittTrigger m_SchmittSyncIn[ nCHANNELS ];
  62. ParamWidget *m_pBpmKnob = NULL;
  63. ParamWidget *m_pHumanKnob = NULL;
  64. // Contructor
  65. MasterClockx4() : Module(nPARAMS, nINPUTS, nOUTPUTS, 0){}
  66. //-----------------------------------------------------
  67. // MyHumanize_Knob
  68. //-----------------------------------------------------
  69. struct MyHumanize_Knob : Knob_Yellow2_26
  70. {
  71. MasterClockx4 *mymodule;
  72. void onChange( EventChange &e ) override
  73. {
  74. mymodule = (MasterClockx4*)module;
  75. if( mymodule && !mymodule->inputs[ INPUT_CHAIN ].active )
  76. mymodule->GetNewHumanizeVal();
  77. RoundKnob::onChange( e );
  78. }
  79. };
  80. //-----------------------------------------------------
  81. // MyBPM_Knob
  82. //-----------------------------------------------------
  83. struct MyBPM_Knob : Knob_Yellow2_56
  84. {
  85. MasterClockx4 *mymodule;
  86. void onChange( EventChange &e ) override
  87. {
  88. mymodule = (MasterClockx4*)module;
  89. if( mymodule && !mymodule->inputs[ INPUT_CHAIN ].active )
  90. mymodule->BPMChange( value, false );
  91. RoundKnob::onChange( e );
  92. }
  93. };
  94. //-----------------------------------------------------
  95. // MyMult_Knob
  96. //-----------------------------------------------------
  97. struct MyMult_Knob : Knob_Yellow2_26_Snap
  98. {
  99. MasterClockx4 *mymodule;
  100. int param, col;
  101. void onChange( EventChange &e ) override
  102. {
  103. mymodule = (MasterClockx4*)module;
  104. if( mymodule )
  105. {
  106. //if( !mymodule->m_bInitialized )
  107. //return;
  108. param = paramId - MasterClockx4::PARAM_MULT;
  109. if( mymodule->m_ChannelMultSelect[ param ] != (int)value )
  110. {
  111. mymodule->SetDisplayLED( param, (int)value );
  112. }
  113. }
  114. RoundKnob::onChange( e );
  115. }
  116. };
  117. // Overrides
  118. void step() override;
  119. json_t* toJson() override;
  120. void fromJson(json_t *rootJ) override;
  121. void onReset() override;
  122. void GetNewHumanizeVal( void );
  123. void BPMChange( float fbmp, bool bforce );
  124. void CalcChannelClockRate( int ch );
  125. void SetDisplayLED( int ch, int val );
  126. };
  127. //-----------------------------------------------------
  128. // MyLEDButton_GlobalStop
  129. //-----------------------------------------------------
  130. void MyLEDButton_GlobalStop( void *pClass, int id, bool bOn )
  131. {
  132. MasterClockx4 *mymodule;
  133. mymodule = (MasterClockx4*)pClass;
  134. mymodule->m_bGlobalStopState = bOn;
  135. }
  136. //-----------------------------------------------------
  137. // MyLEDButton_TimeX2
  138. //-----------------------------------------------------
  139. void MyLEDButton_TimeX2( void *pClass, int id, bool bOn )
  140. {
  141. MasterClockx4 *mymodule;
  142. mymodule = (MasterClockx4*)pClass;
  143. mymodule->m_bTimeX2[ id ] = bOn;
  144. mymodule->SetDisplayLED( id, (int)mymodule->params[ MasterClockx4::PARAM_MULT + id ].value );
  145. }
  146. //-----------------------------------------------------
  147. // MyLEDButton_GlobalTrig
  148. //-----------------------------------------------------
  149. void MyLEDButton_GlobalTrig( void *pClass, int id, bool bOn )
  150. {
  151. MasterClockx4 *mymodule;
  152. mymodule = (MasterClockx4*)pClass;
  153. mymodule->m_bGlobalSync = true;
  154. }
  155. //-----------------------------------------------------
  156. // MyLEDButton_ChannelStop
  157. //-----------------------------------------------------
  158. void MyLEDButton_ChannelStop ( void *pClass, int id, bool bOn )
  159. {
  160. MasterClockx4 *mymodule;
  161. mymodule = (MasterClockx4*)pClass;
  162. mymodule->m_bStopState[ id ] = bOn;
  163. }
  164. //-----------------------------------------------------
  165. // MyLEDButton_ChannelSync
  166. //-----------------------------------------------------
  167. void MyLEDButton_ChannelSync( void *pClass, int id, bool bOn )
  168. {
  169. MasterClockx4 *mymodule;
  170. mymodule = (MasterClockx4*)pClass;
  171. mymodule->m_bChannelSyncPending[ id ] = true;
  172. if( mymodule->m_pButtonTrig[ id ] )
  173. mymodule->m_pButtonTrig[ id ]->Set( true );
  174. }
  175. //-----------------------------------------------------
  176. // Procedure: Widget
  177. //
  178. //-----------------------------------------------------
  179. struct MasterClockx4_Widget : ModuleWidget {
  180. MasterClockx4_Widget( MasterClockx4 *module );
  181. };
  182. MasterClockx4_Widget::MasterClockx4_Widget( MasterClockx4 *module ) : ModuleWidget(module)
  183. {
  184. int ch, x, y;
  185. box.size = Vec( 15*18, 380);
  186. {
  187. SVGPanel *panel = new SVGPanel();
  188. panel->box.size = box.size;
  189. panel->setBackground(SVG::load(assetPlugin( plugin, "res/MasterClockx4.svg")));
  190. addChild(panel);
  191. }
  192. //module->lg.Open("MasterClockx4.txt");
  193. // bpm knob
  194. module->m_pBpmKnob = ParamWidget::create<MasterClockx4::MyBPM_Knob>( Vec( 9, 50 ), module, MasterClockx4::PARAM_BPM, 60.0, 220.0, 120.0 );
  195. addParam( module->m_pBpmKnob );
  196. // bpm display
  197. module->m_pDigitDisplayBPM = new MyLED7DigitDisplay( 5, 115, 0.055, DWRGB( 0, 0, 0 ), DWRGB( 0xFF, 0xFF, 0xFF ), MyLED7DigitDisplay::TYPE_FLOAT, 5 );
  198. addChild( module->m_pDigitDisplayBPM );
  199. // global stop switch
  200. module->m_pButtonGlobalStop = new MyLEDButton( 22, 144, 25, 25, 20.0, DWRGB( 180, 180, 180 ), DWRGB( 255, 0, 0 ), MyLEDButton::TYPE_SWITCH, 0, module, MyLEDButton_GlobalStop );
  201. addChild( module->m_pButtonGlobalStop );
  202. // global sync button
  203. module->m_pButtonGlobalTrig = new MyLEDButton( 22, 202, 25, 25, 20.0, DWRGB( 180, 180, 180 ), DWRGB( 0, 255, 255 ), MyLEDButton::TYPE_MOMENTARY, 0, module, MyLEDButton_GlobalTrig );
  204. addChild( module->m_pButtonGlobalTrig );
  205. // humanize knob
  206. module->m_pHumanKnob = ParamWidget::create<MasterClockx4::MyHumanize_Knob>( Vec( 22, 235 ), module, MasterClockx4::PARAM_HUMANIZE, 0.0, 1.0, 0.0 );
  207. addParam( module->m_pHumanKnob );
  208. // add chain out
  209. addOutput(Port::create<MyPortOutSmall>( Vec( 30, 345 ), Port::OUTPUT, module, MasterClockx4::OUTPUT_CHAIN ) );
  210. // chain in
  211. addInput(Port::create<MyPortInSmall>( Vec( 30, 13 ), Port::INPUT, module, MasterClockx4::INPUT_CHAIN ) );
  212. x = 91;
  213. y = 39;
  214. for( ch = 0; ch < nCHANNELS; ch++ )
  215. {
  216. // x2
  217. module->m_pButtonTimeX2[ ch ] = new MyLEDButton( x + 2, y + 2, 11, 11, 9.0, DWRGB( 180, 180, 180 ), DWRGB( 0, 255, 255 ), MyLEDButton::TYPE_SWITCH, ch, module, MyLEDButton_TimeX2 );
  218. addChild( module->m_pButtonTimeX2[ ch ] );
  219. // clock mult knob
  220. addParam(ParamWidget::create<MasterClockx4::MyMult_Knob>( Vec( x + 13, y + 13 ), module, MasterClockx4::PARAM_MULT + ch, 0, CLOCK_DIVS - 1, MID_INDEX ) );
  221. // mult display
  222. module->m_pDigitDisplayMult[ ch ] = new MyLED7DigitDisplay( x + 10, y + 48, 0.07, DWRGB( 0, 0, 0 ), DWRGB( 0xFF, 0xFF, 0xFF ), MyLED7DigitDisplay::TYPE_INT, 2 );
  223. addChild( module->m_pDigitDisplayMult[ ch ] );
  224. // sync triggers
  225. module->m_pButtonTrig[ ch ] = new MyLEDButton( x + 76, y + 4, 19, 19, 15.0, DWRGB( 180, 180, 180 ), DWRGB( 0, 255, 255 ), MyLEDButton::TYPE_MOMENTARY, ch, module, MyLEDButton_ChannelSync );
  226. addChild( module->m_pButtonTrig[ ch ] );
  227. addInput(Port::create<MyPortInSmall>( Vec( x + 54, y + 5 ), Port::INPUT, module, MasterClockx4::INPUT_EXT_SYNC + ch ) );
  228. addOutput(Port::create<MyPortOutSmall>( Vec( x + 54, y + 31 ), Port::OUTPUT, module, MasterClockx4::OUTPUT_TRIG + (ch * 4) + 0 ) );
  229. addOutput(Port::create<MyPortOutSmall>( Vec( x + 54, y + 53 ), Port::OUTPUT, module, MasterClockx4::OUTPUT_TRIG + (ch * 4) + 1 ) );
  230. addOutput(Port::create<MyPortOutSmall>( Vec( x + 77, y + 31 ), Port::OUTPUT, module, MasterClockx4::OUTPUT_TRIG + (ch * 4) + 2 ) );
  231. addOutput(Port::create<MyPortOutSmall>( Vec( x + 77, y + 53 ), Port::OUTPUT, module, MasterClockx4::OUTPUT_TRIG + (ch * 4) + 3 ) );
  232. // clock out
  233. module->m_pButtonStop[ ch ] = new MyLEDButton( x + 132, y + 4, 19, 19, 15.0, DWRGB( 180, 180, 180 ), DWRGB( 255, 0, 0 ), MyLEDButton::TYPE_SWITCH, ch, module, MyLEDButton_ChannelStop );
  234. addChild( module->m_pButtonStop[ ch ] );
  235. addOutput(Port::create<MyPortOutSmall>( Vec( x + 107, y + 31 ), Port::OUTPUT, module, MasterClockx4::OUTPUT_CLK + (ch * 4) + 0 ) );
  236. addOutput(Port::create<MyPortOutSmall>( Vec( x + 107, y + 53 ), Port::OUTPUT, module, MasterClockx4::OUTPUT_CLK + (ch * 4) + 1 ) );
  237. addOutput(Port::create<MyPortOutSmall>( Vec( x + 130, y + 31 ), Port::OUTPUT, module, MasterClockx4::OUTPUT_CLK + (ch * 4) + 2 ) );
  238. addOutput(Port::create<MyPortOutSmall>( Vec( x + 130, y + 53 ), Port::OUTPUT, module, MasterClockx4::OUTPUT_CLK + (ch * 4) + 3 ) );
  239. y += 80;
  240. }
  241. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  242. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0)));
  243. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  244. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365)));
  245. module->m_bInitialized = true;
  246. module->onReset();
  247. }
  248. //-----------------------------------------------------
  249. // Procedure:
  250. //
  251. //-----------------------------------------------------
  252. json_t *MasterClockx4::toJson()
  253. {
  254. bool *pbool;
  255. json_t *rootJ = json_object();
  256. json_t *gateJ;
  257. // m_bGlobalStopState
  258. json_object_set_new( rootJ, "m_bGlobalStopState", json_boolean (m_bGlobalStopState) );
  259. // m_bStopState
  260. pbool = &m_bStopState[ 0 ];
  261. json_t *gatesJ = json_array();
  262. for (int i = 0; i < nCHANNELS; i++)
  263. {
  264. gateJ = json_boolean( (int) pbool[ i ] );
  265. json_array_append_new( gatesJ, gateJ );
  266. }
  267. json_object_set_new( rootJ, "m_bStopState", gatesJ );
  268. // m_bTimeX2
  269. pbool = &m_bTimeX2[ 0 ];
  270. gatesJ = json_array();
  271. for (int i = 0; i < nCHANNELS; i++)
  272. {
  273. gateJ = json_boolean( (int) pbool[ i ] );
  274. json_array_append_new( gatesJ, gateJ );
  275. }
  276. json_object_set_new( rootJ, "m_bTimeX2", gatesJ );
  277. return rootJ;
  278. }
  279. //-----------------------------------------------------
  280. // Procedure: fromJson
  281. //
  282. //-----------------------------------------------------
  283. void MasterClockx4::fromJson(json_t *rootJ)
  284. {
  285. bool *pbool;
  286. json_t *gateJ;
  287. // m_bGlobalStopState
  288. json_t *revJ = json_object_get(rootJ, "m_bGlobalStopState");
  289. if (revJ)
  290. m_bGlobalStopState = json_is_true( revJ );
  291. // m_bPauseState
  292. pbool = &m_bStopState[ 0 ];
  293. json_t *StepsJ = json_object_get(rootJ, "m_bStopState");
  294. if (StepsJ)
  295. {
  296. for (int i = 0; i < nCHANNELS; i++)
  297. {
  298. gateJ = json_array_get(StepsJ, i);
  299. if (gateJ)
  300. pbool[ i ] = json_boolean_value( gateJ );
  301. }
  302. }
  303. // m_bTimeX2
  304. pbool = &m_bTimeX2[ 0 ];
  305. StepsJ = json_object_get(rootJ, "m_bTimeX2");
  306. if (StepsJ)
  307. {
  308. for (int i = 0; i < nCHANNELS; i++)
  309. {
  310. gateJ = json_array_get(StepsJ, i);
  311. if (gateJ)
  312. pbool[ i ] = json_boolean_value( gateJ );
  313. }
  314. }
  315. m_pButtonGlobalStop->Set( m_bGlobalStopState );
  316. for( int ch = 0; ch < nCHANNELS; ch++ )
  317. {
  318. m_pButtonStop[ ch ]->Set( m_bStopState[ ch ] );
  319. m_pButtonTimeX2[ ch ]->Set( m_bTimeX2[ ch ] );
  320. //lg.f( "value = %d\n", (int)params[ PARAM_MULT + ch ].value );
  321. SetDisplayLED( ch, (int)params[ PARAM_MULT + ch ].value );
  322. }
  323. m_fMainClockCount = 0;
  324. BPMChange( params[ PARAM_BPM ].value, true );
  325. if( m_pDigitDisplayBPM )
  326. m_pDigitDisplayBPM->SetFloat( m_fBPM );
  327. }
  328. //-----------------------------------------------------
  329. // Procedure: reset
  330. //
  331. //-----------------------------------------------------
  332. void MasterClockx4::onReset()
  333. {
  334. if( !m_bInitialized )
  335. return;
  336. m_fBPM = 120;
  337. if( m_pDigitDisplayBPM )
  338. m_pDigitDisplayBPM->SetFloat( m_fBPM );
  339. m_bGlobalStopState = false;
  340. m_pButtonGlobalStop->Set( m_bGlobalStopState );
  341. for( int ch = 0; ch < nCHANNELS; ch++ )
  342. {
  343. m_bTimeX2[ ch ] = false;
  344. m_bStopState[ ch ] = false;
  345. m_pButtonStop[ ch ]->Set( m_bStopState[ ch ] );
  346. SetDisplayLED( ch, MID_INDEX );
  347. }
  348. BPMChange( m_fBPM, true );
  349. }
  350. //-----------------------------------------------------
  351. // Procedure: SetDisplayLED
  352. //
  353. //-----------------------------------------------------
  354. void MasterClockx4::SetDisplayLED( int ch, int val )
  355. {
  356. int col, mult = 1;
  357. if( !m_bInitialized )
  358. return;
  359. if( m_bTimeX2[ ch ] )
  360. mult = 2;
  361. if( val < MID_INDEX )
  362. {
  363. col = DWRGB( 0xFF, 0, 0 );
  364. }
  365. else if( val > MID_INDEX )
  366. {
  367. col = DWRGB( 0, 0xFF, 0xFF );
  368. }
  369. else
  370. {
  371. mult = 1;
  372. col = DWRGB( 0xFF, 0xFF, 0xFF );
  373. }
  374. if( m_pDigitDisplayMult[ ch ] )
  375. {
  376. m_ChannelMultSelect[ ch ] = val;
  377. m_pDigitDisplayMult[ ch ]->SetLEDCol( col );
  378. m_pDigitDisplayMult[ ch ]->SetInt( multdisplayval[ val ] * mult );
  379. }
  380. CalcChannelClockRate( ch );
  381. }
  382. //-----------------------------------------------------
  383. // Procedure: GetNewHumanizeVal
  384. //
  385. //-----------------------------------------------------
  386. void MasterClockx4::GetNewHumanizeVal( void )
  387. {
  388. m_fHumanize = randomUniform() * engineGetSampleRate() * 0.1 * params[ PARAM_HUMANIZE ].value;
  389. if( randomUniform() > 0.5 )
  390. m_fHumanize *= -1;
  391. }
  392. //-----------------------------------------------------
  393. // Procedure: BMPChange
  394. //
  395. //-----------------------------------------------------
  396. void MasterClockx4::BPMChange( float fbpm, bool bforce )
  397. {
  398. // don't change if it is already the same
  399. if( !bforce && ( (int)(fbpm * 1000.0f ) == (int)(m_fBPM * 1000.0f ) ) )
  400. return;
  401. m_fBPM = fbpm;
  402. m_fBeatsPers = fbpm / 60.0;
  403. if( m_pDigitDisplayBPM )
  404. m_pDigitDisplayBPM->SetFloat( m_fBPM );
  405. for( int i = 0; i < nCHANNELS; i++ )
  406. CalcChannelClockRate( i );
  407. }
  408. //-----------------------------------------------------
  409. // Procedure: CalcChannelClockRate
  410. //
  411. //-----------------------------------------------------
  412. void MasterClockx4::CalcChannelClockRate( int ch )
  413. {
  414. int mult = 1;
  415. if( m_bTimeX2[ ch ] )
  416. mult = 2;
  417. // for beat division just keep a count of beats
  418. if( m_ChannelMultSelect[ ch ] == MID_INDEX )
  419. m_ChannelDivBeatCount[ ch ] = 1;
  420. if( m_ChannelMultSelect[ ch ] <= MID_INDEX )
  421. m_ChannelDivBeatCount[ ch ] = multdisplayval[ m_ChannelMultSelect[ ch ] ] * mult;
  422. else
  423. m_fChannelBeatsPers[ ch ] = m_fBeatsPers * (float)( multdisplayval[ m_ChannelMultSelect[ ch ] ] * mult );
  424. }
  425. //-----------------------------------------------------
  426. // Procedure: step
  427. //
  428. //-----------------------------------------------------
  429. void MasterClockx4::step()
  430. {
  431. int ch, mult = 1;
  432. float fSyncPulseOut, fClkPulseOut;
  433. bool bMainClockTrig = false, bChannelClockTrig;
  434. if( !m_bInitialized )
  435. return;
  436. // use the input chain trigger for our clock
  437. if( inputs[ INPUT_CHAIN ].active )
  438. {
  439. if( !m_bWasChained )
  440. {
  441. m_pHumanKnob->visible = false;
  442. m_pBpmKnob->visible = false;
  443. }
  444. m_bWasChained = true;
  445. // value of less than zero is a trig
  446. if( inputs[ INPUT_CHAIN ].value < 10.0 )
  447. {
  448. bMainClockTrig = true;
  449. }
  450. // values greater than zero are the bpm
  451. else
  452. {
  453. BPMChange( inputs[ INPUT_CHAIN ].value, false );
  454. }
  455. }
  456. else
  457. {
  458. // go back to our bpm if chain removed
  459. if( m_bWasChained )
  460. {
  461. m_pHumanKnob->visible = true;
  462. m_pBpmKnob->visible = true;
  463. m_bWasChained = false;
  464. BPMChange( params[ PARAM_BPM ].value, false );
  465. }
  466. // keep track of main bpm
  467. m_fMainClockCount += m_fBeatsPers;
  468. if( ( m_fMainClockCount + m_fHumanize ) >= engineGetSampleRate() )
  469. {
  470. m_fMainClockCount = ( m_fMainClockCount + m_fHumanize ) - engineGetSampleRate();
  471. GetNewHumanizeVal();
  472. bMainClockTrig = true;
  473. }
  474. }
  475. // send chain
  476. if( outputs[ OUTPUT_CHAIN ].active )
  477. {
  478. if( bMainClockTrig )
  479. outputs[ OUTPUT_CHAIN ].value = -1.0;
  480. else
  481. outputs[ OUTPUT_CHAIN ].value = m_fBPM;
  482. }
  483. for( ch = 0; ch < nCHANNELS; ch++ )
  484. {
  485. bChannelClockTrig = false;
  486. // sync triggers
  487. if( m_bGlobalSync || m_SchmittSyncIn[ ch ].process( inputs[ INPUT_EXT_SYNC + ch ].value ) )
  488. {
  489. if( m_pButtonTrig[ ch ] )
  490. m_pButtonTrig[ ch ]->Set( true );
  491. m_bChannelSyncPending[ ch ] = true;
  492. }
  493. // sync all triggers to main clock pulse
  494. if( bMainClockTrig )
  495. {
  496. if( m_bChannelSyncPending[ ch ] )
  497. {
  498. if( m_pButtonTrig[ ch ] )
  499. m_pButtonTrig[ ch ]->Set( true );
  500. m_bChannelSyncPending[ ch ] = false;
  501. m_PulseSync[ ch ].trigger(1e-3);
  502. m_ChannelDivBeatCount[ ch ] = 0;
  503. m_fChannelClockCount[ ch ] = 0;
  504. bChannelClockTrig = true;
  505. }
  506. else
  507. {
  508. // divisions of clock will count beats
  509. if( m_ChannelMultSelect[ ch ] <= MID_INDEX )
  510. {
  511. if( m_bTimeX2[ ch ] )
  512. mult = 2;
  513. if( ++m_ChannelDivBeatCount[ ch ] >= ( multdisplayval[ m_ChannelMultSelect[ ch ] ] * mult ) )
  514. {
  515. m_ChannelDivBeatCount[ ch ] = 0;
  516. bChannelClockTrig = true;
  517. }
  518. }
  519. // multiples of clock will sync with every beat
  520. else
  521. {
  522. m_fChannelClockCount[ ch ] = 0;
  523. bChannelClockTrig = true;
  524. }
  525. }
  526. }
  527. // do multiple clocks
  528. else if( m_ChannelMultSelect[ ch ] > MID_INDEX )
  529. {
  530. m_fChannelClockCount[ ch ] += m_fChannelBeatsPers[ ch ];
  531. if( m_fChannelClockCount[ ch ] >= engineGetSampleRate() )
  532. {
  533. m_fChannelClockCount[ ch ] = m_fChannelClockCount[ ch ] - engineGetSampleRate();
  534. bChannelClockTrig = true;
  535. }
  536. }
  537. if( bChannelClockTrig )
  538. m_PulseClock[ ch ].trigger(1e-3);
  539. // syncs
  540. fSyncPulseOut = m_PulseSync[ ch ].process( 1.0 / engineGetSampleRate() ) ? CV_MAX : 0.0;
  541. outputs[ OUTPUT_TRIG + (ch * 4) + 0 ].value = fSyncPulseOut;
  542. outputs[ OUTPUT_TRIG + (ch * 4) + 1 ].value = fSyncPulseOut;
  543. outputs[ OUTPUT_TRIG + (ch * 4) + 2 ].value = fSyncPulseOut;
  544. outputs[ OUTPUT_TRIG + (ch * 4) + 3 ].value = fSyncPulseOut;
  545. // clocks
  546. fClkPulseOut = m_PulseClock[ ch ].process( 1.0 / engineGetSampleRate() ) ? CV_MAX : 0.0;
  547. if( !m_bGlobalStopState && !m_bStopState[ ch ] )
  548. {
  549. outputs[ OUTPUT_CLK + (ch * 4) + 0 ].value = fClkPulseOut;
  550. outputs[ OUTPUT_CLK + (ch * 4) + 1 ].value = fClkPulseOut;
  551. outputs[ OUTPUT_CLK + (ch * 4) + 2 ].value = fClkPulseOut;
  552. outputs[ OUTPUT_CLK + (ch * 4) + 3 ].value = fClkPulseOut;
  553. }
  554. }
  555. m_bGlobalSync = false;
  556. }
  557. } // namespace rack_plugin_mscHack
  558. using namespace rack_plugin_mscHack;
  559. RACK_PLUGIN_MODEL_INIT(mscHack, MasterClockx4) {
  560. Model *modelMasterClockx4 = Model::create<MasterClockx4, MasterClockx4_Widget>( "mscHack", "MasterClockx4", "Master CLOCK x 4", CLOCK_TAG, QUAD_TAG );
  561. return modelMasterClockx4;
  562. }