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.

776 lines
26KB

  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. static const marbles::Ratio y_divider_ratios[] = {
  120. { 1, 64 },
  121. { 1, 48 },
  122. { 1, 32 },
  123. { 1, 24 },
  124. { 1, 16 },
  125. { 1, 12 },
  126. { 1, 8 },
  127. { 1, 6 },
  128. { 1, 4 },
  129. { 1, 3 },
  130. { 1, 2 },
  131. { 1, 1 },
  132. };
  133. struct Marbles : Module {
  134. enum ParamIds {
  135. T_DEJA_VU_PARAM,
  136. X_DEJA_VU_PARAM,
  137. DEJA_VU_PARAM,
  138. T_RATE_PARAM,
  139. X_SPREAD_PARAM,
  140. T_MODE_PARAM,
  141. X_MODE_PARAM,
  142. DEJA_VU_LENGTH_PARAM,
  143. T_BIAS_PARAM,
  144. X_BIAS_PARAM,
  145. T_RANGE_PARAM,
  146. X_RANGE_PARAM,
  147. EXTERNAL_PARAM,
  148. T_JITTER_PARAM,
  149. X_STEPS_PARAM,
  150. Y_RATE_PARAM,
  151. Y_SPREAD_PARAM,
  152. Y_BIAS_PARAM,
  153. Y_STEPS_PARAM,
  154. GATE_BIAS_PARAM,
  155. GATE_JITTER_PARAM,
  156. NUM_PARAMS
  157. };
  158. enum InputIds {
  159. T_BIAS_INPUT,
  160. X_BIAS_INPUT,
  161. T_CLOCK_INPUT,
  162. T_RATE_INPUT,
  163. T_JITTER_INPUT,
  164. DEJA_VU_INPUT,
  165. X_STEPS_INPUT,
  166. X_SPREAD_INPUT,
  167. X_CLOCK_INPUT,
  168. NUM_INPUTS
  169. };
  170. enum OutputIds {
  171. T1_OUTPUT,
  172. T2_OUTPUT,
  173. T3_OUTPUT,
  174. Y_OUTPUT,
  175. X1_OUTPUT,
  176. X2_OUTPUT,
  177. X3_OUTPUT,
  178. NUM_OUTPUTS
  179. };
  180. enum LightIds {
  181. T_DEJA_VU_LIGHT,
  182. X_DEJA_VU_LIGHT,
  183. ENUMS(T_MODE_LIGHTS, 2),
  184. ENUMS(X_MODE_LIGHTS, 2),
  185. ENUMS(T_RANGE_LIGHTS, 2),
  186. ENUMS(X_RANGE_LIGHTS, 2),
  187. EXTERNAL_LIGHT,
  188. T1_LIGHT,
  189. T2_LIGHT,
  190. T3_LIGHT,
  191. Y_LIGHT,
  192. X1_LIGHT,
  193. X2_LIGHT,
  194. X3_LIGHT,
  195. NUM_LIGHTS
  196. };
  197. marbles::RandomGenerator random_generator;
  198. marbles::RandomStream random_stream;
  199. marbles::TGenerator t_generator;
  200. marbles::XYGenerator xy_generator;
  201. marbles::NoteFilter note_filter;
  202. // State
  203. dsp::BooleanTrigger tDejaVuTrigger;
  204. dsp::BooleanTrigger xDejaVuTrigger;
  205. dsp::BooleanTrigger tModeTrigger;
  206. dsp::BooleanTrigger xModeTrigger;
  207. dsp::BooleanTrigger tRangeTrigger;
  208. dsp::BooleanTrigger xRangeTrigger;
  209. dsp::BooleanTrigger externalTrigger;
  210. bool t_deja_vu;
  211. bool x_deja_vu;
  212. int t_mode;
  213. int x_mode;
  214. int t_range;
  215. int x_range;
  216. bool external;
  217. int x_scale;
  218. int y_divider_index;
  219. int x_clock_source_internal;
  220. int edit_mode;
  221. // Buffers
  222. stmlib::GateFlags t_clocks[BLOCK_SIZE] = {};
  223. stmlib::GateFlags last_t_clock = 0;
  224. stmlib::GateFlags xy_clocks[BLOCK_SIZE] = {};
  225. stmlib::GateFlags last_xy_clock = 0;
  226. float ramp_master[BLOCK_SIZE] = {};
  227. float ramp_external[BLOCK_SIZE] = {};
  228. float ramp_slave[2][BLOCK_SIZE] = {};
  229. bool gates[BLOCK_SIZE * 2] = {};
  230. float voltages[BLOCK_SIZE * 4] = {};
  231. int blockIndex = 0;
  232. Marbles() {
  233. config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
  234. configParam(T_DEJA_VU_PARAM, 0.0, 1.0, 0.0, "t deja vu");
  235. configParam(X_DEJA_VU_PARAM, 0.0, 1.0, 0.0, "X deja vu");
  236. configParam(DEJA_VU_PARAM, 0.0, 1.0, 0.5, "Deja vu probability");
  237. configParam(T_RATE_PARAM, -1.0, 1.0, 0.0, "Clock rate");
  238. configParam(X_SPREAD_PARAM, 0.0, 1.0, 0.5, "Probability distribution");
  239. configParam(T_MODE_PARAM, 0.0, 1.0, 0.0, "t mode");
  240. configParam(X_MODE_PARAM, 0.0, 1.0, 0.0, "X mode");
  241. configParam(DEJA_VU_LENGTH_PARAM, 0.0, 1.0, 0.0, "Loop length");
  242. configParam(T_BIAS_PARAM, 0.0, 1.0, 0.5, "Gate bias");
  243. configParam(X_BIAS_PARAM, 0.0, 1.0, 0.5, "Distribution bias");
  244. configParam(T_RANGE_PARAM, 0.0, 1.0, 0.0, "Clock range mode");
  245. configParam(X_RANGE_PARAM, 0.0, 1.0, 0.0, "Output voltage range mode");
  246. configParam(EXTERNAL_PARAM, 0.0, 1.0, 0.0, "External processing mode");
  247. configParam(T_JITTER_PARAM, 0.0, 1.0, 0.0, "Randomness amount");
  248. configParam(X_STEPS_PARAM, 0.0, 1.0, 0.5, "Smoothness");
  249. configParam(Y_RATE_PARAM, 0.0, 1.0, 4.5 / LENGTHOF(y_divider_ratios), "Clock divide");
  250. configParam(Y_SPREAD_PARAM, 0.0, 1.0, 0.5, "Probability distribution");
  251. configParam(Y_BIAS_PARAM, 0.0, 1.0, 0.5, "Voltage offset");
  252. configParam(Y_STEPS_PARAM, 0.0, 1.0, 0.0, "Smoothness");
  253. configParam(GATE_BIAS_PARAM, 0.0, 1.0, 0.5, "Gate length");
  254. configParam(GATE_JITTER_PARAM, 0.0, 1.0, 0.0, "Gate length randomness");
  255. random_generator.Init(1);
  256. random_stream.Init(&random_generator);
  257. note_filter.Init();
  258. onSampleRateChange();
  259. onReset();
  260. }
  261. void onReset() override {
  262. t_deja_vu = false;
  263. x_deja_vu = false;
  264. t_mode = 0;
  265. x_mode = 0;
  266. t_range = 1;
  267. x_range = 1;
  268. external = false;
  269. x_scale = 0;
  270. y_divider_index = 4;
  271. x_clock_source_internal = 0;
  272. edit_mode = 0;
  273. }
  274. void onRandomize() override {
  275. t_mode = random::u32() % 3;
  276. x_mode = random::u32() % 3;
  277. t_range = random::u32() % 3;
  278. x_range = random::u32() % 3;
  279. }
  280. void onSampleRateChange() override {
  281. float sampleRate = APP->engine->getSampleRate();
  282. t_generator.Init(&random_stream, sampleRate);
  283. xy_generator.Init(&random_stream, sampleRate);
  284. // Set scales
  285. for (int i = 0; i < 6; i++) {
  286. xy_generator.LoadScale(i, preset_scales[i]);
  287. }
  288. }
  289. json_t* dataToJson() override {
  290. json_t* rootJ = json_object();
  291. json_object_set_new(rootJ, "t_deja_vu", json_boolean(t_deja_vu));
  292. json_object_set_new(rootJ, "x_deja_vu", json_boolean(x_deja_vu));
  293. json_object_set_new(rootJ, "t_mode", json_integer(t_mode));
  294. json_object_set_new(rootJ, "x_mode", json_integer(x_mode));
  295. json_object_set_new(rootJ, "t_range", json_integer(t_range));
  296. json_object_set_new(rootJ, "x_range", json_integer(x_range));
  297. json_object_set_new(rootJ, "external", json_boolean(external));
  298. json_object_set_new(rootJ, "x_scale", json_integer(x_scale));
  299. json_object_set_new(rootJ, "y_divider_index", json_integer(y_divider_index));
  300. json_object_set_new(rootJ, "x_clock_source_internal", json_integer(x_clock_source_internal));
  301. json_object_set_new(rootJ, "edit_mode", json_integer(edit_mode));
  302. return rootJ;
  303. }
  304. void dataFromJson(json_t* rootJ) override {
  305. json_t* t_deja_vuJ = json_object_get(rootJ, "t_deja_vu");
  306. if (t_deja_vuJ)
  307. t_deja_vu = json_boolean_value(t_deja_vuJ);
  308. json_t* x_deja_vuJ = json_object_get(rootJ, "x_deja_vu");
  309. if (x_deja_vuJ)
  310. x_deja_vu = json_boolean_value(x_deja_vuJ);
  311. json_t* t_modeJ = json_object_get(rootJ, "t_mode");
  312. if (t_modeJ)
  313. t_mode = json_integer_value(t_modeJ);
  314. json_t* x_modeJ = json_object_get(rootJ, "x_mode");
  315. if (x_modeJ)
  316. x_mode = json_integer_value(x_modeJ);
  317. json_t* t_rangeJ = json_object_get(rootJ, "t_range");
  318. if (t_rangeJ)
  319. t_range = json_integer_value(t_rangeJ);
  320. json_t* x_rangeJ = json_object_get(rootJ, "x_range");
  321. if (x_rangeJ)
  322. x_range = json_integer_value(x_rangeJ);
  323. json_t* externalJ = json_object_get(rootJ, "external");
  324. if (externalJ)
  325. external = json_boolean_value(externalJ);
  326. json_t* x_scaleJ = json_object_get(rootJ, "x_scale");
  327. if (x_scaleJ)
  328. x_scale = json_integer_value(x_scaleJ);
  329. json_t* y_divider_indexJ = json_object_get(rootJ, "y_divider_index");
  330. if (y_divider_indexJ)
  331. y_divider_index = json_integer_value(y_divider_indexJ);
  332. json_t* x_clock_source_internalJ = json_object_get(rootJ, "x_clock_source_internal");
  333. if (x_clock_source_internalJ)
  334. x_clock_source_internal = json_integer_value(x_clock_source_internalJ);
  335. json_t* edit_modeJ = json_object_get(rootJ, "edit_mode");
  336. if (edit_modeJ)
  337. edit_mode = json_boolean_value(edit_modeJ);
  338. }
  339. void process(const ProcessArgs& args) override {
  340. // Buttons
  341. if (tDejaVuTrigger.process(params[T_DEJA_VU_PARAM].getValue() <= 0.f)) {
  342. t_deja_vu = !t_deja_vu;
  343. }
  344. if (xDejaVuTrigger.process(params[X_DEJA_VU_PARAM].getValue() <= 0.f)) {
  345. x_deja_vu = !x_deja_vu;
  346. }
  347. if (tModeTrigger.process(params[T_MODE_PARAM].getValue() <= 0.f)) {
  348. t_mode = (t_mode + 1) % 3;
  349. }
  350. if (xModeTrigger.process(params[X_MODE_PARAM].getValue() <= 0.f)) {
  351. x_mode = (x_mode + 1) % 3;
  352. }
  353. if (tRangeTrigger.process(params[T_RANGE_PARAM].getValue() <= 0.f)) {
  354. t_range = (t_range + 1) % 3;
  355. }
  356. if (xRangeTrigger.process(params[X_RANGE_PARAM].getValue() <= 0.f)) {
  357. x_range = (x_range + 1) % 3;
  358. }
  359. if (externalTrigger.process(params[EXTERNAL_PARAM].getValue() <= 0.f)) {
  360. external = !external;
  361. }
  362. // Clocks
  363. bool t_gate = (inputs[T_CLOCK_INPUT].getVoltage() >= 1.7f);
  364. last_t_clock = stmlib::ExtractGateFlags(last_t_clock, t_gate);
  365. t_clocks[blockIndex] = last_t_clock;
  366. bool x_gate = (inputs[X_CLOCK_INPUT].getVoltage() >= 1.7f);
  367. last_xy_clock = stmlib::ExtractGateFlags(last_xy_clock, x_gate);
  368. xy_clocks[blockIndex] = last_xy_clock;
  369. // Process block
  370. if (++blockIndex >= BLOCK_SIZE) {
  371. blockIndex = 0;
  372. stepBlock();
  373. }
  374. // Lights and outputs
  375. lights[T_DEJA_VU_LIGHT].setBrightness(t_deja_vu);
  376. lights[X_DEJA_VU_LIGHT].setBrightness(x_deja_vu);
  377. lights[T_MODE_LIGHTS + 0].setBrightness(t_mode == 0 || t_mode == 1);
  378. lights[T_MODE_LIGHTS + 1].setBrightness(t_mode == 1 || t_mode == 2);
  379. lights[X_MODE_LIGHTS + 0].setBrightness(x_mode == 0 || x_mode == 1);
  380. lights[X_MODE_LIGHTS + 1].setBrightness(x_mode == 1 || x_mode == 2);
  381. lights[T_RANGE_LIGHTS + 0].setBrightness(t_range == 0 || t_range == 1);
  382. lights[T_RANGE_LIGHTS + 1].setBrightness(t_range == 1 || t_range == 2);
  383. lights[X_RANGE_LIGHTS + 0].setBrightness(x_range == 0 || x_range == 1);
  384. lights[X_RANGE_LIGHTS + 1].setBrightness(x_range == 1 || x_range == 2);
  385. lights[EXTERNAL_LIGHT].setBrightness(external);
  386. outputs[T1_OUTPUT].setVoltage(gates[blockIndex * 2 + 0] ? 10.f : 0.f);
  387. lights[T1_LIGHT].setSmoothBrightness(gates[blockIndex * 2 + 0], args.sampleTime);
  388. outputs[T2_OUTPUT].setVoltage((ramp_master[blockIndex] < 0.5f) ? 10.f : 0.f);
  389. lights[T2_LIGHT].setSmoothBrightness(ramp_master[blockIndex] < 0.5f, args.sampleTime);
  390. outputs[T3_OUTPUT].setVoltage(gates[blockIndex * 2 + 1] ? 10.f : 0.f);
  391. lights[T3_LIGHT].setSmoothBrightness(gates[blockIndex * 2 + 1], args.sampleTime);
  392. outputs[X1_OUTPUT].setVoltage(voltages[blockIndex * 4 + 0]);
  393. lights[X1_LIGHT].setSmoothBrightness(voltages[blockIndex * 4 + 0], args.sampleTime);
  394. outputs[X2_OUTPUT].setVoltage(voltages[blockIndex * 4 + 1]);
  395. lights[X2_LIGHT].setSmoothBrightness(voltages[blockIndex * 4 + 1], args.sampleTime);
  396. outputs[X3_OUTPUT].setVoltage(voltages[blockIndex * 4 + 2]);
  397. lights[X3_LIGHT].setSmoothBrightness(voltages[blockIndex * 4 + 2], args.sampleTime);
  398. outputs[Y_OUTPUT].setVoltage(voltages[blockIndex * 4 + 3]);
  399. lights[Y_LIGHT].setSmoothBrightness(voltages[blockIndex * 4 + 3], args.sampleTime);
  400. }
  401. void stepBlock() {
  402. // Ramps
  403. marbles::Ramps ramps;
  404. ramps.master = ramp_master;
  405. ramps.external = ramp_external;
  406. ramps.slave[0] = ramp_slave[0];
  407. ramps.slave[1] = ramp_slave[1];
  408. float deja_vu = clamp(params[DEJA_VU_PARAM].getValue() + inputs[DEJA_VU_INPUT].getVoltage() / 5.f, 0.f, 1.f);
  409. static const int loop_length[] = {
  410. 1, 1, 1, 2, 2,
  411. 2, 2, 2, 3, 3,
  412. 3, 3, 4, 4, 4,
  413. 4, 4, 5, 5, 6,
  414. 6, 6, 7, 7, 8,
  415. 8, 8, 10, 10, 12,
  416. 12, 12, 14, 14, 16,
  417. 16
  418. };
  419. float deja_vu_length_index = params[DEJA_VU_LENGTH_PARAM].getValue() * (LENGTHOF(loop_length) - 1);
  420. int deja_vu_length = loop_length[(int) roundf(deja_vu_length_index)];
  421. // Set up TGenerator
  422. bool t_external_clock = inputs[T_CLOCK_INPUT].isConnected();
  423. t_generator.set_model((marbles::TGeneratorModel) t_mode);
  424. t_generator.set_range((marbles::TGeneratorRange) t_range);
  425. float t_rate = 60.f * (params[T_RATE_PARAM].getValue() + inputs[T_RATE_INPUT].getVoltage() / 5.f);
  426. t_generator.set_rate(t_rate);
  427. float t_bias = clamp(params[T_BIAS_PARAM].getValue() + inputs[T_BIAS_INPUT].getVoltage() / 5.f, 0.f, 1.f);
  428. t_generator.set_bias(t_bias);
  429. float t_jitter = clamp(params[T_JITTER_PARAM].getValue() + inputs[T_JITTER_INPUT].getVoltage() / 5.f, 0.f, 1.f);
  430. t_generator.set_jitter(t_jitter);
  431. t_generator.set_deja_vu(t_deja_vu ? deja_vu : 0.f);
  432. t_generator.set_length(deja_vu_length);
  433. t_generator.set_pulse_width_mean(params[GATE_BIAS_PARAM].getValue());
  434. t_generator.set_pulse_width_std(params[GATE_JITTER_PARAM].getValue());
  435. t_generator.Process(t_external_clock, t_clocks, ramps, gates, BLOCK_SIZE);
  436. // Set up XYGenerator
  437. marbles::ClockSource x_clock_source = (marbles::ClockSource) x_clock_source_internal;
  438. if (inputs[X_CLOCK_INPUT].isConnected())
  439. x_clock_source = marbles::CLOCK_SOURCE_EXTERNAL;
  440. marbles::GroupSettings x;
  441. x.control_mode = (marbles::ControlMode) x_mode;
  442. x.voltage_range = (marbles::VoltageRange) x_range;
  443. // TODO Fix the scaling
  444. float note_cv = 0.5f * (params[X_SPREAD_PARAM].getValue() + inputs[X_SPREAD_INPUT].getVoltage() / 5.f);
  445. float u = note_filter.Process(0.5f * (note_cv + 1.f));
  446. x.register_mode = external;
  447. x.register_value = u;
  448. float x_spread = clamp(params[X_SPREAD_PARAM].getValue() + inputs[X_SPREAD_INPUT].getVoltage() / 5.f, 0.f, 1.f);
  449. x.spread = x_spread;
  450. float x_bias = clamp(params[X_BIAS_PARAM].getValue() + inputs[X_BIAS_INPUT].getVoltage() / 5.f, 0.f, 1.f);
  451. x.bias = x_bias;
  452. float x_steps = clamp(params[X_STEPS_PARAM].getValue() + inputs[X_STEPS_INPUT].getVoltage() / 5.f, 0.f, 1.f);
  453. x.steps = x_steps;
  454. x.deja_vu = x_deja_vu ? deja_vu : 0.f;
  455. x.length = deja_vu_length;
  456. x.ratio.p = 1;
  457. x.ratio.q = 1;
  458. x.scale_index = x_scale;
  459. marbles::GroupSettings y;
  460. y.control_mode = marbles::CONTROL_MODE_IDENTICAL;
  461. y.voltage_range = marbles::VOLTAGE_RANGE_FULL;
  462. y.register_mode = false;
  463. y.register_value = 0.0f;
  464. y.spread = params[Y_SPREAD_PARAM].getValue();
  465. y.bias = params[Y_BIAS_PARAM].getValue();
  466. y.steps = params[Y_STEPS_PARAM].getValue();
  467. y.deja_vu = 0.0f;
  468. y.length = 1;
  469. uint index = (uint) (params[Y_RATE_PARAM].getValue() * LENGTHOF(y_divider_ratios));
  470. if (index < LENGTHOF(y_divider_ratios))
  471. y_divider_index = index;
  472. y.ratio = y_divider_ratios[y_divider_index];
  473. y.scale_index = x_scale;
  474. xy_generator.Process(x_clock_source, x, y, xy_clocks, ramps, voltages, BLOCK_SIZE);
  475. }
  476. };
  477. template <typename BASE>
  478. struct CKD6Light : BASE {
  479. CKD6Light() {
  480. this->box.size = Vec(22, 22);
  481. }
  482. };
  483. struct MarblesWidget : ModuleWidget {
  484. ParamWidget* yRateParam;
  485. ParamWidget* ySpreadParam;
  486. ParamWidget* yBiasParam;
  487. ParamWidget* yStepsParam;
  488. ParamWidget* gateBiasParam;
  489. ParamWidget* gateJitterParam;
  490. MarblesWidget(Marbles* module) {
  491. setModule(module);
  492. setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Marbles.svg")));
  493. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  494. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  495. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  496. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  497. addParam(createParamCentered<CKD6>(mm2px(Vec(16.545, 17.794)), module, Marbles::T_DEJA_VU_PARAM));
  498. addParam(createParamCentered<CKD6>(mm2px(Vec(74.845, 17.794)), module, Marbles::X_DEJA_VU_PARAM));
  499. addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(45.695, 22.244)), module, Marbles::DEJA_VU_PARAM));
  500. addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(23.467, 35.264)), module, Marbles::T_RATE_PARAM));
  501. addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(67.945, 35.243)), module, Marbles::X_SPREAD_PARAM));
  502. addParam(createParamCentered<TL1105>(mm2px(Vec(6.945, 38.794)), module, Marbles::T_MODE_PARAM));
  503. addParam(createParamCentered<TL1105>(mm2px(Vec(84.445, 38.793)), module, Marbles::X_MODE_PARAM));
  504. addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(45.695, 51.144)), module, Marbles::DEJA_VU_LENGTH_PARAM));
  505. addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(9.545, 58.394)), module, Marbles::T_BIAS_PARAM));
  506. addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(81.844, 58.394)), module, Marbles::X_BIAS_PARAM));
  507. addParam(createParamCentered<TL1105>(mm2px(Vec(26.644, 59.694)), module, Marbles::T_RANGE_PARAM));
  508. addParam(createParamCentered<TL1105>(mm2px(Vec(64.744, 59.694)), module, Marbles::X_RANGE_PARAM));
  509. addParam(createParamCentered<TL1105>(mm2px(Vec(45.694, 67.294)), module, Marbles::EXTERNAL_PARAM));
  510. addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(31.544, 73.694)), module, Marbles::T_JITTER_PARAM));
  511. addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(59.845, 73.694)), module, Marbles::X_STEPS_PARAM));
  512. // Knobs for Y generator edit mode
  513. yRateParam = createParamCentered<Rogan3PSGreen>(mm2px(Vec(23.467, 35.264)), module, Marbles::Y_RATE_PARAM);
  514. addParam(yRateParam);
  515. ySpreadParam = createParamCentered<Rogan3PSGreen>(mm2px(Vec(67.945, 35.243)), module, Marbles::Y_SPREAD_PARAM);
  516. addParam(ySpreadParam);
  517. yBiasParam = createParamCentered<Rogan2PSGreen>(mm2px(Vec(81.844, 58.394)), module, Marbles::Y_BIAS_PARAM);
  518. addParam(yBiasParam);
  519. yStepsParam = createParamCentered<Rogan2PSGreen>(mm2px(Vec(59.845, 73.694)), module, Marbles::Y_STEPS_PARAM);
  520. addParam(yStepsParam);
  521. // Make colored knobs not visible in module browser
  522. yRateParam->visible = false;
  523. ySpreadParam->visible = false;
  524. yBiasParam->visible = false;
  525. yStepsParam->visible = false;
  526. // Knobs for gate edit mode
  527. gateBiasParam = createParamCentered<Rogan2PSRed>(mm2px(Vec(9.545, 58.394)), module, Marbles::GATE_BIAS_PARAM);
  528. addParam(gateBiasParam);
  529. gateJitterParam = createParamCentered<Rogan2PSRed>(mm2px(Vec(31.544, 73.694)), module, Marbles::GATE_JITTER_PARAM);
  530. addParam(gateJitterParam);
  531. // Make colored knobs not visible in module browser
  532. gateBiasParam->visible = false;
  533. gateJitterParam->visible = false;
  534. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(9.545, 81.944)), module, Marbles::T_BIAS_INPUT));
  535. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(81.844, 81.944)), module, Marbles::X_BIAS_INPUT));
  536. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(9.545, 96.544)), module, Marbles::T_CLOCK_INPUT));
  537. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(21.595, 96.544)), module, Marbles::T_RATE_INPUT));
  538. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(33.644, 96.544)), module, Marbles::T_JITTER_INPUT));
  539. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(45.695, 96.544)), module, Marbles::DEJA_VU_INPUT));
  540. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(57.745, 96.544)), module, Marbles::X_STEPS_INPUT));
  541. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(69.795, 96.544)), module, Marbles::X_SPREAD_INPUT));
  542. addInput(createInputCentered<PJ301MPort>(mm2px(Vec(81.844, 96.544)), module, Marbles::X_CLOCK_INPUT));
  543. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(9.545, 111.144)), module, Marbles::T1_OUTPUT));
  544. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(21.595, 111.144)), module, Marbles::T2_OUTPUT));
  545. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(33.644, 111.144)), module, Marbles::T3_OUTPUT));
  546. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(45.695, 111.144)), module, Marbles::Y_OUTPUT));
  547. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(57.745, 111.144)), module, Marbles::X1_OUTPUT));
  548. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(69.795, 111.144)), module, Marbles::X2_OUTPUT));
  549. addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(81.844, 111.144)), module, Marbles::X3_OUTPUT));
  550. addChild(createLightCentered<CKD6Light<GreenLight>>(mm2px(Vec(16.545, 17.794)), module, Marbles::T_DEJA_VU_LIGHT));
  551. addChild(createLightCentered<CKD6Light<GreenLight>>(mm2px(Vec(74.845, 17.794)), module, Marbles::X_DEJA_VU_LIGHT));
  552. addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(6.944, 29.894)), module, Marbles::T_MODE_LIGHTS));
  553. addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(84.444, 29.894)), module, Marbles::X_MODE_LIGHTS));
  554. addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(26.644, 53.994)), module, Marbles::T_RANGE_LIGHTS));
  555. addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(64.744, 53.994)), module, Marbles::X_RANGE_LIGHTS));
  556. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(45.695, 76.194)), module, Marbles::EXTERNAL_LIGHT));
  557. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(6.044, 104.794)), module, Marbles::T1_LIGHT));
  558. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(18.094, 104.794)), module, Marbles::T2_LIGHT));
  559. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(30.145, 104.794)), module, Marbles::T3_LIGHT));
  560. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(42.194, 104.794)), module, Marbles::Y_LIGHT));
  561. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(54.244, 104.794)), module, Marbles::X1_LIGHT));
  562. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(66.294, 104.794)), module, Marbles::X2_LIGHT));
  563. addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(78.344, 104.794)), module, Marbles::X3_LIGHT));
  564. }
  565. void step() override {
  566. Marbles *module = dynamic_cast<Marbles *>(this->module);
  567. if (module) {
  568. yRateParam->visible = (module->edit_mode == 1);
  569. ySpreadParam->visible = (module->edit_mode == 1);
  570. yBiasParam->visible = (module->edit_mode == 1);
  571. yStepsParam->visible = (module->edit_mode == 1);
  572. gateBiasParam->visible = (module->edit_mode == 2);
  573. gateJitterParam->visible = (module->edit_mode == 2);
  574. }
  575. ModuleWidget::step();
  576. }
  577. void appendContextMenu(Menu* menu) override {
  578. Marbles* module = dynamic_cast<Marbles*>(this->module);
  579. struct ScaleItem : MenuItem {
  580. Marbles* module;
  581. int scale;
  582. void onAction(const event::Action& e) override {
  583. module->x_scale = scale;
  584. }
  585. };
  586. menu->addChild(new MenuSeparator);
  587. menu->addChild(createMenuLabel("Scales"));
  588. const std::string scaleLabels[] = {
  589. "Major",
  590. "Minor",
  591. "Pentatonic",
  592. "Pelog",
  593. "Raag Bhairav That",
  594. "Raag Shri",
  595. };
  596. for (int i = 0; i < (int) LENGTHOF(scaleLabels); i++) {
  597. ScaleItem* item = createMenuItem<ScaleItem>(scaleLabels[i], CHECKMARK(module->x_scale == i));
  598. item->module = module;
  599. item->scale = i;
  600. menu->addChild(item);
  601. }
  602. struct XClockSourceInternal : MenuItem {
  603. Marbles* module;
  604. int source;
  605. void onAction(const event::Action& e) override {
  606. module->x_clock_source_internal = source;
  607. }
  608. };
  609. menu->addChild(new MenuSeparator);
  610. menu->addChild(createMenuLabel("Internal X clock source"));
  611. const std::string sourceLabels[] = {
  612. "T₁ → X₁, T₂ → X₂, T₃ → X₃",
  613. "T₁ → X₁, X₂, X₃",
  614. "T₂ → X₁, X₂, X₃",
  615. "T₃ → X₁, X₂, X₃",
  616. };
  617. for (int i = 0; i < (int) LENGTHOF(sourceLabels); i++) {
  618. XClockSourceInternal* item = createMenuItem<XClockSourceInternal>(sourceLabels[i], CHECKMARK(module->x_clock_source_internal == i));
  619. item->module = module;
  620. item->source = i;
  621. menu->addChild(item);
  622. }
  623. struct YDividerIndexItem : MenuItem {
  624. Marbles* module;
  625. int index;
  626. void onAction(const event::Action& e) override {
  627. module->y_divider_index = index;
  628. module->params[module->Y_RATE_PARAM].setValue(index / LENGTHOF(y_divider_ratios));
  629. }
  630. };
  631. struct YDividerItem : MenuItem {
  632. Marbles* module;
  633. Menu* createChildMenu() override {
  634. Menu* menu = new Menu();
  635. const std::string yDividerRatioLabels[] = {
  636. "1/64",
  637. "1/48",
  638. "1/32",
  639. "1/24",
  640. "1/16",
  641. "1/12",
  642. "1/8",
  643. "1/6",
  644. "1/4",
  645. "1/3",
  646. "1/2",
  647. "1",
  648. };
  649. for (int i = 0; i < (int) LENGTHOF(yDividerRatioLabels); i++) {
  650. YDividerIndexItem* item = createMenuItem<YDividerIndexItem>(yDividerRatioLabels[i], CHECKMARK(module->y_divider_index == i));
  651. item->module = module;
  652. item->index = i;
  653. menu->addChild(item);
  654. }
  655. return menu;
  656. }
  657. };
  658. menu->addChild(new MenuSeparator);
  659. YDividerItem* yDividerItem = createMenuItem<YDividerItem>("Y divider ratio");
  660. yDividerItem->module = module;
  661. menu->addChild(yDividerItem);
  662. struct MarblesEditModeItem : MenuItem {
  663. Marbles *module;
  664. int editMode;
  665. void onAction(const event::Action& e) override {
  666. module->edit_mode = editMode;
  667. }
  668. void step() override {
  669. rightText = (module->edit_mode == editMode) ? "✔" : "";
  670. MenuItem::step();
  671. }
  672. };
  673. menu->addChild(new MenuSeparator);
  674. menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Edit Mode"));
  675. menu->addChild(construct<MarblesEditModeItem>(&MenuItem::text, "Default", &MarblesEditModeItem::module, module, &MarblesEditModeItem::editMode, 0));
  676. menu->addChild(construct<MarblesEditModeItem>(&MenuItem::text, "Y generator", &MarblesEditModeItem::module, module, &MarblesEditModeItem::editMode, 1));
  677. menu->addChild(construct<MarblesEditModeItem>(&MenuItem::text, "Gate", &MarblesEditModeItem::module, module, &MarblesEditModeItem::editMode, 2));
  678. }
  679. };
  680. Model* modelMarbles = createModel<Marbles, MarblesWidget>("Marbles");