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.

150 lines
4.7KB

  1. #include "plugin.hpp"
  2. struct Sum : Module {
  3. enum ParamIds {
  4. LEVEL_PARAM,
  5. NUM_PARAMS
  6. };
  7. enum InputIds {
  8. POLY_INPUT,
  9. NUM_INPUTS
  10. };
  11. enum OutputIds {
  12. MONO_OUTPUT,
  13. NUM_OUTPUTS
  14. };
  15. enum LightIds {
  16. ENUMS(VU_LIGHTS, 6),
  17. NUM_LIGHTS
  18. };
  19. dsp::VuMeter2 vuMeter;
  20. dsp::ClockDivider vuDivider;
  21. dsp::ClockDivider lightDivider;
  22. int lastChannels = 0;
  23. Sum() {
  24. config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
  25. configParam(LEVEL_PARAM, 0.f, 1.f, 1.f, "Level", "%", 0.f, 100.f);
  26. configInput(POLY_INPUT, "Polyphonic");
  27. configOutput(MONO_OUTPUT, "Monophonic");
  28. vuMeter.lambda = 1 / 0.1f;
  29. vuDivider.setDivision(16);
  30. lightDivider.setDivision(512);
  31. }
  32. void process(const ProcessArgs& args) override {
  33. float sum = inputs[POLY_INPUT].getVoltageSum();
  34. sum *= params[LEVEL_PARAM].getValue();
  35. outputs[MONO_OUTPUT].setVoltage(sum);
  36. if (vuDivider.process()) {
  37. vuMeter.process(args.sampleTime * vuDivider.getDivision(), sum / 10.f);
  38. }
  39. // Set channel lights infrequently
  40. if (lightDivider.process()) {
  41. lastChannels = inputs[POLY_INPUT].getChannels();
  42. lights[VU_LIGHTS + 0].setBrightness(vuMeter.getBrightness(0, 0));
  43. lights[VU_LIGHTS + 1].setBrightness(vuMeter.getBrightness(-3, 0));
  44. lights[VU_LIGHTS + 2].setBrightness(vuMeter.getBrightness(-6, -3));
  45. lights[VU_LIGHTS + 3].setBrightness(vuMeter.getBrightness(-12, -6));
  46. lights[VU_LIGHTS + 4].setBrightness(vuMeter.getBrightness(-24, -12));
  47. lights[VU_LIGHTS + 5].setBrightness(vuMeter.getBrightness(-36, -24));
  48. }
  49. }
  50. };
  51. struct SumDisplay : LedDisplay {
  52. Sum* module;
  53. void drawLayer(const DrawArgs& args, int layer) override {
  54. if (layer == 1) {
  55. static const std::vector<float> posY = {
  56. mm2px(18.068 - 13.039),
  57. mm2px(23.366 - 13.039),
  58. mm2px(28.663 - 13.039),
  59. mm2px(33.961 - 13.039),
  60. mm2px(39.258 - 13.039),
  61. mm2px(44.556 - 13.039),
  62. };
  63. static const std::vector<std::string> texts = {
  64. " 0", "-3", "-6", "-12", "-24", "-36",
  65. };
  66. std::string fontPath = asset::system("res/fonts/Nunito-Bold.ttf");
  67. std::shared_ptr<Font> font = APP->window->loadFont(fontPath);
  68. if (!font)
  69. return;
  70. nvgSave(args.vg);
  71. nvgFontFaceId(args.vg, font->handle);
  72. nvgFontSize(args.vg, 11);
  73. nvgTextLetterSpacing(args.vg, 0.0);
  74. nvgTextAlign(args.vg, NVG_ALIGN_CENTER | NVG_ALIGN_MIDDLE);
  75. nvgFillColor(args.vg, nvgRGB(99, 99, 99));
  76. for (int i = 0; i < 6; i++) {
  77. nvgText(args.vg, 15.0, posY[i], texts[i].c_str(), NULL);
  78. }
  79. nvgRestore(args.vg);
  80. }
  81. LedDisplay::drawLayer(args, layer);
  82. }
  83. };
  84. struct SumChannelDisplay : ChannelDisplay {
  85. Sum* module;
  86. void step() override {
  87. int channels = 16;
  88. if (module)
  89. channels = module->lastChannels;
  90. text = string::f("%d", channels);
  91. }
  92. };
  93. struct SumWidget : ModuleWidget {
  94. SumWidget(Sum* module) {
  95. setModule(module);
  96. setPanel(createPanel(asset::plugin(pluginInstance, "res/Sum.svg"), asset::plugin(pluginInstance, "res/Sum-dark.svg")));
  97. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  98. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  99. addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  100. addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  101. addParam(createParamCentered<RoundBlackKnob>(mm2px(Vec(7.62, 64.284)), module, Sum::LEVEL_PARAM));
  102. addInput(createInputCentered<ThemedPJ301MPort>(mm2px(Vec(7.62, 96.798)), module, Sum::POLY_INPUT));
  103. addOutput(createOutputCentered<ThemedPJ301MPort>(mm2px(Vec(7.62, 113.066)), module, Sum::MONO_OUTPUT));
  104. SumDisplay* display = createWidget<SumDisplay>(mm2px(Vec(0.0, 13.039)));
  105. display->box.size = mm2px(Vec(15.241, 36.981));
  106. display->module = module;
  107. addChild(display);
  108. addChild(createLightCentered<SmallSimpleLight<RedLight>>(mm2px(Vec(10.808, 18.081)), module, Sum::VU_LIGHTS + 0));
  109. addChild(createLightCentered<SmallSimpleLight<YellowLight>>(mm2px(Vec(10.808, 23.378)), module, Sum::VU_LIGHTS + 1));
  110. addChild(createLightCentered<SmallSimpleLight<GreenLight>>(mm2px(Vec(10.808, 28.676)), module, Sum::VU_LIGHTS + 2));
  111. addChild(createLightCentered<SmallSimpleLight<GreenLight>>(mm2px(Vec(10.808, 33.973)), module, Sum::VU_LIGHTS + 3));
  112. addChild(createLightCentered<SmallSimpleLight<GreenLight>>(mm2px(Vec(10.808, 39.271)), module, Sum::VU_LIGHTS + 4));
  113. addChild(createLightCentered<SmallSimpleLight<GreenLight>>(mm2px(Vec(10.808, 44.568)), module, Sum::VU_LIGHTS + 5));
  114. SumChannelDisplay* channelDisplay = createWidget<SumChannelDisplay>(mm2px(Vec(3.521, 77.191)));
  115. channelDisplay->box.size = mm2px(Vec(8.197, 8.197));
  116. channelDisplay->module = module;
  117. addChild(channelDisplay);
  118. }
  119. };
  120. Model* modelSum = createModel<Sum, SumWidget>("Sum");