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.

115 lines
3.3KB

  1. // Based on Will Pirkle's courses & Vadim Zavalishin's book
  2. #include "Bidoo.hpp"
  3. #include "BidooComponents.hpp"
  4. #include "dsp/decimator.hpp"
  5. using namespace std;
  6. namespace rack_plugin_Bidoo {
  7. #define pi 3.14159265359
  8. struct MultiFilter
  9. {
  10. float q;
  11. float freq;
  12. float smpRate;
  13. float hp = 0.0f,bp = 0.0f,lp = 0.0f,mem1 = 0.0f,mem2 = 0.0f;
  14. void setParams(float freq, float q, float smpRate) {
  15. this->freq = freq;
  16. this->q=q;
  17. this->smpRate=smpRate;
  18. }
  19. void calcOutput(float sample)
  20. {
  21. float g = tan(pi*freq/smpRate);
  22. float R = 1.0f/(2.0f*q);
  23. hp = (sample - (2.0f*R + g)*mem1 - mem2)/(1.0f + 2.0f*R*g + g*g);
  24. bp = g*hp + mem1;
  25. lp = g*bp + mem2;
  26. mem1 = g*hp + bp;
  27. mem2 = g*bp + lp;
  28. }
  29. };
  30. struct PERCO : Module {
  31. enum ParamIds {
  32. CUTOFF_PARAM,
  33. Q_PARAM,
  34. CMOD_PARAM,
  35. NUM_PARAMS
  36. };
  37. enum InputIds {
  38. IN,
  39. CUTOFF_INPUT,
  40. Q_INPUT,
  41. NUM_INPUTS
  42. };
  43. enum OutputIds {
  44. OUT_LP,
  45. OUT_BP,
  46. OUT_HP,
  47. NUM_OUTPUTS
  48. };
  49. enum LightIds {
  50. LEARN_LIGHT,
  51. NUM_LIGHTS
  52. };
  53. MultiFilter filter;
  54. PERCO() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
  55. }
  56. void step() override;
  57. };
  58. void PERCO::step() {
  59. float cfreq = pow(2.0f,rescale(clamp(params[CUTOFF_PARAM].value + params[CMOD_PARAM].value * inputs[CUTOFF_INPUT].value / 5.0f,0.0f,1.0f),0.0f,1.0f,4.5f,13.0f));
  60. float q = 10.0f * clamp(params[Q_PARAM].value + inputs[Q_INPUT].value / 5.0f, 0.1f, 1.0f);
  61. filter.setParams(cfreq,q,engineGetSampleRate());
  62. float in = inputs[IN].value/5.0f; //normalise to -1/+1 we consider VCV Rack standard is #+5/-5V on VCO1
  63. //filtering
  64. filter.calcOutput(in);
  65. outputs[OUT_LP].value = filter.lp * 5.0f;
  66. outputs[OUT_HP].value = filter.hp * 5.0f;
  67. outputs[OUT_BP].value = filter.bp * 5.0f;
  68. }
  69. struct PERCOWidget : ModuleWidget {
  70. PERCOWidget(PERCO *module) : ModuleWidget(module) {
  71. setPanel(SVG::load(assetPlugin(plugin, "res/PERCO.svg")));
  72. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  73. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  74. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  75. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  76. addParam(ParamWidget::create<BidooHugeBlueKnob>(Vec(31, 61), module, PERCO::CUTOFF_PARAM, 0.0f, 1.0f, 1.0f));
  77. addParam(ParamWidget::create<BidooLargeBlueKnob>(Vec(12, 143), module, PERCO::Q_PARAM, 0.1f, 1.0f, 0.1f));
  78. addParam(ParamWidget::create<BidooLargeBlueKnob>(Vec(71, 143), module, PERCO::CMOD_PARAM, -1.0f, 1.0f, 0.0f));
  79. addInput(Port::create<PJ301MPort>(Vec(10, 276), Port::INPUT, module, PERCO::IN));
  80. addInput(Port::create<PJ301MPort>(Vec(48, 276), Port::INPUT, module, PERCO::CUTOFF_INPUT));
  81. addInput(Port::create<PJ301MPort>(Vec(85, 276), Port::INPUT, module, PERCO::Q_INPUT));
  82. addOutput(Port::create<PJ301MPort>(Vec(10, 320), Port::OUTPUT, module, PERCO::OUT_LP));
  83. addOutput(Port::create<PJ301MPort>(Vec(48, 320), Port::OUTPUT, module, PERCO::OUT_BP));
  84. addOutput(Port::create<PJ301MPort>(Vec(85, 320), Port::OUTPUT, module, PERCO::OUT_HP));
  85. }
  86. };
  87. } // namespace rack_plugin_Bidoo
  88. using namespace rack_plugin_Bidoo;
  89. RACK_PLUGIN_MODEL_INIT(Bidoo, PERCO) {
  90. Model *modelPERCO = Model::create<PERCO, PERCOWidget>("Bidoo", "pErCO", "pErCO filter", FILTER_TAG);
  91. return modelPERCO;
  92. }