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.

178 lines
5.3KB

  1. /*
  2. Heads
  3. */////////////////////////////////////////////////////////////////////////////
  4. #include "pvc.hpp"
  5. #include "dsp/digital.hpp"
  6. struct Heads : Module {
  7. enum ParamIds {
  8. PROB_UI,
  9. TOSS_MODE,
  10. TOSS_UI,
  11. FLIP_UI,
  12. SET_A_UI,
  13. SET_B_UI,
  14. NUM_PARAMS
  15. };
  16. enum InputIds {
  17. SIG_A_IN,
  18. SIG_B_IN,
  19. PROB_CV,
  20. TOSS_IN,
  21. FLIP_IN,
  22. SET_A_IN,
  23. SET_B_IN,
  24. NUM_INPUTS
  25. };
  26. enum OutputIds {
  27. SIG_OUT,
  28. GATE_A_OUT,
  29. GATE_B_OUT,
  30. TRIG_A_OUT,
  31. TRIG_B_OUT,
  32. NUM_OUTPUTS
  33. };
  34. enum LightIds {
  35. A_LED,
  36. B_LED,
  37. DIR_LED,
  38. FLP_LED,
  39. NUM_LIGHTS
  40. };
  41. bool gate = false;
  42. bool flipMode = false;
  43. SchmittTrigger tossTrigger;
  44. SchmittTrigger flipTrigger;
  45. SchmittTrigger resetTrigger;
  46. PulseGenerator gatePulse;
  47. Heads() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  48. void step() override;
  49. void reset() override {
  50. gate = false;
  51. flipMode = false;
  52. }
  53. json_t *toJson() override {
  54. json_t *rootJ = json_object();
  55. json_t *gateStateJ = json_boolean(gate);
  56. json_object_set_new(rootJ, "gateState", gateStateJ);
  57. return rootJ;
  58. }
  59. void fromJson(json_t *rootJ) override {
  60. json_t *gateStateJ = json_object_get(rootJ, "gateState");
  61. if (gateStateJ)
  62. gate = json_boolean_value(gateStateJ);
  63. }
  64. };
  65. void Heads::step() {
  66. flipMode = params[TOSS_MODE].value;
  67. if (tossTrigger.process(inputs[TOSS_IN].value + params[TOSS_UI].value)) {
  68. gatePulse.trigger(0.01f);
  69. if (flipMode)
  70. gate = (randomUniform() < params[PROB_UI].value + inputs[PROB_CV].value) ? !gate : gate;
  71. else
  72. gate = (randomUniform() < (params[PROB_UI].value + inputs[PROB_CV].value*0.1f));
  73. }
  74. if (flipTrigger.process(inputs[FLIP_IN].value + params[FLIP_UI].value)) {
  75. gatePulse.trigger(0.01f);
  76. gate = !gate;
  77. }
  78. if (resetTrigger.process(inputs[SET_A_IN].value + params[SET_A_UI].value)) {
  79. gatePulse.trigger(0.01f);
  80. gate = false;
  81. }
  82. if (resetTrigger.process(inputs[SET_B_IN].value + params[SET_B_UI].value)) {
  83. gatePulse.trigger(0.01f);
  84. gate = true;
  85. }
  86. outputs[SIG_OUT].value = !gate ? inputs[SIG_A_IN].value : inputs[SIG_B_IN].value;
  87. outputs[GATE_A_OUT].value = !gate * 10.0f;
  88. outputs[TRIG_A_OUT].value = !gate * gatePulse.process(1.0/engineGetSampleRate()) * 10.0f;
  89. outputs[GATE_B_OUT].value = gate * 10.0f;
  90. outputs[TRIG_B_OUT].value = gate * gatePulse.process(1.0/engineGetSampleRate()) * 10.0f;
  91. lights[A_LED].value = !gate;
  92. lights[B_LED].value = gate;
  93. lights[DIR_LED].value = !flipMode;
  94. lights[FLP_LED].value = flipMode;
  95. }
  96. struct ModeToggle : SVGSwitch, ToggleSwitch {
  97. ModeToggle() {
  98. addFrame(SVG::load(assetPlugin(plugin, "res/components/empty.svg")));
  99. box.size = Vec(12,6);
  100. }
  101. };
  102. struct HeadsWidget : ModuleWidget {
  103. HeadsWidget(Heads *module);
  104. };
  105. HeadsWidget::HeadsWidget(Heads *module) : ModuleWidget(module) {
  106. setPanel(SVG::load(assetPlugin(plugin, "res/panels/Heads.svg")));
  107. // screws
  108. addChild(Widget::create<ScrewHead1>(Vec(15, 0)));
  109. addChild(Widget::create<ScrewHead2>(Vec(box.size.x - 15, 0)));
  110. addChild(Widget::create<ScrewHead3>(Vec(30, 365)));
  111. // addChild(Widget::create<ScrewHead4>(Vec(box.size.x - 15, 365)));
  112. addInput(Port::create<InPortAud>(Vec(4,22), Port::INPUT, module, Heads::SIG_A_IN));
  113. addInput(Port::create<InPortAud>(Vec(34,22), Port::INPUT, module, Heads::SIG_B_IN));
  114. addParam(ParamWidget::create<PvCKnob>(Vec(19,64),module, Heads::PROB_UI, 0.0f, 1.0f, 0.5f));
  115. addInput(Port::create<InPortCtrl>(Vec(19,88), Port::INPUT, module, Heads::PROB_CV));
  116. addInput(Port::create<InPortBin>(Vec(19,124), Port::INPUT, module, Heads::TOSS_IN));
  117. addParam(ParamWidget::create<LabelButtonL>(Vec(12,149), module, Heads::TOSS_UI, 0, 1, 0));
  118. addChild(ModuleLightWidget::create<FourPixLight<OrangeLED>>(Vec(25,165),module, Heads::DIR_LED));
  119. addChild(ModuleLightWidget::create<FourPixLight<BlueLED>>(Vec(31,165),module, Heads::FLP_LED));
  120. addParam(ParamWidget::create<ModeToggle>(Vec(24,164), module, Heads::TOSS_MODE, 0, 1, 0));
  121. addInput(Port::create<InPortBin>(Vec(19,180), Port::INPUT, module, Heads::FLIP_IN));
  122. addParam(ParamWidget::create<LabelButtonL>(Vec(12,205), module, Heads::FLIP_UI, 0, 1, 0));
  123. addInput(Port::create<InPortBin>(Vec(4,222), Port::INPUT, module, Heads::SET_A_IN));
  124. addParam(ParamWidget::create<LabelButtonS>(Vec(3,247), module, Heads::SET_A_UI, 0, 1, 0));
  125. addInput(Port::create<InPortBin>(Vec(34,222), Port::INPUT, module, Heads::SET_B_IN));
  126. addParam(ParamWidget::create<LabelButtonS>(Vec(33,247), module, Heads::SET_B_UI, 0, 1, 0));
  127. addOutput(Port::create<OutPortVal>(Vec(19,276), Port::OUTPUT, module, Heads::SIG_OUT));
  128. addChild(ModuleLightWidget::create<FourPixLight<CyanLED>>(Vec(13,267),module, Heads::A_LED));
  129. addOutput(Port::create<OutPortBin>(Vec(4,312), Port::OUTPUT, module, Heads::GATE_A_OUT));
  130. addOutput(Port::create<OutPortBin>(Vec(4,336), Port::OUTPUT, module, Heads::TRIG_A_OUT));
  131. addChild(ModuleLightWidget::create<FourPixLight<PurpleLED>>(Vec(43,267),module, Heads::B_LED));
  132. addOutput(Port::create<OutPortBin>(Vec(34,312), Port::OUTPUT, module, Heads::GATE_B_OUT));
  133. addOutput(Port::create<OutPortBin>(Vec(34,336), Port::OUTPUT, module, Heads::TRIG_B_OUT));
  134. }
  135. Model *modelHeads = Model::create<Heads, HeadsWidget>(
  136. "PvC", "Heads", "Heads", LOGIC_TAG, SWITCH_TAG, RANDOM_TAG);