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.

751 lines
17KB

  1. #include "mscHack.hpp"
  2. #include "dsp/digital.hpp"
  3. namespace rack_plugin_mscHack {
  4. //-----------------------------------------------------
  5. // General Definition
  6. //-----------------------------------------------------
  7. #define nCHANNELS 2
  8. //-----------------------------------------------------
  9. // filter
  10. //-----------------------------------------------------
  11. enum FILTER_TYPES
  12. {
  13. FILTER_OFF,
  14. FILTER_LP,
  15. FILTER_HP,
  16. FILTER_BP,
  17. FILTER_NT
  18. };
  19. typedef struct
  20. {
  21. int type;
  22. float basef, q, f, qmod, fmod;
  23. float lp1, bp1;
  24. }FILTER_STRUCT;
  25. //-----------------------------------------------------
  26. // Morph oscillator
  27. //-----------------------------------------------------
  28. #define nMORPH_WAVES 2
  29. enum MOD_TYPES
  30. {
  31. MOD_LEVEL,
  32. MOD_REZ,
  33. nMODS
  34. };
  35. #define nBITS 2048
  36. typedef struct
  37. {
  38. int state;
  39. int baud;
  40. float finc;
  41. float fcount;
  42. float fout;
  43. int bits[ nBITS ];
  44. }DIGITAL_OSC_STRUCT;
  45. #define OSC2_NOTES 5
  46. //-----------------------------------------------------
  47. // Module Definition
  48. //
  49. //-----------------------------------------------------
  50. struct Alienz : Module
  51. {
  52. enum ParamIds
  53. {
  54. PARAM_SPEED,
  55. nPARAMS
  56. };
  57. enum InputIds
  58. {
  59. IN_RANDTRIG,
  60. IN_GATE,
  61. nINPUTS
  62. };
  63. enum OutputIds
  64. {
  65. OUT,
  66. nOUTPUTS
  67. };
  68. enum LightIds
  69. {
  70. nLIGHTS
  71. };
  72. enum FADE_STATE
  73. {
  74. FADE_IDLE,
  75. FADE_OUT,
  76. FADE_IN,
  77. };
  78. bool m_bInitialized = false;
  79. CLog lg;
  80. // Contructor
  81. Alienz() : Module(nPARAMS, nINPUTS, nOUTPUTS, nLIGHTS){}
  82. Label *m_pTextLabel = NULL;
  83. Label *m_pTextLabel2 = NULL;
  84. // osc
  85. DIGITAL_OSC_STRUCT m_bitosc = {};
  86. EnvelopeData m_osc2;
  87. float m_osc2notes[ OSC2_NOTES ];
  88. float m_osc2freq;
  89. // modulation envelopes
  90. EnvelopeData m_mod[ nCHANNELS ][ nMODS ] = {};
  91. float m_fval[ nCHANNELS ][ nMODS ] = {};
  92. float m_finc[ nCHANNELS ][ nMODS ] = {};
  93. FILTER_STRUCT m_filter[ nCHANNELS ]={};
  94. // random seed
  95. SchmittTrigger m_SchmitTrigRand;
  96. MyLEDButton *m_pButtonSeed[ 32 ] = {};
  97. MyLEDButton *m_pButtonRand = NULL;
  98. int m_Seed = 0;
  99. int m_FadeState = FADE_IN;
  100. float m_fFade = 0.0f;
  101. float speeds[ 9 ] = { 0.1f, 0.25f, 0.50f, 0.75f, 1.0f, 1.5f, 2.0f, 4.0f, 8.0f };
  102. //-----------------------------------------------------
  103. // MySpeed_Knob
  104. //-----------------------------------------------------
  105. struct MySpeed_Knob : Knob_Yellow3_20_Snap
  106. {
  107. Alienz *mymodule;
  108. char strVal[ 10 ] = {};
  109. void onChange( EventChange &e ) override
  110. {
  111. mymodule = (Alienz*)module;
  112. if( mymodule )
  113. {
  114. if( !mymodule->m_bInitialized )
  115. return;
  116. sprintf( strVal, "x%.2f", mymodule->speeds[ (int)value ] );
  117. mymodule->m_pTextLabel2->text = strVal;
  118. }
  119. RoundKnob::onChange( e );
  120. }
  121. };
  122. void putx( int x );
  123. void putf( float fval );
  124. int getseed( void );
  125. void putseed( int seed );
  126. void ChangeSeedPending( int seed );
  127. void BuildWave( int ch );
  128. void BuildDrone( void );
  129. void RandWave( EnvelopeData *pEnv, float min=0.0f, float max= 1.0f );
  130. void RandPresetWaveAdjust( EnvelopeData *pEnv );
  131. // audio
  132. void ChangeFilterCutoff( int ch, float f );
  133. void processFilter( int ch, float *pIn );
  134. void processReverb( float In, float *pL, float *pR );
  135. // Overrides
  136. void step() override;
  137. void JsonParams( bool bTo, json_t *root);
  138. json_t* toJson() override;
  139. void fromJson(json_t *rootJ) override;
  140. void onRandomize() override;
  141. void onReset() override;
  142. void onCreate() override;
  143. void onDelete() override;
  144. };
  145. //-----------------------------------------------------
  146. // Alienz_SeedButton
  147. //-----------------------------------------------------
  148. void Alienz_SeedButton( void *pClass, int id, bool bOn )
  149. {
  150. Alienz *mymodule;
  151. mymodule = (Alienz*)pClass;
  152. mymodule->ChangeSeedPending( mymodule->getseed() );
  153. }
  154. //-----------------------------------------------------
  155. // Alienz_RandButton
  156. //-----------------------------------------------------
  157. void Alienz_RandButton( void *pClass, int id, bool bOn )
  158. {
  159. Alienz *mymodule;
  160. mymodule = (Alienz*)pClass;
  161. mymodule->ChangeSeedPending( (int)randomu32() );
  162. }
  163. //-----------------------------------------------------
  164. // Procedure: Widget
  165. //
  166. //-----------------------------------------------------
  167. struct Alienz_Widget : ModuleWidget {
  168. Alienz_Widget( Alienz *module );
  169. };
  170. Alienz_Widget::Alienz_Widget( Alienz *module ) : ModuleWidget(module)
  171. {
  172. int i, x, y;
  173. box.size = Vec( 15*5, 380 );
  174. {
  175. SVGPanel *panel = new SVGPanel();
  176. panel->box.size = box.size;
  177. panel->setBackground(SVG::load(assetPlugin(plugin, "res/Alienz.svg")));
  178. addChild(panel);
  179. }
  180. addInput(Port::create<MyPortInSmall>( Vec( 10, 20 ), Port::INPUT, module, Alienz::IN_GATE ) );
  181. addInput(Port::create<MyPortInSmall>( Vec( 10, 241 ), Port::INPUT, module, Alienz::IN_RANDTRIG ) );
  182. // random button
  183. module->m_pButtonRand = new MyLEDButton( 40, 238, 25, 25, 20.0, DWRGB( 180, 180, 180 ), DWRGB( 255, 0, 0 ), MyLEDButton::TYPE_MOMENTARY, 0, module, Alienz_RandButton );
  184. addChild( module->m_pButtonRand );
  185. addOutput(Port::create<MyPortOutSmall>( Vec( 48, 20 ), Port::OUTPUT, module, Alienz::OUT ) );
  186. y = 95;
  187. x = 9;
  188. //module->lg.Open("c://users//mark//documents//rack//Alienz.txt");
  189. for( i = 31; i >=0; i-- )
  190. {
  191. module->m_pButtonSeed[ i ] = new MyLEDButton( x, y, 11, 11, 8.0, DWRGB( 180, 180, 180 ), DWRGB( 255, 255, 0 ), MyLEDButton::TYPE_SWITCH, i, module, Alienz_SeedButton );
  192. addChild( module->m_pButtonSeed[ i ] );
  193. if( i % 4 == 0 )
  194. {
  195. y += 15;
  196. x = 9;
  197. }
  198. else
  199. {
  200. x += 15;
  201. }
  202. }
  203. addParam(ParamWidget::create<Alienz::MySpeed_Knob>( Vec( 10, 280 ), module, Alienz::PARAM_SPEED, 0.0, 8.0, 4.0 ) );
  204. module->m_pTextLabel2 = new Label();
  205. module->m_pTextLabel2->box.pos = Vec( 30, 280 );
  206. module->m_pTextLabel2->text = "x1.00";
  207. addChild( module->m_pTextLabel2 );
  208. module->m_pTextLabel = new Label();
  209. module->m_pTextLabel->box.pos = Vec( 0, 213 );
  210. module->m_pTextLabel->text = "----";
  211. addChild( module->m_pTextLabel );
  212. addChild(Widget::create<ScrewSilver>(Vec(30, 0)));
  213. addChild(Widget::create<ScrewSilver>(Vec(30, 365)));
  214. module->putseed( (int)randomu32() );
  215. module->BuildDrone();
  216. }
  217. //-----------------------------------------------------
  218. // Procedure: JsonParams
  219. //
  220. //-----------------------------------------------------
  221. void Alienz::JsonParams( bool bTo, json_t *root)
  222. {
  223. JsonDataInt( bTo, "m_Seed", root, &m_Seed, 1 );
  224. }
  225. //-----------------------------------------------------
  226. // Procedure: toJson
  227. //
  228. //-----------------------------------------------------
  229. json_t *Alienz::toJson()
  230. {
  231. json_t *root = json_object();
  232. if( !root )
  233. return NULL;
  234. JsonParams( TOJSON, root );
  235. return root;
  236. }
  237. //-----------------------------------------------------
  238. // Procedure: fromJson
  239. //
  240. //-----------------------------------------------------
  241. void Alienz::fromJson( json_t *root )
  242. {
  243. //char strVal[ 10 ] = {};
  244. JsonParams( FROMJSON, root );
  245. ChangeSeedPending( m_Seed );
  246. //sprintf( strVal, "x%.2f", speeds[ (int)params[ PARAM_SPEED ].value ] );
  247. //m_pTextLabel2->text = strVal;
  248. }
  249. //-----------------------------------------------------
  250. // Procedure: onCreate
  251. //
  252. //-----------------------------------------------------
  253. void Alienz::onCreate()
  254. {
  255. }
  256. //-----------------------------------------------------
  257. // Procedure: onDelete
  258. //
  259. //-----------------------------------------------------
  260. void Alienz::onDelete()
  261. {
  262. }
  263. //-----------------------------------------------------
  264. // Procedure: onReset
  265. //
  266. //-----------------------------------------------------
  267. void Alienz::onReset()
  268. {
  269. }
  270. //-----------------------------------------------------
  271. // Procedure: onRandomize
  272. //
  273. //-----------------------------------------------------
  274. void Alienz::onRandomize()
  275. {
  276. ChangeSeedPending( (int)randomu32() );
  277. }
  278. //-----------------------------------------------------
  279. // Procedure: getseed
  280. //
  281. //-----------------------------------------------------
  282. int Alienz::getseed( void )
  283. {
  284. int seed = 0, shift= 1;;
  285. for( int i = 0; i < 32; i++ )
  286. {
  287. if( m_pButtonSeed[ i ]->m_bOn )
  288. seed |= shift;
  289. shift<<=1;
  290. }
  291. return seed;
  292. }
  293. //-----------------------------------------------------
  294. // Procedure: putseed
  295. //
  296. //-----------------------------------------------------
  297. void Alienz::putseed( int seed )
  298. {
  299. m_Seed = seed;
  300. init_rand( seed );
  301. putx( seed );
  302. for( int i = 0; i < 32; i++ )
  303. {
  304. m_pButtonSeed[ i ]->Set( (bool)(seed & 1) );
  305. seed>>=1;
  306. }
  307. }
  308. //-----------------------------------------------------
  309. // Procedure: ChangeSeedPending
  310. //
  311. //-----------------------------------------------------
  312. void Alienz::ChangeSeedPending( int seed )
  313. {
  314. m_FadeState = FADE_OUT;
  315. putseed( seed );
  316. }
  317. //-----------------------------------------------------
  318. // Procedure: RandWave
  319. //-----------------------------------------------------
  320. void Alienz::RandWave( EnvelopeData *pEnv, float min, float max )
  321. {
  322. int i;
  323. for( i = 0; i < ENVELOPE_HANDLES - 1; i++ )
  324. pEnv->setVal( i, frand_mm( min, max ) );
  325. pEnv->setVal( i, pEnv->m_HandleVal[ 0 ] );
  326. }
  327. //-----------------------------------------------------
  328. // Procedure: RandPresetWaveAdjust
  329. //-----------------------------------------------------
  330. void Alienz::RandPresetWaveAdjust( EnvelopeData *pEnv )
  331. {
  332. int i;
  333. float fval;
  334. if( frand_perc( 25.0f ) )
  335. {
  336. RandWave( pEnv, 0.0f, 1.0f );
  337. }
  338. else
  339. {
  340. //pEnv->Preset( (int)frand_mm( 2.0f, 7.25f) );
  341. pEnv->Preset( EnvelopeData::PRESET_SIN );
  342. for( i = 0; i < ENVELOPE_HANDLES - 1; i++ )
  343. {
  344. fval = clamp( pEnv->m_HandleVal[ i ] + frand_mm( -0.01f, 0.01f ), -1.0f, 1.0f );
  345. pEnv->setVal( i, fval );
  346. }
  347. }
  348. }
  349. //-----------------------------------------------------
  350. // Procedure: BuildWave
  351. //
  352. //-----------------------------------------------------
  353. void Alienz::BuildWave( int ch )
  354. {
  355. // modulation waveforms
  356. m_mod[ ch ][ MOD_LEVEL ].Init( EnvelopeData::MODE_LOOP, EnvelopeData::RANGE_0to1, false, 1.0f );
  357. m_finc[ ch ][ MOD_LEVEL ] = 1.0f / frand_mm( 14.5f, 38.0f );
  358. if( ch == 0 )
  359. RandWave( &m_mod[ ch ][ MOD_LEVEL ], 0.8f, 0.9f );
  360. else
  361. RandWave( &m_mod[ ch ][ MOD_LEVEL ], 0.1f, 0.4f );
  362. m_mod[ ch ][ MOD_REZ ].Init( EnvelopeData::MODE_LOOP, EnvelopeData::RANGE_0to1, false, 1.0f );
  363. m_finc[ ch ][ MOD_REZ ] = 1.0f / frand_mm( 14.5f, 38.0f );
  364. RandWave( &m_mod[ ch ][ MOD_REZ ], 0.9f, 1.0f );
  365. }
  366. //-----------------------------------------------------
  367. // Procedure: BuildDrone
  368. //
  369. //-----------------------------------------------------
  370. int bauds[ 4 ] = { 2400, 4800, 9600, 19200 };
  371. void Alienz::BuildDrone( void )
  372. {
  373. int ch, i;
  374. int byte;
  375. int bit;
  376. init_rand( m_Seed );
  377. for( ch = 0; ch < nCHANNELS; ch++ )
  378. {
  379. BuildWave( ch );
  380. ChangeFilterCutoff( ch, frand_mm( 0.1, 0.5 ) );
  381. }
  382. //set up osc
  383. m_bitosc.baud = bauds[ srand() & 3 ];
  384. m_bitosc.finc = engineGetSampleRate() / frand_mm( 100.0f, 400.0f );
  385. m_bitosc.fcount = 0.0f;
  386. m_bitosc.fout = 0.0f;
  387. for( i= 0; i < nBITS; i+=8 )
  388. {
  389. byte = (int)frand_mm( (float)0x20, (float)0x80 );
  390. for( bit = 0; bit < 8; bit++ )
  391. {
  392. m_bitosc.bits[ i + bit ] = (byte >> bit) & 1;
  393. }
  394. }
  395. // osc 2
  396. m_osc2.Init( EnvelopeData::MODE_LOOP, EnvelopeData::RANGE_n1to1, false, 1.0f );
  397. m_osc2.Preset( EnvelopeData::PRESET_TRI_FULL );
  398. for( i = 0; i < OSC2_NOTES; i++ )
  399. m_osc2notes[ i ] = frand_mm( 3.0f, 6.0f );
  400. m_osc2freq = engineGetSampleRate() / frand_mm( 60.0f, 90.0f );
  401. m_bInitialized = true;
  402. }
  403. //-----------------------------------------------------
  404. // Procedure: putf
  405. //
  406. //-----------------------------------------------------
  407. void Alienz::putf( float fval )
  408. {
  409. char strVal[ 10 ] = {};
  410. sprintf( strVal, "%.3f", fval );
  411. m_pTextLabel->text = strVal;
  412. }
  413. //-----------------------------------------------------
  414. // Procedure: putf
  415. //
  416. //-----------------------------------------------------
  417. void Alienz::putx( int x )
  418. {
  419. char strVal[ 10 ] = {};
  420. sprintf( strVal, "%.8X", x );
  421. m_pTextLabel->text = strVal;
  422. }
  423. //-----------------------------------------------------
  424. // Procedure: ChangeFilterCutoff
  425. //
  426. //-----------------------------------------------------
  427. void Alienz::ChangeFilterCutoff( int ch, float f )
  428. {
  429. float fx, fx2, fx3, fx5, fx7, cutfreq;
  430. FILTER_STRUCT *pf;
  431. pf = &m_filter[ ch ];
  432. cutfreq = f;
  433. // clamp at 1.0 and 20/samplerate
  434. cutfreq = fmax(cutfreq, 20 / engineGetSampleRate());
  435. cutfreq = fmin(cutfreq, 1.0);
  436. // calculate eq rez freq
  437. fx = 3.141592 * (cutfreq * 0.026315789473684210526315789473684) * 2 * 3.141592;
  438. fx2 = fx*fx;
  439. fx3 = fx2*fx;
  440. fx5 = fx3*fx2;
  441. fx7 = fx5*fx2;
  442. pf->f = 2.0 * (fx
  443. - (fx3 * 0.16666666666666666666666666666667)
  444. + (fx5 * 0.0083333333333333333333333333333333)
  445. - (fx7 * 0.0001984126984126984126984126984127));
  446. }
  447. //-----------------------------------------------------
  448. // Procedure: Filter
  449. //
  450. //-----------------------------------------------------
  451. #define MULTI (0.33333333333333333333333333333333f)
  452. void Alienz::processFilter( int ch, float *pIn )
  453. {
  454. float rez, hp1;
  455. float input, lowpass, bandpass, highpass;
  456. FILTER_STRUCT *pf;
  457. rez = 1.0 - m_fval[ ch ][ MOD_REZ ];
  458. pf = &m_filter[ ch ];
  459. input = *pIn;
  460. input = input + 0.000000001;
  461. pf->lp1 = pf->lp1 + pf->f * pf->bp1;
  462. hp1 = input - pf->lp1 - rez * pf->bp1;
  463. pf->bp1 = pf->f * hp1 + pf->bp1;
  464. lowpass = pf->lp1;
  465. highpass = hp1;
  466. bandpass = pf->bp1;
  467. pf->lp1 = pf->lp1 + pf->f * pf->bp1;
  468. hp1 = input - pf->lp1 - rez * pf->bp1;
  469. pf->bp1 = pf->f * hp1 + pf->bp1;
  470. lowpass = lowpass + pf->lp1;
  471. highpass = highpass + hp1;
  472. bandpass = bandpass + pf->bp1;
  473. input = input - 0.000000001;
  474. pf->lp1 = pf->lp1 + pf->f * pf->bp1;
  475. hp1 = input - pf->lp1 - rez * pf->bp1;
  476. pf->bp1 = pf->f * hp1 + pf->bp1;
  477. lowpass = (lowpass + pf->lp1) * MULTI;
  478. highpass = (highpass + hp1) * MULTI;
  479. bandpass = (bandpass + pf->bp1) * MULTI;
  480. /*switch( pf->type )
  481. {
  482. case FILTER_LP:
  483. out = lowpass;
  484. break;
  485. case FILTER_HP:
  486. out = highpass;
  487. break;
  488. case FILTER_BP:
  489. out = bandpass;
  490. break;
  491. case FILTER_NT:
  492. out = lowpass + highpass;
  493. break;
  494. default:
  495. return;
  496. }*/
  497. *pIn = lowpass;
  498. }
  499. //-----------------------------------------------------
  500. // Procedure: step
  501. //
  502. //-----------------------------------------------------
  503. void Alienz::step()
  504. {
  505. float In = 0.0f, fout;
  506. int i, ch;
  507. static int bcount = 0, note = 0, fcount = 0;
  508. if( !m_bInitialized )
  509. return;
  510. // randomize trigger
  511. if( m_SchmitTrigRand.process( inputs[ IN_RANDTRIG ].normalize( 0.0f ) ) )
  512. {
  513. m_pButtonRand->Set( true );
  514. ChangeSeedPending( (int)randomu32() );
  515. }
  516. switch( m_FadeState )
  517. {
  518. case FADE_OUT:
  519. m_fFade -= 0.0005f;
  520. if( m_fFade <= 0.0f )
  521. {
  522. m_fFade = 0.0f;
  523. BuildDrone();
  524. m_FadeState = FADE_IN;
  525. }
  526. break;
  527. case FADE_IN:
  528. m_fFade += 0.0005f;
  529. if( m_fFade >= 1.0f )
  530. {
  531. m_fFade = 1.0f;
  532. m_FadeState = FADE_IDLE;
  533. }
  534. break;
  535. case FADE_IDLE:
  536. default:
  537. break;
  538. }
  539. if( inputs[ IN_GATE ].active )
  540. {
  541. if( inputs[ IN_GATE ].value < 0.000001 )
  542. {
  543. outputs[ OUT ].value= 0.0f;
  544. return;
  545. }
  546. }
  547. // process oscillators
  548. for( ch = 0; ch < nCHANNELS; ch++ )
  549. {
  550. // process modulation waves
  551. for( i = 0; i < nMODS; i++ )
  552. {
  553. m_mod[ ch ][ i ].m_Clock.syncInc = m_finc[ ch ][ i ] * speeds[ (int)params[ PARAM_SPEED ].value ];
  554. m_fval[ ch ][ i ] = m_mod[ ch ][ i ].procStep( false, false );
  555. }
  556. }
  557. m_bitosc.fcount -= 1.0f;
  558. // change
  559. if( m_bitosc.fcount <= 0.0f )
  560. {
  561. m_bitosc.fcount += m_bitosc.finc;
  562. if( m_bitosc.state == 2 )
  563. m_bitosc.state = m_bitosc.bits[ ( bcount++ ) & (nBITS - 1) ];
  564. else
  565. m_bitosc.state = 2;
  566. switch( m_bitosc.state )
  567. {
  568. case 0:
  569. m_bitosc.fout = -0.7f;
  570. break;
  571. case 1:
  572. m_bitosc.fout = 0.7f;
  573. break;
  574. case 2:
  575. m_bitosc.fout = 0.0f;
  576. break;
  577. }
  578. }
  579. In = m_bitosc.fout;
  580. processFilter( 0, &In );
  581. // osc2
  582. fcount -= 1.0f;
  583. // change
  584. if( fcount <= 0.0f )
  585. {
  586. fcount += m_osc2freq;
  587. if( ++note >= OSC2_NOTES )
  588. note = 0;
  589. m_osc2.m_Clock.syncInc = 32.7032f * clamp( powf( 2.0f, m_osc2notes[ note ] ), 0.0f, 4186.01f );
  590. }
  591. fout = m_osc2.procStep( false, false );
  592. processFilter( 1, &fout );
  593. fout *= AUDIO_MAX * m_fval[ 1 ][ MOD_LEVEL ];
  594. fout += In * m_fval[ 0 ][ MOD_LEVEL ] * AUDIO_MAX;
  595. outputs[ OUT ].value = fout * m_fFade;
  596. }
  597. } // namespace rack_plugin_mscHack
  598. using namespace rack_plugin_mscHack;
  599. RACK_PLUGIN_MODEL_INIT(mscHack, Alienz) {
  600. Model *modelAlienz = Model::create<Alienz, Alienz_Widget>( "mscHack", "Alienz", "Alienz module", OSCILLATOR_TAG, MULTIPLE_TAG );
  601. return modelAlienz;
  602. }