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.

671 lines
21KB

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