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.

172 lines
5.9KB

  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 Chainsaw : Module
  20. {
  21. enum ParamIds
  22. {
  23. OCTAVE,
  24. OSC1_SHAPE,
  25. OSC1_TUNE,
  26. OSC2_SHAPE,
  27. OSC2_TUNE,
  28. OSC3_SHAPE,
  29. OSC3_TUNE,
  30. ALIGN,
  31. NUM_PARAMS
  32. };
  33. enum InputIds
  34. {
  35. PITCH,
  36. CV_OSC1_SHAPE,
  37. CV_OSC1_TUNE,
  38. CV_OSC2_SHAPE,
  39. CV_OSC2_TUNE,
  40. CV_OSC3_SHAPE,
  41. CV_OSC3_TUNE,
  42. CV_ALIGN,
  43. NUM_INPUTS
  44. };
  45. enum OutputIds
  46. {
  47. OUTPUT,
  48. NUM_OUTPUTS
  49. };
  50. enum LightIds
  51. {
  52. NUM_LIGHTS
  53. };
  54. Chainsaw() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  55. void step() override;
  56. float osc1_phase = 0.0;
  57. float osc2_phase = 0.0;
  58. float osc3_phase = 0.0;
  59. float osc_wave1_mix[3] = {0.0, 0.0, 0.0};
  60. float osc_wave2_mix[3] = {0.0, 0.0, 0.0};
  61. float osc_wave3_mix[3] = {0.0, 0.0, 0.0};
  62. float osc[3] = {0.0, 0.0, 0.0};
  63. float osc_freq[3] = {0.0, 0.0, 0.0};
  64. float osc_phase[3] = {0.0, 0.0, 0.0};
  65. };
  66. void Chainsaw::step()
  67. {
  68. float pitch = params[OCTAVE].value;
  69. pitch += inputs[PITCH].value;
  70. pitch = clamp(pitch, -4.0, 4.0);
  71. for (unsigned int f = 0; f < 3; f++)
  72. {
  73. osc_freq[f] = 261.626 * powf(2.0, pitch + (inputs[(f * 2) + 2].value / 5.0) + params[(f * 2) + 2].value);
  74. }
  75. for (unsigned int p = 0; p < 3; p++)
  76. {
  77. osc_phase[p] += 2.0 * (osc_freq[p] / engineGetSampleRate());
  78. if (osc_phase[p] >= 1.0)
  79. {
  80. osc_phase[p] -= 2.0;
  81. }
  82. }
  83. for (unsigned int o = 0; o < 3; o++)
  84. {
  85. osc_wave1_mix[o] = (-1.0 * params[(o * 2) + 1].value) + (inputs[(o * 2) + 1].value / -5.0);
  86. osc_wave1_mix[o] = clamp(osc_wave1_mix[o], 0.0, 1.0);
  87. osc_wave3_mix[o] = params[(o * 2) + 1].value + (inputs[(o * 2) + 1].value / 5.0);
  88. osc_wave3_mix[o] = clamp(osc_wave3_mix[o], 0.0, 1.0);
  89. osc_wave2_mix[o] = (2.0 - osc_wave1_mix[o] - osc_wave3_mix[o]) * 0.5;
  90. }
  91. for (unsigned int i = 0; i < 3; i++)
  92. {
  93. osc[i] = ((osc_wave1_mix[i] * powf(osc_phase[i], 4.0)) - (0.2 * osc_wave1_mix[i])) + (osc_wave2_mix[i] * osc_phase[i]) + (osc_wave3_mix[i] * 0.8 * cbrt(cbrt(osc_phase[i])));
  94. }
  95. outputs[OUTPUT].value = (osc[0] + osc[1] + osc[2]) * (5.0 / 3.0);
  96. if (params[ALIGN].value != 0.0 || inputs[CV_ALIGN].value != 0)
  97. {
  98. osc_phase[1] = osc_phase[0];
  99. osc_phase[2] = osc_phase[0];
  100. }
  101. }
  102. struct ChainsawWidget : ModuleWidget
  103. {
  104. ChainsawWidget(Chainsaw *module);
  105. };
  106. ChainsawWidget::ChainsawWidget(Chainsaw *module) : ModuleWidget(module)
  107. {
  108. box.size = Vec(15 * 12, 380);
  109. {
  110. SVGPanel *panel = new SVGPanel();
  111. panel->box.size = box.size;
  112. panel->setBackground(SVG::load(assetPlugin(plugin, "res/chainsaw.svg")));
  113. addChild(panel);
  114. }
  115. addChild(Widget::create<SonusScrew>(Vec(0, 0)));
  116. addChild(Widget::create<SonusScrew>(Vec(box.size.x - 15, 0)));
  117. addChild(Widget::create<SonusScrew>(Vec(0, 365)));
  118. addChild(Widget::create<SonusScrew>(Vec(box.size.x - 15, 365)));
  119. addInput(Port::create<PJ301MPort>(Vec(14, 67), Port::INPUT, module, Chainsaw::PITCH));
  120. addInput(Port::create<PJ301MPort>(Vec(14, 132), Port::INPUT, module, Chainsaw::CV_OSC1_SHAPE));
  121. addInput(Port::create<PJ301MPort>(Vec(143, 132), Port::INPUT, module, Chainsaw::CV_OSC1_TUNE));
  122. addInput(Port::create<PJ301MPort>(Vec(14, 197), Port::INPUT, module, Chainsaw::CV_OSC2_SHAPE));
  123. addInput(Port::create<PJ301MPort>(Vec(143, 197), Port::INPUT, module, Chainsaw::CV_OSC2_TUNE));
  124. addInput(Port::create<PJ301MPort>(Vec(14, 262), Port::INPUT, module, Chainsaw::CV_OSC3_SHAPE));
  125. addInput(Port::create<PJ301MPort>(Vec(143, 262), Port::INPUT, module, Chainsaw::CV_OSC3_TUNE));
  126. addInput(Port::create<PJ301MPort>(Vec(100, 324), Port::INPUT, module, Chainsaw::CV_ALIGN));
  127. addOutput(Port::create<PJ301MPort>(Vec(143, 67), Port::OUTPUT, module, Chainsaw::OUTPUT));
  128. addParam(ParamWidget::create<SonusKnob>(Vec(72, 65), module, Chainsaw::OCTAVE, -3.0, 3.0, 0.0));
  129. addParam(ParamWidget::create<SonusKnob>(Vec(50, 128), module, Chainsaw::OSC1_SHAPE, -1.0, 1.0, 0.0));
  130. addParam(ParamWidget::create<SonusKnob>(Vec(94, 128), module, Chainsaw::OSC1_TUNE, -1.0, 1.0, 0.0));
  131. addParam(ParamWidget::create<SonusKnob>(Vec(50, 193), module, Chainsaw::OSC2_SHAPE, -1.0, 1.0, 0.0));
  132. addParam(ParamWidget::create<SonusKnob>(Vec(94, 193), module, Chainsaw::OSC2_TUNE, -1.0, 1.0, 0.0));
  133. addParam(ParamWidget::create<SonusKnob>(Vec(50, 258), module, Chainsaw::OSC3_SHAPE, -1.0, 1.0, 0.0));
  134. addParam(ParamWidget::create<SonusKnob>(Vec(94, 258), module, Chainsaw::OSC3_TUNE, -1.0, 1.0, 0.0));
  135. addParam(ParamWidget::create<CKD6>(Vec(67,322), module, Chainsaw::ALIGN, 0.0, 1.0, 0.0));
  136. }
  137. } // namespace rack_plugin_SonusModular
  138. using namespace rack_plugin_SonusModular;
  139. RACK_PLUGIN_MODEL_INIT(SonusModular, Chainsaw) {
  140. Model *modelChainsaw = Model::create<Chainsaw, ChainsawWidget>("Sonus Modular", "Chainsaw", "Chainsaw | Fat Sawish Osc", OSCILLATOR_TAG);
  141. return modelChainsaw;
  142. }