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.

187 lines
6.6KB

  1. #pragma once
  2. #include <JuceHeader.h>
  3. #include "WEFilters/AREnvelopeFollowerSquareLaw.h"
  4. #include "ModulationSourceDefinition.hpp"
  5. #include "PluginConfigurator.hpp"
  6. struct ChainSlotBase {
  7. bool isBypassed;
  8. ChainSlotBase(bool newIsBypassed) : isBypassed(newIsBypassed) {}
  9. virtual ~ChainSlotBase() = default;
  10. virtual ChainSlotBase* clone() const = 0;
  11. };
  12. /**
  13. * Represents a gain stage in a slot in a processing chain.
  14. */
  15. struct ChainSlotGainStage : ChainSlotBase {
  16. // Linear 0 to 1 (or a little more) values
  17. float gain;
  18. // -1 to 1 values
  19. float pan;
  20. int numMainChannels;
  21. std::array<WECore::AREnv::AREnvelopeFollowerSquareLaw, 2> meterEnvelopes;
  22. ChainSlotGainStage(float newGain, float newPan, bool newIsBypassed, const juce::AudioProcessor::BusesLayout& busesLayout)
  23. : ChainSlotBase(newIsBypassed), gain(newGain), pan(newPan), numMainChannels(busesLayout.getMainInputChannels()) {
  24. _setUpEnvelopes();
  25. }
  26. ~ChainSlotGainStage() = default;
  27. ChainSlotGainStage* clone() const override {
  28. return new ChainSlotGainStage(gain, pan, isBypassed, numMainChannels);
  29. }
  30. private:
  31. void _setUpEnvelopes() {
  32. for (auto& env : meterEnvelopes) {
  33. env.setAttackTimeMs(1);
  34. env.setReleaseTimeMs(50);
  35. env.setFilterEnabled(false);
  36. }
  37. }
  38. ChainSlotGainStage(
  39. float newGain,
  40. float newPan,
  41. bool newIsBypassed,
  42. int newNumMainChannels)
  43. : ChainSlotBase(newIsBypassed), gain(newGain), pan(newPan), numMainChannels(newNumMainChannels) {
  44. _setUpEnvelopes();
  45. }
  46. };
  47. struct PluginParameterModulationSource {
  48. // Definition of the modulation source
  49. ModulationSourceDefinition definition;
  50. // Amount of modulation to be applied (-1 : 1)
  51. float modulationAmount;
  52. PluginParameterModulationSource() : definition(0, MODULATION_TYPE::MACRO), modulationAmount(0) { }
  53. PluginParameterModulationSource(ModulationSourceDefinition newDefinition,
  54. float newModulationAmount) :
  55. definition(newDefinition),
  56. modulationAmount(newModulationAmount) { }
  57. };
  58. struct PluginParameterModulationConfig {
  59. // Name of the parameter being modulated
  60. juce::String targetParameterName;
  61. // Parameter value without modulation applied (0 : 1)
  62. float restValue;
  63. // All the sources being provided for this parameter
  64. std::vector<std::shared_ptr<PluginParameterModulationSource>> sources;
  65. // Used when retrieving the parameter name from a juce::AudioProcessorParameter
  66. static constexpr int PLUGIN_PARAMETER_NAME_LENGTH_LIMIT {30};
  67. PluginParameterModulationConfig() : restValue(0) {}
  68. PluginParameterModulationConfig* clone() const {
  69. auto newConfig = new PluginParameterModulationConfig();
  70. newConfig->targetParameterName = targetParameterName;
  71. newConfig->restValue = restValue;
  72. for (auto& source : sources) {
  73. newConfig->sources.push_back(std::make_shared<PluginParameterModulationSource>(source->definition, source->modulationAmount));
  74. }
  75. return newConfig;
  76. }
  77. };
  78. struct PluginModulationConfig {
  79. bool isActive;
  80. std::vector<std::shared_ptr<PluginParameterModulationConfig>> parameterConfigs;
  81. PluginModulationConfig() : isActive(false) {}
  82. PluginModulationConfig& operator=(const PluginModulationConfig& other) {
  83. isActive = other.isActive;
  84. parameterConfigs = other.parameterConfigs;
  85. return *this;
  86. }
  87. PluginModulationConfig* clone() const {
  88. auto newConfig = new PluginModulationConfig();
  89. newConfig->isActive = isActive;
  90. for (auto& parameterConfig : parameterConfigs) {
  91. newConfig->parameterConfigs.push_back(std::shared_ptr<PluginParameterModulationConfig>(parameterConfig->clone()));
  92. }
  93. return newConfig;
  94. }
  95. };
  96. struct PluginEditorBoundsContainer {
  97. juce::Rectangle<int> editorBounds;
  98. juce::Rectangle<int> displayArea;
  99. PluginEditorBoundsContainer(
  100. juce::Rectangle<int> newEditorBounds,
  101. juce::Rectangle<int> newDisplayAreaBounds) : editorBounds(newEditorBounds),
  102. displayArea(newDisplayAreaBounds) { }
  103. };
  104. typedef std::optional<PluginEditorBoundsContainer> PluginEditorBounds;
  105. /**
  106. * Represents a plugin in a slot in a processing chain.
  107. */
  108. struct ChainSlotPlugin : ChainSlotBase {
  109. std::shared_ptr<juce::AudioPluginInstance> plugin;
  110. std::shared_ptr<PluginModulationConfig> modulationConfig;
  111. std::function<float(int, MODULATION_TYPE)> getModulationValueCallback;
  112. std::shared_ptr<PluginEditorBounds> editorBounds;
  113. // AUs always require a sidechain input, but if Syndicate is loaded as a VST3 it might not have
  114. // one, as VST3s don't require a sidechain input. So we keep this empty buffer to provide as a
  115. // sidechain for AUs if needed.
  116. std::unique_ptr<juce::AudioBuffer<float>> spareSCBuffer;
  117. ChainSlotPlugin(std::shared_ptr<juce::AudioPluginInstance> newPlugin,
  118. bool newIsBypassed,
  119. std::function<float(int, MODULATION_TYPE)> newGetModulationValueCallback,
  120. HostConfiguration config)
  121. : ChainSlotBase(newIsBypassed),
  122. plugin(newPlugin),
  123. modulationConfig(std::make_shared<PluginModulationConfig>()),
  124. getModulationValueCallback(newGetModulationValueCallback),
  125. editorBounds(new PluginEditorBounds()),
  126. spareSCBuffer(new juce::AudioBuffer<float>(config.layout.getMainInputChannels() * 2, config.blockSize)) {}
  127. ~ChainSlotPlugin() = default;
  128. ChainSlotPlugin* clone() const override {
  129. auto newSpareSCBuffer = std::make_unique<juce::AudioBuffer<float>>(spareSCBuffer->getNumChannels(), spareSCBuffer->getNumSamples());
  130. return new ChainSlotPlugin(plugin, isBypassed, modulationConfig, getModulationValueCallback, editorBounds, std::move(newSpareSCBuffer));
  131. }
  132. private:
  133. ChainSlotPlugin(
  134. std::shared_ptr<juce::AudioPluginInstance> newPlugin,
  135. bool newIsBypassed,
  136. std::shared_ptr<PluginModulationConfig> newModulationConfig,
  137. std::function<float(int, MODULATION_TYPE)> newGetModulationValueCallback,
  138. std::shared_ptr<PluginEditorBounds> newEditorBounds,
  139. std::unique_ptr<juce::AudioBuffer<float>> newSpareSCBuffer)
  140. : ChainSlotBase(newIsBypassed),
  141. plugin(newPlugin),
  142. modulationConfig(std::shared_ptr<PluginModulationConfig>(newModulationConfig->clone())),
  143. getModulationValueCallback(newGetModulationValueCallback),
  144. editorBounds(newEditorBounds),
  145. spareSCBuffer(std::move(newSpareSCBuffer)) {}
  146. };