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.

647 lines
15KB

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