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.

168 lines
4.9KB

  1. #include "AH.hpp"
  2. #include "Core.hpp"
  3. #include "UI.hpp"
  4. #include <iostream>
  5. namespace rack_plugin_AmalgamatedHarmonics {
  6. struct ScaleQuantizer : AHModule {
  7. enum ParamIds {
  8. NUM_PARAMS
  9. };
  10. enum InputIds {
  11. IN_INPUT,
  12. KEY_INPUT,
  13. SCALE_INPUT,
  14. NUM_INPUTS
  15. };
  16. enum OutputIds {
  17. OUT_OUTPUT,
  18. TRIG_OUTPUT,
  19. GATE_OUTPUT,
  20. NUM_OUTPUTS = GATE_OUTPUT + 12
  21. };
  22. enum LightIds {
  23. NOTE_LIGHT,
  24. KEY_LIGHT = NOTE_LIGHT + 12,
  25. SCALE_LIGHT = KEY_LIGHT + 12,
  26. DEGREE_LIGHT = SCALE_LIGHT + 12,
  27. NUM_LIGHTS = DEGREE_LIGHT + 12
  28. };
  29. ScaleQuantizer() : AHModule(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
  30. void step() override;
  31. bool firstStep = true;
  32. int lastScale = 0;
  33. int lastRoot = 0;
  34. float lastPitch = 0.0;
  35. int currScale = 0;
  36. int currRoot = 0;
  37. int currNote = 0;
  38. int currDegree = 0;
  39. float currPitch = 0.0;
  40. };
  41. void ScaleQuantizer::step() {
  42. stepX++;
  43. lastScale = currScale;
  44. lastRoot = currRoot;
  45. lastPitch = currPitch;
  46. // Get the input pitch
  47. float volts = inputs[IN_INPUT].value;
  48. float root = inputs[KEY_INPUT].value;
  49. float scale = inputs[SCALE_INPUT].value;
  50. // Calculate output pitch from raw voltage
  51. currPitch = CoreUtil().getPitchFromVolts(volts, root, scale, &currRoot, &currScale, &currNote, &currDegree);
  52. // Set the value
  53. outputs[OUT_OUTPUT].value = currPitch;
  54. // update tone lights
  55. for (int i = 0; i < Core::NUM_NOTES; i++) {
  56. lights[NOTE_LIGHT + i].value = 0.0;
  57. }
  58. lights[NOTE_LIGHT + currNote].value = 1.0;
  59. // update degree lights
  60. for (int i = 0; i < Core::NUM_NOTES; i++) {
  61. lights[DEGREE_LIGHT + i].value = 0.0;
  62. outputs[GATE_OUTPUT + i].value = 0.0;
  63. }
  64. lights[DEGREE_LIGHT + currDegree].value = 1.0;
  65. outputs[GATE_OUTPUT + currDegree].value = 10.0;
  66. if (lastScale != currScale || firstStep) {
  67. for (int i = 0; i < Core::NUM_NOTES; i++) {
  68. lights[SCALE_LIGHT + i].value = 0.0;
  69. }
  70. lights[SCALE_LIGHT + currScale].value = 1.0;
  71. }
  72. if (lastRoot != currRoot || firstStep) {
  73. for (int i = 0; i < Core::NUM_NOTES; i++) {
  74. lights[KEY_LIGHT + i].value = 0.0;
  75. }
  76. lights[KEY_LIGHT + currRoot].value = 1.0;
  77. }
  78. if (lastPitch != currPitch || firstStep) {
  79. outputs[TRIG_OUTPUT].value = 10.0;
  80. } else {
  81. outputs[TRIG_OUTPUT].value = 0.0;
  82. }
  83. firstStep = false;
  84. }
  85. struct ScaleQuantizerWidget : ModuleWidget {
  86. ScaleQuantizerWidget(ScaleQuantizer *module);
  87. };
  88. ScaleQuantizerWidget::ScaleQuantizerWidget(ScaleQuantizer *module) : ModuleWidget(module) {
  89. UI ui;
  90. box.size = Vec(240, 380);
  91. {
  92. SVGPanel *panel = new SVGPanel();
  93. panel->box.size = box.size;
  94. panel->setBackground(SVG::load(assetPlugin(plugin, "res/ScaleQuantizer.svg")));
  95. addChild(panel);
  96. }
  97. addChild(Widget::create<ScrewSilver>(Vec(15, 0)));
  98. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 0)));
  99. addChild(Widget::create<ScrewSilver>(Vec(15, 365)));
  100. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 30, 365)));
  101. addInput(Port::create<PJ301MPort>(ui.getPosition(UI::PORT, 0, 5, false, false), Port::INPUT, module, ScaleQuantizer::IN_INPUT));
  102. addInput(Port::create<PJ301MPort>(ui.getPosition(UI::PORT, 1, 5, false, false), Port::INPUT, module, ScaleQuantizer::KEY_INPUT));
  103. addInput(Port::create<PJ301MPort>(ui.getPosition(UI::PORT, 2, 5, false, false), Port::INPUT, module, ScaleQuantizer::SCALE_INPUT));
  104. addOutput(Port::create<PJ301MPort>(ui.getPosition(UI::PORT, 3, 5, false, false), Port::OUTPUT, module, ScaleQuantizer::TRIG_OUTPUT));
  105. addOutput(Port::create<PJ301MPort>(ui.getPosition(UI::PORT, 4, 5, false, false), Port::OUTPUT, module, ScaleQuantizer::OUT_OUTPUT));
  106. float xOffset = 18.0;
  107. float xSpace = 21.0;
  108. float xPos = 0.0;
  109. float yPos = 0.0;
  110. int scale = 0;
  111. for (int i = 0; i < 12; i++) {
  112. addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(Vec(xOffset + i * 18.0, 280.0), module, ScaleQuantizer::SCALE_LIGHT + i));
  113. ui.calculateKeyboard(i, xSpace, xOffset, 230.0, &xPos, &yPos, &scale);
  114. addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(Vec(xPos, yPos), module, ScaleQuantizer::KEY_LIGHT + scale));
  115. ui.calculateKeyboard(i, xSpace, xOffset + 72.0, 165.0, &xPos, &yPos, &scale);
  116. addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(Vec(xPos, yPos), module, ScaleQuantizer::NOTE_LIGHT + scale));
  117. ui.calculateKeyboard(i, 30.0, xOffset + 9.5, 110.0, &xPos, &yPos, &scale);
  118. addChild(ModuleLightWidget::create<SmallLight<GreenLight>>(Vec(xPos, yPos), module, ScaleQuantizer::DEGREE_LIGHT + scale));
  119. ui.calculateKeyboard(i, 30.0, xOffset, 85.0, &xPos, &yPos, &scale);
  120. addOutput(Port::create<PJ301MPort>(Vec(xPos, yPos), Port::OUTPUT, module, ScaleQuantizer::GATE_OUTPUT + scale));
  121. }
  122. }
  123. } // namespace rack_plugin_AmalgamatedHarmonics
  124. using namespace rack_plugin_AmalgamatedHarmonics;
  125. RACK_PLUGIN_MODEL_INIT(AmalgamatedHarmonics, ScaleQuantizer) {
  126. Model *modelScaleQuantizer = Model::create<ScaleQuantizer, ScaleQuantizerWidget>( "Amalgamated Harmonics", "ScaleQuantizer", "Scale Quantizer (deprecated)", QUANTIZER_TAG);
  127. return modelScaleQuantizer;
  128. }