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.

441 lines
17KB

  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 GroupInfo {
  37. int first_segment = 0;
  38. int segment_count = 0;
  39. bool gated = false;
  40. };
  41. struct GroupBuilder {
  42. GroupInfo groups[NUM_CHANNELS];
  43. int groupCount = 0;
  44. bool buildGroups(std::vector<Input> *gateInputs, size_t first, size_t count) {
  45. bool any_gates = false;
  46. GroupInfo nextGroups[NUM_CHANNELS];
  47. int currentGroup = 0;
  48. for (int i = 0; i < NUM_CHANNELS; i++) {
  49. bool gated = (*gateInputs)[first + i].active;
  50. if (!any_gates) {
  51. if (!gated) {
  52. // No gates at all yet, segments are all single segment groups
  53. nextGroups[currentGroup].first_segment = i;
  54. nextGroups[currentGroup].segment_count = 1;
  55. nextGroups[currentGroup].gated = false;
  56. currentGroup++;
  57. }
  58. else {
  59. // first gate, current group is start of a segment group
  60. any_gates = true;
  61. nextGroups[currentGroup].first_segment = i;
  62. nextGroups[currentGroup].segment_count = 1;
  63. nextGroups[currentGroup].gated = true;
  64. currentGroup++;
  65. }
  66. }
  67. else {
  68. if (!gated) {
  69. // We've had a gate, this ungated segment is part of the previous group
  70. nextGroups[currentGroup-1].segment_count++;
  71. }
  72. else {
  73. // This gated input indicates the start of the next group
  74. nextGroups[currentGroup].first_segment = i;
  75. nextGroups[currentGroup].segment_count = 1;
  76. nextGroups[currentGroup].gated = true;
  77. currentGroup++;
  78. }
  79. }
  80. }
  81. bool changed = false;
  82. if (currentGroup != groupCount) {
  83. changed = true;
  84. groupCount = currentGroup;
  85. }
  86. for (int i = 0; i < groupCount; i++) {
  87. if (nextGroups[i].segment_count != groups[i].segment_count ||
  88. nextGroups[i].gated != groups[i].gated ||
  89. nextGroups[i].first_segment != groups[i].first_segment) {
  90. changed = true;
  91. }
  92. groups[i].first_segment = nextGroups[i].first_segment;
  93. groups[i].segment_count = nextGroups[i].segment_count;
  94. groups[i].gated = nextGroups[i].gated;
  95. }
  96. return changed;
  97. }
  98. };
  99. struct Stages : Module {
  100. enum ParamIds {
  101. ENUMS(SHAPE_PARAMS, NUM_CHANNELS),
  102. ENUMS(TYPE_PARAMS, NUM_CHANNELS),
  103. ENUMS(LEVEL_PARAMS, NUM_CHANNELS),
  104. NUM_PARAMS
  105. };
  106. enum InputIds {
  107. ENUMS(LEVEL_INPUTS, NUM_CHANNELS),
  108. ENUMS(GATE_INPUTS, NUM_CHANNELS),
  109. NUM_INPUTS
  110. };
  111. enum OutputIds {
  112. ENUMS(ENVELOPE_OUTPUTS, NUM_CHANNELS),
  113. NUM_OUTPUTS
  114. };
  115. enum LightIds {
  116. ENUMS(TYPE_LIGHTS, NUM_CHANNELS * 2),
  117. ENUMS(ENVELOPE_LIGHTS, NUM_CHANNELS),
  118. NUM_LIGHTS
  119. };
  120. stages::segment::Configuration configurations[NUM_CHANNELS];
  121. bool configuration_changed[NUM_CHANNELS];
  122. stages::SegmentGenerator segment_generator[NUM_CHANNELS];
  123. float lightOscillatorPhase;
  124. // Buttons
  125. LongPressButton typeButtons[NUM_CHANNELS];
  126. // Buffers
  127. float envelopeBuffer[NUM_CHANNELS][BLOCK_SIZE] = {};
  128. stmlib::GateFlags last_gate_flags[NUM_CHANNELS] = {};
  129. stmlib::GateFlags gate_flags[NUM_CHANNELS][BLOCK_SIZE] = {};
  130. int blockIndex = 0;
  131. GroupBuilder groupBuilder;
  132. Stages() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
  133. onReset();
  134. }
  135. void onReset() override {
  136. for (size_t i = 0; i < NUM_CHANNELS; ++i) {
  137. segment_generator[i].Init();
  138. configurations[i].type = stages::segment::TYPE_RAMP;
  139. configurations[i].loop = false;
  140. configuration_changed[i] = true;
  141. }
  142. lightOscillatorPhase = 0.f;
  143. onSampleRateChange();
  144. }
  145. json_t *toJson() override {
  146. json_t *rootJ = json_object();
  147. json_t *configurationsJ = json_array();
  148. for (int i = 0; i < NUM_CHANNELS; i++) {
  149. json_t *configurationJ = json_object();
  150. json_object_set_new(configurationJ, "type", json_integer(configurations[i].type));
  151. json_object_set_new(configurationJ, "loop", json_boolean(configurations[i].loop));
  152. json_array_insert_new(configurationsJ, i, configurationJ);
  153. }
  154. json_object_set_new(rootJ, "configurations", configurationsJ);
  155. return rootJ;
  156. }
  157. void fromJson(json_t *rootJ) override {
  158. json_t *configurationsJ = json_object_get(rootJ, "configurations");
  159. for (int i = 0; i < NUM_CHANNELS; i++) {
  160. json_t *configurationJ = json_array_get(configurationsJ, i);
  161. if (configurationJ) {
  162. json_t *typeJ = json_object_get(configurationJ, "type");
  163. if (typeJ)
  164. configurations[i].type = (stages::segment::Type) json_integer_value(typeJ);
  165. json_t *loopJ = json_object_get(configurationJ, "loop");
  166. if (loopJ)
  167. configurations[i].loop = json_boolean_value(loopJ);
  168. }
  169. }
  170. }
  171. void onSampleRateChange() override {
  172. for (int i = 0; i < NUM_CHANNELS; i++) {
  173. segment_generator[i].SetSampleRate(engineGetSampleRate());
  174. }
  175. }
  176. void stepBlock() {
  177. // Get parameters
  178. float primaries[NUM_CHANNELS];
  179. float secondaries[NUM_CHANNELS];
  180. for (int i = 0; i < NUM_CHANNELS; i++) {
  181. primaries[i] = clamp(params[LEVEL_PARAMS + i].value + inputs[LEVEL_INPUTS + i].value / 8.f, 0.f, 1.f);
  182. secondaries[i] = params[SHAPE_PARAMS + i].value;
  183. }
  184. // See if the group associations have changed since the last group
  185. bool groups_changed = groupBuilder.buildGroups(&inputs, GATE_INPUTS, NUM_CHANNELS);
  186. // Process block
  187. stages::SegmentGenerator::Output out[BLOCK_SIZE] = {};
  188. for (int i = 0; i < groupBuilder.groupCount; i++) {
  189. GroupInfo &group = groupBuilder.groups[i];
  190. // Check if the config needs applying to the segment generator for this group
  191. bool apply_config = groups_changed;
  192. int numberOfLoopsInGroup = 0;
  193. for (int j = 0; j < group.segment_count; j++) {
  194. int segment = group.first_segment + j;
  195. numberOfLoopsInGroup += configurations[segment].loop ? 1 : 0;
  196. apply_config |= configuration_changed[segment];
  197. configuration_changed[segment] = false;
  198. }
  199. if (numberOfLoopsInGroup > 2) {
  200. // Too many segments are looping, turn them all off
  201. apply_config = true;
  202. for (int j = 0; j < group.segment_count; j++) {
  203. configurations[group.first_segment + j].loop = false;
  204. }
  205. }
  206. if (apply_config) {
  207. segment_generator[i].Configure(group.gated, &configurations[group.first_segment], group.segment_count);
  208. }
  209. // Set the segment parameters on the generator we're about to process
  210. for (int j = 0; j < group.segment_count; j++) {
  211. segment_generator[i].set_segment_parameters(j, primaries[group.first_segment + j], secondaries[group.first_segment + j]);
  212. }
  213. segment_generator[i].Process(gate_flags[group.first_segment], out, BLOCK_SIZE);
  214. for (int j = 0; j < BLOCK_SIZE; j++) {
  215. for (int k = 1; k < group.segment_count; k++) {
  216. int segment = group.first_segment + k;
  217. if (k == out[j].segment) {
  218. // Set the phase output for the active segment
  219. envelopeBuffer[segment][j] = 1.f - out[j].phase;
  220. }
  221. else {
  222. // Non active segments have 0.f output
  223. envelopeBuffer[segment][j] = 0.f;
  224. }
  225. }
  226. // First group segment gets the actual output
  227. envelopeBuffer[group.first_segment][j] = out[j].value;
  228. }
  229. }
  230. }
  231. void toggleMode(int i) {
  232. configurations[i].type = (stages::segment::Type) ((configurations[i].type + 1) % 3);
  233. configuration_changed[i] = true;
  234. }
  235. void toggleLoop(int segment) {
  236. configuration_changed[segment] = true;
  237. configurations[segment].loop = !configurations[segment].loop;
  238. // ensure that we don't have too many looping segments in the group
  239. if (configurations[segment].loop) {
  240. int segment_count = 0;
  241. for (int i = 0; i < groupBuilder.groupCount; i++) {
  242. segment_count += groupBuilder.groups[i].segment_count;
  243. if (segment_count > segment) {
  244. GroupInfo &group = groupBuilder.groups[i];
  245. // See how many loop items we have
  246. int numberOfLoopsInGroup = 0;
  247. for (int j = 0; j < group.segment_count; j++) {
  248. numberOfLoopsInGroup += configurations[group.first_segment + j].loop ? 1 : 0;
  249. }
  250. // If we've got too many loop items, clear down to the one looping segment
  251. if (numberOfLoopsInGroup > 2) {
  252. for (int j = 0; j < group.segment_count; j++) {
  253. configurations[group.first_segment + j].loop = (group.first_segment + j) == segment;
  254. }
  255. }
  256. break;
  257. }
  258. }
  259. }
  260. }
  261. void step() override {
  262. // Oscillate flashing the type lights
  263. lightOscillatorPhase += 0.5f * engineGetSampleTime();
  264. if (lightOscillatorPhase >= 1.0f)
  265. lightOscillatorPhase -= 1.0f;
  266. // Buttons
  267. for (int i = 0; i < NUM_CHANNELS; i++) {
  268. switch (typeButtons[i].step(params[TYPE_PARAMS + i])) {
  269. default:
  270. case LongPressButton::NO_PRESS: break;
  271. case LongPressButton::SHORT_PRESS: toggleMode(i); break;
  272. case LongPressButton::LONG_PRESS: toggleLoop(i); break;
  273. }
  274. }
  275. // Input
  276. for (int i = 0; i < NUM_CHANNELS; i++) {
  277. bool gate = (inputs[GATE_INPUTS + i].value >= 1.7f);
  278. last_gate_flags[i] = stmlib::ExtractGateFlags(last_gate_flags[i], gate);
  279. gate_flags[i][blockIndex] = last_gate_flags[i];
  280. }
  281. // Process block
  282. if (++blockIndex >= BLOCK_SIZE) {
  283. blockIndex = 0;
  284. stepBlock();
  285. }
  286. // Output
  287. for (int i = 0; i < groupBuilder.groupCount; i++) {
  288. GroupInfo &group = groupBuilder.groups[i];
  289. int numberOfLoopsInGroup = 0;
  290. for (int j = 0; j < group.segment_count; j++) {
  291. int segment = group.first_segment + j;
  292. float envelope = envelopeBuffer[segment][blockIndex];
  293. outputs[ENVELOPE_OUTPUTS + segment].value = envelope * 8.f;
  294. lights[ENVELOPE_LIGHTS + segment].setBrightnessSmooth(envelope);
  295. numberOfLoopsInGroup += configurations[segment].loop ? 1 : 0;
  296. float flashlevel = 1.f;
  297. if (configurations[segment].loop && numberOfLoopsInGroup == 1) {
  298. flashlevel = abs(sinf(2.0f * M_PI * lightOscillatorPhase));
  299. }
  300. else if (configurations[segment].loop && numberOfLoopsInGroup > 1) {
  301. float advancedPhase = lightOscillatorPhase + 0.25f;
  302. if (advancedPhase > 1.0f)
  303. advancedPhase -= 1.0f;
  304. flashlevel = abs(sinf(2.0f * M_PI * advancedPhase));
  305. }
  306. lights[TYPE_LIGHTS + segment * 2 + 0].setBrightness((configurations[segment].type == 0 || configurations[segment].type == 1) * flashlevel);
  307. lights[TYPE_LIGHTS + segment * 2 + 1].setBrightness((configurations[segment].type == 1 || configurations[segment].type == 2) * flashlevel);
  308. }
  309. }
  310. }
  311. };
  312. struct StagesWidget : ModuleWidget {
  313. StagesWidget(Stages *module) : ModuleWidget(module) {
  314. setPanel(SVG::load(assetPlugin(plugin, "res/Stages.svg")));
  315. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  316. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  317. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  318. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  319. addParam(ParamWidget::create<Trimpot>(mm2px(Vec(3.72965, 13.98158)), module, Stages::SHAPE_PARAMS + 0, 0.0, 1.0, 0.5));
  320. addParam(ParamWidget::create<Trimpot>(mm2px(Vec(15.17012, 13.98158)), module, Stages::SHAPE_PARAMS + 1, 0.0, 1.0, 0.5));
  321. addParam(ParamWidget::create<Trimpot>(mm2px(Vec(26.6099, 13.98158)), module, Stages::SHAPE_PARAMS + 2, 0.0, 1.0, 0.5));
  322. addParam(ParamWidget::create<Trimpot>(mm2px(Vec(38.07174, 13.98158)), module, Stages::SHAPE_PARAMS + 3, 0.0, 1.0, 0.5));
  323. addParam(ParamWidget::create<Trimpot>(mm2px(Vec(49.51152, 13.98158)), module, Stages::SHAPE_PARAMS + 4, 0.0, 1.0, 0.5));
  324. addParam(ParamWidget::create<Trimpot>(mm2px(Vec(60.95199, 13.98158)), module, Stages::SHAPE_PARAMS + 5, 0.0, 1.0, 0.5));
  325. addParam(ParamWidget::create<TL1105>(mm2px(Vec(4.17259, 32.37248)), module, Stages::TYPE_PARAMS + 0, 0.0, 1.0, 0.0));
  326. addParam(ParamWidget::create<TL1105>(mm2px(Vec(15.61237, 32.37248)), module, Stages::TYPE_PARAMS + 1, 0.0, 1.0, 0.0));
  327. addParam(ParamWidget::create<TL1105>(mm2px(Vec(27.05284, 32.37248)), module, Stages::TYPE_PARAMS + 2, 0.0, 1.0, 0.0));
  328. addParam(ParamWidget::create<TL1105>(mm2px(Vec(38.51399, 32.37248)), module, Stages::TYPE_PARAMS + 3, 0.0, 1.0, 0.0));
  329. addParam(ParamWidget::create<TL1105>(mm2px(Vec(49.95446, 32.37248)), module, Stages::TYPE_PARAMS + 4, 0.0, 1.0, 0.0));
  330. addParam(ParamWidget::create<TL1105>(mm2px(Vec(61.39424, 32.37248)), module, Stages::TYPE_PARAMS + 5, 0.0, 1.0, 0.0));
  331. addParam(ParamWidget::create<LEDSliderGreen>(mm2px(Vec(3.36193, 43.06508)), module, Stages::LEVEL_PARAMS + 0, 0.0, 1.0, 0.5));
  332. addParam(ParamWidget::create<LEDSliderGreen>(mm2px(Vec(14.81619, 43.06508)), module, Stages::LEVEL_PARAMS + 1, 0.0, 1.0, 0.5));
  333. addParam(ParamWidget::create<LEDSliderGreen>(mm2px(Vec(26.26975, 43.06508)), module, Stages::LEVEL_PARAMS + 2, 0.0, 1.0, 0.5));
  334. addParam(ParamWidget::create<LEDSliderGreen>(mm2px(Vec(37.70265, 43.06508)), module, Stages::LEVEL_PARAMS + 3, 0.0, 1.0, 0.5));
  335. addParam(ParamWidget::create<LEDSliderGreen>(mm2px(Vec(49.15759, 43.06508)), module, Stages::LEVEL_PARAMS + 4, 0.0, 1.0, 0.5));
  336. addParam(ParamWidget::create<LEDSliderGreen>(mm2px(Vec(60.61184, 43.06508)), module, Stages::LEVEL_PARAMS + 5, 0.0, 1.0, 0.5));
  337. addInput(Port::create<PJ301MPort>(mm2px(Vec(2.70756, 77.75277)), Port::INPUT, module, Stages::LEVEL_INPUTS + 0));
  338. addInput(Port::create<PJ301MPort>(mm2px(Vec(14.14734, 77.75277)), Port::INPUT, module, Stages::LEVEL_INPUTS + 1));
  339. addInput(Port::create<PJ301MPort>(mm2px(Vec(25.58781, 77.75277)), Port::INPUT, module, Stages::LEVEL_INPUTS + 2));
  340. addInput(Port::create<PJ301MPort>(mm2px(Vec(37.04896, 77.75277)), Port::INPUT, module, Stages::LEVEL_INPUTS + 3));
  341. addInput(Port::create<PJ301MPort>(mm2px(Vec(48.48943, 77.75277)), Port::INPUT, module, Stages::LEVEL_INPUTS + 4));
  342. addInput(Port::create<PJ301MPort>(mm2px(Vec(59.92921, 77.75277)), Port::INPUT, module, Stages::LEVEL_INPUTS + 5));
  343. addInput(Port::create<PJ301MPort>(mm2px(Vec(2.70756, 92.35239)), Port::INPUT, module, Stages::GATE_INPUTS + 0));
  344. addInput(Port::create<PJ301MPort>(mm2px(Vec(14.14734, 92.35239)), Port::INPUT, module, Stages::GATE_INPUTS + 1));
  345. addInput(Port::create<PJ301MPort>(mm2px(Vec(25.58781, 92.35239)), Port::INPUT, module, Stages::GATE_INPUTS + 2));
  346. addInput(Port::create<PJ301MPort>(mm2px(Vec(37.04896, 92.35239)), Port::INPUT, module, Stages::GATE_INPUTS + 3));
  347. addInput(Port::create<PJ301MPort>(mm2px(Vec(48.48943, 92.35239)), Port::INPUT, module, Stages::GATE_INPUTS + 4));
  348. addInput(Port::create<PJ301MPort>(mm2px(Vec(59.92921, 92.35239)), Port::INPUT, module, Stages::GATE_INPUTS + 5));
  349. addOutput(Port::create<PJ301MPort>(mm2px(Vec(2.70756, 106.95203)), Port::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 0));
  350. addOutput(Port::create<PJ301MPort>(mm2px(Vec(14.14734, 106.95203)), Port::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 1));
  351. addOutput(Port::create<PJ301MPort>(mm2px(Vec(25.58781, 106.95203)), Port::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 2));
  352. addOutput(Port::create<PJ301MPort>(mm2px(Vec(37.04896, 106.95203)), Port::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 3));
  353. addOutput(Port::create<PJ301MPort>(mm2px(Vec(48.48943, 106.95203)), Port::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 4));
  354. addOutput(Port::create<PJ301MPort>(mm2px(Vec(59.92921, 106.95203)), Port::OUTPUT, module, Stages::ENVELOPE_OUTPUTS + 5));
  355. addChild(ModuleLightWidget::create<MediumLight<GreenRedLight>>(mm2px(Vec(5.27737, 26.74447)), module, Stages::TYPE_LIGHTS + 0 * 2));
  356. addChild(ModuleLightWidget::create<MediumLight<GreenRedLight>>(mm2px(Vec(16.73784, 26.74447)), module, Stages::TYPE_LIGHTS + 1 * 2));
  357. addChild(ModuleLightWidget::create<MediumLight<GreenRedLight>>(mm2px(Vec(28.1783, 26.74447)), module, Stages::TYPE_LIGHTS + 2 * 2));
  358. addChild(ModuleLightWidget::create<MediumLight<GreenRedLight>>(mm2px(Vec(39.61877, 26.74447)), module, Stages::TYPE_LIGHTS + 3 * 2));
  359. addChild(ModuleLightWidget::create<MediumLight<GreenRedLight>>(mm2px(Vec(51.07923, 26.74447)), module, Stages::TYPE_LIGHTS + 4 * 2));
  360. addChild(ModuleLightWidget::create<MediumLight<GreenRedLight>>(mm2px(Vec(62.51971, 26.74447)), module, Stages::TYPE_LIGHTS + 5 * 2));
  361. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(mm2px(Vec(2.29462, 103.19253)), module, Stages::ENVELOPE_LIGHTS + 0));
  362. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(mm2px(Vec(13.73509, 103.19253)), module, Stages::ENVELOPE_LIGHTS + 1));
  363. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(mm2px(Vec(25.17556, 103.19253)), module, Stages::ENVELOPE_LIGHTS + 2));
  364. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(mm2px(Vec(36.63671, 103.19253)), module, Stages::ENVELOPE_LIGHTS + 3));
  365. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(mm2px(Vec(48.07649, 103.19253)), module, Stages::ENVELOPE_LIGHTS + 4));
  366. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(mm2px(Vec(59.51696, 103.19253)), module, Stages::ENVELOPE_LIGHTS + 5));
  367. }
  368. };
  369. Model *modelStages = Model::create<Stages, StagesWidget>("Audible Instruments", "Stages", "Segment Generator", FUNCTION_GENERATOR_TAG, ENVELOPE_GENERATOR_TAG);