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.

404 lines
15KB

  1. #include "AudibleInstruments.hpp"
  2. #include "dsp/digital.hpp"
  3. #include "stages/segment_generator.h"
  4. #include "stages/oscillator.h"
  5. // Must match io_buffer.h
  6. static const int NUM_CHANNELS = 6;
  7. static const int BLOCK_SIZE = 8;
  8. struct LongPressButton {
  9. enum Events {
  10. NO_PRESS,
  11. SHORT_PRESS,
  12. LONG_PRESS
  13. };
  14. float pressedTime = 0.f;
  15. BooleanTrigger trigger;
  16. Events step(Param &param) {
  17. Events result = NO_PRESS;
  18. bool pressed = param.value > 0.f;
  19. if (pressed && pressedTime >= 0.f) {
  20. pressedTime += engineGetSampleTime();
  21. if (pressedTime >= 1.f) {
  22. pressedTime = -1.f;
  23. result = LONG_PRESS;
  24. }
  25. }
  26. // Check if released
  27. if (trigger.process(!pressed)) {
  28. if (pressedTime >= 0.f) {
  29. result = SHORT_PRESS;
  30. }
  31. pressedTime = 0.f;
  32. }
  33. return result;
  34. }
  35. };
  36. struct GroupBuilder {
  37. GroupBuilder() {
  38. for (size_t i = 0; i < NUM_CHANNELS; i++) {
  39. groupSize[i] = 0;
  40. }
  41. }
  42. size_t groupSize[NUM_CHANNELS];
  43. bool isPatched = false;
  44. bool buildGroups(std::vector<Input> *inputs, size_t first, size_t count) {
  45. bool changed = false;
  46. isPatched = false;
  47. size_t activeGroup = 0;
  48. for (int i = count - 1; i >= 0; i -= 1) {
  49. bool patched = (*inputs)[first + i].active;
  50. activeGroup++;
  51. if (!patched) {
  52. changed = changed || (groupSize[i] != 0);
  53. groupSize[i] = 0;
  54. }
  55. else if (patched) {
  56. isPatched = true;
  57. changed = changed || (groupSize[i] != activeGroup);
  58. groupSize[i] = activeGroup;
  59. activeGroup = 0;
  60. }
  61. }
  62. return changed;
  63. }
  64. int groupForSegment(int segment) {
  65. int group = 0;
  66. int currentGroupSize = 0;
  67. for (int i = 0; i < NUM_CHANNELS; i++) {
  68. if (currentGroupSize <= 0) {
  69. currentGroupSize = max(1, groupSize[i]);
  70. group = i;
  71. }
  72. if (segment == i) {
  73. return group;
  74. }
  75. currentGroupSize -= 1;
  76. }
  77. return segment;
  78. }
  79. };
  80. struct Stages : Module {
  81. enum ParamIds {
  82. ENUMS(SHAPE_PARAMS, NUM_CHANNELS),
  83. ENUMS(TYPE_PARAMS, NUM_CHANNELS),
  84. ENUMS(LEVEL_PARAMS, NUM_CHANNELS),
  85. NUM_PARAMS
  86. };
  87. enum InputIds {
  88. ENUMS(LEVEL_INPUTS, NUM_CHANNELS),
  89. ENUMS(GATE_INPUTS, NUM_CHANNELS),
  90. NUM_INPUTS
  91. };
  92. enum OutputIds {
  93. ENUMS(ENVELOPE_OUTPUTS, NUM_CHANNELS),
  94. NUM_OUTPUTS
  95. };
  96. enum LightIds {
  97. ENUMS(TYPE_LIGHTS, NUM_CHANNELS * 2),
  98. ENUMS(ENVELOPE_LIGHTS, NUM_CHANNELS),
  99. NUM_LIGHTS
  100. };
  101. stages::segment::Configuration configurations[NUM_CHANNELS];
  102. bool configuration_changed[NUM_CHANNELS];
  103. stages::SegmentGenerator segment_generator[NUM_CHANNELS];
  104. float lightOscillatorPhase;
  105. // Buttons
  106. LongPressButton typeButtons[NUM_CHANNELS];
  107. // Buffers
  108. float envelopeBuffer[NUM_CHANNELS][BLOCK_SIZE] = {};
  109. stmlib::GateFlags last_gate_flags[NUM_CHANNELS] = {};
  110. stmlib::GateFlags gate_flags[NUM_CHANNELS][BLOCK_SIZE] = {};
  111. int blockIndex = 0;
  112. GroupBuilder groupBuilder;
  113. Stages() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
  114. onReset();
  115. }
  116. void onReset() override {
  117. for (size_t i = 0; i < NUM_CHANNELS; ++i) {
  118. segment_generator[i].Init();
  119. configurations[i].type = stages::segment::TYPE_RAMP;
  120. configurations[i].loop = false;
  121. configuration_changed[i] = true;
  122. }
  123. lightOscillatorPhase = 0.f;
  124. onSampleRateChange();
  125. }
  126. json_t *toJson() override {
  127. json_t *rootJ = json_object();
  128. json_t *configurationsJ = json_array();
  129. for (int i = 0; i < NUM_CHANNELS; i++) {
  130. json_t *configurationJ = json_object();
  131. json_object_set_new(configurationJ, "type", json_integer(configurations[i].type));
  132. json_object_set_new(configurationJ, "loop", json_boolean(configurations[i].loop));
  133. json_array_insert_new(configurationsJ, i, configurationJ);
  134. }
  135. json_object_set_new(rootJ, "configurations", configurationsJ);
  136. return rootJ;
  137. }
  138. void fromJson(json_t *rootJ) override {
  139. json_t *configurationsJ = json_object_get(rootJ, "configurations");
  140. for (int i = 0; i < NUM_CHANNELS; i++) {
  141. json_t *configurationJ = json_array_get(configurationsJ, i);
  142. if (configurationJ) {
  143. json_t *typeJ = json_object_get(configurationJ, "type");
  144. if (typeJ)
  145. configurations[i].type = (stages::segment::Type) json_integer_value(typeJ);
  146. json_t *loopJ = json_object_get(configurationJ, "loop");
  147. if (loopJ)
  148. configurations[i].loop = json_boolean_value(loopJ);
  149. }
  150. }
  151. }
  152. void onSampleRateChange() override {
  153. for (int i = 0; i < NUM_CHANNELS; i++) {
  154. segment_generator[i].SetSampleRate(engineGetSampleRate());
  155. }
  156. }
  157. void stepBlock() {
  158. // Get parameters
  159. float primaries[NUM_CHANNELS];
  160. float secondaries[NUM_CHANNELS];
  161. for (int i = 0; i < NUM_CHANNELS; i++) {
  162. primaries[i] = clamp(params[LEVEL_PARAMS + i].value + inputs[LEVEL_INPUTS + i].value / 8.f, 0.f, 1.f);
  163. secondaries[i] = params[SHAPE_PARAMS + i].value;
  164. }
  165. // See if the group associations have changed since the last group
  166. bool groups_changed = groupBuilder.buildGroups(&inputs, GATE_INPUTS, NUM_CHANNELS);
  167. // Process block
  168. stages::SegmentGenerator::Output out[BLOCK_SIZE] = {};
  169. for (int i = 0; i < NUM_CHANNELS;) {
  170. // Check if the config needs applying to the segment generator for this group
  171. bool segment_changed = groups_changed;
  172. int numberOfLoops = 0;
  173. for (int j = 0; j < max(1, groupBuilder.groupSize[i]); j++) {
  174. numberOfLoops += configurations[i + j].loop ? 1 : 0;
  175. segment_changed |= configuration_changed[i + j];
  176. configuration_changed[i + j] = false;
  177. }
  178. if (segment_changed) {
  179. if (numberOfLoops > 2) {
  180. for (int j = 0; j < max(1, groupBuilder.groupSize[i]); j++) {
  181. configurations[i + j].loop = false;
  182. }
  183. }
  184. segment_generator[i].Configure(groupBuilder.groupSize[i] > 0, &configurations[i], max(1, groupBuilder.groupSize[i]));
  185. }
  186. // Set the segment parameters on the generator we're about to process
  187. for (int j = 0; j < segment_generator[i].num_segments(); j++) {
  188. segment_generator[i].set_segment_parameters(j, primaries[i + j], secondaries[i + j]);
  189. }
  190. segment_generator[i].Process(gate_flags[i], out, BLOCK_SIZE);
  191. // Set the outputs for the active segment in each output sample
  192. // All outputs also go to the first segment
  193. for (int j = 0; j < BLOCK_SIZE; j++) {
  194. for (int k = 1; k < segment_generator[i].num_segments(); k++) {
  195. envelopeBuffer[i + k][j] = k == out[j].segment ? 1 - out[j].phase : 0.f;
  196. }
  197. envelopeBuffer[i][j] = out[j].value;
  198. }
  199. i += segment_generator[i].num_segments();
  200. }
  201. }
  202. void toggleMode(int i) {
  203. configurations[i].type = (stages::segment::Type) ((configurations[i].type + 1) % 3);
  204. configuration_changed[i] = true;
  205. }
  206. void toggleLoop(int i) {
  207. configuration_changed[i] = true;
  208. configurations[i].loop = !configurations[i].loop;
  209. // ensure that we're the only loop item in the group
  210. if (configurations[i].loop) {
  211. int group = groupBuilder.groupForSegment(i);
  212. // See how many loop items we have
  213. int loopitems = 0;
  214. for (size_t j = 0; j < groupBuilder.groupSize[group]; j++) {
  215. loopitems += configurations[group + j].loop ? 1 : 0;
  216. }
  217. // If we've got too many loop items, clear down to the one looping segment
  218. if (loopitems > 2) {
  219. for (size_t j = 0; j < groupBuilder.groupSize[group]; j++) {
  220. configurations[group + j].loop = (group + (int)j) == i;
  221. }
  222. loopitems = 1;
  223. }
  224. }
  225. }
  226. void step() override {
  227. // Oscillate flashing the type lights
  228. lightOscillatorPhase += 0.5f * engineGetSampleTime();
  229. if (lightOscillatorPhase >= 1.0f)
  230. lightOscillatorPhase -= 1.0f;
  231. // Buttons
  232. for (int i = 0; i < NUM_CHANNELS; i++) {
  233. switch (typeButtons[i].step(params[TYPE_PARAMS + i])) {
  234. default:
  235. case LongPressButton::NO_PRESS: break;
  236. case LongPressButton::SHORT_PRESS: toggleMode(i); break;
  237. case LongPressButton::LONG_PRESS: toggleLoop(i); break;
  238. }
  239. }
  240. // Input
  241. for (int i = 0; i < NUM_CHANNELS; i++) {
  242. bool gate = (inputs[GATE_INPUTS + i].value >= 1.7f);
  243. last_gate_flags[i] = stmlib::ExtractGateFlags(last_gate_flags[i], gate);
  244. gate_flags[i][blockIndex] = last_gate_flags[i];
  245. }
  246. // Process block
  247. if (++blockIndex >= BLOCK_SIZE) {
  248. blockIndex = 0;
  249. stepBlock();
  250. }
  251. // Output
  252. int currentGroupSize = 0;
  253. int loopcount = 0;
  254. for (int i = 0; i < NUM_CHANNELS; i++) {
  255. float envelope = envelopeBuffer[i][blockIndex];
  256. outputs[ENVELOPE_OUTPUTS + i].value = envelope * 8.f;
  257. lights[ENVELOPE_LIGHTS + i].setBrightnessSmooth(envelope);
  258. if (currentGroupSize <= 0) {
  259. currentGroupSize = max(1, groupBuilder.groupSize[i]);
  260. loopcount = 0;
  261. }
  262. currentGroupSize -= 1;
  263. loopcount += configurations[i].loop ? 1 : 0;
  264. float flashlevel = 1.f;
  265. if (configurations[i].loop && loopcount == 1) {
  266. flashlevel = abs(sinf(2.0f * M_PI * lightOscillatorPhase));
  267. }
  268. else if (configurations[i].loop && loopcount > 1) {
  269. float advancedPhase = lightOscillatorPhase + 0.25f;
  270. if (advancedPhase > 1.0f)
  271. advancedPhase -= 1.0f;
  272. flashlevel = abs(sinf(2.0f * M_PI * advancedPhase));
  273. }
  274. lights[TYPE_LIGHTS + i * 2 + 0].setBrightness((configurations[i].type == 0 || configurations[i].type == 1) * flashlevel);
  275. lights[TYPE_LIGHTS + i * 2 + 1].setBrightness((configurations[i].type == 1 || configurations[i].type == 2) * flashlevel);
  276. }
  277. }
  278. };
  279. struct StagesWidget : ModuleWidget {
  280. StagesWidget(Stages *module) : ModuleWidget(module) {
  281. setPanel(SVG::load(assetPlugin(plugin, "res/Stages.svg")));
  282. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  283. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  284. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  285. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  286. addParam(ParamWidget::create<Trimpot>(mm2px(Vec(3.72965, 13.98158)), module, Stages::SHAPE_PARAMS + 0, 0.0, 1.0, 0.5));
  287. addParam(ParamWidget::create<Trimpot>(mm2px(Vec(15.17012, 13.98158)), module, Stages::SHAPE_PARAMS + 1, 0.0, 1.0, 0.5));
  288. addParam(ParamWidget::create<Trimpot>(mm2px(Vec(26.6099, 13.98158)), module, Stages::SHAPE_PARAMS + 2, 0.0, 1.0, 0.5));
  289. addParam(ParamWidget::create<Trimpot>(mm2px(Vec(38.07174, 13.98158)), module, Stages::SHAPE_PARAMS + 3, 0.0, 1.0, 0.5));
  290. addParam(ParamWidget::create<Trimpot>(mm2px(Vec(49.51152, 13.98158)), module, Stages::SHAPE_PARAMS + 4, 0.0, 1.0, 0.5));
  291. addParam(ParamWidget::create<Trimpot>(mm2px(Vec(60.95199, 13.98158)), module, Stages::SHAPE_PARAMS + 5, 0.0, 1.0, 0.5));
  292. addParam(ParamWidget::create<TL1105>(mm2px(Vec(4.17259, 32.37248)), module, Stages::TYPE_PARAMS + 0, 0.0, 1.0, 0.0));
  293. addParam(ParamWidget::create<TL1105>(mm2px(Vec(15.61237, 32.37248)), module, Stages::TYPE_PARAMS + 1, 0.0, 1.0, 0.0));
  294. addParam(ParamWidget::create<TL1105>(mm2px(Vec(27.05284, 32.37248)), module, Stages::TYPE_PARAMS + 2, 0.0, 1.0, 0.0));
  295. addParam(ParamWidget::create<TL1105>(mm2px(Vec(38.51399, 32.37248)), module, Stages::TYPE_PARAMS + 3, 0.0, 1.0, 0.0));
  296. addParam(ParamWidget::create<TL1105>(mm2px(Vec(49.95446, 32.37248)), module, Stages::TYPE_PARAMS + 4, 0.0, 1.0, 0.0));
  297. addParam(ParamWidget::create<TL1105>(mm2px(Vec(61.39424, 32.37248)), module, Stages::TYPE_PARAMS + 5, 0.0, 1.0, 0.0));
  298. addParam(ParamWidget::create<LEDSliderGreen>(mm2px(Vec(3.36193, 43.06508)), module, Stages::LEVEL_PARAMS + 0, 0.0, 1.0, 1.0));
  299. addParam(ParamWidget::create<LEDSliderGreen>(mm2px(Vec(14.81619, 43.06508)), module, Stages::LEVEL_PARAMS + 1, 0.0, 1.0, 1.0));
  300. addParam(ParamWidget::create<LEDSliderGreen>(mm2px(Vec(26.26975, 43.06508)), module, Stages::LEVEL_PARAMS + 2, 0.0, 1.0, 1.0));
  301. addParam(ParamWidget::create<LEDSliderGreen>(mm2px(Vec(37.70265, 43.06508)), module, Stages::LEVEL_PARAMS + 3, 0.0, 1.0, 1.0));
  302. addParam(ParamWidget::create<LEDSliderGreen>(mm2px(Vec(49.15759, 43.06508)), module, Stages::LEVEL_PARAMS + 4, 0.0, 1.0, 1.0));
  303. addParam(ParamWidget::create<LEDSliderGreen>(mm2px(Vec(60.61184, 43.06508)), module, Stages::LEVEL_PARAMS + 5, 0.0, 1.0, 1.0));
  304. addInput(Port::create<PJ301MPort>(mm2px(Vec(2.70756, 77.75277)), Port::INPUT, module, Stages::LEVEL_INPUTS + 0));
  305. addInput(Port::create<PJ301MPort>(mm2px(Vec(14.14734, 77.75277)), Port::INPUT, module, Stages::LEVEL_INPUTS + 1));
  306. addInput(Port::create<PJ301MPort>(mm2px(Vec(25.58781, 77.75277)), Port::INPUT, module, Stages::LEVEL_INPUTS + 2));
  307. addInput(Port::create<PJ301MPort>(mm2px(Vec(37.04896, 77.75277)), Port::INPUT, module, Stages::LEVEL_INPUTS + 3));
  308. addInput(Port::create<PJ301MPort>(mm2px(Vec(48.48943, 77.75277)), Port::INPUT, module, Stages::LEVEL_INPUTS + 4));
  309. addInput(Port::create<PJ301MPort>(mm2px(Vec(59.92921, 77.75277)), Port::INPUT, module, Stages::LEVEL_INPUTS + 5));
  310. addInput(Port::create<PJ301MPort>(mm2px(Vec(2.70756, 92.35239)), Port::INPUT, module, Stages::GATE_INPUTS + 0));
  311. addInput(Port::create<PJ301MPort>(mm2px(Vec(14.14734, 92.35239)), Port::INPUT, module, Stages::GATE_INPUTS + 1));
  312. addInput(Port::create<PJ301MPort>(mm2px(Vec(25.58781, 92.35239)), Port::INPUT, module, Stages::GATE_INPUTS + 2));
  313. addInput(Port::create<PJ301MPort>(mm2px(Vec(37.04896, 92.35239)), Port::INPUT, module, Stages::GATE_INPUTS + 3));
  314. addInput(Port::create<PJ301MPort>(mm2px(Vec(48.48943, 92.35239)), Port::INPUT, module, Stages::GATE_INPUTS + 4));
  315. addInput(Port::create<PJ301MPort>(mm2px(Vec(59.92921, 92.35239)), Port::INPUT, module, Stages::GATE_INPUTS + 5));
  316. addOutput(Port::create<PJ301MPort>(mm2px(Vec(2.70756, 106.95203)), Port::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 0));
  317. addOutput(Port::create<PJ301MPort>(mm2px(Vec(14.14734, 106.95203)), Port::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 1));
  318. addOutput(Port::create<PJ301MPort>(mm2px(Vec(25.58781, 106.95203)), Port::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 2));
  319. addOutput(Port::create<PJ301MPort>(mm2px(Vec(37.04896, 106.95203)), Port::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 3));
  320. addOutput(Port::create<PJ301MPort>(mm2px(Vec(48.48943, 106.95203)), Port::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 4));
  321. addOutput(Port::create<PJ301MPort>(mm2px(Vec(59.92921, 106.95203)), Port::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 5));
  322. addChild(ModuleLightWidget::create<MediumLight<GreenRedLight>>(mm2px(Vec(5.27737, 26.74447)), module, Stages::TYPE_LIGHTS + 0 * 2));
  323. addChild(ModuleLightWidget::create<MediumLight<GreenRedLight>>(mm2px(Vec(16.73784, 26.74447)), module, Stages::TYPE_LIGHTS + 1 * 2));
  324. addChild(ModuleLightWidget::create<MediumLight<GreenRedLight>>(mm2px(Vec(28.1783, 26.74447)), module, Stages::TYPE_LIGHTS + 2 * 2));
  325. addChild(ModuleLightWidget::create<MediumLight<GreenRedLight>>(mm2px(Vec(39.61877, 26.74447)), module, Stages::TYPE_LIGHTS + 3 * 2));
  326. addChild(ModuleLightWidget::create<MediumLight<GreenRedLight>>(mm2px(Vec(51.07923, 26.74447)), module, Stages::TYPE_LIGHTS + 4 * 2));
  327. addChild(ModuleLightWidget::create<MediumLight<GreenRedLight>>(mm2px(Vec(62.51971, 26.74447)), module, Stages::TYPE_LIGHTS + 5 * 2));
  328. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(mm2px(Vec(2.29462, 103.19253)), module, Stages::ENVELOPE_LIGHTS + 0));
  329. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(mm2px(Vec(13.73509, 103.19253)), module, Stages::ENVELOPE_LIGHTS + 1));
  330. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(mm2px(Vec(25.17556, 103.19253)), module, Stages::ENVELOPE_LIGHTS + 2));
  331. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(mm2px(Vec(36.63671, 103.19253)), module, Stages::ENVELOPE_LIGHTS + 3));
  332. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(mm2px(Vec(48.07649, 103.19253)), module, Stages::ENVELOPE_LIGHTS + 4));
  333. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(mm2px(Vec(59.51696, 103.19253)), module, Stages::ENVELOPE_LIGHTS + 5));
  334. }
  335. };
  336. Model *modelStages = Model::create<Stages, StagesWidget>("Audible Instruments", "Stages", "Segment Generator", FUNCTION_GENERATOR_TAG, ENVELOPE_GENERATOR_TAG);