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.

771 lines
25KB

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