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.

147 lines
4.5KB

  1. #include "dsp/Oscillator.hpp"
  2. #include "LindenbergResearch.hpp"
  3. namespace rack_plugin_LindenbergResearch {
  4. struct VCO : LRModule {
  5. enum ParamIds {
  6. FREQUENCY_PARAM,
  7. OCTAVE_PARAM,
  8. FM_CV_PARAM,
  9. SHAPE_CV_PARAM,
  10. PW_CV_PARAM,
  11. SHAPE_PARAM,
  12. PW_PARAM,
  13. NUM_PARAMS
  14. };
  15. enum InputIds {
  16. VOCT_INPUT,
  17. FM_CV_INPUT,
  18. PW_CV_INPUT,
  19. SHAPE_CV_INPUT,
  20. NUM_INPUTS
  21. };
  22. enum OutputIds {
  23. SAW_OUTPUT,
  24. PULSE_OUTPUT,
  25. SINE_OUTPUT,
  26. TRI_OUTPUT,
  27. NUM_OUTPUTS
  28. };
  29. enum LightIds {
  30. NUM_LIGHTS
  31. };
  32. dsp::BLITOscillator *osc = new dsp::BLITOscillator();
  33. LCDWidget *label1 = new LCDWidget(COLOR_CYAN, 6);
  34. VCO() : LRModule(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  35. void step() override;
  36. };
  37. void VCO::step() {
  38. LRModule::step();
  39. float fm = clamp(inputs[FM_CV_INPUT].value, -10.f, 10.f) * 400.f * quadraticBipolar(params[FM_CV_PARAM].value);
  40. osc->updatePitch(inputs[VOCT_INPUT].value, clamp(fm, -10000.f, 10000.f), params[FREQUENCY_PARAM].value, params[OCTAVE_PARAM].value);
  41. float shape = quadraticBipolar(params[SHAPE_PARAM].value);
  42. float pw = params[PW_CV_PARAM].value;
  43. if (osc->shape != shape) {
  44. osc->setShape(shape);
  45. }
  46. if (osc->pw != pw) {
  47. osc->setPulseWidth(pw);
  48. }
  49. osc->proccess();
  50. outputs[SAW_OUTPUT].value = osc->saw;
  51. outputs[PULSE_OUTPUT].value = osc->pulse;
  52. outputs[SINE_OUTPUT].value = osc->sine;
  53. outputs[TRI_OUTPUT].value = osc->tri;
  54. if (cnt % 1200 == 0) {
  55. label1->text = stringf("%.2f Hz", osc->getFrequency());
  56. }
  57. }
  58. /**
  59. * @brief Woldemar VCO
  60. */
  61. struct VCOWidget : LRModuleWidget {
  62. VCOWidget(VCO *module);
  63. };
  64. VCOWidget::VCOWidget(VCO *module) : LRModuleWidget(module) {
  65. // setPanel(SVG::load(assetPlugin(plugin, "res/VCO.svg")));
  66. panel = new LRPanel(20,40);
  67. panel->setBackground(SVG::load(assetPlugin(plugin, "res/VCO.svg")));
  68. addChild(panel);
  69. box.size = panel->box.size;
  70. // ***** SCREWS **********
  71. addChild(Widget::create<ScrewDarkA>(Vec(15, 1)));
  72. addChild(Widget::create<ScrewDarkA>(Vec(box.size.x - 30, 1)));
  73. addChild(Widget::create<ScrewDarkA>(Vec(15, 366)));
  74. addChild(Widget::create<ScrewDarkA>(Vec(box.size.x - 30, 366)));
  75. // ***** SCREWS **********
  76. // ***** MAIN KNOBS ******
  77. addParam(ParamWidget::create<LRMiddleKnob>(Vec(83, 172.0), module, VCO::FREQUENCY_PARAM, -15.f, 15.f, 0.f));
  78. addParam(ParamWidget::create<LRToggleKnob>(Vec(85, 240), module, VCO::OCTAVE_PARAM, -3.f, 3.f, 0.f));
  79. addParam(ParamWidget::create<LRSmallKnob>(Vec(118, 111.5), module, VCO::PW_PARAM, -.1f, 1.f, 1.f));
  80. addParam(ParamWidget::create<LRSmallKnob>(Vec(65, 60), module, VCO::SHAPE_CV_PARAM, -1.f, 1.f, 0.f));
  81. addParam(ParamWidget::create<LRSmallKnob>(Vec(15, 267), module, VCO::FM_CV_PARAM, -1.f, 1.f, 0.f));
  82. addParam(ParamWidget::create<LRSmallKnob>(Vec(65, 111.5), module, VCO::PW_CV_PARAM, 0.02f, 1.f, 1.f));
  83. addParam(ParamWidget::create<LRSmallKnob>(Vec(118, 59), module, VCO::SHAPE_PARAM, 1.f, 5.f, 1.f));
  84. // ***** MAIN KNOBS ******
  85. // ***** INPUTS **********
  86. addInput(Port::create<IOPort>(Vec(15, 182), Port::INPUT, module, VCO::VOCT_INPUT));
  87. addInput(Port::create<IOPort>(Vec(15, 228), Port::INPUT, module, VCO::FM_CV_INPUT));
  88. addInput(Port::create<IOPort>(Vec(15, 112), Port::INPUT, module, VCO::PW_CV_INPUT));
  89. addInput(Port::create<IOPort>(Vec(15, 60), Port::INPUT, module, VCO::SHAPE_CV_INPUT));
  90. // addInput(createInput<IOPort>(Vec(71, 60), module, VCO::RESHAPER_CV_INPUT));
  91. // ***** INPUTS **********
  92. // ***** OUTPUTS *********
  93. // addOutput(createOutput<IOPort>(Vec(20, 320), module, VCO::SAW_OUTPUT));
  94. addOutput(Port::create<IOPort>(Vec(20.8, 304.5), Port::OUTPUT, module, VCO::SAW_OUTPUT));
  95. addOutput(Port::create<IOPort>(Vec(57.2, 304.5), Port::OUTPUT, module, VCO::PULSE_OUTPUT));
  96. addOutput(Port::create<IOPort>(Vec(96.1, 304.5), Port::OUTPUT, module, VCO::SINE_OUTPUT));
  97. addOutput(Port::create<IOPort>(Vec(132, 304.5), Port::OUTPUT, module, VCO::TRI_OUTPUT));
  98. // ***** OUTPUTS *********
  99. module->label1->box.pos = Vec(30,110);
  100. addChild(module->label1);
  101. }
  102. } // namespace rack_plugin_LindenbergResearch
  103. using namespace rack_plugin_LindenbergResearch;
  104. RACK_PLUGIN_MODEL_INIT(LindenbergResearch, VCO) {
  105. Model *modelVCO = Model::create<VCO, VCOWidget>("Lindenberg Research", "VCO", "Voltage Controlled Oscillator", OSCILLATOR_TAG);
  106. return modelVCO;
  107. }