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.

179 lines
5.5KB

  1. #include "Fundamental.hpp"
  2. struct VCA : Module {
  3. enum ParamIds {
  4. LEVEL1_PARAM,
  5. LEVEL2_PARAM,
  6. NUM_PARAMS
  7. };
  8. enum InputIds {
  9. EXP1_INPUT,
  10. LIN1_INPUT,
  11. IN1_INPUT,
  12. EXP2_INPUT,
  13. LIN2_INPUT,
  14. IN2_INPUT,
  15. NUM_INPUTS
  16. };
  17. enum OutputIds {
  18. OUT1_OUTPUT,
  19. OUT2_OUTPUT,
  20. NUM_OUTPUTS
  21. };
  22. VCA() {
  23. config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS);
  24. params[LEVEL1_PARAM].config(0.0, 1.0, 0.0, "Ch 1 level", "%", 0, 100);
  25. params[LEVEL2_PARAM].config(0.0, 1.0, 0.0, "Ch 2 level", "%", 0, 100);
  26. }
  27. void stepChannel(InputIds in, ParamIds level, InputIds lin, InputIds exp, OutputIds out) {
  28. float v = inputs[in].value * params[level].value;
  29. if (inputs[lin].active)
  30. v *= clamp(inputs[lin].value / 10.0f, 0.0f, 1.0f);
  31. const float expBase = 50.0f;
  32. if (inputs[exp].active)
  33. v *= rescale(std::pow(expBase, clamp(inputs[exp].value / 10.0f, 0.0f, 1.0f)), 1.0f, expBase, 0.0f, 1.0f);
  34. outputs[out].value = v;
  35. }
  36. void step() override {
  37. stepChannel(IN1_INPUT, LEVEL1_PARAM, LIN1_INPUT, EXP1_INPUT, OUT1_OUTPUT);
  38. stepChannel(IN2_INPUT, LEVEL2_PARAM, LIN2_INPUT, EXP2_INPUT, OUT2_OUTPUT);
  39. }
  40. };
  41. struct VCAWidget : ModuleWidget {
  42. VCAWidget(VCA *module) {
  43. setModule(module);
  44. setPanel(SVG::load(asset::plugin(plugin, "res/VCA.svg")));
  45. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  46. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  47. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  48. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  49. addParam(createParam<RoundLargeBlackKnob>(mm2px(Vec(6.35, 19.11753)), module, VCA::LEVEL1_PARAM));
  50. addParam(createParam<RoundLargeBlackKnob>(mm2px(Vec(6.35, 74.80544)), module, VCA::LEVEL2_PARAM));
  51. addInput(createInput<PJ301MPort>(mm2px(Vec(2.5907, 38.19371)), module, VCA::EXP1_INPUT));
  52. addInput(createInput<PJ301MPort>(mm2px(Vec(14.59752, 38.19371)), module, VCA::LIN1_INPUT));
  53. addInput(createInput<PJ301MPort>(mm2px(Vec(2.5907, 52.80642)), module, VCA::IN1_INPUT));
  54. addInput(createInput<PJ301MPort>(mm2px(Vec(2.5907, 93.53435)), module, VCA::EXP2_INPUT));
  55. addInput(createInput<PJ301MPort>(mm2px(Vec(14.59752, 93.53435)), module, VCA::LIN2_INPUT));
  56. addInput(createInput<PJ301MPort>(mm2px(Vec(2.5907, 108.14706)), module, VCA::IN2_INPUT));
  57. addOutput(createOutput<PJ301MPort>(mm2px(Vec(14.59752, 52.80642)), module, VCA::OUT1_OUTPUT));
  58. addOutput(createOutput<PJ301MPort>(mm2px(Vec(14.59752, 108.14706)), module, VCA::OUT2_OUTPUT));
  59. }
  60. };
  61. Model *modelVCA = createModel<VCA, VCAWidget>("VCA");
  62. struct VCA_1 : Module {
  63. enum ParamIds {
  64. LEVEL_PARAM,
  65. EXP_PARAM,
  66. NUM_PARAMS
  67. };
  68. enum InputIds {
  69. CV_INPUT,
  70. IN_INPUT,
  71. NUM_INPUTS
  72. };
  73. enum OutputIds {
  74. OUT_OUTPUT,
  75. NUM_OUTPUTS
  76. };
  77. enum LightIds {
  78. NUM_LIGHTS
  79. };
  80. float lastCv = 0.f;
  81. VCA_1() {
  82. config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
  83. params[LEVEL_PARAM].config(0.0, 1.0, 1.0, "Level", "%", 0, 100);
  84. params[EXP_PARAM].config(0.0, 1.0, 1.0, "Response mode");
  85. }
  86. void step() override {
  87. float cv = inputs[CV_INPUT].getNormalVoltage(10.f) / 10.f;
  88. if ((int) params[EXP_PARAM].value == 0)
  89. cv = std::pow(cv, 4.f);
  90. lastCv = cv;
  91. outputs[OUT_OUTPUT].value = inputs[IN_INPUT].value * params[LEVEL_PARAM].value * cv;
  92. }
  93. };
  94. struct VCA_1VUKnob : SliderKnob {
  95. VCA_1 *module = NULL;
  96. VCA_1VUKnob() {
  97. box.size = mm2px(Vec(10, 46));
  98. }
  99. void draw(const DrawContext &ctx) override {
  100. float lastCv = module ? module->lastCv : 1.f;
  101. nvgBeginPath(ctx.vg);
  102. nvgRoundedRect(ctx.vg, 0, 0, box.size.x, box.size.y, 2.0);
  103. nvgFillColor(ctx.vg, nvgRGB(0, 0, 0));
  104. nvgFill(ctx.vg);
  105. const int segs = 25;
  106. const Vec margin = Vec(3, 3);
  107. Rect r = box.zeroPos().grow(margin.neg());
  108. for (int i = 0; i < segs; i++) {
  109. float value = paramQuantity ? paramQuantity->getValue() : 1.f;
  110. float segValue = clamp(value * segs - (segs - i - 1), 0.f, 1.f);
  111. float amplitude = value * lastCv;
  112. float segAmplitude = clamp(amplitude * segs - (segs - i - 1), 0.f, 1.f);
  113. nvgBeginPath(ctx.vg);
  114. nvgRect(ctx.vg, r.pos.x, r.pos.y + r.size.y / segs * i + 0.5,
  115. r.size.x, r.size.y / segs - 1.0);
  116. if (segValue > 0.f) {
  117. nvgFillColor(ctx.vg, color::alpha(nvgRGBf(0.33, 0.33, 0.33), segValue));
  118. nvgFill(ctx.vg);
  119. }
  120. if (segAmplitude > 0.f) {
  121. nvgFillColor(ctx.vg, color::alpha(SCHEME_GREEN, segAmplitude));
  122. nvgFill(ctx.vg);
  123. }
  124. }
  125. }
  126. };
  127. struct VCA_1Widget : ModuleWidget {
  128. VCA_1Widget(VCA_1 *module) {
  129. setModule(module);
  130. setPanel(SVG::load(asset::plugin(plugin, "res/VCA-1.svg")));
  131. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  132. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  133. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  134. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  135. VCA_1VUKnob *levelParam = createParam<VCA_1VUKnob>(mm2px(Vec(2.62103, 12.31692)), module, VCA_1::LEVEL_PARAM);
  136. levelParam->module = module;
  137. addParam(levelParam);
  138. addParam(createParam<CKSS>(mm2px(Vec(5.24619, 79.9593)), module, VCA_1::EXP_PARAM));
  139. addInput(createInput<PJ301MPort>(mm2px(Vec(3.51261, 60.4008)), module, VCA_1::CV_INPUT));
  140. addInput(createInput<PJ301MPort>(mm2px(Vec(3.51398, 97.74977)), module, VCA_1::IN_INPUT));
  141. addOutput(createOutput<PJ301MPort>(mm2px(Vec(3.51398, 108.64454)), module, VCA_1::OUT_OUTPUT));
  142. }
  143. };
  144. Model *modelVCA_1 = createModel<VCA_1, VCA_1Widget>("VCA-1");