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.

199 lines
5.0KB

  1. /******************************************************************************
  2. * Copyright 2017-2018 Valerio Orlandini / Sonus Dept. <sonusdept@gmail.com>
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *****************************************************************************/
  17. #include "sonusmodular.hpp"
  18. namespace rack_plugin_SonusModular {
  19. struct Luppolo : Module
  20. {
  21. enum ParamIds
  22. {
  23. CLEAR,
  24. NUM_PARAMS
  25. };
  26. enum InputIds
  27. {
  28. INPUT,
  29. TRIGGER,
  30. OVERDUB,
  31. CV_CLEAR,
  32. NUM_INPUTS
  33. };
  34. enum OutputIds
  35. {
  36. OUTPUT,
  37. NUM_OUTPUTS
  38. };
  39. enum LightIds
  40. {
  41. REC_LIGHT,
  42. PLAY_LIGHT,
  43. NUM_LIGHTS
  44. };
  45. Luppolo() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  46. void step() override;
  47. std::vector<float> loop;
  48. bool is_recording = false;
  49. bool master_rec = false;
  50. bool overdubbing = false;
  51. unsigned int sample = 0;
  52. float trig_last_value = 0.0;
  53. float overdub_last_value = 0.0;
  54. };
  55. void Luppolo::step()
  56. {
  57. float in = inputs[INPUT].value;
  58. float out = 0.0;
  59. if ((inputs[TRIGGER].value != trig_last_value) && (trig_last_value == 0.0))
  60. {
  61. if (!is_recording)
  62. {
  63. loop.clear();
  64. sample = 0;
  65. master_rec = false;
  66. overdubbing = false;
  67. }
  68. else
  69. {
  70. master_rec = true;
  71. }
  72. is_recording = !is_recording;
  73. }
  74. trig_last_value = inputs[TRIGGER].value;
  75. if ((inputs[OVERDUB].value != overdub_last_value) && (overdub_last_value == 0.0))
  76. {
  77. if (!overdubbing && master_rec)
  78. {
  79. overdubbing = true;
  80. }
  81. else if (overdubbing && master_rec)
  82. {
  83. overdubbing = false;
  84. }
  85. }
  86. overdub_last_value = inputs[OVERDUB].value;
  87. if ((params[CLEAR].value != 0.0) || (inputs[CV_CLEAR].value != 0.0))
  88. {
  89. master_rec = false;
  90. is_recording = false;
  91. overdubbing = false;
  92. loop.clear();
  93. sample = 0;
  94. }
  95. if (is_recording)
  96. {
  97. out = in;
  98. loop.push_back(in);
  99. }
  100. else
  101. {
  102. if (!loop.empty())
  103. {
  104. if (overdubbing)
  105. {
  106. loop.at(sample) += in;
  107. }
  108. out = loop.at(sample);
  109. }
  110. else
  111. {
  112. out = 0.0;
  113. }
  114. if (++sample >= loop.size())
  115. {
  116. sample = 0;
  117. }
  118. }
  119. outputs[OUTPUT].value = out;
  120. if (is_recording || overdubbing)
  121. {
  122. lights[REC_LIGHT].value = 1.0;
  123. }
  124. else
  125. {
  126. lights[REC_LIGHT].value = 0.0;
  127. }
  128. if (master_rec)
  129. {
  130. lights[PLAY_LIGHT].value = 1.0;
  131. }
  132. else
  133. {
  134. lights[PLAY_LIGHT].value = 0.0;
  135. }
  136. }
  137. struct LuppoloWidget : ModuleWidget
  138. {
  139. LuppoloWidget(Luppolo *module);
  140. };
  141. LuppoloWidget::LuppoloWidget(Luppolo *module) : ModuleWidget(module)
  142. {
  143. box.size = Vec(15 * 6, 380);
  144. {
  145. SVGPanel *panel = new SVGPanel();
  146. panel->box.size = box.size;
  147. panel->setBackground(SVG::load(assetPlugin(plugin, "res/luppolo.svg")));
  148. addChild(panel);
  149. }
  150. addChild(Widget::create<SonusScrew>(Vec(0, 0)));
  151. addChild(Widget::create<SonusScrew>(Vec(box.size.x - 15, 0)));
  152. addChild(Widget::create<SonusScrew>(Vec(0, 365)));
  153. addChild(Widget::create<SonusScrew>(Vec(box.size.x - 15, 365)));
  154. addInput(Port::create<PJ301MPort>(Vec(14, 67), Port::INPUT, module, Luppolo::INPUT));
  155. addOutput(Port::create<PJ301MPort>(Vec(52, 67), Port::OUTPUT, module, Luppolo::OUTPUT));
  156. addInput(Port::create<PJ301MPort>(Vec(33, 155), Port::INPUT, module, Luppolo::TRIGGER));
  157. addInput(Port::create<PJ301MPort>(Vec(33, 215), Port::INPUT, module, Luppolo::OVERDUB));
  158. addInput(Port::create<PJ301MPort>(Vec(14,272), Port::INPUT, module, Luppolo::CV_CLEAR));
  159. addParam(ParamWidget::create<CKD6>(Vec(50,270), module, Luppolo::CLEAR, 0.0, 1.0, 0.0));
  160. addChild(ModuleLightWidget::create<MediumLight<RedLight>>(Vec(22, 127), module, Luppolo::REC_LIGHT));
  161. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(61, 127), module, Luppolo::PLAY_LIGHT));
  162. }
  163. } // namespace rack_plugin_SonusModular
  164. using namespace rack_plugin_SonusModular;
  165. RACK_PLUGIN_MODEL_INIT(SonusModular, Luppolo) {
  166. Model *modelLuppolo = Model::create<Luppolo, LuppoloWidget>("Sonus Modular", "Luppolo", "Luppolo | Simple Looper", SAMPLER_TAG);
  167. return modelLuppolo;
  168. }