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.

171 lines
4.9KB

  1. #include "Bidoo.hpp"
  2. #include "dsp/digital.hpp"
  3. #include "BidooComponents.hpp"
  4. #include <vector>
  5. #include "cmath"
  6. using namespace std;
  7. namespace rack_plugin_Bidoo {
  8. struct CHUTE : Module {
  9. enum ParamIds {
  10. ALTITUDE_PARAM,
  11. GRAVITY_PARAM,
  12. COR_PARAM,
  13. RUN_PARAM,
  14. NUM_PARAMS
  15. };
  16. enum InputIds {
  17. TRIG_INPUT,
  18. ALTITUDE_INPUT,
  19. GRAVITY_INPUT,
  20. COR_INPUT,
  21. NUM_INPUTS
  22. };
  23. enum OutputIds {
  24. GATE_OUTPUT,
  25. PITCH_OUTPUT,
  26. PITCHSTEP_OUTPUT,
  27. NUM_OUTPUTS
  28. };
  29. enum LightIds {
  30. NUM_LIGHTS
  31. };
  32. bool running = false;
  33. float phase = 0.0f;
  34. float altitude = 0.0f;
  35. float altitudeInit = 0.0f;
  36. float minAlt = 0.0f;
  37. float speed = 0.0f;
  38. bool desc = false;
  39. SchmittTrigger playTrigger;
  40. SchmittTrigger gateTypeTrigger;
  41. CHUTE() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { }
  42. void step() override;
  43. };
  44. void CHUTE::step() {
  45. // Running
  46. if (playTrigger.process(params[RUN_PARAM].value + inputs[TRIG_INPUT].value)) {
  47. running = true;
  48. desc = true;
  49. altitude = params[ALTITUDE_PARAM].value + inputs[ALTITUDE_INPUT].value;
  50. altitudeInit = altitude;
  51. minAlt = altitude;
  52. speed = 0.0f;
  53. }
  54. // Altitude calculation
  55. if (running) {
  56. if (minAlt<0.0001f) {
  57. running = false;
  58. altitude = 0.0f;
  59. minAlt = 0.0f;
  60. }
  61. else
  62. {
  63. phase = 1.0f / engineGetSampleRate();
  64. if (desc) {
  65. speed += (params[GRAVITY_PARAM].value + inputs[GRAVITY_INPUT].value)*phase;
  66. altitude = altitude - (speed * phase);
  67. if (altitude <= 0.0f) {
  68. desc=false;
  69. speed = speed * (params[COR_PARAM].value + + inputs[COR_INPUT].value);
  70. altitude = 0.0f;
  71. }
  72. }
  73. else {
  74. speed = speed - (params[GRAVITY_PARAM].value + inputs[GRAVITY_INPUT].value)*phase;
  75. if (speed<=0.0f) {
  76. speed = 0.0f;
  77. desc=true;
  78. minAlt=min(minAlt,altitude);
  79. }
  80. else {
  81. altitude = altitude + (speed * phase);
  82. }
  83. }
  84. }
  85. }
  86. //Calculate output
  87. outputs[GATE_OUTPUT].value = running ? desc ? 10.0f : 0.0f : 0.0f;
  88. outputs[PITCH_OUTPUT].value = running ? 10.0f * altitude/ altitudeInit : 0.0f;
  89. outputs[PITCHSTEP_OUTPUT].value = running ? 10.0f * minAlt/ altitudeInit : 0.0f;
  90. }
  91. struct CHUTEDisplay : TransparentWidget {
  92. CHUTE *module;
  93. int frame = 0;
  94. shared_ptr<Font> font;
  95. CHUTEDisplay() {
  96. font = Font::load(assetPlugin(plugin, "res/DejaVuSansMono.ttf"));
  97. }
  98. void draw(NVGcontext *vg) override {
  99. frame = 0;
  100. nvgFontSize(vg, 18.0f);
  101. nvgFontFaceId(vg, font->handle);
  102. nvgTextLetterSpacing(vg, -2.0f);
  103. nvgFillColor(vg, nvgRGBA(0x00, 0x00, 0x00, 0xff));
  104. float altRatio = clamp(module->altitude / module->altitudeInit, 0.0f, 1.0f);
  105. int pos = roundl(box.size.y + altRatio * (9.0f - box.size.y));
  106. nvgText(vg, 6.0f, pos, "☻", NULL);
  107. }
  108. };
  109. struct CHUTEWidget : ModuleWidget {
  110. CHUTEWidget(CHUTE *module) : ModuleWidget(module) {
  111. setPanel(SVG::load(assetPlugin(plugin, "res/CHUTE.svg")));
  112. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  113. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  114. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  115. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  116. {
  117. CHUTEDisplay *display = new CHUTEDisplay();
  118. display->module = module;
  119. display->box.pos = Vec(110.0f, 30.0f);
  120. display->box.size = Vec(40.0f, 180.0f);
  121. addChild(display);
  122. }
  123. static const float portX[2] = {20.0f, 60.0f};
  124. static const float portY[3] = {52.0f, 116.0f, 178.0f};
  125. addInput(Port::create<PJ301MPort>(Vec(portX[0], portY[0]),Port::INPUT, module, CHUTE::ALTITUDE_INPUT));
  126. addParam(ParamWidget::create<BidooBlueKnob>(Vec(portX[1]-1, portY[0]-2.0f), module, CHUTE::ALTITUDE_PARAM, 0.01f, 3.0f, 1.0f));
  127. addInput(Port::create<PJ301MPort>(Vec(portX[0], portY[1]),Port::INPUT, module, CHUTE::GRAVITY_INPUT));
  128. addParam(ParamWidget::create<BidooBlueKnob>(Vec(portX[1]-1, portY[1]-2.0f), module, CHUTE::GRAVITY_PARAM, 1.622f, 11.15f, 9.798f)); // between the Moon and Neptune
  129. addInput(Port::create<PJ301MPort>(Vec(portX[0], portY[2]),Port::INPUT, module, CHUTE::COR_INPUT));
  130. addParam(ParamWidget::create<BidooBlueKnob>(Vec(portX[1]-1, portY[2]-2.0f), module, CHUTE::COR_PARAM, 0.0f, 1.0f, 0.69f)); // 0 inelastic, 1 perfect elastic, 0.69 glass
  131. addParam(ParamWidget::create<BlueCKD6>(Vec(51.0f, 269.0f), module, CHUTE::RUN_PARAM, 0.0f, 1.0f, 0.0f));
  132. addInput(Port::create<PJ301MPort>(Vec(11.0f, 270.0f),Port::INPUT, module, CHUTE::TRIG_INPUT));
  133. addOutput(Port::create<PJ301MPort>(Vec(11.0f, 320.0f),Port::OUTPUT, module, CHUTE::GATE_OUTPUT));
  134. addOutput(Port::create<PJ301MPort>(Vec(54.0f, 320.0f),Port::OUTPUT, module, CHUTE::PITCH_OUTPUT));
  135. addOutput(Port::create<PJ301MPort>(Vec(96.0f, 320.0f),Port::OUTPUT, module, CHUTE::PITCHSTEP_OUTPUT));
  136. }
  137. };
  138. } // namespace rack_plugin_Bidoo
  139. using namespace rack_plugin_Bidoo;
  140. RACK_PLUGIN_MODEL_INIT(Bidoo, CHUTE) {
  141. Model *modelCHUTE = Model::create<CHUTE, CHUTEWidget>("Bidoo", "ChUTE", "ChUTE trigger", SEQUENCER_TAG);
  142. return modelCHUTE;
  143. }