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.

195 lines
7.4KB

  1. //============================================================================================================
  2. //!
  3. //! \file Fade-G2.cpp
  4. //!
  5. //! \brief Fade-G2 is a four input six voice two-dimensional fader.
  6. //!
  7. //============================================================================================================
  8. #include "Gratrix.hpp"
  9. namespace rack_plugin_Gratrix {
  10. //============================================================================================================
  11. //! \brief The module.
  12. struct GtxModule_Fade_G2 : Module
  13. {
  14. enum ParamIds {
  15. BLEND12_PARAM,
  16. BLENDAB_PARAM,
  17. NUM_PARAMS
  18. };
  19. enum InputIds {
  20. BLEND12_INPUT,
  21. BLENDAB_INPUT,
  22. IN1A_INPUT,
  23. IN1B_INPUT,
  24. IN2A_INPUT,
  25. IN2B_INPUT,
  26. NUM_INPUTS,
  27. OFF_INPUTS = IN1A_INPUT
  28. };
  29. enum OutputIds {
  30. OUT1A_OUTPUT,
  31. OUT2B_OUTPUT,
  32. NUM_OUTPUTS,
  33. OFF_OUTPUTS = OUT1A_OUTPUT
  34. };
  35. enum LightIds {
  36. IN_1AP_GREEN, IN_1AP_RED,
  37. IN_1AQ_GREEN, IN_1AQ_RED,
  38. IN_1BP_GREEN, IN_1BP_RED,
  39. IN_1BQ_GREEN, IN_1BQ_RED,
  40. IN_2AP_GREEN, IN_2AP_RED,
  41. IN_2AQ_GREEN, IN_2AQ_RED,
  42. IN_2BP_GREEN, IN_2BP_RED,
  43. IN_2BQ_GREEN, IN_2BQ_RED,
  44. OUT_1AP_GREEN, OUT_1AP_RED,
  45. OUT_1AQ_GREEN, OUT_1AQ_RED,
  46. OUT_2BP_GREEN, OUT_2BP_RED,
  47. OUT_2BQ_GREEN, OUT_2BQ_RED,
  48. NUM_LIGHTS
  49. };
  50. GtxModule_Fade_G2()
  51. :
  52. Module(NUM_PARAMS,
  53. (GTX__N+1) * (NUM_INPUTS - OFF_INPUTS ) + OFF_INPUTS,
  54. (GTX__N ) * (NUM_OUTPUTS - OFF_OUTPUTS) + OFF_OUTPUTS,
  55. NUM_LIGHTS)
  56. {
  57. lights[IN_1AP_GREEN].value = 0.0f; lights[IN_1AP_RED].value = 1.0f;
  58. lights[IN_1AQ_GREEN].value = 0.0f; lights[IN_1AQ_RED].value = 1.0f;
  59. lights[IN_1BP_GREEN].value = 1.0f; lights[IN_1BP_RED].value = 0.0f;
  60. lights[IN_1BQ_GREEN].value = 0.0f; lights[IN_1BQ_RED].value = 1.0f;
  61. lights[IN_2AP_GREEN].value = 0.0f; lights[IN_2AP_RED].value = 1.0f;
  62. lights[IN_2AQ_GREEN].value = 1.0f; lights[IN_2AQ_RED].value = 0.0f;
  63. lights[IN_2BP_GREEN].value = 1.0f; lights[IN_2BP_RED].value = 0.0f;
  64. lights[IN_2BQ_GREEN].value = 1.0f; lights[IN_2BQ_RED].value = 0.0f;
  65. }
  66. static constexpr std::size_t imap(std::size_t port, std::size_t bank)
  67. {
  68. return (port < OFF_INPUTS) ? port : port + bank * (NUM_INPUTS - OFF_INPUTS);
  69. }
  70. static constexpr std::size_t omap(std::size_t port, std::size_t bank)
  71. {
  72. return port + bank * NUM_OUTPUTS;
  73. }
  74. void step() override
  75. {
  76. float blend12 = params[BLEND12_PARAM].value;
  77. float blendAB = params[BLENDAB_PARAM].value;
  78. if (inputs[BLEND12_INPUT].active) blend12 *= clamp(inputs[BLEND12_INPUT].normalize(10.0f) / 10.0f, 0.0f, 1.0f);
  79. if (inputs[BLENDAB_INPUT].active) blendAB *= clamp(inputs[BLENDAB_INPUT].normalize(10.0f) / 10.0f, 0.0f, 1.0f);
  80. for (std::size_t i=0; i<GTX__N; ++i)
  81. {
  82. float input1A = inputs[imap(IN1A_INPUT, i)].active ? inputs[imap(IN1A_INPUT, i)].value : inputs[imap(IN1A_INPUT, GTX__N)].value;
  83. float input1B = inputs[imap(IN1B_INPUT, i)].active ? inputs[imap(IN1B_INPUT, i)].value : inputs[imap(IN1B_INPUT, GTX__N)].value;
  84. float input2A = inputs[imap(IN2A_INPUT, i)].active ? inputs[imap(IN2A_INPUT, i)].value : inputs[imap(IN2A_INPUT, GTX__N)].value;
  85. float input2B = inputs[imap(IN2B_INPUT, i)].active ? inputs[imap(IN2B_INPUT, i)].value : inputs[imap(IN2B_INPUT, GTX__N)].value;
  86. float delta1AB = blendAB * (input1B - input1A);
  87. float delta2AB = blendAB * (input2B - input2A);
  88. float temp_1A = input1A + delta1AB;
  89. float temp_1B = input1B - delta1AB;
  90. float temp_2A = input2A + delta2AB;
  91. float temp_2B = input2B - delta2AB;
  92. float delta12A = blend12 * (temp_2A - temp_1A);
  93. float delta12B = blend12 * (temp_2B - temp_1B);
  94. outputs[omap(OUT1A_OUTPUT, i)].value = temp_1A + delta12A;
  95. outputs[omap(OUT2B_OUTPUT, i)].value = temp_2B - delta12B;
  96. }
  97. lights[OUT_1AP_GREEN].value = lights[OUT_2BP_RED].value = blendAB;
  98. lights[OUT_1AQ_GREEN].value = lights[OUT_2BQ_RED].value = blend12;
  99. lights[OUT_2BP_GREEN].value = lights[OUT_1AP_RED].value = 1.0f - blendAB;
  100. lights[OUT_2BQ_GREEN].value = lights[OUT_1AQ_RED].value = 1.0f - blend12;
  101. }
  102. };
  103. //============================================================================================================
  104. //! \brief The widget.
  105. struct GtxWidget_Fade_G2 : ModuleWidget
  106. {
  107. GtxWidget_Fade_G2(GtxModule_Fade_G2 *module) : ModuleWidget(module)
  108. {
  109. GTX__WIDGET();
  110. box.size = Vec(18*15, 380);
  111. #if GTX__SAVE_SVG
  112. {
  113. PanelGen pg(assetPlugin(plugin, "build/res/Fade-G2.svg"), box.size, "FADE-G2");
  114. // ― is a horizontal bar see https://en.wikipedia.org/wiki/Dash#Horizontal_bar
  115. pg.prt_in2(0, -0.28, "CV 1―2"); pg.nob_big(1, 0, "1―2");
  116. pg.prt_in2(0, +0.28, "CV A―B"); pg.nob_big(2, 0, "A―B");
  117. pg.bus_in(0, 1, "IN 1A"); pg.bus_out(2, 1, "OUT");
  118. pg.bus_in(1, 1, "IN 1B");
  119. pg.bus_in(0, 2, "IN 2A");
  120. pg.bus_in(1, 2, "IN 2B"); pg.bus_out(2, 2, "INV OUT");
  121. }
  122. #endif
  123. setPanel(SVG::load(assetPlugin(plugin, "res/Fade-G2.svg")));
  124. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  125. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 0)));
  126. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  127. addChild(Widget::create<ScrewSilver>(Vec(box.size.x-30, 365)));
  128. addParam(createParamGTX<KnobFreeHug>(Vec(fx(1), fy(0)), module, GtxModule_Fade_G2::BLENDAB_PARAM, 0.0f, 1.0f, 0.0f));
  129. addParam(createParamGTX<KnobFreeHug>(Vec(fx(2), fy(0)), module, GtxModule_Fade_G2::BLEND12_PARAM, 0.0f, 1.0f, 0.0f));
  130. addInput(createInputGTX<PortInMed>(Vec(fx(0), fy(-0.28)), module, GtxModule_Fade_G2::BLENDAB_INPUT));
  131. addInput(createInputGTX<PortInMed>(Vec(fx(0), fy(+0.28)), module, GtxModule_Fade_G2::BLEND12_INPUT));
  132. for (std::size_t i=0; i<GTX__N; ++i)
  133. {
  134. addInput(createInputGTX<PortInMed>(Vec(px(0, i), py(1, i)), module, GtxModule_Fade_G2::imap(GtxModule_Fade_G2::IN1A_INPUT, i)));
  135. addInput(createInputGTX<PortInMed>(Vec(px(0, i), py(2, i)), module, GtxModule_Fade_G2::imap(GtxModule_Fade_G2::IN1B_INPUT, i)));
  136. addInput(createInputGTX<PortInMed>(Vec(px(1, i), py(1, i)), module, GtxModule_Fade_G2::imap(GtxModule_Fade_G2::IN2A_INPUT, i)));
  137. addInput(createInputGTX<PortInMed>(Vec(px(1, i), py(2, i)), module, GtxModule_Fade_G2::imap(GtxModule_Fade_G2::IN2B_INPUT, i)));
  138. addOutput(createOutputGTX<PortOutMed>(Vec(px(2, i), py(1, i)), module, GtxModule_Fade_G2::omap(GtxModule_Fade_G2::OUT1A_OUTPUT, i)));
  139. addOutput(createOutputGTX<PortOutMed>(Vec(px(2, i), py(2, i)), module, GtxModule_Fade_G2::omap(GtxModule_Fade_G2::OUT2B_OUTPUT, i)));
  140. }
  141. addInput(createInputGTX<PortInMed>(Vec(gx(0), gy(1)), module, GtxModule_Fade_G2::imap(GtxModule_Fade_G2::IN1A_INPUT, GTX__N)));
  142. addInput(createInputGTX<PortInMed>(Vec(gx(0), gy(2)), module, GtxModule_Fade_G2::imap(GtxModule_Fade_G2::IN1B_INPUT, GTX__N)));
  143. addInput(createInputGTX<PortInMed>(Vec(gx(1), gy(1)), module, GtxModule_Fade_G2::imap(GtxModule_Fade_G2::IN2A_INPUT, GTX__N)));
  144. addInput(createInputGTX<PortInMed>(Vec(gx(1), gy(2)), module, GtxModule_Fade_G2::imap(GtxModule_Fade_G2::IN2B_INPUT, GTX__N)));
  145. for (std::size_t i=0, x=0; x<3; ++x)
  146. {
  147. for (std::size_t y=0; y<2; ++y)
  148. {
  149. addChild(ModuleLightWidget::create<SmallLight<GreenRedLight>>(l_s(gx(x)+rad_l_s()/2+28, gy(y+1)-47.5-(1+rad_l_s())), module, i)); i+=2;
  150. addChild(ModuleLightWidget::create<SmallLight<GreenRedLight>>(l_s(gx(x)+rad_l_s()/2+28, gy(y+1)-47.5+(1+rad_l_s())), module, i)); i+=2;
  151. }
  152. }
  153. }
  154. };
  155. } // namespace rack_plugin_Gratrix
  156. using namespace rack_plugin_Gratrix;
  157. RACK_PLUGIN_MODEL_INIT(Gratrix, Fade_G2) {
  158. Model *model = Model::create<GtxModule_Fade_G2, GtxWidget_Fade_G2>("Gratrix", "Fade-G2", "Fade-G2", MIXER_TAG); // right tag?
  159. return model;
  160. }