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.

183 lines
8.8KB

  1. #include "Nohmad.hpp"
  2. namespace rack_plugin_Nohmad {
  3. struct LorenzAttractor {
  4. float sigma, beta, rho, pitch; // Params
  5. float x, y, z; // Out
  6. static constexpr float DEFAULT_SIGNMA_VALUE = 10.0f;
  7. static constexpr float DEFAULT_BETA_VALUE = 8.0f / 3.0f;
  8. static constexpr float DEFAULT_RHO_VALUE = 28.0f;
  9. static constexpr float DEFAULT_PITCH_VALUE = 0.5f;
  10. LorenzAttractor() :
  11. sigma(DEFAULT_SIGNMA_VALUE), beta(DEFAULT_BETA_VALUE), rho(DEFAULT_RHO_VALUE), pitch(DEFAULT_PITCH_VALUE),
  12. x(1.0f), y(1.0f), z(1.0f) {}
  13. void process(float dt) {
  14. float dx = sigma * (y - x);
  15. float dy = x * (rho - z) - y;
  16. float dz = (x * y) - (beta * z);
  17. x += dx * dt * pitch * 375.0f;
  18. y += dy * dt * pitch * 375.0f;
  19. z += dz * dt * pitch * 375.0f;
  20. }
  21. };
  22. struct RosslerAttractor {
  23. float a, b, c, pitch; // Params
  24. float x, y, z; // Out
  25. static constexpr float DEFAULT_A_VALUE = 0.2f;
  26. static constexpr float DEFAULT_B_VALUE = 0.2f;
  27. static constexpr float DEFAULT_C_VALUE = 5.7f;
  28. static constexpr float DEFAULT_PITCH_VALUE = 0.5f;
  29. RosslerAttractor() :
  30. a(DEFAULT_A_VALUE), b(DEFAULT_B_VALUE), c(DEFAULT_C_VALUE), pitch(DEFAULT_PITCH_VALUE),
  31. x(1.0f), y(1.0f), z(1.0f) {}
  32. void process(float dt) {
  33. float dx = -y - z;
  34. float dy = x + (a * y);
  35. float dz = b + z * (x - c);
  36. x += dx * dt * pitch * 2910.0f;
  37. y += dy * dt * pitch * 2910.0f;
  38. z += dz * dt * pitch * 2910.0f;
  39. }
  40. };
  41. struct StrangeAttractors : Module {
  42. enum ParamIds {
  43. LORENZ_SIGMA_PARAM,
  44. LORENZ_BETA_PARAM,
  45. LORENZ_RHO_PARAM,
  46. LORENZ_PITCH_PARAM,
  47. ROSSLER_A_PARAM,
  48. ROSSLER_B_PARAM,
  49. ROSSLER_C_PARAM,
  50. ROSSLER_PITCH_PARAM,
  51. NUM_PARAMS
  52. };
  53. enum InputIds {
  54. LORENZ_SIGMA_INPUT,
  55. LORENZ_BETA_INPUT,
  56. LORENZ_RHO_INPUT,
  57. LORENZ_PITCH_INPUT,
  58. ROSSLER_A_INPUT,
  59. ROSSLER_B_INPUT,
  60. ROSSLER_C_INPUT,
  61. ROSSLER_PITCH_INPUT,
  62. NUM_INPUTS
  63. };
  64. enum OutputIds {
  65. LORENZ_X_OUTPUT,
  66. LORENZ_Y_OUTPUT,
  67. ROSSLER_X_OUTPUT,
  68. ROSSLER_Y_OUTPUT,
  69. NUM_OUTPUTS
  70. };
  71. LorenzAttractor lorenz;
  72. RosslerAttractor rossler;
  73. static constexpr float LORENZ_SIGMA_PARAM_MIN = 3.0f;
  74. static constexpr float LORENZ_SIGMA_PARAM_MAX = 30.0f;
  75. static constexpr float LORENZ_BETA_PARAM_MIN = 0.5f;
  76. static constexpr float LORENZ_BETA_PARAM_MAX = 3.0f;
  77. static constexpr float LORENZ_RHO_PARAM_MIN = 13.0f;
  78. static constexpr float LORENZ_RHO_PARAM_MAX = 80.0f;
  79. static constexpr float LORENZ_PITCH_PARAM_MIN = 0.001f;
  80. static constexpr float LORENZ_PITCH_PARAM_MAX = 1.0f;
  81. static constexpr float ROSSLER_A_PARAM_MIN = 0.0f;
  82. static constexpr float ROSSLER_A_PARAM_MAX = 0.2f;
  83. static constexpr float ROSSLER_B_PARAM_MIN = 0.1f;
  84. static constexpr float ROSSLER_B_PARAM_MAX = 1.0f;
  85. static constexpr float ROSSLER_C_PARAM_MIN = 3.0f;
  86. static constexpr float ROSSLER_C_PARAM_MAX = 12.0f;
  87. static constexpr float ROSSLER_PITCH_PARAM_MIN = 0.001f;
  88. static constexpr float ROSSLER_PITCH_PARAM_MAX = 1.0f;
  89. StrangeAttractors() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS) {}
  90. void step() override;
  91. };
  92. void StrangeAttractors::step() {
  93. if (outputs[LORENZ_X_OUTPUT].active || outputs[LORENZ_Y_OUTPUT].active) {
  94. lorenz.sigma = clamp(params[LORENZ_SIGMA_PARAM].value + inputs[LORENZ_SIGMA_INPUT].value * 0.1f, LORENZ_SIGMA_PARAM_MIN, LORENZ_SIGMA_PARAM_MAX);
  95. lorenz.beta = clamp(params[LORENZ_BETA_PARAM].value + inputs[LORENZ_BETA_INPUT].value * 0.1f, LORENZ_BETA_PARAM_MIN, LORENZ_BETA_PARAM_MAX);
  96. lorenz.rho = clamp(params[LORENZ_RHO_PARAM].value + inputs[LORENZ_RHO_INPUT].value * 0.1f, LORENZ_RHO_PARAM_MIN, LORENZ_RHO_PARAM_MAX);
  97. lorenz.pitch = clamp(params[LORENZ_PITCH_PARAM].value + inputs[LORENZ_PITCH_INPUT].value * 0.1f, LORENZ_PITCH_PARAM_MIN, LORENZ_PITCH_PARAM_MAX);
  98. lorenz.process(1.0f / engineGetSampleRate());
  99. outputs[LORENZ_X_OUTPUT].value = 5.0f * 0.044f * lorenz.x;
  100. outputs[LORENZ_Y_OUTPUT].value = 5.0f * 0.0328f * lorenz.y;
  101. }
  102. if (outputs[ROSSLER_X_OUTPUT].active || outputs[ROSSLER_Y_OUTPUT].active) {
  103. rossler.a = clamp(params[ROSSLER_A_PARAM].value + inputs[ROSSLER_A_INPUT].value * 0.1f, ROSSLER_A_PARAM_MIN, ROSSLER_A_PARAM_MAX);
  104. rossler.b = clamp(params[ROSSLER_B_PARAM].value + inputs[ROSSLER_B_INPUT].value * 0.1f, ROSSLER_B_PARAM_MIN, ROSSLER_B_PARAM_MAX);
  105. rossler.c = clamp(params[ROSSLER_C_PARAM].value + inputs[ROSSLER_C_INPUT].value * 0.1f, ROSSLER_C_PARAM_MIN, ROSSLER_C_PARAM_MAX);
  106. rossler.pitch = clamp(params[ROSSLER_PITCH_PARAM].value + inputs[ROSSLER_PITCH_INPUT].value * 0.1f, ROSSLER_PITCH_PARAM_MIN, ROSSLER_PITCH_PARAM_MAX);
  107. rossler.process(1.0f / engineGetSampleRate());
  108. outputs[ROSSLER_X_OUTPUT].value = 5.0f * 0.054f * rossler.x;
  109. outputs[ROSSLER_Y_OUTPUT].value = 5.0f * 0.0569f * rossler.y;
  110. }
  111. }
  112. struct StrangeAttractorsWidget : ModuleWidget {
  113. StrangeAttractorsWidget(StrangeAttractors *module);
  114. };
  115. StrangeAttractorsWidget::StrangeAttractorsWidget(StrangeAttractors *module) : ModuleWidget(module) {
  116. box.size = Vec(15 * 12, 380);
  117. {
  118. SVGPanel *panel = new SVGPanel();
  119. panel->box.size = box.size;
  120. panel->setBackground(SVG::load(assetPlugin(plugin, "res/StrangeAttractors.svg")));
  121. addChild(panel);
  122. }
  123. addParam(ParamWidget::create<Davies1900hBlackKnob>(Vec(8, 45), module, StrangeAttractors::LORENZ_SIGMA_PARAM, StrangeAttractors::LORENZ_SIGMA_PARAM_MIN, StrangeAttractors::LORENZ_SIGMA_PARAM_MAX, LorenzAttractor::DEFAULT_SIGNMA_VALUE));
  124. addParam(ParamWidget::create<Davies1900hBlackKnob>(Vec(50, 45), module, StrangeAttractors::LORENZ_BETA_PARAM, StrangeAttractors::LORENZ_BETA_PARAM_MIN, StrangeAttractors::LORENZ_BETA_PARAM_MAX, LorenzAttractor::DEFAULT_BETA_VALUE));
  125. addParam(ParamWidget::create<Davies1900hBlackKnob>(Vec(92.5, 45), module, StrangeAttractors::LORENZ_RHO_PARAM, StrangeAttractors::LORENZ_RHO_PARAM_MIN, StrangeAttractors::LORENZ_RHO_PARAM_MAX, LorenzAttractor::DEFAULT_RHO_VALUE));
  126. addParam(ParamWidget::create<Davies1900hBlackKnob>(Vec(135, 45), module, StrangeAttractors::LORENZ_PITCH_PARAM, StrangeAttractors::LORENZ_PITCH_PARAM_MIN, StrangeAttractors::LORENZ_PITCH_PARAM_MAX, LorenzAttractor::DEFAULT_PITCH_VALUE));
  127. addParam(ParamWidget::create<Davies1900hBlackKnob>(Vec(8, 237), module, StrangeAttractors::ROSSLER_A_PARAM, StrangeAttractors::ROSSLER_A_PARAM_MIN, StrangeAttractors::ROSSLER_A_PARAM_MAX, RosslerAttractor::DEFAULT_A_VALUE));
  128. addParam(ParamWidget::create<Davies1900hBlackKnob>(Vec(50, 237), module, StrangeAttractors::ROSSLER_B_PARAM, StrangeAttractors::ROSSLER_B_PARAM_MIN, StrangeAttractors::ROSSLER_B_PARAM_MAX, RosslerAttractor::DEFAULT_B_VALUE));
  129. addParam(ParamWidget::create<Davies1900hBlackKnob>(Vec(92.5, 237), module, StrangeAttractors::ROSSLER_C_PARAM, StrangeAttractors::ROSSLER_C_PARAM_MIN, StrangeAttractors::ROSSLER_C_PARAM_MAX, RosslerAttractor::DEFAULT_C_VALUE));
  130. addParam(ParamWidget::create<Davies1900hBlackKnob>(Vec(135, 237), module, StrangeAttractors::ROSSLER_PITCH_PARAM, StrangeAttractors::ROSSLER_PITCH_PARAM_MIN, StrangeAttractors::ROSSLER_PITCH_PARAM_MAX, RosslerAttractor::DEFAULT_PITCH_VALUE));
  131. addInput(Port::create<PJ301MPort>(Vec(12.5, 110), Port::INPUT, module, StrangeAttractors::LORENZ_SIGMA_INPUT));
  132. addInput(Port::create<PJ301MPort>(Vec(55, 110), Port::INPUT, module, StrangeAttractors::LORENZ_BETA_INPUT));
  133. addInput(Port::create<PJ301MPort>(Vec(97.5, 110), Port::INPUT, module, StrangeAttractors::LORENZ_RHO_INPUT));
  134. addInput(Port::create<PJ301MPort>(Vec(140, 110), Port::INPUT, module, StrangeAttractors::LORENZ_PITCH_INPUT));
  135. addInput(Port::create<PJ301MPort>(Vec(12.5, 300), Port::INPUT, module, StrangeAttractors::ROSSLER_A_INPUT));
  136. addInput(Port::create<PJ301MPort>(Vec(55, 300), Port::INPUT, module, StrangeAttractors::ROSSLER_B_INPUT));
  137. addInput(Port::create<PJ301MPort>(Vec(97.5, 300), Port::INPUT, module, StrangeAttractors::ROSSLER_C_INPUT));
  138. addInput(Port::create<PJ301MPort>(Vec(140, 300), Port::INPUT, module, StrangeAttractors::ROSSLER_PITCH_INPUT));
  139. addOutput(Port::create<PJ301MPort>(Vec(12.5, 154), Port::OUTPUT, module, StrangeAttractors::LORENZ_X_OUTPUT));
  140. addOutput(Port::create<PJ301MPort>(Vec(140, 154), Port::OUTPUT, module, StrangeAttractors::LORENZ_Y_OUTPUT));
  141. addOutput(Port::create<PJ301MPort>(Vec(12.5, 345), Port::OUTPUT, module, StrangeAttractors::ROSSLER_X_OUTPUT));
  142. addOutput(Port::create<PJ301MPort>(Vec(140, 345), Port::OUTPUT, module, StrangeAttractors::ROSSLER_Y_OUTPUT));
  143. }
  144. } // namespace rack_plugin_Nohmad
  145. using namespace rack_plugin_Nohmad;
  146. RACK_PLUGIN_MODEL_INIT(Nohmad, StrangeAttractors) {
  147. Model *modelStrangeAttractors = Model::create<StrangeAttractors, StrangeAttractorsWidget>("Nohmad", "StrangeAttractors", "Strange Attractors", OSCILLATOR_TAG, LFO_TAG);
  148. return modelStrangeAttractors;
  149. }