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.

150 lines
4.5KB

  1. #pragma once
  2. #include "common.hpp"
  3. #include "string.hpp"
  4. #include "plugin/Model.hpp"
  5. #include "engine/Param.hpp"
  6. #include "engine/Port.hpp"
  7. #include "engine/Light.hpp"
  8. #include "engine/ParamQuantity.hpp"
  9. #include <vector>
  10. #include <jansson.h>
  11. namespace rack {
  12. namespace plugin {
  13. struct Model;
  14. }
  15. namespace engine {
  16. /** DSP processor instance for your module. */
  17. struct Module {
  18. plugin::Model *model = NULL; /** Unique ID for referring to the module in the engine.
  19. Assigned when added to the engine.
  20. */
  21. int id = -1;
  22. /** Arrays of components.
  23. Initialized with config().
  24. */
  25. std::vector<Param> params;
  26. std::vector<Output> outputs;
  27. std::vector<Input> inputs;
  28. std::vector<Light> lights;
  29. std::vector<ParamQuantity*> paramQuantities;
  30. /** ID of the Module immediately to the left, or -1 if nonexistent. */
  31. int leftModuleId = -1;
  32. /** Pointer to the left Module, or NULL if nonexistent. */
  33. Module *leftModule = NULL;
  34. /** Double buffer for receiving messages from adjacent modules.
  35. If this module receives messages from adjacent modules, allocate both message buffers with identical blocks of memory (arrays, structs, etc).
  36. Remember to free the buffer in the Module destructor.
  37. Example:
  38. leftProducerMessage = new MyModuleMessage;
  39. leftConsumerMessage = new MyModuleMessage;
  40. At the end of each timestep, the buffers are flipped/swapped.
  41. You may choose for the Module to write to its own message buffer for consumption by other modules.
  42. As long as this convention is followed by the left Module, this is fine.
  43. */
  44. void *leftProducerMessage = NULL;
  45. void *leftConsumerMessage = NULL;
  46. int rightModuleId = -1;
  47. Module *rightModule = NULL;
  48. void *rightProducerMessage = NULL;
  49. void *rightConsumerMessage = NULL;
  50. /** Seconds spent in the process() method, with exponential smoothing.
  51. Only written when CPU timing is enabled, since time measurement is expensive.
  52. */
  53. float cpuTime = 0.f;
  54. /** Whether the Module is skipped from stepping by the engine.
  55. Module subclasses should not read/write this variable.
  56. */
  57. bool bypass = false;
  58. /** Constructs a Module with no params, inputs, outputs, and lights. */
  59. Module();
  60. /** Use config() instead. */
  61. DEPRECATED Module(int numParams, int numInputs, int numOutputs, int numLights = 0) : Module() {
  62. config(numParams, numInputs, numOutputs, numLights);
  63. }
  64. virtual ~Module();
  65. /** Configures the number of Params, Outputs, Inputs, and Lights. */
  66. void config(int numParams, int numInputs, int numOutputs, int numLights = 0);
  67. template <class TParamQuantity = ParamQuantity>
  68. void configParam(int paramId, float minValue, float maxValue, float defaultValue, std::string label = "", std::string unit = "", float displayBase = 0.f, float displayMultiplier = 1.f, float displayOffset = 0.f) {
  69. assert(paramId < (int) params.size() && paramId < (int) paramQuantities.size());
  70. if (paramQuantities[paramId])
  71. delete paramQuantities[paramId];
  72. Param *p = &params[paramId];
  73. p->value = defaultValue;
  74. ParamQuantity *q = new TParamQuantity;
  75. q->module = this;
  76. q->paramId = paramId;
  77. q->minValue = minValue;
  78. q->maxValue = maxValue;
  79. q->defaultValue = defaultValue;
  80. if (!label.empty())
  81. q->label = label;
  82. else
  83. q->label = string::f("#%d", paramId + 1);
  84. q->unit = unit;
  85. q->displayBase = displayBase;
  86. q->displayMultiplier = displayMultiplier;
  87. q->displayOffset = displayOffset;
  88. paramQuantities[paramId] = q;
  89. }
  90. struct ProcessArgs {
  91. float sampleRate;
  92. float sampleTime;
  93. };
  94. /** Advances the module by one audio sample.
  95. Override this method to read Inputs and Params and to write Outputs and Lights.
  96. */
  97. virtual void process(const ProcessArgs &args) {
  98. #pragma GCC diagnostic push
  99. #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
  100. step();
  101. #pragma GCC diagnostic pop
  102. }
  103. /** Override process(const ProcessArgs &args) instead. */
  104. DEPRECATED virtual void step() {}
  105. /** Called when the engine sample rate is changed. */
  106. virtual void onSampleRateChange() {}
  107. /** Called when user clicks Initialize in the module context menu. */
  108. virtual void onReset() {}
  109. /** Called when user clicks Randomize in the module context menu. */
  110. virtual void onRandomize() {}
  111. /** Called when the Module is added to the Engine */
  112. virtual void onAdd() {}
  113. /** Called when the Module is removed from the Engine */
  114. virtual void onRemove() {}
  115. json_t *toJson();
  116. void fromJson(json_t *rootJ);
  117. /** Override to store extra internal data in the "data" property of the module's JSON object. */
  118. virtual json_t *dataToJson() { return NULL; }
  119. virtual void dataFromJson(json_t *root) {}
  120. };
  121. } // namespace engine
  122. } // namespace rack