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.

675 lines
22KB

  1. #include "plugin.hpp"
  2. #include "marbles/random/random_generator.h"
  3. #include "marbles/random/random_stream.h"
  4. #include "marbles/random/t_generator.h"
  5. #include "marbles/random/x_y_generator.h"
  6. #include "marbles/note_filter.h"
  7. static const int BLOCK_SIZE = 5;
  8. static const marbles::Scale preset_scales[6] = {
  9. // C major
  10. {
  11. 1.0f,
  12. 12,
  13. {
  14. { 0.0000f, 255 }, // C
  15. { 0.0833f, 16 }, // C#
  16. { 0.1667f, 96 }, // D
  17. { 0.2500f, 24 }, // D#
  18. { 0.3333f, 128 }, // E
  19. { 0.4167f, 64 }, // F
  20. { 0.5000f, 8 }, // F#
  21. { 0.5833f, 192 }, // G
  22. { 0.6667f, 16 }, // G#
  23. { 0.7500f, 96 }, // A
  24. { 0.8333f, 24 }, // A#
  25. { 0.9167f, 128 }, // B
  26. }
  27. },
  28. // C minor
  29. {
  30. 1.0f,
  31. 12,
  32. {
  33. { 0.0000f, 255 }, // C
  34. { 0.0833f, 16 }, // C#
  35. { 0.1667f, 96 }, // D
  36. { 0.2500f, 128 }, // Eb
  37. { 0.3333f, 8 }, // E
  38. { 0.4167f, 64 }, // F
  39. { 0.5000f, 4 }, // F#
  40. { 0.5833f, 192 }, // G
  41. { 0.6667f, 16 }, // G#
  42. { 0.7500f, 96 }, // A
  43. { 0.8333f, 128 }, // Bb
  44. { 0.9167f, 16 }, // B
  45. }
  46. },
  47. // Pentatonic
  48. {
  49. 1.0f,
  50. 12,
  51. {
  52. { 0.0000f, 255 }, // C
  53. { 0.0833f, 4 }, // C#
  54. { 0.1667f, 96 }, // D
  55. { 0.2500f, 4 }, // Eb
  56. { 0.3333f, 4 }, // E
  57. { 0.4167f, 140 }, // F
  58. { 0.5000f, 4 }, // F#
  59. { 0.5833f, 192 }, // G
  60. { 0.6667f, 4 }, // G#
  61. { 0.7500f, 96 }, // A
  62. { 0.8333f, 4 }, // Bb
  63. { 0.9167f, 4 }, // B
  64. }
  65. },
  66. // Pelog
  67. {
  68. 1.0f,
  69. 7,
  70. {
  71. { 0.0000f, 255 }, // C
  72. { 0.1275f, 128 }, // Db+
  73. { 0.2625f, 32 }, // Eb-
  74. { 0.4600f, 8 }, // F#-
  75. { 0.5883f, 192 }, // G
  76. { 0.7067f, 64 }, // Ab
  77. { 0.8817f, 16 }, // Bb+
  78. }
  79. },
  80. // Raag Bhairav That
  81. {
  82. 1.0f,
  83. 12,
  84. {
  85. { 0.0000f, 255 }, // ** Sa
  86. { 0.0752f, 128 }, // ** Komal Re
  87. { 0.1699f, 4 }, // Re
  88. { 0.2630f, 4 }, // Komal Ga
  89. { 0.3219f, 128 }, // ** Ga
  90. { 0.4150f, 64 }, // ** Ma
  91. { 0.4918f, 4 }, // Tivre Ma
  92. { 0.5850f, 192 }, // ** Pa
  93. { 0.6601f, 64 }, // ** Komal Dha
  94. { 0.7549f, 4 }, // Dha
  95. { 0.8479f, 4 }, // Komal Ni
  96. { 0.9069f, 64 }, // ** Ni
  97. }
  98. },
  99. // Raag Shri
  100. {
  101. 1.0f,
  102. 12,
  103. {
  104. { 0.0000f, 255 }, // ** Sa
  105. { 0.0752f, 4 }, // Komal Re
  106. { 0.1699f, 128 }, // ** Re
  107. { 0.2630f, 64 }, // ** Komal Ga
  108. { 0.3219f, 4 }, // Ga
  109. { 0.4150f, 128 }, // ** Ma
  110. { 0.4918f, 4 }, // Tivre Ma
  111. { 0.5850f, 192 }, // ** Pa
  112. { 0.6601f, 4 }, // Komal Dha
  113. { 0.7549f, 64 }, // ** Dha
  114. { 0.8479f, 128 }, // ** Komal Ni
  115. { 0.9069f, 4 }, // Ni
  116. }
  117. },
  118. };
  119. struct Marbles : Module {
  120. enum ParamIds {
  121. T_DEJA_VU_PARAM,
  122. X_DEJA_VU_PARAM,
  123. DEJA_VU_PARAM,
  124. T_RATE_PARAM,
  125. X_SPREAD_PARAM,
  126. T_MODE_PARAM,
  127. X_MODE_PARAM,
  128. DEJA_VU_LENGTH_PARAM,
  129. T_BIAS_PARAM,
  130. X_BIAS_PARAM,
  131. T_RANGE_PARAM,
  132. X_RANGE_PARAM,
  133. EXTERNAL_PARAM,
  134. T_JITTER_PARAM,
  135. X_STEPS_PARAM,
  136. NUM_PARAMS
  137. };
  138. enum InputIds {
  139. T_BIAS_INPUT,
  140. X_BIAS_INPUT,
  141. T_CLOCK_INPUT,
  142. T_RATE_INPUT,
  143. T_JITTER_INPUT,
  144. DEJA_VU_INPUT,
  145. X_STEPS_INPUT,
  146. X_SPREAD_INPUT,
  147. X_CLOCK_INPUT,
  148. NUM_INPUTS
  149. };
  150. enum OutputIds {
  151. T1_OUTPUT,
  152. T2_OUTPUT,
  153. T3_OUTPUT,
  154. Y_OUTPUT,
  155. X1_OUTPUT,
  156. X2_OUTPUT,
  157. X3_OUTPUT,
  158. NUM_OUTPUTS
  159. };
  160. enum LightIds {
  161. T_DEJA_VU_LIGHT,
  162. X_DEJA_VU_LIGHT,
  163. ENUMS(T_MODE_LIGHTS, 2),
  164. ENUMS(X_MODE_LIGHTS, 2),
  165. ENUMS(T_RANGE_LIGHTS, 2),
  166. ENUMS(X_RANGE_LIGHTS, 2),
  167. EXTERNAL_LIGHT,
  168. T1_LIGHT,
  169. T2_LIGHT,
  170. T3_LIGHT,
  171. Y_LIGHT,
  172. X1_LIGHT,
  173. X2_LIGHT,
  174. X3_LIGHT,
  175. NUM_LIGHTS
  176. };
  177. marbles::RandomGenerator random_generator;
  178. marbles::RandomStream random_stream;
  179. marbles::TGenerator t_generator;
  180. marbles::XYGenerator xy_generator;
  181. marbles::NoteFilter note_filter;
  182. // State
  183. dsp::BooleanTrigger tDejaVuTrigger;
  184. dsp::BooleanTrigger xDejaVuTrigger;
  185. dsp::BooleanTrigger tModeTrigger;
  186. dsp::BooleanTrigger xModeTrigger;
  187. dsp::BooleanTrigger tRangeTrigger;
  188. dsp::BooleanTrigger xRangeTrigger;
  189. dsp::BooleanTrigger externalTrigger;
  190. bool t_deja_vu;
  191. bool x_deja_vu;
  192. int t_mode;
  193. int x_mode;
  194. int t_range;
  195. int x_range;
  196. bool external;
  197. int x_scale;
  198. int y_divider_index;
  199. int x_clock_source_internal;
  200. // Buffers
  201. stmlib::GateFlags t_clocks[BLOCK_SIZE] = {};
  202. stmlib::GateFlags last_t_clock = 0;
  203. stmlib::GateFlags xy_clocks[BLOCK_SIZE] = {};
  204. stmlib::GateFlags last_xy_clock = 0;
  205. float ramp_master[BLOCK_SIZE] = {};
  206. float ramp_external[BLOCK_SIZE] = {};
  207. float ramp_slave[2][BLOCK_SIZE] = {};
  208. bool gates[BLOCK_SIZE * 2] = {};
  209. float voltages[BLOCK_SIZE * 4] = {};
  210. int blockIndex = 0;
  211. Marbles() {
  212. config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
  213. configButton(T_DEJA_VU_PARAM, "T deja vu");
  214. configButton(X_DEJA_VU_PARAM, "X deja vu");
  215. configParam(DEJA_VU_PARAM, 0.0, 1.0, 0.5, "Deja vu probability");
  216. configParam(T_RATE_PARAM, -1.0, 1.0, 0.0, "Clock rate");
  217. configParam(X_SPREAD_PARAM, 0.0, 1.0, 0.5, "Probability distribution");
  218. configButton(T_MODE_PARAM, "T mode");
  219. configButton(X_MODE_PARAM, "X mode");
  220. configParam(DEJA_VU_LENGTH_PARAM, 0.0, 1.0, 0.0, "Loop length");
  221. configParam(T_BIAS_PARAM, 0.0, 1.0, 0.5, "Gate bias");
  222. configParam(X_BIAS_PARAM, 0.0, 1.0, 0.5, "Distribution bias");
  223. configButton(T_RANGE_PARAM, "Clock range mode");
  224. configButton(X_RANGE_PARAM, "Output voltage range mode");
  225. configButton(EXTERNAL_PARAM, "External processing mode");
  226. configParam(T_JITTER_PARAM, 0.0, 1.0, 0.0, "Randomness amount");
  227. configParam(X_STEPS_PARAM, 0.0, 1.0, 0.5, "Smoothness");
  228. configInput(T_BIAS_INPUT, "T bias");
  229. configInput(X_BIAS_INPUT, "X bias");
  230. configInput(T_CLOCK_INPUT, "T clock");
  231. configInput(T_RATE_INPUT, "T rate");
  232. configInput(T_JITTER_INPUT, "T jitter");
  233. configInput(DEJA_VU_INPUT, "Deja vu");
  234. configInput(X_STEPS_INPUT, "X steps");
  235. configInput(X_SPREAD_INPUT, "X spread");
  236. configInput(X_CLOCK_INPUT, "X clock");
  237. configOutput(T1_OUTPUT, "T₁");
  238. configOutput(T2_OUTPUT, "T₂");
  239. configOutput(T3_OUTPUT, "T₃");
  240. configOutput(Y_OUTPUT, "Y");
  241. configOutput(X1_OUTPUT, "X₁");
  242. configOutput(X2_OUTPUT, "X₂");
  243. configOutput(X3_OUTPUT, "X₃");
  244. random_generator.Init(1);
  245. random_stream.Init(&random_generator);
  246. note_filter.Init();
  247. onSampleRateChange();
  248. onReset();
  249. }
  250. void onReset() override {
  251. t_deja_vu = false;
  252. x_deja_vu = false;
  253. t_mode = 0;
  254. x_mode = 0;
  255. t_range = 1;
  256. x_range = 1;
  257. external = false;
  258. x_scale = 0;
  259. y_divider_index = 8;
  260. x_clock_source_internal = 0;
  261. }
  262. void onRandomize() override {
  263. t_mode = random::u32() % 3;
  264. x_mode = random::u32() % 3;
  265. t_range = random::u32() % 3;
  266. x_range = random::u32() % 3;
  267. }
  268. void onSampleRateChange() override {
  269. float sampleRate = APP->engine->getSampleRate();
  270. t_generator.Init(&random_stream, sampleRate);
  271. xy_generator.Init(&random_stream, sampleRate);
  272. // Set scales
  273. for (int i = 0; i < 6; i++) {
  274. xy_generator.LoadScale(i, preset_scales[i]);
  275. }
  276. }
  277. json_t* dataToJson() override {
  278. json_t* rootJ = json_object();
  279. json_object_set_new(rootJ, "t_deja_vu", json_boolean(t_deja_vu));
  280. json_object_set_new(rootJ, "x_deja_vu", json_boolean(x_deja_vu));
  281. json_object_set_new(rootJ, "t_mode", json_integer(t_mode));
  282. json_object_set_new(rootJ, "x_mode", json_integer(x_mode));
  283. json_object_set_new(rootJ, "t_range", json_integer(t_range));
  284. json_object_set_new(rootJ, "x_range", json_integer(x_range));
  285. json_object_set_new(rootJ, "external", json_boolean(external));
  286. json_object_set_new(rootJ, "x_scale", json_integer(x_scale));
  287. json_object_set_new(rootJ, "y_divider_index", json_integer(y_divider_index));
  288. json_object_set_new(rootJ, "x_clock_source_internal", json_integer(x_clock_source_internal));
  289. return rootJ;
  290. }
  291. void dataFromJson(json_t* rootJ) override {
  292. json_t* t_deja_vuJ = json_object_get(rootJ, "t_deja_vu");
  293. if (t_deja_vuJ)
  294. t_deja_vu = json_boolean_value(t_deja_vuJ);
  295. json_t* x_deja_vuJ = json_object_get(rootJ, "x_deja_vu");
  296. if (x_deja_vuJ)
  297. x_deja_vu = json_boolean_value(x_deja_vuJ);
  298. json_t* t_modeJ = json_object_get(rootJ, "t_mode");
  299. if (t_modeJ)
  300. t_mode = json_integer_value(t_modeJ);
  301. json_t* x_modeJ = json_object_get(rootJ, "x_mode");
  302. if (x_modeJ)
  303. x_mode = json_integer_value(x_modeJ);
  304. json_t* t_rangeJ = json_object_get(rootJ, "t_range");
  305. if (t_rangeJ)
  306. t_range = json_integer_value(t_rangeJ);
  307. json_t* x_rangeJ = json_object_get(rootJ, "x_range");
  308. if (x_rangeJ)
  309. x_range = json_integer_value(x_rangeJ);
  310. json_t* externalJ = json_object_get(rootJ, "external");
  311. if (externalJ)
  312. external = json_boolean_value(externalJ);
  313. json_t* x_scaleJ = json_object_get(rootJ, "x_scale");
  314. if (x_scaleJ)
  315. x_scale = json_integer_value(x_scaleJ);
  316. json_t* y_divider_indexJ = json_object_get(rootJ, "y_divider_index");
  317. if (y_divider_indexJ)
  318. y_divider_index = json_integer_value(y_divider_indexJ);
  319. json_t* x_clock_source_internalJ = json_object_get(rootJ, "x_clock_source_internal");
  320. if (x_clock_source_internalJ)
  321. x_clock_source_internal = json_integer_value(x_clock_source_internalJ);
  322. }
  323. void process(const ProcessArgs& args) override {
  324. // Buttons
  325. if (tDejaVuTrigger.process(params[T_DEJA_VU_PARAM].getValue() <= 0.f)) {
  326. t_deja_vu = !t_deja_vu;
  327. }
  328. if (xDejaVuTrigger.process(params[X_DEJA_VU_PARAM].getValue() <= 0.f)) {
  329. x_deja_vu = !x_deja_vu;
  330. }
  331. if (tModeTrigger.process(params[T_MODE_PARAM].getValue() <= 0.f)) {
  332. t_mode = (t_mode + 1) % 3;
  333. }
  334. if (xModeTrigger.process(params[X_MODE_PARAM].getValue() <= 0.f)) {
  335. x_mode = (x_mode + 1) % 3;
  336. }
  337. if (tRangeTrigger.process(params[T_RANGE_PARAM].getValue() <= 0.f)) {
  338. t_range = (t_range + 1) % 3;
  339. }
  340. if (xRangeTrigger.process(params[X_RANGE_PARAM].getValue() <= 0.f)) {
  341. x_range = (x_range + 1) % 3;
  342. }
  343. if (externalTrigger.process(params[EXTERNAL_PARAM].getValue() <= 0.f)) {
  344. external = !external;
  345. }
  346. // Clocks
  347. bool t_gate = (inputs[T_CLOCK_INPUT].getVoltage() >= 1.7f);
  348. last_t_clock = stmlib::ExtractGateFlags(last_t_clock, t_gate);
  349. t_clocks[blockIndex] = last_t_clock;
  350. bool x_gate = (inputs[X_CLOCK_INPUT].getVoltage() >= 1.7f);
  351. last_xy_clock = stmlib::ExtractGateFlags(last_xy_clock, x_gate);
  352. xy_clocks[blockIndex] = last_xy_clock;
  353. // Process block
  354. if (++blockIndex >= BLOCK_SIZE) {
  355. blockIndex = 0;
  356. stepBlock();
  357. }
  358. // Lights and outputs
  359. lights[T_DEJA_VU_LIGHT].setBrightness(t_deja_vu);
  360. lights[X_DEJA_VU_LIGHT].setBrightness(x_deja_vu);
  361. int t_mode3 = t_mode % 3;
  362. lights[T_MODE_LIGHTS + 0].setBrightness(t_mode3 == 0 || t_mode3 == 1);
  363. lights[T_MODE_LIGHTS + 1].setBrightness(t_mode3 == 1 || t_mode3 == 2);
  364. lights[X_MODE_LIGHTS + 0].setBrightness(x_mode == 0 || x_mode == 1);
  365. lights[X_MODE_LIGHTS + 1].setBrightness(x_mode == 1 || x_mode == 2);
  366. lights[T_RANGE_LIGHTS + 0].setBrightness(t_range == 0 || t_range == 1);
  367. lights[T_RANGE_LIGHTS + 1].setBrightness(t_range == 1 || t_range == 2);
  368. lights[X_RANGE_LIGHTS + 0].setBrightness(x_range == 0 || x_range == 1);
  369. lights[X_RANGE_LIGHTS + 1].setBrightness(x_range == 1 || x_range == 2);
  370. lights[EXTERNAL_LIGHT].setBrightness(external);
  371. outputs[T1_OUTPUT].setVoltage(gates[blockIndex * 2 + 0] ? 10.f : 0.f);
  372. lights[T1_LIGHT].setSmoothBrightness(gates[blockIndex * 2 + 0], args.sampleTime);
  373. outputs[T2_OUTPUT].setVoltage((ramp_master[blockIndex] < 0.5f) ? 10.f : 0.f);
  374. lights[T2_LIGHT].setSmoothBrightness(ramp_master[blockIndex] < 0.5f, args.sampleTime);
  375. outputs[T3_OUTPUT].setVoltage(gates[blockIndex * 2 + 1] ? 10.f : 0.f);
  376. lights[T3_LIGHT].setSmoothBrightness(gates[blockIndex * 2 + 1], args.sampleTime);
  377. outputs[X1_OUTPUT].setVoltage(voltages[blockIndex * 4 + 0]);
  378. lights[X1_LIGHT].setSmoothBrightness(voltages[blockIndex * 4 + 0], args.sampleTime);
  379. outputs[X2_OUTPUT].setVoltage(voltages[blockIndex * 4 + 1]);
  380. lights[X2_LIGHT].setSmoothBrightness(voltages[blockIndex * 4 + 1], args.sampleTime);
  381. outputs[X3_OUTPUT].setVoltage(voltages[blockIndex * 4 + 2]);
  382. lights[X3_LIGHT].setSmoothBrightness(voltages[blockIndex * 4 + 2], args.sampleTime);
  383. outputs[Y_OUTPUT].setVoltage(voltages[blockIndex * 4 + 3]);
  384. lights[Y_LIGHT].setSmoothBrightness(voltages[blockIndex * 4 + 3], args.sampleTime);
  385. }
  386. void stepBlock() {
  387. // Ramps
  388. marbles::Ramps ramps;
  389. ramps.master = ramp_master;
  390. ramps.external = ramp_external;
  391. ramps.slave[0] = ramp_slave[0];
  392. ramps.slave[1] = ramp_slave[1];
  393. float deja_vu = clamp(params[DEJA_VU_PARAM].getValue() + inputs[DEJA_VU_INPUT].getVoltage() / 5.f, 0.f, 1.f);
  394. static const int loop_length[] = {
  395. 1, 1, 1, 2, 2,
  396. 2, 2, 2, 3, 3,
  397. 3, 3, 4, 4, 4,
  398. 4, 4, 5, 5, 6,
  399. 6, 6, 7, 7, 8,
  400. 8, 8, 10, 10, 12,
  401. 12, 12, 14, 14, 16,
  402. 16
  403. };
  404. float deja_vu_length_index = params[DEJA_VU_LENGTH_PARAM].getValue() * (LENGTHOF(loop_length) - 1);
  405. int deja_vu_length = loop_length[(int) roundf(deja_vu_length_index)];
  406. // Set up TGenerator
  407. bool t_external_clock = inputs[T_CLOCK_INPUT].isConnected();
  408. t_generator.set_model((marbles::TGeneratorModel) t_mode);
  409. t_generator.set_range((marbles::TGeneratorRange) t_range);
  410. float t_rate = 60.f * (params[T_RATE_PARAM].getValue() + inputs[T_RATE_INPUT].getVoltage() / 5.f);
  411. t_generator.set_rate(t_rate);
  412. float t_bias = clamp(params[T_BIAS_PARAM].getValue() + inputs[T_BIAS_INPUT].getVoltage() / 5.f, 0.f, 1.f);
  413. t_generator.set_bias(t_bias);
  414. float t_jitter = clamp(params[T_JITTER_PARAM].getValue() + inputs[T_JITTER_INPUT].getVoltage() / 5.f, 0.f, 1.f);
  415. t_generator.set_jitter(t_jitter);
  416. t_generator.set_deja_vu(t_deja_vu ? deja_vu : 0.f);
  417. t_generator.set_length(deja_vu_length);
  418. // TODO
  419. t_generator.set_pulse_width_mean(0.f);
  420. t_generator.set_pulse_width_std(0.f);
  421. t_generator.Process(t_external_clock, t_clocks, ramps, gates, BLOCK_SIZE);
  422. // Set up XYGenerator
  423. marbles::ClockSource x_clock_source = (marbles::ClockSource) x_clock_source_internal;
  424. if (inputs[X_CLOCK_INPUT].isConnected())
  425. x_clock_source = marbles::CLOCK_SOURCE_EXTERNAL;
  426. marbles::GroupSettings x;
  427. x.control_mode = (marbles::ControlMode) x_mode;
  428. x.voltage_range = (marbles::VoltageRange) x_range;
  429. // TODO Fix the scaling
  430. float note_cv = 0.5f * (params[X_SPREAD_PARAM].getValue() + inputs[X_SPREAD_INPUT].getVoltage() / 5.f);
  431. float u = note_filter.Process(0.5f * (note_cv + 1.f));
  432. x.register_mode = external;
  433. x.register_value = u;
  434. float x_spread = clamp(params[X_SPREAD_PARAM].getValue() + inputs[X_SPREAD_INPUT].getVoltage() / 5.f, 0.f, 1.f);
  435. x.spread = x_spread;
  436. float x_bias = clamp(params[X_BIAS_PARAM].getValue() + inputs[X_BIAS_INPUT].getVoltage() / 5.f, 0.f, 1.f);
  437. x.bias = x_bias;
  438. float x_steps = clamp(params[X_STEPS_PARAM].getValue() + inputs[X_STEPS_INPUT].getVoltage() / 5.f, 0.f, 1.f);
  439. x.steps = x_steps;
  440. x.deja_vu = x_deja_vu ? deja_vu : 0.f;
  441. x.length = deja_vu_length;
  442. x.ratio.p = 1;
  443. x.ratio.q = 1;
  444. x.scale_index = x_scale;
  445. marbles::GroupSettings y;
  446. y.control_mode = marbles::CONTROL_MODE_IDENTICAL;
  447. // TODO
  448. y.voltage_range = (marbles::VoltageRange) x_range;
  449. y.register_mode = false;
  450. y.register_value = 0.0f;
  451. // TODO
  452. y.spread = x_spread;
  453. y.bias = x_bias;
  454. y.steps = x_steps;
  455. y.deja_vu = 0.0f;
  456. y.length = 1;
  457. static const marbles::Ratio y_divider_ratios[] = {
  458. { 1, 64 },
  459. { 1, 48 },
  460. { 1, 32 },
  461. { 1, 24 },
  462. { 1, 16 },
  463. { 1, 12 },
  464. { 1, 8 },
  465. { 1, 6 },
  466. { 1, 4 },
  467. { 1, 3 },
  468. { 1, 2 },
  469. { 1, 1 },
  470. };
  471. y.ratio = y_divider_ratios[y_divider_index];
  472. y.scale_index = x_scale;
  473. xy_generator.Process(x_clock_source, x, y, xy_clocks, ramps, voltages, BLOCK_SIZE);
  474. }
  475. };
  476. template <typename BASE>
  477. struct CKD6Light : BASE {
  478. CKD6Light() {
  479. this->box.size = Vec(22, 22);
  480. }
  481. };
  482. struct MarblesWidget : ModuleWidget {
  483. MarblesWidget(Marbles* module) {
  484. setModule(module);
  485. setPanel(Svg::load(asset::plugin(pluginInstance, "res/Marbles.svg")));
  486. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  487. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  488. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  489. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  490. addParam(createParamCentered<CKD6>(mm2px(Vec(16.545, 17.794)), module, Marbles::T_DEJA_VU_PARAM));
  491. addParam(createParamCentered<CKD6>(mm2px(Vec(74.845, 17.794)), module, Marbles::X_DEJA_VU_PARAM));
  492. addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(45.695, 22.244)), module, Marbles::DEJA_VU_PARAM));
  493. addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(23.467, 35.264)), module, Marbles::T_RATE_PARAM));
  494. addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(67.945, 35.243)), module, Marbles::X_SPREAD_PARAM));
  495. addParam(createParamCentered<TL1105>(mm2px(Vec(6.945, 38.794)), module, Marbles::T_MODE_PARAM));
  496. addParam(createParamCentered<TL1105>(mm2px(Vec(84.445, 38.793)), module, Marbles::X_MODE_PARAM));
  497. addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(45.695, 51.144)), module, Marbles::DEJA_VU_LENGTH_PARAM));
  498. addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(9.545, 58.394)), module, Marbles::T_BIAS_PARAM));
  499. addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(81.844, 58.394)), module, Marbles::X_BIAS_PARAM));
  500. addParam(createParamCentered<TL1105>(mm2px(Vec(26.644, 59.694)), module, Marbles::T_RANGE_PARAM));
  501. addParam(createParamCentered<TL1105>(mm2px(Vec(64.744, 59.694)), module, Marbles::X_RANGE_PARAM));
  502. addParam(createParamCentered<TL1105>(mm2px(Vec(45.694, 67.294)), module, Marbles::EXTERNAL_PARAM));
  503. addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(31.544, 73.694)), module, Marbles::T_JITTER_PARAM));
  504. addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(59.845, 73.694)), module, Marbles::X_STEPS_PARAM));
  505. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(9.545, 81.944)), module, Marbles::T_BIAS_INPUT));
  506. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(81.844, 81.944)), module, Marbles::X_BIAS_INPUT));
  507. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(9.545, 96.544)), module, Marbles::T_CLOCK_INPUT));
  508. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(21.595, 96.544)), module, Marbles::T_RATE_INPUT));
  509. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(33.644, 96.544)), module, Marbles::T_JITTER_INPUT));
  510. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(45.695, 96.544)), module, Marbles::DEJA_VU_INPUT));
  511. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(57.745, 96.544)), module, Marbles::X_STEPS_INPUT));
  512. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(69.795, 96.544)), module, Marbles::X_SPREAD_INPUT));
  513. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(81.844, 96.544)), module, Marbles::X_CLOCK_INPUT));
  514. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(9.545, 111.144)), module, Marbles::T1_OUTPUT));
  515. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(21.595, 111.144)), module, Marbles::T2_OUTPUT));
  516. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(33.644, 111.144)), module, Marbles::T3_OUTPUT));
  517. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(45.695, 111.144)), module, Marbles::Y_OUTPUT));
  518. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(57.745, 111.144)), module, Marbles::X1_OUTPUT));
  519. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(69.795, 111.144)), module, Marbles::X2_OUTPUT));
  520. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(81.844, 111.144)), module, Marbles::X3_OUTPUT));
  521. addChild(createLightCentered<CKD6Light<GreenLight>>(mm2px(Vec(16.545, 17.794)), module, Marbles::T_DEJA_VU_LIGHT));
  522. addChild(createLightCentered<CKD6Light<GreenLight>>(mm2px(Vec(74.845, 17.794)), module, Marbles::X_DEJA_VU_LIGHT));
  523. addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(6.944, 29.894)), module, Marbles::T_MODE_LIGHTS));
  524. addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(84.444, 29.894)), module, Marbles::X_MODE_LIGHTS));
  525. addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(26.644, 53.994)), module, Marbles::T_RANGE_LIGHTS));
  526. addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(64.744, 53.994)), module, Marbles::X_RANGE_LIGHTS));
  527. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(45.695, 76.194)), module, Marbles::EXTERNAL_LIGHT));
  528. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(6.044, 104.794)), module, Marbles::T1_LIGHT));
  529. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(18.094, 104.794)), module, Marbles::T2_LIGHT));
  530. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(30.145, 104.794)), module, Marbles::T3_LIGHT));
  531. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(42.194, 104.794)), module, Marbles::Y_LIGHT));
  532. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(54.244, 104.794)), module, Marbles::X1_LIGHT));
  533. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(66.294, 104.794)), module, Marbles::X2_LIGHT));
  534. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(78.344, 104.794)), module, Marbles::X3_LIGHT));
  535. }
  536. void appendContextMenu(Menu* menu) override {
  537. Marbles* module = dynamic_cast<Marbles*>(this->module);
  538. menu->addChild(new MenuSeparator);
  539. menu->addChild(createIndexPtrSubmenuItem("T mode", {
  540. "Complementary Bernoulli",
  541. "Clusters",
  542. "Drums",
  543. "Independent Bernoulli",
  544. "Divider",
  545. "Three states",
  546. "Markov",
  547. }, &module->t_mode));
  548. menu->addChild(createIndexPtrSubmenuItem("T range", {
  549. "1/4x",
  550. "1x",
  551. "4x",
  552. }, &module->t_range));
  553. menu->addChild(createIndexPtrSubmenuItem("X mode", {
  554. "Identical",
  555. "Bump",
  556. "Tilt",
  557. }, &module->x_mode));
  558. menu->addChild(createIndexPtrSubmenuItem("X range", {
  559. "Narrow",
  560. "Positive",
  561. "Full",
  562. }, &module->x_range));
  563. menu->addChild(createIndexPtrSubmenuItem("Scales", {
  564. "Major",
  565. "Minor",
  566. "Pentatonic",
  567. "Pelog",
  568. "Raag Bhairav That",
  569. "Raag Shri",
  570. }, &module->x_scale));
  571. menu->addChild(createIndexPtrSubmenuItem("Internal X clock source", {
  572. "T₁ → X₁, T₂ → X₂, T₃ → X₃",
  573. "T₁ → X₁, X₂, X₃",
  574. "T₂ → X₁, X₂, X₃",
  575. "T₃ → X₁, X₂, X₃",
  576. }, &module->x_clock_source_internal));
  577. menu->addChild(createIndexPtrSubmenuItem("Y divider ratio", {
  578. "1/64",
  579. "1/48",
  580. "1/32",
  581. "1/24",
  582. "1/16",
  583. "1/12",
  584. "1/8",
  585. "1/6",
  586. "1/4",
  587. "1/3",
  588. "1/2",
  589. "1",
  590. }, &module->y_divider_index));
  591. }
  592. };
  593. Model* modelMarbles = createModel<Marbles, MarblesWidget>("Marbles");