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.

446 lines
16KB

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