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.

201 lines
6.8KB

  1. #include "Squinky.hpp"
  2. #include "WidgetComposite.h"
  3. #include "VocalAnimator.h"
  4. /**
  5. * Implementation class for VocalWidget
  6. */
  7. struct VocalModule : Module
  8. {
  9. VocalModule();
  10. /**
  11. * Overrides of Module functions
  12. */
  13. void step() override;
  14. void onSampleRateChange() override;
  15. using Animator = VocalAnimator<WidgetComposite>;
  16. Animator animator;
  17. private:
  18. typedef float T;
  19. };
  20. VocalModule::VocalModule() : Module(animator.NUM_PARAMS, animator.NUM_INPUTS, animator.NUM_OUTPUTS, animator.NUM_LIGHTS),
  21. animator(this)
  22. {
  23. onSampleRateChange();
  24. animator.init();
  25. }
  26. void VocalModule::onSampleRateChange()
  27. {
  28. T rate = engineGetSampleRate();
  29. animator.setSampleRate(rate);
  30. }
  31. void VocalModule::step()
  32. {
  33. animator.step();
  34. }
  35. ////////////////////
  36. // module widget
  37. ////////////////////
  38. struct VocalWidget : ModuleWidget
  39. {
  40. VocalWidget(VocalModule *);
  41. };
  42. template <typename BASE>
  43. struct MuteLight : BASE
  44. {
  45. MuteLight()
  46. {
  47. this->box.size = mm2px(Vec(6.0f, 6.0f));
  48. }
  49. };
  50. struct NKK2 : SVGSwitch, ToggleSwitch
  51. {
  52. NKK2()
  53. {
  54. addFrame(SVG::load(assetGlobal("res/ComponentLibrary/NKK_0.svg")));
  55. addFrame(SVG::load(assetGlobal("res/ComponentLibrary/NKK_2.svg")));
  56. }
  57. };
  58. /**
  59. * Widget constructor will describe my implementation structure and
  60. * provide meta-data.
  61. * This is not shared by all modules in the DLL, just one
  62. */
  63. VocalWidget::VocalWidget(VocalModule *module) : ModuleWidget(module)
  64. {
  65. const float width = 14 * RACK_GRID_WIDTH;
  66. box.size = Vec(width, RACK_GRID_HEIGHT);
  67. {
  68. SVGPanel *panel = new SVGPanel();
  69. panel->box.size = box.size;
  70. panel->setBackground(SVG::load(assetPlugin(plugin, "res/vocal_animator_panel.svg")));
  71. addChild(panel);
  72. }
  73. /**
  74. * LEDs and LFO outputs
  75. */
  76. const float lfoBlockY = 38; // was 22. move down to make space
  77. const float ledX = width - 46;
  78. const float ledY = lfoBlockY + 7.5;
  79. const float ledSpacingY = 30;
  80. const float lfoOutY = lfoBlockY;
  81. const float lfoOutX = width - 30;
  82. const float lfoInputX = 24;
  83. const float lfoInputY = lfoBlockY + 0;
  84. const float lfoTrimX = 68;
  85. const float lfoTrimY = lfoInputY + 3;
  86. const float lfoRateKnobX = 100;
  87. const float lfoRateKnobY = lfoBlockY + 24;
  88. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(
  89. Vec(ledX, ledY), module, module->animator.LFO0_LIGHT));
  90. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(
  91. Vec(ledX, ledY + ledSpacingY), module, module->animator.LFO1_LIGHT));
  92. addChild(ModuleLightWidget::create<MediumLight<GreenLight>>(
  93. Vec(ledX, ledY + 2 * ledSpacingY), module, module->animator.LFO2_LIGHT));
  94. addOutput(Port::create<PJ301MPort>(
  95. Vec(lfoOutX, lfoOutY), Port::OUTPUT, module, VocalModule::Animator::LFO0_OUTPUT));
  96. addOutput(Port::create<PJ301MPort>(
  97. Vec(lfoOutX, lfoOutY + 1 * ledSpacingY), Port::OUTPUT, module, VocalModule::Animator::LFO1_OUTPUT));
  98. addOutput(Port::create<PJ301MPort>(
  99. Vec(lfoOutX, lfoOutY + 2 * ledSpacingY), Port::OUTPUT, module, VocalModule::Animator::LFO2_OUTPUT));
  100. addParam(ParamWidget::create<Rogan1PSBlue>(
  101. Vec(lfoRateKnobX, lfoRateKnobY), module, module->animator.LFO_RATE_PARAM, -5.0, 5.0, 0.0));
  102. addInput(Port::create<PJ301MPort>(
  103. Vec(lfoInputX, lfoInputY), Port::INPUT, module, VocalModule::Animator::LFO_RATE_CV_INPUT));
  104. addParam(ParamWidget::create<Trimpot>(
  105. Vec(lfoTrimX, lfoTrimY), module, module->animator.LFO_RATE_TRIM_PARAM, -1.0, 1.0, 1.0));
  106. // the matrix switch
  107. addParam(ParamWidget::create<NKK>(
  108. Vec(42, 65), module, module->animator.LFO_MIX_PARAM, 0.0f, 2.0f, 0.0f));
  109. /**
  110. * Parameters and CV
  111. */
  112. const float mainBlockY = 140;
  113. const float mainBlockX = 20;
  114. const float colSpacingX = 64;
  115. const float knobX = mainBlockX + 0;
  116. const float knobY = mainBlockY + 24;
  117. const float trimX = mainBlockX + 11;
  118. const float trimY = mainBlockY + 78;
  119. const float inputX = mainBlockX + 8;
  120. const float inputY = mainBlockY + 108;
  121. addParam(ParamWidget::create<Rogan1PSBlue>(
  122. Vec(knobX, knobY), module, module->animator.FILTER_FC_PARAM, -5.0, 5.0, 0.0));
  123. addInput(Port::create<PJ301MPort>(
  124. Vec(inputX, inputY), Port::INPUT, module, VocalModule::Animator::FILTER_FC_CV_INPUT));
  125. addParam(ParamWidget::create<Trimpot>(
  126. Vec(trimX, trimY), module, module->animator.FILTER_FC_TRIM_PARAM, -1.0, 1.0, 1.0));
  127. addParam(ParamWidget::create<Rogan1PSBlue>(
  128. Vec(knobX + colSpacingX, knobY), module, module->animator.FILTER_Q_PARAM, -5.0, 5.0, 0.0));
  129. addInput(Port::create<PJ301MPort>(
  130. Vec(inputX + colSpacingX, inputY), Port::INPUT, module, VocalModule::Animator::FILTER_Q_CV_INPUT));
  131. addParam(ParamWidget::create<Trimpot>(
  132. Vec(trimX + colSpacingX, trimY), module, module->animator.FILTER_Q_TRIM_PARAM, -1.0, 1.0, 1.0));
  133. addParam(ParamWidget::create<Rogan1PSBlue>(
  134. Vec(knobX + 2 * colSpacingX, knobY), module, module->animator.FILTER_MOD_DEPTH_PARAM, -5.0, 5.0, 0.0));
  135. addInput(Port::create<PJ301MPort>(
  136. Vec(inputX + 2 * colSpacingX, inputY), Port::INPUT, module, VocalModule::Animator::FILTER_MOD_DEPTH_CV_INPUT));
  137. addParam(ParamWidget::create<Trimpot>(
  138. Vec(trimX + 2 * colSpacingX, trimY), module, module->animator.FILTER_MOD_DEPTH_TRIM_PARAM, -1.0, 1.0, 1.0));
  139. const float row3 = 310;
  140. // I.O on row 3
  141. const float AudioInputX = inputX;
  142. const float outputX = inputX + 2 * colSpacingX;
  143. addInput(Port::create<PJ301MPort>(
  144. Vec(AudioInputX, row3), Port::INPUT, module, VocalModule::Animator::AUDIO_INPUT));
  145. addOutput(Port::create<PJ301MPort>(
  146. Vec(outputX, row3), Port::OUTPUT, module, VocalModule::Animator::AUDIO_OUTPUT));
  147. const float bassX = inputX + colSpacingX - 4;
  148. const float bassY = row3 - 8;
  149. // the bass boost switch
  150. addParam(ParamWidget::create<NKK2>(
  151. Vec(bassX, bassY), module, module->animator.BASS_EXP_PARAM, 0.0f, 1.0f, 0.0f));
  152. /*************************************************
  153. * screws
  154. */
  155. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  156. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  157. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  158. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  159. }
  160. RACK_PLUGIN_MODEL_INIT(squinkylabs_plug1, Vocal) {
  161. Model *modelVocalModule = Model::create<VocalModule, VocalWidget>("Squinky Labs",
  162. "squinkylabs-vocalanimator",
  163. "Vocal Animator", EFFECT_TAG, FILTER_TAG, LFO_TAG, RANDOM_TAG);
  164. return modelVocalModule;
  165. }