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.

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