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.

294 lines
8.2KB

  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 Campione : Module
  20. {
  21. enum ParamIds
  22. {
  23. RECORD,
  24. PLAY,
  25. SPEED,
  26. DIRECTION,
  27. CLEAR,
  28. START,
  29. END,
  30. LOOP,
  31. ONE_SHOT,
  32. NUM_PARAMS
  33. };
  34. enum InputIds
  35. {
  36. INPUT,
  37. CV_RECORD,
  38. CV_PLAY,
  39. CV_SPEED,
  40. CV_DIRECTION,
  41. CV_CLEAR,
  42. NUM_INPUTS
  43. };
  44. enum OutputIds
  45. {
  46. OUTPUT,
  47. NUM_OUTPUTS
  48. };
  49. enum LightIds
  50. {
  51. REC_LIGHT,
  52. PLAY_LIGHT,
  53. NUM_LIGHTS
  54. };
  55. Campione() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  56. void step() override;
  57. std::deque<float> sample;
  58. bool loop = false;
  59. bool forward = true;
  60. bool recording = false;
  61. bool one_shot = true;
  62. bool playing = false;
  63. float pos = 0.0;
  64. unsigned int count = 0;
  65. float play_last_value[2] = {0.0, 0.0};
  66. float rec_last_value[2] = {0.0, 0.0};
  67. float clear_last_value[2] = {0.0, 0.0};
  68. float dir_last_value[2] = {0.0, 0.0};
  69. float increase = 0.0;
  70. int start = 0;
  71. int end = 0;
  72. };
  73. void Campione::step()
  74. {
  75. float in = inputs[INPUT].value;
  76. float out = 0.0;
  77. if (!sample.empty())
  78. {
  79. start = (unsigned int)(floorf(params[START].value * sample.size()));
  80. end = (unsigned int)(ceilf(params[END].value * sample.size()));
  81. if (start == (int)sample.size())
  82. {
  83. --start;
  84. if (start < 0)
  85. {
  86. start = 0;
  87. }
  88. }
  89. if (end < start)
  90. {
  91. end = start;
  92. }
  93. }
  94. else
  95. {
  96. start = 0;
  97. end = 0;
  98. }
  99. params[ONE_SHOT].value == 0.0 ? one_shot = false : one_shot = true;
  100. params[LOOP].value == 0.0 ? loop = false : loop = true;
  101. increase = (((inputs[CV_SPEED].value + 5.0) / 5.0) + params[SPEED].value) / 2.0;
  102. if (((inputs[CV_RECORD].value != rec_last_value[0]) && (rec_last_value[0] == 0.0)) || ((params[RECORD].value != rec_last_value[1]) && (rec_last_value[1] == 0.0)))
  103. {
  104. if (!recording)
  105. {
  106. sample.clear();
  107. pos = 0;
  108. }
  109. recording = !recording;
  110. }
  111. rec_last_value[0] = inputs[CV_RECORD].value;
  112. rec_last_value[1] = params[RECORD].value;
  113. if (((inputs[CV_DIRECTION].value != dir_last_value[0]) && (dir_last_value[0] == 0.0)) || ((params[DIRECTION].value != dir_last_value[1]) && (dir_last_value[1] == 0.0)))
  114. {
  115. forward = !forward;
  116. }
  117. dir_last_value[0] = inputs[CV_DIRECTION].value;
  118. dir_last_value[1] = params[DIRECTION].value;
  119. if (one_shot)
  120. {
  121. if (((inputs[CV_PLAY].value != play_last_value[0]) && (play_last_value[0] == 0.0)) || ((params[PLAY].value != play_last_value[1]) && (play_last_value[1] == 0.0)))
  122. {
  123. playing = !playing;
  124. forward ? pos = (float)start : pos = (float)end - 1.0;
  125. count = 0;
  126. }
  127. }
  128. else
  129. {
  130. if ((inputs[CV_PLAY].value != 0.0) || (params[PLAY].value != 0.0))
  131. {
  132. playing = true;
  133. }
  134. else
  135. {
  136. playing = false;
  137. forward ? pos = (float)start : pos = (float)end - 1.0;
  138. count = 0;
  139. }
  140. }
  141. play_last_value[0] = inputs[CV_PLAY].value;
  142. play_last_value[1] = params[PLAY].value;
  143. if (count > 0 && !loop)
  144. {
  145. playing = false;
  146. forward ? pos = (float)start : pos = (float)end - 1.0;
  147. }
  148. if (recording)
  149. {
  150. out = in;
  151. sample.push_back(in);
  152. }
  153. else
  154. {
  155. if (!sample.empty() && playing)
  156. {
  157. out = sample.at((int)floorf(pos));
  158. }
  159. else
  160. {
  161. out = 0.0;
  162. }
  163. if (forward)
  164. {
  165. pos += increase;
  166. if (pos >= (float)end)
  167. {
  168. ++count;
  169. pos = (float)start;
  170. }
  171. }
  172. else
  173. {
  174. pos -= increase;
  175. if (pos < (float)start)
  176. {
  177. ++count;
  178. pos = (float)end - 1.0;
  179. }
  180. }
  181. }
  182. outputs[OUTPUT].value = out;
  183. if (((inputs[CV_CLEAR].value != clear_last_value[0]) && (clear_last_value[0] == 0.0)) || ((params[CLEAR].value != clear_last_value[1]) && (clear_last_value[1] == 0.0)))
  184. {
  185. sample.clear();
  186. pos = 0.0;
  187. }
  188. clear_last_value[0] = inputs[CV_CLEAR].value;
  189. clear_last_value[1] = params[CLEAR].value;
  190. if (recording)
  191. {
  192. lights[REC_LIGHT].value = 1.0;
  193. }
  194. else
  195. {
  196. lights[REC_LIGHT].value = 0.0;
  197. }
  198. if (playing && !recording)
  199. {
  200. lights[PLAY_LIGHT].value = 1.0;
  201. }
  202. else
  203. {
  204. lights[PLAY_LIGHT].value = 0.0;
  205. }
  206. }
  207. struct CampioneWidget : ModuleWidget
  208. {
  209. CampioneWidget(Campione *module);
  210. };
  211. CampioneWidget::CampioneWidget(Campione *module) : ModuleWidget(module)
  212. {
  213. box.size = Vec(15 * 12, 380);
  214. {
  215. SVGPanel *panel = new SVGPanel();
  216. panel->box.size = box.size;
  217. panel->setBackground(SVG::load(assetPlugin(plugin, "res/campione.svg")));
  218. addChild(panel);
  219. }
  220. addChild(Widget::create<SonusScrew>(Vec(0, 0)));
  221. addChild(Widget::create<SonusScrew>(Vec(box.size.x - 15, 0)));
  222. addChild(Widget::create<SonusScrew>(Vec(0, 365)));
  223. addChild(Widget::create<SonusScrew>(Vec(box.size.x - 15, 365)));
  224. addInput(Port::create<PJ301MPort>(Vec(14, 67), Port::INPUT, module, Campione::INPUT));
  225. addOutput(Port::create<PJ301MPort>(Vec(52, 67), Port::OUTPUT, module, Campione::OUTPUT));
  226. addInput(Port::create<PJ301MPort>(Vec(14, 152), Port::INPUT, module, Campione::CV_RECORD));
  227. addParam(ParamWidget::create<CKD6>(Vec(50,150), module, Campione::RECORD, 0.0, 1.0, 0.0));
  228. addInput(Port::create<PJ301MPort>(Vec(14, 212), Port::INPUT, module, Campione::CV_PLAY));
  229. addParam(ParamWidget::create<CKD6>(Vec(50,210), module, Campione::PLAY, 0.0, 1.0, 0.0));
  230. addInput(Port::create<PJ301MPort>(Vec(14, 272), Port::INPUT, module, Campione::CV_CLEAR));
  231. addParam(ParamWidget::create<CKD6>(Vec(50,270), module, Campione::CLEAR, 0.0, 1.0, 0.0));
  232. addInput(Port::create<PJ301MPort>(Vec(104, 152), Port::INPUT, module, Campione::CV_DIRECTION));
  233. addParam(ParamWidget::create<CKD6>(Vec(140,150), module, Campione::DIRECTION, 0.0, 1.0, 0.0));
  234. addInput(Port::create<PJ301MPort>(Vec(104, 212), Port::INPUT, module, Campione::CV_SPEED));
  235. addParam(ParamWidget::create<SonusKnob>(Vec(140, 206), module, Campione::SPEED, 0.0, 2.0, 1.0));
  236. addParam(ParamWidget::create<CKSS>(Vec(153, 53), module, Campione::ONE_SHOT, 0.0, 1.0, 0.0));
  237. addParam(ParamWidget::create<CKSS>(Vec(153, 85), module, Campione::LOOP, 0.0, 1.0, 0.0));
  238. addParam(ParamWidget::create<SonusKnob>(Vec(94, 266), module, Campione::START, 0.0, 1.0, 0.0));
  239. addParam(ParamWidget::create<SonusKnob>(Vec(140, 266), module, Campione::END, 0.0, 1.0, 1.0));
  240. addChild(ModuleLightWidget::create<MediumLight<RedLight>>(Vec(71, 127), module, Campione::REC_LIGHT));
  241. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(Vec(104, 127), module, Campione::PLAY_LIGHT));
  242. }
  243. } // namespace rack_plugin_SonusModular
  244. using namespace rack_plugin_SonusModular;
  245. RACK_PLUGIN_MODEL_INIT(SonusModular, Campione) {
  246. Model *modelCampione = Model::create<Campione, CampioneWidget>("Sonus Modular", "Campione", "Campione | Live Sampler", SAMPLER_TAG);
  247. return modelCampione;
  248. }