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.

133 lines
3.9KB

  1. #include "huaba.hpp"
  2. #include "eq3.hpp"
  3. #include "math.h"
  4. namespace rack_plugin_huaba {
  5. struct EQ3 : Module {
  6. enum ParamIds {
  7. LOW_PARAM,
  8. MID_PARAM,
  9. HIGH_PARAM,
  10. NUM_PARAMS
  11. };
  12. enum InputIds {
  13. IN1_INPUT,
  14. IN2_INPUT,
  15. CV1_INPUT,
  16. CV2_INPUT,
  17. CV3_INPUT,
  18. NUM_INPUTS
  19. };
  20. enum OutputIds {
  21. OUT1_OUTPUT,
  22. OUT2_OUTPUT,
  23. NUM_OUTPUTS
  24. };
  25. enum LightIds {
  26. BLINK_LIGHT,
  27. NUM_LIGHTS
  28. };
  29. EQSTATE *eq=new EQSTATE();
  30. const double vsa = (1.0 / 4294967295.0); // Denormal Fix
  31. EQ3() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
  32. init_3band_state(eq, 880, 5000, engineGetSampleRate());
  33. }
  34. void step() override;
  35. void init_3band_state(EQSTATE* es, int lowfreq, int highfreq, int mixfreq) {
  36. // Clear state
  37. memset(es,0,sizeof(EQSTATE));
  38. // Set Low/Mid/High gains to unity
  39. es->lg = 1.0;
  40. es->mg = 1.0;
  41. es->hg = 1.0;
  42. // Calculate filter cutoff frequencies
  43. es->lf = 2 * sin(M_PI * ((double)lowfreq / (double)mixfreq));
  44. es->hf = 2 * sin(M_PI * ((double)highfreq / (double)mixfreq));
  45. }
  46. double do_3band(EQSTATE* es, double sample) {
  47. // Low / Mid / High - Sample Values
  48. double l,m,h;
  49. // Filter #1 (lowpass)
  50. es->f1p0 += (es->lf * (sample - es->f1p0)) + vsa;
  51. es->f1p1 += (es->lf * (es->f1p0 - es->f1p1));
  52. es->f1p2 += (es->lf * (es->f1p1 - es->f1p2));
  53. es->f1p3 += (es->lf * (es->f1p2 - es->f1p3));
  54. l = es->f1p3;
  55. // Filter #2 (highpass)
  56. es->f2p0 += (es->hf * (sample - es->f2p0)) + vsa;
  57. es->f2p1 += (es->hf * (es->f2p0 - es->f2p1));
  58. es->f2p2 += (es->hf * (es->f2p1 - es->f2p2));
  59. es->f2p3 += (es->hf * (es->f2p2 - es->f2p3));
  60. h = es->sdm3 - es->f2p3;
  61. // Calculate midrange (signal - (low + high))
  62. m = es->sdm3 - (h + l);
  63. // Scale, Combine and store
  64. l *= es->lg;
  65. m *= es->mg;
  66. h *= es->hg;
  67. // Shuffle history buffer
  68. es->sdm3 = es->sdm2;
  69. es->sdm2 = es->sdm1;
  70. es->sdm1 = sample;
  71. // Return result
  72. return(l + m + h);
  73. }
  74. };
  75. void EQ3::step() {
  76. eq->lg = clamp(params[LOW_PARAM].value + inputs[CV3_INPUT].value / 10.0f, 0.0f, 2.0f);
  77. eq->mg = clamp(params[MID_PARAM].value + inputs[CV2_INPUT].value / 10.0f, 0.0f, 2.0f);
  78. eq->hg = clamp(params[HIGH_PARAM].value + inputs[CV1_INPUT].value / 10.0f, 0.0f, 2.0f);
  79. if (outputs[OUT1_OUTPUT].active && inputs[IN1_INPUT].active)
  80. outputs[OUT1_OUTPUT].value = do_3band(eq, inputs[IN1_INPUT].value);
  81. if (outputs[OUT2_OUTPUT].active && inputs[IN2_INPUT].active)
  82. outputs[OUT2_OUTPUT].value = do_3band(eq, inputs[IN2_INPUT].value);
  83. }
  84. struct EQ3Widget : ModuleWidget {
  85. EQ3Widget(EQ3 *module) : ModuleWidget(module) {
  86. setPanel(SVG::load(assetPlugin(plugin, "res/EQ3.svg")));
  87. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  88. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  89. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  90. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  91. addParam(ParamWidget::create<RoundBlackKnob>(Vec(8, 56), module, EQ3::HIGH_PARAM, 0.0, 2.0, 1.0));
  92. addInput(Port::create<PJ301MPort>(Vec(10.5, 89), Port::INPUT, module, EQ3::CV1_INPUT));
  93. addParam(ParamWidget::create<RoundBlackKnob>(Vec(8, 136), module, EQ3::MID_PARAM, 0.0, 2.0, 1.0));
  94. addInput(Port::create<PJ301MPort>(Vec(10.5, 169), Port::INPUT, module, EQ3::CV2_INPUT));
  95. addParam(ParamWidget::create<RoundBlackKnob>(Vec(8, 215), module, EQ3::LOW_PARAM, 0.0, 2.0, 1.0));
  96. addInput(Port::create<PJ301MPort>(Vec(10.5, 248), Port::INPUT, module, EQ3::CV3_INPUT));
  97. addInput(Port::create<PJ301MPort>(Vec(10.5, 280), Port::INPUT, module, EQ3::IN1_INPUT));
  98. addOutput(Port::create<PJ301MPort>(Vec(10.5, 320), Port::OUTPUT, module, EQ3::OUT1_OUTPUT));
  99. }
  100. };
  101. } // namespace rack_plugin_huaba
  102. using namespace rack_plugin_huaba;
  103. RACK_PLUGIN_MODEL_INIT(huaba, EQ3) {
  104. Model *modelEQ3 = Model::create<EQ3, EQ3Widget>("huaba", "EQ3", "EQ3", EQUALIZER_TAG);
  105. return modelEQ3;
  106. }