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.

170 lines
4.4KB

  1. #include <iostream>
  2. #include <stdlib.h>
  3. #include <random>
  4. #include <cmath>
  5. #include "dsp/digital.hpp"
  6. #include "dsp/samplerate.hpp"
  7. #include "dsp/ringbuffer.hpp"
  8. #include "dsp/filter.hpp"
  9. #include "RJModules.hpp"
  10. #include "VAStateVariableFilter.h"
  11. namespace rack_plugin_RJModules {
  12. #define HISTORY_SIZE (1<<21)
  13. struct Stutter : Module {
  14. enum ParamIds {
  15. TIME_PARAM,
  16. MIX_PARAM,
  17. ONOFF_PARAM,
  18. NUM_PARAMS
  19. };
  20. enum InputIds {
  21. CH1_INPUT,
  22. TIME_CV_INPUT,
  23. MIX_CV_INPUT,
  24. ONOFF_INPUT,
  25. NUM_INPUTS
  26. };
  27. enum OutputIds {
  28. CH1_OUTPUT,
  29. CH2_OUTPUT,
  30. NUM_OUTPUTS
  31. };
  32. enum LightIds {
  33. RESET_LIGHT,
  34. NUM_LIGHTS
  35. };
  36. DoubleRingBuffer<float, HISTORY_SIZE> historyBuffer;
  37. DoubleRingBuffer<float, 16> outBuffer;
  38. SampleRateConverter<1> src;
  39. bool on = false;
  40. float last_press = 999999;
  41. SchmittTrigger resetTrigger;
  42. float bufferedSamples[36000] = {0.0};
  43. int tapeHead = 0;
  44. Stutter() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  45. void step() override;
  46. };
  47. struct BigSwitchLEDButton : SVGSwitch, MomentarySwitch {
  48. BigSwitchLEDButton() {
  49. addFrame(SVG::load(assetPlugin(plugin, "res/SwitchLEDButton.svg")));
  50. }
  51. };
  52. template <typename BASE>
  53. struct GiantLight : BASE {
  54. GiantLight() {
  55. this->box.size = mm2px(Vec(16, 16));
  56. }
  57. };
  58. void Stutter::step(){
  59. float in = inputs[CH1_INPUT].value;
  60. float on_off = params[ONOFF_PARAM].value;
  61. int time = params[TIME_PARAM].value * clamp(inputs[TIME_CV_INPUT].normalize(10.0f) / 10.0f, 0.0f, 1.0f); ;
  62. float wet = in;
  63. // issa hack
  64. if (last_press > 6000){
  65. if(resetTrigger.process(inputs[ONOFF_INPUT].value)){
  66. // tapeHead=0;
  67. on = !on;
  68. last_press = 0;
  69. }
  70. if(resetTrigger.process(on_off)){
  71. // tapeHead=0;
  72. on = !on;
  73. last_press = 0;
  74. }
  75. }
  76. // issa hack
  77. if (time == 0){
  78. time = 143;
  79. }
  80. if(!on){
  81. bufferedSamples[tapeHead] = in;
  82. }
  83. if(on){
  84. wet = bufferedSamples[tapeHead];
  85. if(tapeHead >= time){
  86. tapeHead = -1;
  87. }
  88. } else{
  89. if(tapeHead >= (36000-1)){
  90. tapeHead = -1;
  91. }
  92. }
  93. tapeHead++;
  94. last_press++;
  95. //mix
  96. float mix_percent = params[MIX_PARAM].value * clamp(inputs[MIX_CV_INPUT].normalize(10.0f) / 10.0f, 0.0f, 1.0f);
  97. float mixed = ((wet * mix_percent)) + (in * (1-mix_percent));
  98. outputs[CH1_OUTPUT].value = mixed;
  99. if(on){
  100. lights[RESET_LIGHT].value = 1.0;
  101. } else{
  102. lights[RESET_LIGHT].value = 0.0;
  103. }
  104. }
  105. struct StutterWidget: ModuleWidget {
  106. StutterWidget(Stutter *module);
  107. };
  108. StutterWidget::StutterWidget(Stutter *module) : ModuleWidget(module) {
  109. box.size = Vec(15*10, 380);
  110. {
  111. SVGPanel *panel = new SVGPanel();
  112. panel->box.size = box.size;
  113. panel->setBackground(SVG::load(assetPlugin(plugin, "res/Stutter.svg")));
  114. addChild(panel);
  115. }
  116. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  117. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0)));
  118. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  119. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365)));
  120. //addParam(ParamWidget::create<RoundHugeBlackKnob>(Vec(47, 61), module, Stutter::ONOFF_PARAM, 0.0, 1.0, 1.0));
  121. addParam(ParamWidget::create<BigSwitchLEDButton>(Vec(47, 61), module, Stutter::ONOFF_PARAM, 0.0, 1.0, 0.0));
  122. addChild(ModuleLightWidget::create<GiantLight<GreenLight>>(Vec(53, 67), module, Stutter::RESET_LIGHT));
  123. addParam(ParamWidget::create<RoundHugeBlackKnob>(Vec(47, 143), module, Stutter::TIME_PARAM, 0, 36000, 4000));
  124. addParam(ParamWidget::create<RoundHugeBlackKnob>(Vec(47, 228), module, Stutter::MIX_PARAM, 0.0, 1.0, 1.0));
  125. addInput(Port::create<PJ301MPort>(Vec(22, 100), Port::INPUT, module, Stutter::ONOFF_INPUT));
  126. addInput(Port::create<PJ301MPort>(Vec(22, 190), Port::INPUT, module, Stutter::TIME_CV_INPUT));
  127. addInput(Port::create<PJ301MPort>(Vec(22, 270), Port::INPUT, module, Stutter::MIX_CV_INPUT));
  128. addInput(Port::create<PJ301MPort>(Vec(22, 315), Port::INPUT, module, Stutter::CH1_INPUT));
  129. addOutput(Port::create<PJ301MPort>(Vec(100, 315), Port::OUTPUT, module, Stutter::CH1_OUTPUT));
  130. }
  131. } // namespace rack_plugin_RJModules
  132. using namespace rack_plugin_RJModules;
  133. RACK_PLUGIN_MODEL_INIT(RJModules, Stutter) {
  134. Model *modelStutter = Model::create<Stutter, StutterWidget>("RJModules", "Stutter", "[FX] Stutter", DELAY_TAG);
  135. return modelStutter;
  136. }