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.

670 lines
16KB

  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 3
  7. #define CHANNEL_H 90
  8. #define CHANNEL_Y 65
  9. #define CHANNEL_X 10
  10. #define freqMAX 300.0f
  11. #define ADS_MAX_TIME_SECONDS 0.5f
  12. #define WAVE_BUFFER_LEN ( 192000 / 20 ) // (9600) based on quality for 20Hz at max sample rate 192000
  13. typedef struct
  14. {
  15. int state;
  16. int a, s, r;
  17. int acount, scount, rcount, fadecount;
  18. float fainc, fsinc, frinc, fadeinc;
  19. float out;
  20. bool bTrig;
  21. }ASR_STRUCT;
  22. typedef struct
  23. {
  24. int wavetype;
  25. // wave
  26. float phase;
  27. //filter
  28. float q, f;
  29. bool bHighpass;
  30. float lp1, bp1;
  31. float hpIn;
  32. float lpIn;
  33. float mpIn;
  34. // ads
  35. ASR_STRUCT adsr_wave;
  36. ASR_STRUCT adsr_freq;
  37. }OSC_PARAM_STRUCT;
  38. //-----------------------------------------------------
  39. // Module Definition
  40. //
  41. //-----------------------------------------------------
  42. struct SynthDrums : Module
  43. {
  44. enum WaveTypes
  45. {
  46. WAVE_SIN,
  47. WAVE_TRI,
  48. WAVE_SQR,
  49. WAVE_SAW,
  50. WAVE_NOISE,
  51. nWAVEFORMS
  52. };
  53. enum ParamIds
  54. {
  55. PARAM_FREQ,
  56. PARAM_ATT = PARAM_FREQ + nCHANNELS,
  57. PARAM_REL = PARAM_ATT + nCHANNELS,
  58. PARAM_REZ = PARAM_REL + nCHANNELS,
  59. PARAM_WAVES = PARAM_REZ + nCHANNELS,
  60. nPARAMS = PARAM_WAVES + (nWAVEFORMS * nCHANNELS)
  61. };
  62. enum InputIds
  63. {
  64. IN_LEVEL,
  65. IN_TRIG = IN_LEVEL + nCHANNELS,
  66. IN_FREQ_MOD = IN_TRIG + nCHANNELS,
  67. nINPUTS = IN_FREQ_MOD + nCHANNELS
  68. };
  69. enum OutputIds
  70. {
  71. OUTPUT_AUDIO,
  72. nOUTPUTS = OUTPUT_AUDIO + nCHANNELS
  73. };
  74. enum ADSRSTATES
  75. {
  76. ADSR_OFF,
  77. ADSR_FADE,
  78. ADSR_ON,
  79. ADSR_ATTACK,
  80. ADSR_SUSTAIN,
  81. ADSR_RELEASE
  82. };
  83. CLog lg;
  84. SchmittTrigger m_SchTrig[ nCHANNELS ];
  85. OSC_PARAM_STRUCT m_Wave[ nCHANNELS ] = {};
  86. MyLEDButtonStrip *m_pButtonWaveSelect[ nCHANNELS ] = {};
  87. // waveforms
  88. float m_BufferWave[ nWAVEFORMS ][ WAVE_BUFFER_LEN ] = {};
  89. // Contructor
  90. SynthDrums() : Module( nPARAMS, nINPUTS, nOUTPUTS, 0 ){}
  91. //-----------------------------------------------------
  92. // MyParamKnob
  93. //-----------------------------------------------------
  94. struct MyParamFreq : Knob_Yellow2_26
  95. {
  96. SynthDrums *mymodule;
  97. int param;
  98. void onChange( EventChange &e ) override
  99. {
  100. mymodule = (SynthDrums*)module;
  101. if( mymodule )
  102. {
  103. param = paramId - SynthDrums::PARAM_FREQ;
  104. if( mymodule->m_Wave[ param ].wavetype == WAVE_NOISE )
  105. mymodule->ChangeFilterCutoff( param, value );
  106. else
  107. mymodule->ChangeFilterCutoff( param, 0.6 );
  108. }
  109. RoundKnob::onChange( e );
  110. }
  111. };
  112. // Overrides
  113. void step() override;
  114. json_t* toJson() override;
  115. void fromJson(json_t *rootJ) override;
  116. void onRandomize() override;
  117. void onReset() override;
  118. void SetWaveLights( void );
  119. void BuildWaves( void );
  120. void ChangeFilterCutoff( int ch, float cutfreq );
  121. float Filter( int ch, float in, bool bHighPass );
  122. float GetWave( int type, float phase );
  123. float ProcessADS( int ch, bool bWave );
  124. float GetAudio( int ch );
  125. };
  126. //-----------------------------------------------------
  127. // SynthDrums_WaveSelect
  128. //-----------------------------------------------------
  129. void SynthDrums_WaveSelect( void *pClass, int id, int nbutton, bool bOn )
  130. {
  131. SynthDrums *mymodule;
  132. mymodule = (SynthDrums*)pClass;
  133. mymodule->m_Wave[ id ].wavetype = nbutton;
  134. }
  135. //-----------------------------------------------------
  136. // Procedure:
  137. //
  138. //-----------------------------------------------------
  139. json_t *SynthDrums::toJson()
  140. {
  141. json_t *gatesJ;
  142. json_t *rootJ = json_object();
  143. // wavetypes
  144. gatesJ = json_array();
  145. for (int i = 0; i < nCHANNELS; i++)
  146. {
  147. json_t *gateJ = json_integer( m_Wave[ i ].wavetype );
  148. json_array_append_new( gatesJ, gateJ );
  149. }
  150. json_object_set_new( rootJ, "wavetypes", gatesJ );
  151. return rootJ;
  152. }
  153. //-----------------------------------------------------
  154. // Procedure: fromJson
  155. //
  156. //-----------------------------------------------------
  157. void SynthDrums::fromJson(json_t *rootJ)
  158. {
  159. int i;
  160. json_t *StepsJ;
  161. // wave select
  162. StepsJ = json_object_get( rootJ, "wavetypes" );
  163. if (StepsJ)
  164. {
  165. for ( i = 0; i < nCHANNELS; i++)
  166. {
  167. json_t *gateJ = json_array_get(StepsJ, i);
  168. if (gateJ)
  169. m_Wave[ i ].wavetype = json_integer_value( gateJ );
  170. }
  171. }
  172. SetWaveLights();
  173. }
  174. //-----------------------------------------------------
  175. // Procedure: Widget
  176. //
  177. //-----------------------------------------------------
  178. struct SynthDrums_Widget : ModuleWidget {
  179. SynthDrums_Widget( SynthDrums *module );
  180. };
  181. SynthDrums_Widget::SynthDrums_Widget( SynthDrums *module ) : ModuleWidget(module)
  182. {
  183. int ch, x, y;
  184. box.size = Vec( 15*11, 380);
  185. {
  186. SVGPanel *panel = new SVGPanel();
  187. panel->box.size = box.size;
  188. panel->setBackground(SVG::load(assetPlugin(plugin, "res/SynthDrums.svg")));
  189. addChild(panel);
  190. }
  191. //module->lg.Open("SynthDrums.txt");
  192. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  193. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0)));
  194. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  195. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365)));
  196. y = CHANNEL_Y;
  197. x = CHANNEL_X;
  198. for( ch = 0; ch < nCHANNELS; ch++ )
  199. {
  200. x = CHANNEL_X;
  201. // IN_FREQ_MOD
  202. addInput(Port::create<MyPortInSmall>( Vec( x + 48, y ), Port::INPUT, module, SynthDrums::IN_FREQ_MOD + ch ) );
  203. // inputs
  204. addInput(Port::create<MyPortInSmall>( Vec( x, y ), Port::INPUT, module, SynthDrums::IN_LEVEL + ch ) );
  205. y += 43;
  206. addInput(Port::create<MyPortInSmall>( Vec( x, y ), Port::INPUT, module, SynthDrums::IN_TRIG + ch ) );
  207. x += 32;
  208. y += 7;
  209. // wave select buttons
  210. module->m_pButtonWaveSelect[ ch ] = new MyLEDButtonStrip( x, y, 11, 11, 5, 8.0, 5, false, DWRGB( 180, 180, 180 ), DWRGB( 255, 255, 0 ), MyLEDButtonStrip::TYPE_EXCLUSIVE, ch, module, SynthDrums_WaveSelect );
  211. addChild( module->m_pButtonWaveSelect[ ch ] );
  212. x = CHANNEL_X + 25;
  213. y -= 34;
  214. // params
  215. addParam(ParamWidget::create<SynthDrums::MyParamFreq>( Vec( x, y ), module, SynthDrums::PARAM_FREQ + ch, 0.0, 1.0, 0.0 ) );
  216. x += 34;
  217. addParam(ParamWidget::create<Knob_Yellow2_26>( Vec( x, y ), module, SynthDrums::PARAM_ATT + ch, 0.0, 0.1, 0.0 ) );
  218. x += 34;
  219. addParam(ParamWidget::create<Knob_Yellow2_26>( Vec( x, y ), module, SynthDrums::PARAM_REL + ch, 0.0, 1.0, 0.0 ) );
  220. y -= 15;
  221. x += 34;
  222. // outputs
  223. addOutput(Port::create<MyPortOutSmall>( Vec( x, y ), Port::OUTPUT, module, SynthDrums::OUTPUT_AUDIO + ch ) );
  224. y += CHANNEL_H;
  225. }
  226. module->BuildWaves();
  227. module->ChangeFilterCutoff( 0, 0.6 );
  228. module->ChangeFilterCutoff( 1, 0.6 );
  229. module->ChangeFilterCutoff( 2, 0.6 );
  230. module->SetWaveLights();
  231. }
  232. //-----------------------------------------------------
  233. // Procedure: reset
  234. //
  235. //-----------------------------------------------------
  236. void SynthDrums::onReset()
  237. {
  238. }
  239. //-----------------------------------------------------
  240. // Procedure: randomize
  241. //
  242. //-----------------------------------------------------
  243. void SynthDrums::onRandomize()
  244. {
  245. int ch;
  246. for( ch = 0; ch < nCHANNELS; ch++ )
  247. {
  248. m_Wave[ ch ].wavetype = (int)( randomUniform() * (nWAVEFORMS-1) );
  249. }
  250. SetWaveLights();
  251. }
  252. //-----------------------------------------------------
  253. // Procedure: SetWaveLights
  254. //
  255. //-----------------------------------------------------
  256. void SynthDrums::SetWaveLights( void )
  257. {
  258. int ch;
  259. for( ch = 0; ch < nCHANNELS; ch++ )
  260. m_pButtonWaveSelect[ ch ]->Set( m_Wave[ ch ].wavetype, true );
  261. }
  262. //-----------------------------------------------------
  263. // Procedure: initialize
  264. //
  265. //-----------------------------------------------------
  266. //#define DEG2RAD( x ) ( ( x ) * ( 3.14159f / 180.0f ) )
  267. void SynthDrums::BuildWaves( void )
  268. {
  269. int i;
  270. float finc, pos, val;
  271. finc = 360.0 / WAVE_BUFFER_LEN;
  272. pos = 0;
  273. // create sin wave
  274. for( i = 0; i < WAVE_BUFFER_LEN; i++ )
  275. {
  276. m_BufferWave[ WAVE_SIN ][ i ] = sin( DEG2RAD( pos ) );
  277. pos += finc;
  278. }
  279. // create sqr wave
  280. for( i = 0; i < WAVE_BUFFER_LEN; i++ )
  281. {
  282. if( i < WAVE_BUFFER_LEN / 2 )
  283. m_BufferWave[ WAVE_SQR ][ i ] = 1.0;
  284. else
  285. m_BufferWave[ WAVE_SQR ][ i ] = -1.0;
  286. }
  287. finc = 2.0 / (float)WAVE_BUFFER_LEN;
  288. val = 1.0;
  289. // create saw wave
  290. for( i = 0; i < WAVE_BUFFER_LEN; i++ )
  291. {
  292. m_BufferWave[ WAVE_SAW ][ i ] = val;
  293. val -= finc;
  294. }
  295. finc = 4 / (float)WAVE_BUFFER_LEN;
  296. val = 0;
  297. // create tri wave
  298. for( i = 0; i < WAVE_BUFFER_LEN; i++ )
  299. {
  300. m_BufferWave[ WAVE_TRI ][ i ] = val;
  301. if( i < WAVE_BUFFER_LEN / 4 )
  302. val += finc;
  303. else if( i < (WAVE_BUFFER_LEN / 4) * 3 )
  304. val -= finc;
  305. else if( i < WAVE_BUFFER_LEN )
  306. val += finc;
  307. }
  308. }
  309. //-----------------------------------------------------
  310. // Procedure: GetAudio
  311. //
  312. //-----------------------------------------------------
  313. float SynthDrums::GetWave( int type, float phase )
  314. {
  315. float fval = 0.0;
  316. float ratio = (float)(WAVE_BUFFER_LEN-1) / engineGetSampleRate();
  317. switch( type )
  318. {
  319. case WAVE_SIN:
  320. case WAVE_TRI:
  321. case WAVE_SQR:
  322. case WAVE_SAW:
  323. fval = m_BufferWave[ type ][ int( ( phase * ratio ) + 0.5 ) ];
  324. break;
  325. case WAVE_NOISE:
  326. fval = ( randomUniform() > 0.5 ) ? (randomUniform() * -1.0) : randomUniform();
  327. break;
  328. default:
  329. break;
  330. }
  331. return fval;
  332. }
  333. //-----------------------------------------------------
  334. // Procedure: ProcessADS
  335. //
  336. //-----------------------------------------------------
  337. float SynthDrums::ProcessADS( int ch, bool bWave )
  338. {
  339. ASR_STRUCT *pasr;
  340. if( bWave )
  341. pasr = &m_Wave[ ch ].adsr_wave;
  342. else
  343. pasr = &m_Wave[ ch ].adsr_freq;
  344. // rettrig the adsr
  345. if( pasr->bTrig )
  346. {
  347. pasr->state = ADSR_FADE;
  348. pasr->fadecount = 900;
  349. pasr->fadeinc = pasr->out / (float)pasr->fadecount;
  350. pasr->acount = 20;
  351. pasr->fainc = 1.0 / pasr->acount;
  352. pasr->scount = 0;//(int)(.1 * engineGetSampleRate());
  353. pasr->fsinc = 0;//1.0 / pasr->scount;
  354. if( bWave )
  355. {
  356. // for the wave asr the release is the waveform release
  357. pasr->rcount = (int)( params[ PARAM_REL + ch ].value * ADS_MAX_TIME_SECONDS * engineGetSampleRate() );
  358. }
  359. else
  360. {
  361. // for the wave asr the release is the hit
  362. pasr->rcount = (int)( params[ PARAM_ATT + ch ].value * ADS_MAX_TIME_SECONDS * engineGetSampleRate() );
  363. }
  364. if( pasr->rcount )
  365. pasr->frinc = 1.0 / pasr->rcount;
  366. pasr->bTrig = false;
  367. }
  368. // process
  369. switch( pasr->state )
  370. {
  371. case ADSR_FADE:
  372. if( --pasr->fadecount <= 0 )
  373. {
  374. pasr->state = ADSR_ATTACK;
  375. pasr->out = 0.0f;
  376. m_Wave[ ch ].phase = 0.0;
  377. }
  378. else
  379. {
  380. pasr->out -= pasr->fadeinc;
  381. }
  382. break;
  383. case ADSR_OFF:
  384. pasr->out = 0.0;
  385. break;
  386. case ADSR_ATTACK:
  387. if( --pasr->acount <= 0 )
  388. {
  389. pasr->state = ADSR_SUSTAIN;
  390. }
  391. else
  392. {
  393. pasr->out += pasr->fainc;
  394. }
  395. break;
  396. case ADSR_SUSTAIN:
  397. pasr->out = 1.0;
  398. if( --pasr->scount <= 0 )
  399. {
  400. pasr->state = ADSR_RELEASE;
  401. }
  402. break;
  403. case ADSR_RELEASE:
  404. if( --pasr->rcount <= 0 )
  405. {
  406. pasr->out = 0.0f;
  407. pasr->state = ADSR_OFF;
  408. }
  409. else
  410. {
  411. pasr->out -= pasr->frinc;
  412. }
  413. break;
  414. }
  415. return clamp( pasr->out, 0.0f, 1.0f );
  416. }
  417. //-----------------------------------------------------
  418. // Procedure: ChangeFilterCutoff
  419. //
  420. //-----------------------------------------------------
  421. void SynthDrums::ChangeFilterCutoff( int ch, float cutfreq )
  422. {
  423. float fx, fx2, fx3, fx5, fx7;
  424. // clamp at 1.0 and 20/samplerate
  425. cutfreq = fmax(cutfreq, 20 / engineGetSampleRate());
  426. cutfreq = fmin(cutfreq, 1.0);
  427. // calculate eq rez freq
  428. fx = 3.141592 * (cutfreq * 0.026315789473684210526315789473684) * 2 * 3.141592;
  429. fx2 = fx*fx;
  430. fx3 = fx2*fx;
  431. fx5 = fx3*fx2;
  432. fx7 = fx5*fx2;
  433. m_Wave[ ch ].f = 2.0 * (fx
  434. - (fx3 * 0.16666666666666666666666666666667)
  435. + (fx5 * 0.0083333333333333333333333333333333)
  436. - (fx7 * 0.0001984126984126984126984126984127));
  437. }
  438. //-----------------------------------------------------
  439. // Procedure: Filter
  440. //
  441. //-----------------------------------------------------
  442. #define MULTI (0.33333333333333333333333333333333f)
  443. float SynthDrums::Filter( int ch, float in, bool bHighPass )
  444. {
  445. OSC_PARAM_STRUCT *p;
  446. float rez, hp1;
  447. float lowpass, highpass;
  448. p = &m_Wave[ ch ];
  449. rez = 1.00;//1.00 - p->q;
  450. in = in + 0.000000001;
  451. p->lp1 = p->lp1 + p->f * p->bp1;
  452. hp1 = in - p->lp1 - rez * p->bp1;
  453. p->bp1 = p->f * hp1 + p->bp1;
  454. lowpass = p->lp1;
  455. highpass = hp1;
  456. //bandpass = p->bp1;
  457. p->lp1 = p->lp1 + p->f * p->bp1;
  458. hp1 = in - p->lp1 - rez * p->bp1;
  459. p->bp1 = p->f * hp1 + p->bp1;
  460. lowpass = lowpass + p->lp1;
  461. highpass = highpass + hp1;
  462. //bandpass = bandpass + p->bp1;
  463. in = in - 0.000000001;
  464. p->lp1 = p->lp1 + p->f * p->bp1;
  465. hp1 = in - p->lp1 - rez * p->bp1;
  466. p->bp1 = p->f * hp1 + p->bp1;
  467. lowpass = (lowpass + p->lp1) * MULTI;
  468. highpass = (highpass + hp1) * MULTI;
  469. //bandpass = (bandpass + p->bp1) * MULTI;
  470. if( bHighPass )
  471. return highpass;
  472. return lowpass;
  473. }
  474. //-----------------------------------------------------
  475. // Procedure: GetAudio
  476. //
  477. //-----------------------------------------------------
  478. float SynthDrums::GetAudio( int ch )
  479. {
  480. float fout = 0, fenv = 0.0, freq, freqmod;
  481. if( outputs[ OUTPUT_AUDIO + ch ].active )
  482. {
  483. freqmod = clamp( inputs[ IN_FREQ_MOD + ch ].value / CV_MAX, 0.0f, 1.0f );
  484. // process our second envelope for hit
  485. fenv = ProcessADS( ch, false );
  486. // if noise then frequency affects the filter cutoff and not the wave frequency
  487. if( m_Wave[ ch ].wavetype == WAVE_NOISE )
  488. {
  489. freq = clamp( ( ( freqmod + params[ PARAM_FREQ + ch ].value ) + (fenv*2) ), 0.0f, 1.0f );
  490. ChangeFilterCutoff( ch, freq );
  491. }
  492. // other signals the second ADS affects the frequency for the hit
  493. else
  494. {
  495. m_Wave[ ch ].phase += 35 + ( ( freqmod + params[ PARAM_FREQ + ch ].value ) * freqMAX ) + ( fenv * 400.0f );
  496. if( m_Wave[ ch ].phase >= engineGetSampleRate() )
  497. m_Wave[ ch ].phase = m_Wave[ ch ].phase - engineGetSampleRate();
  498. }
  499. fout = ProcessADS( ch, true ) * GetWave( m_Wave[ ch ].wavetype, m_Wave[ ch ].phase );
  500. fout = Filter( ch, fout, ( m_Wave[ ch ].wavetype == WAVE_NOISE ) );
  501. }
  502. return fout;
  503. }
  504. //-----------------------------------------------------
  505. // Procedure: step
  506. //
  507. //-----------------------------------------------------
  508. void SynthDrums::step()
  509. {
  510. int ch;
  511. // check for triggers
  512. for( ch = 0; ch < nCHANNELS; ch++ )
  513. {
  514. if( inputs[ IN_TRIG + ch ].active )
  515. {
  516. if( m_SchTrig[ ch ].process( inputs[ IN_TRIG + ch ].value ) )
  517. {
  518. m_Wave[ ch ].adsr_freq.bTrig = true;
  519. m_Wave[ ch ].adsr_wave.bTrig = true;
  520. }
  521. }
  522. }
  523. // process sounds
  524. outputs[ OUTPUT_AUDIO + 0 ].value = GetAudio( 0 ) * AUDIO_MAX * clamp( (inputs[ IN_LEVEL + 0 ].value / CV_MAX), 0.0f, 1.0f );
  525. outputs[ OUTPUT_AUDIO + 1 ].value = GetAudio( 1 ) * AUDIO_MAX * clamp( (inputs[ IN_LEVEL + 1 ].value / CV_MAX), 0.0f, 1.0f );
  526. outputs[ OUTPUT_AUDIO + 2 ].value = GetAudio( 2 ) * AUDIO_MAX * clamp( (inputs[ IN_LEVEL + 2 ].value / CV_MAX), 0.0f, 1.0f );
  527. }
  528. } // namespace rack_plugin_mscHack
  529. using namespace rack_plugin_mscHack;
  530. RACK_PLUGIN_MODEL_INIT(mscHack, SynthDrums) {
  531. Model *modelSynthDrums = Model::create<SynthDrums, SynthDrums_Widget>( "mscHack", "SynthDrums", "SYNTH Drums", DRUM_TAG, MULTIPLE_TAG );
  532. return modelSynthDrums;
  533. }