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.

235 lines
7.0KB

  1. #include "Southpole.hpp"
  2. #include "dsp/digital.hpp"
  3. namespace rack_plugin_Southpole {
  4. struct Pulse : Module {
  5. enum ParamIds {
  6. TRIG_PARAM,
  7. REPEAT_PARAM,
  8. RESET_PARAM,
  9. RANGE_PARAM,
  10. DELAY_PARAM,
  11. TIME_PARAM,
  12. AMP_PARAM,
  13. // OFFSET_PARAM,
  14. SLEW_PARAM,
  15. NUM_PARAMS
  16. };
  17. enum InputIds {
  18. TRIG_INPUT,
  19. CLOCK_INPUT,
  20. // REPEAT_INPUT,
  21. // RESET_INPUT,
  22. DELAY_INPUT,
  23. TIME_INPUT,
  24. AMP_INPUT,
  25. // OFFSET_INPUT,
  26. SLEW_INPUT,
  27. NUM_INPUTS
  28. };
  29. enum OutputIds {
  30. CLOCK_OUTPUT,
  31. GATE_OUTPUT,
  32. EOC_OUTPUT,
  33. NUM_OUTPUTS
  34. };
  35. enum LightIds {
  36. EOC_LIGHT,
  37. GATE_LIGHT,
  38. NUM_LIGHTS
  39. };
  40. SchmittTrigger clock;
  41. SchmittTrigger trigger;
  42. SchmittTrigger triggerBtn;
  43. PulseGenerator clkPulse;
  44. PulseGenerator eocPulse;
  45. unsigned long delayt = 0;
  46. unsigned long gatet = 0;
  47. unsigned long clockt = 0;
  48. unsigned long clockp = 0;
  49. unsigned long delayTarget = 0;
  50. unsigned long gateTarget = 0;
  51. float level = 0;
  52. bool reset = true;
  53. bool repeat = false;
  54. bool range = false;
  55. bool gateOn = false;
  56. bool delayOn = false;
  57. float amp;
  58. float slew;
  59. static const int ndurations = 12;
  60. const float durations[ndurations] = {
  61. 1.f/256.f, 1.f/128.f, 1.f/64.f, 1.f/32.f, 1.f/16.f, 1.f/8.f, 3.f/16.f, 1.f/4.f, 1.f/3.f, 1.f/2.f, 3.f/4.f, .99f
  62. //,2.,3.,4. //,5.,6.,7.,8.,12.,16.
  63. };
  64. Pulse() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) { }
  65. void step() override;
  66. };
  67. void Pulse::step() {
  68. bool triggered = false;
  69. reset = params[RESET_PARAM].value;
  70. repeat = params[REPEAT_PARAM].value;
  71. range = params[RANGE_PARAM].value;
  72. if (triggerBtn.process(params[TRIG_PARAM].value)) {
  73. triggered = true;
  74. }
  75. if (trigger.process(inputs[TRIG_INPUT].normalize(0.))) {
  76. triggered = true;
  77. //printf("%lu\n", gateTarget);
  78. }
  79. if (clock.process(inputs[CLOCK_INPUT].normalize(0.))) {
  80. triggered = true;
  81. clkPulse.trigger(1e-3);
  82. clockp = clockt;
  83. clockt = 0;
  84. }
  85. float dt = 1e-3*engineGetSampleRate();
  86. float sr = engineGetSampleRate();
  87. amp = clamp(params[AMP_PARAM].value + inputs[AMP_INPUT].normalize(0.) / 10.0f, 0.0f, 1.0f);
  88. slew = clamp(params[SLEW_PARAM].value + inputs[SLEW_INPUT].normalize(0.) / 10.0f, 0.0f, 1.0f);
  89. slew = pow(2.,(1.-slew)*log2(sr))/sr;
  90. if (range) slew *= .1;
  91. float delayTarget_ = clamp(params[DELAY_PARAM].value + inputs[DELAY_INPUT].normalize(0.) / 10.0f, 0.0f, 1.0f);
  92. float gateTarget_ = clamp(params[TIME_PARAM].value + inputs[TIME_INPUT].normalize(0.) / 10.0f, 0.0f, 1.0f);
  93. if (inputs[CLOCK_INPUT].active) {
  94. clockt++;
  95. delayTarget = clockp*durations[int((ndurations-1)*delayTarget_)];
  96. gateTarget = clockp*durations[int((ndurations-1)*gateTarget_)];
  97. if (gateTarget < dt) gateTarget = dt;
  98. } else {
  99. unsigned int r = range ? 10 : 1;
  100. delayTarget = r * delayTarget_*sr;
  101. gateTarget = r * gateTarget_*sr + dt;
  102. }
  103. if (triggered && (reset || !gateOn || !delayOn)) {
  104. delayt = 0;
  105. delayOn = true;
  106. gateOn = false;
  107. }
  108. if (delayOn) {
  109. if (delayt < delayTarget) {
  110. delayt++;
  111. } else {
  112. delayOn = false;
  113. gateOn = true;
  114. gatet = 0;
  115. }
  116. }
  117. if (gateOn) {
  118. if (gatet < gateTarget) {
  119. gatet++;
  120. } else {
  121. eocPulse.trigger(1e-3);
  122. gateOn = false;
  123. if (repeat) {
  124. delayt = 0;
  125. delayOn = true;
  126. }
  127. }
  128. if (level < 1.) level += slew;
  129. if (level > 1.) level = 1.;
  130. } else {
  131. if (level > 0.) level -= slew;
  132. if (level < 0.) level = 0.;
  133. }
  134. outputs[CLOCK_OUTPUT].value = 10.*clkPulse.process(1.0 / engineGetSampleRate());
  135. outputs[EOC_OUTPUT].value = 10.*eocPulse.process(1.0 / engineGetSampleRate());
  136. outputs[GATE_OUTPUT].value = clamp( 10.f * level * amp, -10.f, 10.f );
  137. lights[EOC_LIGHT].setBrightnessSmooth( outputs[EOC_OUTPUT].value );
  138. lights[GATE_LIGHT].setBrightnessSmooth( outputs[GATE_OUTPUT].value );
  139. }
  140. struct PulseWidget : ModuleWidget {
  141. PulseWidget(Module *module) : ModuleWidget(module) {
  142. box.size = Vec(15*4, 380);
  143. {
  144. SVGPanel *panel = new SVGPanel();
  145. panel->box.size = box.size;
  146. panel->setBackground(SVG::load(assetPlugin(plugin, "res/Pulse.svg")));
  147. addChild(panel);
  148. }
  149. const float x1 = 5.;
  150. const float x2 = 35.;
  151. const float y1 = 40.;
  152. const float yh = 35.;
  153. addInput(Port::create<sp_Port>(Vec(x1, y1+0*yh), Port::INPUT, module, Pulse::CLOCK_INPUT));
  154. addOutput(Port::create<sp_Port>(Vec(x2, y1+0*yh), Port::OUTPUT, module, Pulse::CLOCK_OUTPUT));
  155. addInput(Port::create<sp_Port>(Vec(x1, y1+1*yh), Port::INPUT, module, Pulse::TRIG_INPUT));
  156. addParam(ParamWidget::create<TL1105>(Vec(x2, y1+1*yh), module, Pulse::TRIG_PARAM, 0.0, 1.0, 0.));
  157. addParam(ParamWidget::create<sp_Switch>(Vec(x1, y1+1.75*yh), module, Pulse::RESET_PARAM, 0.0, 1.0, 0.0));
  158. addParam(ParamWidget::create<sp_Switch>(Vec(x1, y1+2.25*yh), module, Pulse::REPEAT_PARAM, 0.0, 1.0, 0.0));
  159. addParam(ParamWidget::create<sp_Switch>(Vec(x1, y1+2.75*yh), module, Pulse::RANGE_PARAM, 0.0, 1.0, 0.0));
  160. addInput(Port::create<sp_Port>(Vec(x1, y1+4*yh), Port::INPUT, module, Pulse::TIME_INPUT));
  161. addParam(ParamWidget::create<sp_SmallBlackKnob>(Vec(x2, y1+4*yh), module, Pulse::TIME_PARAM, 0.0, 1.0, 0.0));
  162. addInput(Port::create<sp_Port>(Vec(x1, y1+5*yh), Port::INPUT, module, Pulse::DELAY_INPUT));
  163. addParam(ParamWidget::create<sp_SmallBlackKnob>(Vec(x2, y1+5*yh), module, Pulse::DELAY_PARAM, 0.0, 1.0, 0.0));
  164. addInput(Port::create<sp_Port>(Vec(x1, y1+6*yh), Port::INPUT, module, Pulse::AMP_INPUT));
  165. addParam(ParamWidget::create<sp_SmallBlackKnob>(Vec(x2, y1+6*yh), module, Pulse::AMP_PARAM, 0.0, 1.0, 1.0));
  166. //addInput(Port::create<sp_Port> (Vec(x1, y1+7*yh), module, Pulse::OFFSET_INPUT));
  167. //addParam(ParamWidget::create<sp_SmallBlackKnob>(Vec(x2, y1+7*yh), module, Pulse::OFFSET_PARAM, -1.0, 1.0, 0.));
  168. addInput(Port::create<sp_Port>(Vec(x1, y1+7*yh), Port::INPUT, module, Pulse::SLEW_INPUT));
  169. addParam(ParamWidget::create<sp_SmallBlackKnob>(Vec(x2, y1+7*yh), module, Pulse::SLEW_PARAM, 0.0, 1.0, 0.));
  170. addOutput(Port::create<sp_Port>(Vec(x1, y1+8.25*yh), Port::OUTPUT, module, Pulse::EOC_OUTPUT));
  171. addOutput(Port::create<sp_Port>(Vec(x2, y1+8.25*yh), Port::OUTPUT, module, Pulse::GATE_OUTPUT));
  172. addChild(ModuleLightWidget::create<SmallLight<RedLight>>(Vec(x1+7, y1+7.65*yh), module, Pulse::EOC_LIGHT));
  173. addChild(ModuleLightWidget::create<SmallLight<RedLight>>(Vec(x2+7, y1+7.65*yh), module, Pulse::GATE_LIGHT));
  174. }
  175. };
  176. } // namespace rack_plugin_Southpole
  177. using namespace rack_plugin_Southpole;
  178. RACK_PLUGIN_MODEL_INIT(Southpole, Pulse) {
  179. Model *modelPulse = Model::create<Pulse,PulseWidget>( "Southpole", "Pulse", "Pulse - pulse generator", ENVELOPE_GENERATOR_TAG);
  180. return modelPulse;
  181. }