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.

380 lines
16KB

  1. #pragma once
  2. #include <JuceHeader.h>
  3. #include "ChainMutators.hpp"
  4. #include "PluginChain.hpp"
  5. #include "FFTProvider.hpp"
  6. #include "CrossoverState.hpp"
  7. #include "CrossoverMutators.hpp"
  8. #include "CrossoverProcessors.hpp"
  9. /**
  10. * Stores a plugin chain and any associated data.
  11. */
  12. struct PluginChainWrapper {
  13. PluginChainWrapper(std::shared_ptr<PluginChain> newChain, bool newIsSoloed)
  14. : chain(newChain), isSoloed(newIsSoloed) {}
  15. std::shared_ptr<PluginChain> chain;
  16. bool isSoloed;
  17. };
  18. /**
  19. * Base class which provides the audio splitting functionality.
  20. *
  21. * Each derived class contains one or more plugin chains (one for each split).
  22. *
  23. * A splitter may contain more chains than it can actually use if they have been carried over from
  24. * a previous splitter that could handle more. In this case its processBlock will just ignore the
  25. * extra chains.
  26. */
  27. class PluginSplitter {
  28. public:
  29. std::vector<PluginChainWrapper> chains;
  30. size_t numChainsSoloed;
  31. HostConfiguration config;
  32. std::function<float(int, MODULATION_TYPE)> getModulationValueCallback;
  33. std::function<void(int)> notifyProcessorOnLatencyChange;
  34. bool shouldNotifyProcessorOnLatencyChange;
  35. PluginSplitter(int defaultNumChains,
  36. HostConfiguration newConfig,
  37. std::function<float(int, MODULATION_TYPE)> newGetModulationValueCallback,
  38. std::function<void(int)> latencyChangeCallback)
  39. : numChainsSoloed(0),
  40. config(newConfig),
  41. getModulationValueCallback(newGetModulationValueCallback),
  42. notifyProcessorOnLatencyChange(latencyChangeCallback),
  43. shouldNotifyProcessorOnLatencyChange(true) {
  44. // Set up the default number of chains
  45. for (int idx {0}; idx < defaultNumChains; idx++) {
  46. chains.emplace_back(std::make_shared<PluginChain>(getModulationValueCallback), false);
  47. chains[chains.size() - 1].chain->latencyListener.setSplitter(this);
  48. }
  49. onLatencyChange();
  50. }
  51. PluginSplitter(std::shared_ptr<PluginSplitter> otherSplitter, int defaultNumChains)
  52. : chains(otherSplitter->chains),
  53. numChainsSoloed(otherSplitter->numChainsSoloed),
  54. config(otherSplitter->config),
  55. getModulationValueCallback(otherSplitter->getModulationValueCallback),
  56. notifyProcessorOnLatencyChange(otherSplitter->notifyProcessorOnLatencyChange),
  57. shouldNotifyProcessorOnLatencyChange(true) {
  58. // Move the latency listeners for the existing chains to point to this splitter
  59. for (auto& chain : chains) {
  60. chain.chain->latencyListener.setSplitter(this);
  61. }
  62. // Add chains if we still need to reach the default
  63. while (defaultNumChains > chains.size()) {
  64. chains.emplace_back(std::make_shared<PluginChain>(getModulationValueCallback), false);
  65. chains[chains.size() - 1].chain->latencyListener.setSplitter(this);
  66. }
  67. onLatencyChange();
  68. }
  69. virtual ~PluginSplitter() = default;
  70. void onLatencyChange() {
  71. // The latency of the splitter is the latency of the slowest chain, so iterate through each
  72. // chain and report the highest latency
  73. int highestLatency {0};
  74. for (const PluginChainWrapper& chain : chains) {
  75. const int thisLatency {chain.chain->latencyListener.calculatedTotalPluginLatency};
  76. if (highestLatency < thisLatency) {
  77. highestLatency = thisLatency;
  78. }
  79. }
  80. // Tell each chain the latency of the slowest chain, so they can all add compensation to match
  81. // it
  82. for (PluginChainWrapper& chain : chains) {
  83. ChainMutators::setRequiredLatency(chain.chain, highestLatency, config);
  84. }
  85. if (shouldNotifyProcessorOnLatencyChange) {
  86. notifyProcessorOnLatencyChange(highestLatency);
  87. }
  88. }
  89. virtual PluginSplitter* clone() const = 0;
  90. protected:
  91. PluginSplitter(std::vector<PluginChainWrapper> newChains,
  92. HostConfiguration newConfig,
  93. std::function<float(int, MODULATION_TYPE)> newGetModulationValueCallback,
  94. std::function<void(int)> newNotifyProcessorOnLatencyChange) :
  95. numChainsSoloed(0),
  96. config(newConfig),
  97. getModulationValueCallback(newGetModulationValueCallback),
  98. notifyProcessorOnLatencyChange(newNotifyProcessorOnLatencyChange),
  99. shouldNotifyProcessorOnLatencyChange(true) {
  100. for (auto& chain : newChains) {
  101. std::shared_ptr<PluginChain> newChain(chain.chain->clone());
  102. newChain->latencyListener.setSplitter(this);
  103. chains.emplace_back(newChain, chain.isSoloed);
  104. if (chain.isSoloed) {
  105. numChainsSoloed++;
  106. }
  107. }
  108. }
  109. };
  110. /**
  111. * Contains a single plugin graph for plugins arranged in series.
  112. */
  113. class PluginSplitterSeries : public PluginSplitter {
  114. public:
  115. static constexpr int DEFAULT_NUM_CHAINS {1};
  116. PluginSplitterSeries(HostConfiguration newConfig,
  117. std::function<float(int, MODULATION_TYPE)> getModulationValueCallback,
  118. std::function<void(int)> latencyChangeCallback)
  119. : PluginSplitter(DEFAULT_NUM_CHAINS, newConfig, getModulationValueCallback, latencyChangeCallback) {
  120. juce::Logger::writeToLog("Constructed PluginSplitterSeries");
  121. }
  122. PluginSplitterSeries(std::shared_ptr<PluginSplitter> otherSplitter)
  123. : PluginSplitter(otherSplitter, DEFAULT_NUM_CHAINS) {
  124. juce::Logger::writeToLog("Converted to PluginSplitterSeries");
  125. // We only have one active chain in the series splitter, so it can't be muted or soloed
  126. ChainMutators::setChainMute(chains[0].chain, false);
  127. }
  128. PluginSplitterSeries* clone() const override {
  129. return new PluginSplitterSeries(chains, config, getModulationValueCallback, notifyProcessorOnLatencyChange);
  130. }
  131. private:
  132. PluginSplitterSeries(std::vector<PluginChainWrapper> newChains,
  133. HostConfiguration newConfig,
  134. std::function<float(int, MODULATION_TYPE)> newGetModulationValueCallback,
  135. std::function<void(int)> newNotifyProcessorOnLatencyChange) :
  136. PluginSplitter(newChains, newConfig, newGetModulationValueCallback, newNotifyProcessorOnLatencyChange) {
  137. }
  138. };
  139. /**
  140. * Contains a single plugin graph for plugins arranged in parallel.
  141. */
  142. class PluginSplitterParallel : public PluginSplitter {
  143. public:
  144. static constexpr int DEFAULT_NUM_CHAINS {1};
  145. std::unique_ptr<juce::AudioBuffer<float>> inputBuffer;
  146. std::unique_ptr<juce::AudioBuffer<float>> outputBuffer;
  147. PluginSplitterParallel(HostConfiguration newConfig,
  148. std::function<float(int, MODULATION_TYPE)> getModulationValueCallback,
  149. std::function<void(int)> latencyChangeCallback)
  150. : PluginSplitter(DEFAULT_NUM_CHAINS, newConfig, getModulationValueCallback, latencyChangeCallback) {
  151. juce::Logger::writeToLog("Constructed PluginSplitterParallel");
  152. }
  153. PluginSplitterParallel(std::shared_ptr<PluginSplitter> otherSplitter)
  154. : PluginSplitter(otherSplitter, DEFAULT_NUM_CHAINS) {
  155. juce::Logger::writeToLog("Converted to PluginSplitterParallel");
  156. }
  157. PluginSplitterParallel* clone() const override {
  158. return new PluginSplitterParallel(
  159. chains,
  160. config,
  161. getModulationValueCallback,
  162. notifyProcessorOnLatencyChange,
  163. *inputBuffer,
  164. *outputBuffer);
  165. }
  166. private:
  167. PluginSplitterParallel(std::vector<PluginChainWrapper> newChains,
  168. HostConfiguration newConfig,
  169. std::function<float(int, MODULATION_TYPE)> newGetModulationValueCallback,
  170. std::function<void(int)> newNotifyProcessorOnLatencyChange,
  171. const juce::AudioBuffer<float>& newInputBuffer,
  172. const juce::AudioBuffer<float>& newOutputBuffer) :
  173. PluginSplitter(newChains, newConfig, newGetModulationValueCallback, newNotifyProcessorOnLatencyChange) {
  174. // We need to copy the buffers as well
  175. inputBuffer.reset(new juce::AudioBuffer<float>(newInputBuffer));
  176. outputBuffer.reset(new juce::AudioBuffer<float>(newOutputBuffer));
  177. }
  178. };
  179. /**
  180. * Contains a single plugin graph for plugins arranged in a multiband split.
  181. */
  182. class PluginSplitterMultiband : public PluginSplitter {
  183. public:
  184. static constexpr int DEFAULT_NUM_CHAINS {2};
  185. std::shared_ptr<CrossoverState> crossover;
  186. FFTProvider fftProvider;
  187. PluginSplitterMultiband(HostConfiguration newConfig,
  188. std::function<float(int, MODULATION_TYPE)> getModulationValueCallback,
  189. std::function<void(int)> latencyChangeCallback)
  190. : PluginSplitter(DEFAULT_NUM_CHAINS, newConfig, getModulationValueCallback, latencyChangeCallback),
  191. crossover(createDefaultCrossoverState(config)) {
  192. juce::Logger::writeToLog("Constructed PluginSplitterMultiband");
  193. CrossoverProcessors::prepareToPlay(*crossover.get(), config.sampleRate, config.blockSize, config.layout);
  194. }
  195. PluginSplitterMultiband(std::shared_ptr<PluginSplitter> otherSplitter, std::optional<std::vector<float>> crossoverFrequencies)
  196. : PluginSplitter(otherSplitter, DEFAULT_NUM_CHAINS),
  197. crossover(createDefaultCrossoverState(config)) {
  198. juce::Logger::writeToLog("Converted to PluginSplitterMultiband");
  199. // Set the crossover to have the correct number of bands (this will also default the frequencies)
  200. while (chains.size() > CrossoverMutators::getNumBands(crossover)) {
  201. CrossoverMutators::addBand(crossover);
  202. }
  203. // Restore the crossover frequencies if there are previous ones
  204. if (crossoverFrequencies.has_value()) {
  205. const size_t numCrossovers {std::min(crossoverFrequencies.value().size(), CrossoverMutators::getNumBands(crossover))};
  206. for (int index {0}; index < numCrossovers; index++) {
  207. CrossoverMutators::setCrossoverFrequency(crossover, index, crossoverFrequencies.value()[index]);
  208. }
  209. }
  210. // Set the processors
  211. for (size_t bandIndex {0}; bandIndex < CrossoverMutators::getNumBands(crossover); bandIndex++) {
  212. std::shared_ptr<PluginChain> newChain {chains[bandIndex].chain};
  213. CrossoverMutators::setPluginChain(crossover, bandIndex, newChain);
  214. CrossoverMutators::setIsSoloed(crossover, bandIndex, chains[bandIndex].isSoloed);
  215. }
  216. CrossoverProcessors::prepareToPlay(*crossover.get(), config.sampleRate, config.blockSize, config.layout);
  217. }
  218. PluginSplitterMultiband* clone() const override {
  219. auto clonedSplitter = new PluginSplitterMultiband(
  220. chains,
  221. config,
  222. getModulationValueCallback,
  223. notifyProcessorOnLatencyChange,
  224. std::shared_ptr<CrossoverState>(crossover->clone()));
  225. // The crossover we cloned needs to be updated to use the new chains that were just cloned
  226. for (int chainIndex {0}; chainIndex < clonedSplitter->chains.size(); chainIndex++) {
  227. CrossoverMutators::setPluginChain(clonedSplitter->crossover, chainIndex, clonedSplitter->chains[chainIndex].chain);
  228. }
  229. // Set up the fft provider
  230. clonedSplitter->fftProvider.setSampleRate(config.sampleRate);
  231. clonedSplitter->fftProvider.setIsStereo(canDoStereoSplitTypes(config.layout));
  232. return clonedSplitter;
  233. }
  234. private:
  235. PluginSplitterMultiband(std::vector<PluginChainWrapper> newChains,
  236. HostConfiguration newConfig,
  237. std::function<float(int, MODULATION_TYPE)> newGetModulationValueCallback,
  238. std::function<void(int)> newNotifyProcessorOnLatencyChange,
  239. std::shared_ptr<CrossoverState> newCrossover) :
  240. PluginSplitter(newChains, newConfig, newGetModulationValueCallback, newNotifyProcessorOnLatencyChange),
  241. crossover(newCrossover) {
  242. }
  243. };
  244. /**
  245. * Contains a single plugin graph for plugins arranged in a left right split.
  246. */
  247. class PluginSplitterLeftRight : public PluginSplitter {
  248. public:
  249. static constexpr int DEFAULT_NUM_CHAINS {2};
  250. std::unique_ptr<juce::AudioBuffer<float>> leftBuffer;
  251. std::unique_ptr<juce::AudioBuffer<float>> rightBuffer;
  252. PluginSplitterLeftRight(HostConfiguration newConfig,
  253. std::function<float(int, MODULATION_TYPE)> getModulationValueCallback,
  254. std::function<void(int)> latencyChangeCallback)
  255. : PluginSplitter(DEFAULT_NUM_CHAINS, newConfig, getModulationValueCallback, latencyChangeCallback) {
  256. juce::Logger::writeToLog("Constructed PluginSplitterLeftRight");
  257. }
  258. PluginSplitterLeftRight(std::shared_ptr<PluginSplitter> otherSplitter)
  259. : PluginSplitter(otherSplitter, DEFAULT_NUM_CHAINS) {
  260. juce::Logger::writeToLog("Converted to PluginSplitterLeftRight");
  261. }
  262. PluginSplitterLeftRight* clone() const override {
  263. return new PluginSplitterLeftRight(
  264. chains,
  265. config,
  266. getModulationValueCallback,
  267. notifyProcessorOnLatencyChange,
  268. *leftBuffer,
  269. *rightBuffer);
  270. }
  271. private:
  272. PluginSplitterLeftRight(std::vector<PluginChainWrapper> newChains,
  273. HostConfiguration newConfig,
  274. std::function<float(int, MODULATION_TYPE)> newGetModulationValueCallback,
  275. std::function<void(int)> newNotifyProcessorOnLatencyChange,
  276. const juce::AudioBuffer<float>& newLeftBuffer,
  277. const juce::AudioBuffer<float>& newRightBuffer) :
  278. PluginSplitter(newChains, newConfig, newGetModulationValueCallback, newNotifyProcessorOnLatencyChange) {
  279. // We need to copy the buffers as well
  280. leftBuffer.reset(new juce::AudioBuffer<float>(newLeftBuffer));
  281. rightBuffer.reset(new juce::AudioBuffer<float>(newRightBuffer));
  282. }
  283. };
  284. /**
  285. * Contains a single plugin graph for plugins arranged in a mid side split.
  286. */
  287. class PluginSplitterMidSide : public PluginSplitter {
  288. public:
  289. static constexpr int DEFAULT_NUM_CHAINS {2};
  290. std::unique_ptr<juce::AudioBuffer<float>> midBuffer;
  291. std::unique_ptr<juce::AudioBuffer<float>> sideBuffer;
  292. PluginSplitterMidSide(HostConfiguration newConfig,
  293. std::function<float(int, MODULATION_TYPE)> getModulationValueCallback,
  294. std::function<void(int)> latencyChangeCallback)
  295. : PluginSplitter(DEFAULT_NUM_CHAINS, newConfig, getModulationValueCallback, latencyChangeCallback) {
  296. juce::Logger::writeToLog("Constructed PluginSplitterMidSide");
  297. }
  298. PluginSplitterMidSide(std::shared_ptr<PluginSplitter> otherSplitter)
  299. : PluginSplitter(otherSplitter, DEFAULT_NUM_CHAINS) {
  300. juce::Logger::writeToLog("Converted to PluginSplitterMidSide");
  301. }
  302. PluginSplitterMidSide* clone() const override {
  303. return new PluginSplitterMidSide(
  304. chains,
  305. config,
  306. getModulationValueCallback,
  307. notifyProcessorOnLatencyChange,
  308. *midBuffer,
  309. *sideBuffer);
  310. }
  311. private:
  312. PluginSplitterMidSide(std::vector<PluginChainWrapper> newChains,
  313. HostConfiguration newConfig,
  314. std::function<float(int, MODULATION_TYPE)> newGetModulationValueCallback,
  315. std::function<void(int)> newNotifyProcessorOnLatencyChange,
  316. const juce::AudioBuffer<float>& newMidBuffer,
  317. const juce::AudioBuffer<float>& newSideBuffer) :
  318. PluginSplitter(newChains, newConfig, newGetModulationValueCallback, newNotifyProcessorOnLatencyChange) {
  319. // We need to copy the buffers as well
  320. midBuffer.reset(new juce::AudioBuffer<float>(newMidBuffer));
  321. sideBuffer.reset(new juce::AudioBuffer<float>(newSideBuffer));
  322. }
  323. };