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.

395 lines
16KB

  1. #include "dsp/digital.hpp"
  2. #include "moDllz.hpp"
  3. /*
  4. * TwinGlider
  5. */
  6. namespace rack_plugin_moDllz {
  7. struct TwinGlider : Module {
  8. enum ParamIds {
  9. RISE_PARAM,
  10. FALL_PARAM=2,
  11. LINK_PARAM=4,
  12. RISEMODE_PARAM=6,
  13. FALLMODE_PARAM=8,
  14. TRIG_PARAM=10,
  15. SMPNGLIDE_PARAM=12,
  16. NUM_PARAMS=14
  17. };
  18. enum InputIds {
  19. RISE_INPUT,
  20. FALL_INPUT=2,
  21. GATE_INPUT=4,
  22. CLOCK_INPUT=6,
  23. IN_INPUT=8,
  24. NUM_INPUTS=10
  25. };
  26. enum OutputIds {
  27. TRIGRISE_OUTPUT,
  28. TRIG_OUTPUT=2,
  29. TRIGFALL_OUTPUT=4,
  30. GATERISE_OUTPUT=6,
  31. GATEFALL_OUTPUT=8,
  32. OUT_OUTPUT=10,
  33. NUM_OUTPUTS=12
  34. };
  35. enum LightIds {
  36. RISING_LIGHT,
  37. FALLING_LIGHT=2,
  38. NUM_LIGHTS=4
  39. };
  40. struct gliderObj{
  41. float out = 0.0f;
  42. float in = 0.0f;
  43. // float jump = 0.0f;
  44. int risemode = 0.0f;
  45. int fallmode = 0.0f;
  46. float riseval = 0.0f;
  47. float fallval = 0.0f;
  48. float prevriseval = 0.0f;
  49. float prevfallval = 0.0f;
  50. float riseramp = 0.0f;
  51. float fallramp = 0.0f;
  52. bool rising = false;
  53. bool falling = false;
  54. bool newgate = false;
  55. bool pulse = false;
  56. bool newin = false;
  57. bool trigR = false;
  58. bool trigF = false;
  59. int clocksafe = 0;
  60. // int frameTime = 0;
  61. PulseGenerator risePulse;
  62. PulseGenerator fallPulse;
  63. };
  64. gliderObj glider[2];
  65. const float threshold = 0.01f;
  66. // int testVal = 0;
  67. TwinGlider() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  68. // ~TwinGlider() {
  69. // };
  70. void step() override;
  71. void onReset() override {
  72. for (int ix = 0; ix < 2 ; ix++){
  73. // gliding[ix] = false;
  74. outputs[OUT_OUTPUT + ix].value = inputs[IN_INPUT + ix].value;
  75. lights[RISING_LIGHT + ix].value = 0;
  76. lights[FALLING_LIGHT + ix].value = 0;
  77. outputs[GATERISE_OUTPUT + ix].value = 0;
  78. outputs[GATEFALL_OUTPUT + ix].value = 0;
  79. }
  80. }
  81. };
  82. ///////////////////////////////////////////
  83. ///////////////STEP //////////////////
  84. /////////////////////////////////////////////
  85. void TwinGlider::step() {
  86. for (int ix = 0; ix < 2; ix++){
  87. if (inputs[IN_INPUT + ix].active) {
  88. if (std::abs(glider[ix].in - inputs[IN_INPUT + ix].value) > threshold){
  89. glider[ix].newin = true;
  90. }
  91. if (params[SMPNGLIDE_PARAM + ix].value > 0.5f){
  92. bool allowin = false;
  93. if (inputs[CLOCK_INPUT + ix].active){
  94. // External clock
  95. if ((glider[ix].clocksafe > 8) && (inputs[CLOCK_INPUT + ix].value > 2.5f)){
  96. allowin = true;
  97. glider[ix].in = inputs[IN_INPUT + ix].value;
  98. glider[ix].clocksafe = 0;
  99. }else if ((glider[ix].clocksafe <10) && (inputs[CLOCK_INPUT + ix].value < 0.01f)) glider[ix].clocksafe ++;
  100. } else allowin = ((!glider[ix].rising) && (!glider[ix].falling));
  101. if (allowin) if (glider[ix].newin) glider[ix].in = inputs[IN_INPUT + ix].value;
  102. }
  103. else if (glider[ix].newin) glider[ix].in = inputs[IN_INPUT + ix].value;
  104. //Check for legato from Gate
  105. bool glideMe = false;
  106. if (inputs[GATE_INPUT + ix].active){
  107. if (inputs[GATE_INPUT + ix ].value < 0.5f) {
  108. glider[ix].newgate = true;
  109. glider[ix].out = glider[ix].in;
  110. }else if (glider[ix].newgate) {
  111. glider[ix].out = glider[ix].in ;
  112. glider[ix].newgate = false;
  113. }else glideMe= true;/// GLIDE !!!!!
  114. }else glideMe = true;//// GLIDE !!!!
  115. if (glideMe) {
  116. //////////////// GLIDE FUNCTION ////////////>>>>>>>>>>>>>>>>>>>>>
  117. glider[ix].risemode = static_cast<int> (params[RISEMODE_PARAM + ix].value);
  118. glider[ix].fallmode = static_cast<int> (params[FALLMODE_PARAM + ix].value);
  119. if (glider[ix].in > glider[ix].out){
  120. if (inputs[RISE_INPUT + ix].active)
  121. glider[ix].riseval = inputs[RISE_INPUT + ix].value / 10.0f * params[RISE_PARAM + ix].value;
  122. else glider[ix].riseval = params[RISE_PARAM + ix].value;
  123. if (glider[ix].riseval > 0.0f) {
  124. switch (glider[ix].risemode) {
  125. case 0: /// Hi Rate
  126. glider[ix].riseramp = 1.0f/(1.0f + glider[ix].riseval * 0.005f * engineGetSampleRate());
  127. break;
  128. case 1: /// Rate
  129. glider[ix].riseramp = 1.0f/(1.0f + glider[ix].riseval * 2.0f * engineGetSampleRate());
  130. break;
  131. case 2: /// Time
  132. if ((glider[ix].newin)||(glider[ix].riseval != glider[ix].prevriseval)){
  133. glider[ix].prevriseval = glider[ix].riseval;
  134. glider[ix].newin = false;
  135. glider[ix].riseramp = (glider[ix].in - glider[ix].out) * engineGetSampleTime() /(glider[ix].riseval * glider[ix].riseval * 10.0f);
  136. if (glider[ix].riseramp< 1e-6) glider[ix].riseramp = 1e-6;
  137. }
  138. break;
  139. default:
  140. break;
  141. }
  142. glider[ix].out += glider[ix].riseramp;
  143. glider[ix].rising = true;
  144. glider[ix].falling = false;
  145. if (glider[ix].out >= glider[ix].in) {///////REACH RISE
  146. glider[ix].out = glider[ix].in;
  147. glider[ix].rising = false;
  148. glider[ix].trigR = true;
  149. }
  150. } else {
  151. glider[ix].rising = false;
  152. glider[ix].out = glider[ix].in;
  153. glider[ix].trigR = true;
  154. }
  155. } else if (glider[ix].in < glider[ix].out){
  156. if (params[LINK_PARAM + ix].value > 0.5f) {
  157. glider[ix].fallmode = glider[ix].risemode;
  158. glider[ix].fallval = glider[ix].riseval;
  159. }else{
  160. if (inputs[FALL_INPUT + ix].active)
  161. glider[ix].fallval = inputs[FALL_INPUT + ix].value / 10.0f * params[FALL_PARAM + ix].value;
  162. else glider[ix].fallval = params[FALL_PARAM + ix].value;
  163. }
  164. if (glider[ix].fallval > 0.0f) {
  165. switch (glider[ix].fallmode) {
  166. case 0:
  167. glider[ix].fallramp = 1.0f/(1.0f + glider[ix].fallval * 0.005f * engineGetSampleRate());
  168. break;
  169. case 1:
  170. glider[ix].fallramp = 1.0f/(1.0f + glider[ix].fallval * 2.0f * engineGetSampleRate());
  171. break;
  172. case 2:
  173. if ((glider[ix].newin) || (glider[ix].fallval != glider[ix].prevfallval)){
  174. glider[ix].prevfallval = glider[ix].fallval;
  175. glider[ix].newin = false;
  176. glider[ix].fallramp = (glider[ix].out - glider[ix].in) * engineGetSampleTime() /(glider[ix].fallval * glider[ix].fallval * 10.0f);
  177. if (glider[ix].fallramp < 1e-6) glider[ix].fallramp= 1e-6;
  178. }
  179. break;
  180. default:
  181. break;
  182. }
  183. glider[ix].out -= glider[ix].fallramp;
  184. glider[ix].falling = true;
  185. glider[ix].rising = false;
  186. if (glider[ix].out <= glider[ix].in){////////REACH FALL
  187. glider[ix].out = glider[ix].in;
  188. glider[ix].falling = false;
  189. glider[ix].trigF = true;
  190. }
  191. }else{
  192. glider[ix].falling = false;
  193. glider[ix].out = glider[ix].in;
  194. glider[ix].trigF = true;
  195. }
  196. } else {
  197. glider[ix].rising = false;
  198. glider[ix].falling = false;
  199. glider[ix].out = glider[ix].in;
  200. }
  201. }else{
  202. glider[ix].rising = false;
  203. glider[ix].falling = false;
  204. glider[ix].out = glider[ix].in;
  205. }
  206. ///testVal = static_cast<int> (gliding[0] * 10^7);
  207. lights[RISING_LIGHT + ix].value = glider[ix].rising? 1.0 : 0.0f;
  208. lights[FALLING_LIGHT + ix].value = glider[ix].falling? 1.0 : 0.0f;
  209. outputs[GATERISE_OUTPUT + ix].value = glider[ix].rising? 10.0 : 0.0f;
  210. outputs[GATEFALL_OUTPUT + ix].value = glider[ix].falling? 10.0 : 0.0f;
  211. outputs[OUT_OUTPUT + ix].value = glider[ix].out;
  212. // //// do triggers and reset flags
  213. if (outputs[TRIGRISE_OUTPUT + ix].active||outputs[TRIG_OUTPUT + ix].active||outputs[TRIGFALL_OUTPUT + ix].active) {
  214. if (glider[ix].trigR) {
  215. glider[ix].risePulse.trigger(1e-3f);
  216. glider[ix].trigR = false;
  217. }
  218. if (glider[ix].trigF) {
  219. glider[ix].fallPulse.trigger(1e-3f);
  220. glider[ix].trigF = false;
  221. }
  222. //
  223. bool pulseR = glider[ix].risePulse.process(1.0f / engineGetSampleRate());
  224. outputs[TRIGRISE_OUTPUT + ix].value = pulseR ? 10.0 : 0.0;
  225. bool pulseF = glider[ix].fallPulse.process(1.0f / engineGetSampleRate());
  226. outputs[TRIGFALL_OUTPUT + ix].value = pulseF ? 10.0 : 0.0;
  227. outputs[TRIG_OUTPUT + ix].value = (pulseR || pulseF) ? 10.0 : 0.0;
  228. //
  229. }
  230. ///else {
  231. // trigR[ix] = false;
  232. // trigF[ix] = false;
  233. // }
  234. /// else from if input ACTIVE....
  235. }else{
  236. //disconnected in...reset Output if connected...
  237. // outputs[OUT_OUTPUT + ix].value = 0;
  238. outputs[GATERISE_OUTPUT + ix].value = 0.0f;
  239. outputs[GATEFALL_OUTPUT + ix].value = 0.0f;
  240. lights[RISING_LIGHT + ix].value = 0.0f;
  241. lights[FALLING_LIGHT + ix].value = 0.0f;
  242. glider[ix].out = 0.0f;
  243. glider[ix].in = 0.0f;
  244. // gliding[ix] = false;
  245. glider[ix].newgate = false;
  246. // allowin[ix] = true;
  247. }/// Closing if input ACTIVE
  248. } //for loop ix
  249. }//closing STEP
  250. /////////////////////////////////////////////
  251. ///// TEST DISPLAY //////
  252. //struct testDisplay : TransparentWidget {
  253. // testDisplay() {
  254. // font = Font::load(FONT_FILE);
  255. // }
  256. // float mdfontSize = 16.f;
  257. // std::shared_ptr<Font> font;
  258. // std::string displayedVal;
  259. // int *valP;
  260. // int val = 0;
  261. // void draw(NVGcontext* vg)
  262. // {
  263. // val = *valP;
  264. // displayedVal = std::to_string(val);
  265. // nvgFillColor(vg, nvgRGB(0xFF,0xFF,0x00));
  266. // nvgFontSize(vg, mdfontSize);
  267. // //nvgTextLetterSpacing(vg, 2.0f);
  268. // //nvgTextAlign(vg, NVG_ALIGN_CENTER);
  269. // nvgTextBox(vg, 0.0f, 20.0f, 165.0f, displayedVal.c_str(), NULL);
  270. //
  271. // }
  272. //
  273. //};
  274. ////////////////////////////////////////////
  275. ///////////////////////////////////////////
  276. struct TwinGliderWidget : ModuleWidget {
  277. TwinGliderWidget(TwinGlider *module): ModuleWidget(module){
  278. setPanel(SVG::load(assetPlugin(plugin, "res/TwinGlider.svg")));
  279. //Screws
  280. addChild(Widget::create<ScrewBlack>(Vec(0, 0)));
  281. addChild(Widget::create<ScrewBlack>(Vec(box.size.x - 15, 0)));
  282. addChild(Widget::create<ScrewBlack>(Vec(0, 365)));
  283. addChild(Widget::create<ScrewBlack>(Vec(box.size.x - 15, 365)));
  284. float Ystep = 30.0f ;
  285. float Ypos = 0.0f;
  286. for (int i=0; i<2; i++){
  287. Ypos = 25.0f + static_cast<float>(i* 173); //2nd panel offset
  288. // Gliding Leds
  289. addChild(ModuleLightWidget::create<TinyLight<RedLight>>(Vec(6.75, Ypos+1), module, TwinGlider::RISING_LIGHT + i));
  290. addChild(ModuleLightWidget::create<TinyLight<RedLight>>(Vec(154.75, Ypos+1), module, TwinGlider::FALLING_LIGHT + i));
  291. /// Glide Knobs
  292. addParam(ParamWidget::create<moDllzKnobM>(Vec(19, Ypos-4), module, TwinGlider::RISE_PARAM + i, 0.0, 1.0, 0.0));
  293. addParam(ParamWidget::create<moDllzKnobM>(Vec(102, Ypos-4), module, TwinGlider::FALL_PARAM + i, 0.0, 1.0, 0.0));
  294. Ypos += Ystep; //55
  295. // LINK SWITCH//CKSS
  296. addParam(ParamWidget::create<moDllzSwitchLedH>(Vec(73, Ypos-12), module, TwinGlider::LINK_PARAM + i, 0.0, 1.0, 1.0));
  297. /// Glides CVs
  298. addInput(Port::create<moDllzPort>(Vec(23, Ypos+5.5), Port::INPUT, module, TwinGlider::RISE_INPUT + i));
  299. addInput(Port::create<moDllzPort>(Vec(117.5, Ypos+5.5), Port::INPUT, module, TwinGlider::FALL_INPUT + i));
  300. Ypos += Ystep; //85
  301. /// Mode switches
  302. addParam(ParamWidget::create<moDllzSwitchT>(Vec(55, Ypos-7), module, TwinGlider::RISEMODE_PARAM + i, 0.0, 2.0, 2.0));
  303. addParam(ParamWidget::create<moDllzSwitchT>(Vec(100, Ypos-7), module, TwinGlider::FALLMODE_PARAM + i, 0.0, 2.0, 2.0));
  304. /// GATES OUT
  305. addOutput(Port::create<moDllzPort>(Vec(10.5, Ypos+14), Port::OUTPUT, module, TwinGlider::GATERISE_OUTPUT + i));
  306. addOutput(Port::create<moDllzPort>(Vec(130.5, Ypos+14), Port::OUTPUT, module, TwinGlider::GATEFALL_OUTPUT + i));
  307. Ypos += Ystep; //115
  308. /// TRIGGERS OUT
  309. addOutput(Port::create<moDllzPort>(Vec(43, Ypos-4.5), Port::OUTPUT, module, TwinGlider::TRIGRISE_OUTPUT + i));
  310. addOutput(Port::create<moDllzPort>(Vec(71, Ypos-4.5), Port::OUTPUT, module, TwinGlider::TRIG_OUTPUT + i));
  311. addOutput(Port::create<moDllzPort>(Vec(98, Ypos-4.5), Port::OUTPUT, module, TwinGlider::TRIGFALL_OUTPUT + i));
  312. Ypos += Ystep; //145
  313. // GATE IN
  314. addInput(Port::create<moDllzPort>(Vec(44, Ypos+7), Port::INPUT, module, TwinGlider::GATE_INPUT + i));
  315. // CLOCK IN
  316. addInput(Port::create<moDllzPort>(Vec(75, Ypos+7), Port::INPUT, module, TwinGlider::CLOCK_INPUT + i));
  317. // Sample&Glide SWITCH
  318. addParam(ParamWidget::create<moDllzSwitchLed>(Vec(108, Ypos+19), module, TwinGlider::SMPNGLIDE_PARAM + i, 0.0, 1.0, 0.0));
  319. // IN OUT
  320. addInput(Port::create<moDllzPort>(Vec(13.5, Ypos+6.5), Port::INPUT, module, TwinGlider::IN_INPUT + i));
  321. addOutput(Port::create<moDllzPort>(Vec(128.5, Ypos+6.5), Port::OUTPUT, module, TwinGlider::OUT_OUTPUT + i));
  322. }
  323. // {
  324. // testDisplay *mDisplay = new testDisplay();
  325. // mDisplay->box.pos = Vec(0.0f, 360.0f);
  326. // mDisplay->box.size = {165.0f, 20.0f};
  327. // mDisplay->valP = &(module->testVal);
  328. // addChild(mDisplay);
  329. // }
  330. }
  331. };
  332. //void TwinGliderWidget::step() {
  333. // ModuleWidget::step();
  334. //}
  335. // Specify the Module and ModuleWidget subclass, human-readable
  336. // manufacturer name for categorization, module slug (should never
  337. // change), human-readable module name, and any number of tags
  338. // (found in `include/tags.hpp`) separated by commas.
  339. } // namespace rack_plugin_moDllz
  340. using namespace rack_plugin_moDllz;
  341. RACK_PLUGIN_MODEL_INIT(moDllz, TwinGlider) {
  342. Model *modelTwinGlider = Model::create<TwinGlider, TwinGliderWidget>("moDllz", "TwinGlider", "TwinGlider Dual Portamento", SLEW_LIMITER_TAG, DUAL_TAG, ENVELOPE_FOLLOWER_TAG);
  343. return modelTwinGlider;
  344. }