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.

193 lines
6.6KB

  1. #include <sstream>
  2. #include "Squinky.hpp"
  3. #include "WidgetComposite.h"
  4. #include "Tremolo.h"
  5. /**
  6. */
  7. struct TremoloModule : Module
  8. {
  9. public:
  10. TremoloModule();
  11. /**
  12. * Overrides of Module functions
  13. */
  14. void step() override;
  15. void onSampleRateChange() override;
  16. Tremolo<WidgetComposite> tremolo;
  17. private:
  18. };
  19. void TremoloModule::onSampleRateChange()
  20. {
  21. float rate = engineGetSampleRate();
  22. tremolo.setSampleRate(rate);
  23. }
  24. TremoloModule::TremoloModule()
  25. : Module(tremolo.NUM_PARAMS,
  26. tremolo.NUM_INPUTS,
  27. tremolo.NUM_OUTPUTS,
  28. tremolo.NUM_LIGHTS),
  29. tremolo(this)
  30. {
  31. onSampleRateChange();
  32. tremolo.init();
  33. }
  34. void TremoloModule::step()
  35. {
  36. tremolo.step();
  37. }
  38. ////////////////////
  39. // module widget
  40. ////////////////////
  41. struct TremoloWidget : ModuleWidget
  42. {
  43. TremoloWidget(TremoloModule *);
  44. void addLabel(const Vec& v, const char* str, const NVGcolor& color = COLOR_BLACK)
  45. {
  46. Label* label = new Label();
  47. label->box.pos = v;
  48. label->text = str;
  49. label->color = color;
  50. addChild(label);
  51. }
  52. void addClockSection(TremoloModule *module);
  53. void addIOSection(TremoloModule *module);
  54. void addMainSection(TremoloModule *module);
  55. };
  56. void TremoloWidget::addClockSection(TremoloModule *module)
  57. {
  58. const float y = 40; // global offset for clock block
  59. const float labelY = y + 36;
  60. addInput(Port::create<PJ301MPort>(Vec(10, y + 7), Port::INPUT, module, module->tremolo.CLOCK_INPUT));
  61. addLabel(Vec(2, labelY), "ckin");
  62. addParam(ParamWidget::create<RoundBlackKnob>(
  63. Vec(110, y), module, module->tremolo.LFO_RATE_PARAM, -5.0, 5.0, 0.0));
  64. addLabel(Vec(104, labelY), "Rate");
  65. const float cmy = y;
  66. const float cmx = 60;
  67. addParam(ParamWidget::create<RoundBlackSnapKnob>(
  68. Vec(cmx, cmy), module, module->tremolo.CLOCK_MULT_PARAM, 0.0f, 4.0f, 4.0f));
  69. addLabel(Vec(cmx - 8, labelY), "Clock");
  70. addLabel(Vec(cmx - 19, cmy + 20), "x1");
  71. addLabel(Vec(cmx + 21, cmy + 20), "int");
  72. addLabel(Vec(cmx - 24, cmy + 0), "x2");
  73. addLabel(Vec(cmx + 24, cmy + 0), "x4");
  74. addLabel(Vec(cmx, cmy - 16), "x3");
  75. }
  76. void TremoloWidget::addIOSection(TremoloModule *module)
  77. {
  78. const float rowIO = 317;
  79. const float label = rowIO - 17;
  80. const float deltaX = 35;
  81. const float x = 10;
  82. addInput(Port::create<PJ301MPort>(Vec(x, rowIO), Port::INPUT, module, module->tremolo.AUDIO_INPUT));
  83. addLabel(Vec(8, label), "in");
  84. addOutput(Port::create<PJ301MPort>(Vec(x + deltaX, rowIO), Port::OUTPUT, module, module->tremolo.AUDIO_OUTPUT));
  85. addLabel(Vec(x + deltaX - 6, label), "out", COLOR_WHITE);
  86. addOutput(Port::create<PJ301MPort>(Vec(x + 2 * deltaX, rowIO), Port::OUTPUT, module, module->tremolo.SAW_OUTPUT));
  87. addLabel(Vec(x + 2 * deltaX - 7, label), "saw", COLOR_WHITE);
  88. addOutput(Port::create<PJ301MPort>(Vec(x + 3 * deltaX, rowIO), Port::OUTPUT, module, module->tremolo.LFO_OUTPUT));
  89. addLabel(Vec(x + 3 * deltaX - 2, label), "lfo", COLOR_WHITE);
  90. }
  91. void TremoloWidget::addMainSection(TremoloModule *module)
  92. {
  93. const float knobX = 64;
  94. const float knobY = 100;
  95. const float knobDy = 50;
  96. const float labelX = 100;
  97. const float labelY = knobY;
  98. const float trimX = 40;
  99. const float trimY = knobY + 10;
  100. const float inY = knobY + 6;
  101. const float inX = 8;
  102. addParam(ParamWidget::create<Rogan1PSBlue>(
  103. Vec(knobX, knobY + 0 * knobDy), module, module->tremolo.LFO_SHAPE_PARAM, -5.0, 5.0, 0.0));
  104. addParam(ParamWidget::create<Trimpot>(
  105. Vec(trimX, trimY + 0 * knobDy), module, module->tremolo.LFO_SHAPE_TRIM_PARAM, -1.0, 1.0, 1.0));
  106. addInput(Port::create<PJ301MPort>(
  107. Vec(inX, inY + 0 * knobDy), Port::INPUT, module, module->tremolo.LFO_SHAPE_INPUT));
  108. addLabel(
  109. Vec(labelX, labelY + 0 * knobDy), "Shape");
  110. addParam(ParamWidget::create<Rogan1PSBlue>(
  111. Vec(knobX, knobY + 1 * knobDy), module, module->tremolo.LFO_SKEW_PARAM, -5.0, 5.0, 0.0));
  112. addParam(ParamWidget::create<Trimpot>(
  113. Vec(trimX, trimY + 1 * knobDy), module, module->tremolo.LFO_SKEW_TRIM_PARAM, -1.0, 1.0, 1.0));
  114. addInput(Port::create<PJ301MPort>(
  115. Vec(inX, labelY + 1 * knobDy + 6), Port::INPUT, module, module->tremolo.LFO_SKEW_INPUT));
  116. addLabel(
  117. Vec(labelX+1, labelY + 1 * knobDy), "Skew");
  118. addParam(ParamWidget::create<Rogan1PSBlue>(
  119. Vec(knobX, knobY + 2 * knobDy), module, module->tremolo.LFO_PHASE_PARAM, -5.0, 5.0, 0.0));
  120. addParam(ParamWidget::create<Trimpot>(
  121. Vec(trimX, trimY + 2 * knobDy), module, module->tremolo.LFO_PHASE_TRIM_PARAM, -1.0, 1.0, 1.0));
  122. addInput(Port::create<PJ301MPort>(
  123. Vec(inX, labelY + 2 * knobDy + 6), Port::INPUT, module, module->tremolo.LFO_PHASE_INPUT));
  124. addLabel(
  125. Vec(labelX, labelY + 2 * knobDy), "Phase");
  126. addParam(ParamWidget::create<Rogan1PSBlue>(
  127. Vec(knobX, knobY + 3 * knobDy), module, module->tremolo.MOD_DEPTH_PARAM, -5.0, 5.0, 0.0));
  128. addParam(ParamWidget::create<Trimpot>(
  129. Vec(trimX, trimY + 3 * knobDy), module, module->tremolo.MOD_DEPTH_TRIM_PARAM, -1.0, 1.0, 1.0));
  130. addInput(Port::create<PJ301MPort>(
  131. Vec(inX, labelY + 3 * knobDy + 6), Port::INPUT, module, module->tremolo.MOD_DEPTH_INPUT));
  132. addLabel(
  133. Vec(labelX, labelY + 3 * knobDy), "Depth");
  134. }
  135. /**
  136. * Widget constructor will describe my implementation structure and
  137. * provide meta-data.
  138. * This is not shared by all modules in the DLL, just one
  139. */
  140. TremoloWidget::TremoloWidget(TremoloModule *module) : ModuleWidget(module)
  141. {
  142. box.size = Vec(10 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT);
  143. {
  144. SVGPanel *panel = new SVGPanel();
  145. panel->box.size = box.size;
  146. panel->setBackground(SVG::load(assetPlugin(plugin, "res/trem_panel.svg")));
  147. addChild(panel);
  148. }
  149. addClockSection(module);
  150. addMainSection(module);
  151. addIOSection(module);
  152. // screws
  153. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
  154. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
  155. addChild(Widget::create<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  156. addChild(Widget::create<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
  157. }
  158. RACK_PLUGIN_MODEL_INIT(squinkylabs_plug1, Tremolo) {
  159. Model *modelTremoloModule = Model::create<TremoloModule,
  160. TremoloWidget>("Squinky Labs",
  161. "squinkylabs-tremolo",
  162. "Chopper Tremolo", EFFECT_TAG, LFO_TAG);
  163. return modelTremoloModule;
  164. }