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.

730 lines
23KB

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