The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
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.

462 lines
21KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2020 - Raw Material Software Limited
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 6 End-User License
  8. Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
  9. End User License Agreement: www.juce.com/juce-6-licence
  10. Privacy Policy: www.juce.com/juce-privacy-policy
  11. Or: You may also use this code under the terms of the GPL v3 (see
  12. www.gnu.org/licenses).
  13. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  14. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  15. DISCLAIMED.
  16. ==============================================================================
  17. */
  18. #include <JuceHeader.h>
  19. #include <juce_audio_plugin_client/juce_audio_plugin_client.h>
  20. #include "InternalPlugins.h"
  21. #include "PluginGraph.h"
  22. #include "../../../../examples/Plugins/AUv3SynthPluginDemo.h"
  23. #include "../../../../examples/Plugins/ArpeggiatorPluginDemo.h"
  24. #include "../../../../examples/Plugins/AudioPluginDemo.h"
  25. #include "../../../../examples/Plugins/DSPModulePluginDemo.h"
  26. #include "../../../../examples/Plugins/GainPluginDemo.h"
  27. #include "../../../../examples/Plugins/MidiLoggerPluginDemo.h"
  28. #include "../../../../examples/Plugins/MultiOutSynthPluginDemo.h"
  29. #include "../../../../examples/Plugins/NoiseGatePluginDemo.h"
  30. #include "../../../../examples/Plugins/SamplerPluginDemo.h"
  31. #include "../../../../examples/Plugins/SurroundPluginDemo.h"
  32. //==============================================================================
  33. class InternalPlugin : public AudioPluginInstance
  34. {
  35. public:
  36. explicit InternalPlugin (std::unique_ptr<AudioProcessor> innerIn)
  37. : inner (std::move (innerIn))
  38. {
  39. jassert (inner != nullptr);
  40. for (auto isInput : { true, false })
  41. matchChannels (isInput);
  42. setBusesLayout (inner->getBusesLayout());
  43. }
  44. //==============================================================================
  45. const String getName() const override { return inner->getName(); }
  46. StringArray getAlternateDisplayNames() const override { return inner->getAlternateDisplayNames(); }
  47. double getTailLengthSeconds() const override { return inner->getTailLengthSeconds(); }
  48. bool acceptsMidi() const override { return inner->acceptsMidi(); }
  49. bool producesMidi() const override { return inner->producesMidi(); }
  50. AudioProcessorEditor* createEditor() override { return inner->createEditor(); }
  51. bool hasEditor() const override { return inner->hasEditor(); }
  52. int getNumPrograms() override { return inner->getNumPrograms(); }
  53. int getCurrentProgram() override { return inner->getCurrentProgram(); }
  54. void setCurrentProgram (int i) override { inner->setCurrentProgram (i); }
  55. const String getProgramName (int i) override { return inner->getProgramName (i); }
  56. void changeProgramName (int i, const String& n) override { inner->changeProgramName (i, n); }
  57. void getStateInformation (juce::MemoryBlock& b) override { inner->getStateInformation (b); }
  58. void setStateInformation (const void* d, int s) override { inner->setStateInformation (d, s); }
  59. void getCurrentProgramStateInformation (juce::MemoryBlock& b) override { inner->getCurrentProgramStateInformation (b); }
  60. void setCurrentProgramStateInformation (const void* d, int s) override { inner->setCurrentProgramStateInformation (d, s); }
  61. void prepareToPlay (double sr, int bs) override { inner->setRateAndBufferSizeDetails (sr, bs); inner->prepareToPlay (sr, bs); }
  62. void releaseResources() override { inner->releaseResources(); }
  63. void memoryWarningReceived() override { inner->memoryWarningReceived(); }
  64. void processBlock (AudioBuffer<float>& a, MidiBuffer& m) override { inner->processBlock (a, m); }
  65. void processBlock (AudioBuffer<double>& a, MidiBuffer& m) override { inner->processBlock (a, m); }
  66. void processBlockBypassed (AudioBuffer<float>& a, MidiBuffer& m) override { inner->processBlockBypassed (a, m); }
  67. void processBlockBypassed (AudioBuffer<double>& a, MidiBuffer& m) override { inner->processBlockBypassed (a, m); }
  68. bool supportsDoublePrecisionProcessing() const override { return inner->supportsDoublePrecisionProcessing(); }
  69. bool supportsMPE() const override { return inner->supportsMPE(); }
  70. bool isMidiEffect() const override { return inner->isMidiEffect(); }
  71. void reset() override { inner->reset(); }
  72. void setNonRealtime (bool b) noexcept override { inner->setNonRealtime (b); }
  73. void refreshParameterList() override { inner->refreshParameterList(); }
  74. void numChannelsChanged() override { inner->numChannelsChanged(); }
  75. void numBusesChanged() override { inner->numBusesChanged(); }
  76. void processorLayoutsChanged() override { inner->processorLayoutsChanged(); }
  77. void setPlayHead (AudioPlayHead* p) override { inner->setPlayHead (p); }
  78. void updateTrackProperties (const TrackProperties& p) override { inner->updateTrackProperties (p); }
  79. bool isBusesLayoutSupported (const BusesLayout& layout) const override { return inner->checkBusesLayoutSupported (layout); }
  80. bool canAddBus (bool) const override { return true; }
  81. bool canRemoveBus (bool) const override { return true; }
  82. //==============================================================================
  83. void fillInPluginDescription (PluginDescription& description) const override
  84. {
  85. description = getPluginDescription (*inner);
  86. }
  87. private:
  88. static PluginDescription getPluginDescription (const AudioProcessor& proc)
  89. {
  90. const auto ins = proc.getTotalNumInputChannels();
  91. const auto outs = proc.getTotalNumOutputChannels();
  92. const auto identifier = proc.getName();
  93. const auto registerAsGenerator = ins == 0;
  94. const auto acceptsMidi = proc.acceptsMidi();
  95. PluginDescription descr;
  96. descr.name = identifier;
  97. descr.descriptiveName = identifier;
  98. descr.pluginFormatName = InternalPluginFormat::getIdentifier();
  99. descr.category = (registerAsGenerator ? (acceptsMidi ? "Synth" : "Generator") : "Effect");
  100. descr.manufacturerName = "JUCE";
  101. descr.version = ProjectInfo::versionString;
  102. descr.fileOrIdentifier = identifier;
  103. descr.uid = identifier.hashCode();
  104. descr.isInstrument = (acceptsMidi && registerAsGenerator);
  105. descr.numInputChannels = ins;
  106. descr.numOutputChannels = outs;
  107. return descr;
  108. }
  109. void matchChannels (bool isInput)
  110. {
  111. const auto inBuses = inner->getBusCount (isInput);
  112. while (getBusCount (isInput) < inBuses)
  113. addBus (isInput);
  114. while (inBuses < getBusCount (isInput))
  115. removeBus (isInput);
  116. }
  117. std::unique_ptr<AudioProcessor> inner;
  118. //==============================================================================
  119. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InternalPlugin)
  120. };
  121. //==============================================================================
  122. class SineWaveSynth : public AudioProcessor
  123. {
  124. public:
  125. SineWaveSynth()
  126. : AudioProcessor (BusesProperties().withOutput ("Output", AudioChannelSet::stereo()))
  127. {
  128. const int numVoices = 8;
  129. // Add some voices...
  130. for (int i = numVoices; --i >= 0;)
  131. synth.addVoice (new SineWaveVoice());
  132. // ..and give the synth a sound to play
  133. synth.addSound (new SineWaveSound());
  134. }
  135. static String getIdentifier()
  136. {
  137. return "Sine Wave Synth";
  138. }
  139. //==============================================================================
  140. void prepareToPlay (double newSampleRate, int) override
  141. {
  142. synth.setCurrentPlaybackSampleRate (newSampleRate);
  143. }
  144. void releaseResources() override {}
  145. //==============================================================================
  146. void processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages) override
  147. {
  148. const int numSamples = buffer.getNumSamples();
  149. buffer.clear();
  150. synth.renderNextBlock (buffer, midiMessages, 0, numSamples);
  151. buffer.applyGain (0.8f);
  152. }
  153. using AudioProcessor::processBlock;
  154. const String getName() const override { return getIdentifier(); }
  155. double getTailLengthSeconds() const override { return 0.0; }
  156. bool acceptsMidi() const override { return true; }
  157. bool producesMidi() const override { return true; }
  158. AudioProcessorEditor* createEditor() override { return nullptr; }
  159. bool hasEditor() const override { return false; }
  160. int getNumPrograms() override { return 1; }
  161. int getCurrentProgram() override { return 0; }
  162. void setCurrentProgram (int) override {}
  163. const String getProgramName (int) override { return {}; }
  164. void changeProgramName (int, const String&) override {}
  165. void getStateInformation (juce::MemoryBlock&) override {}
  166. void setStateInformation (const void*, int) override {}
  167. private:
  168. //==============================================================================
  169. struct SineWaveSound : public SynthesiserSound
  170. {
  171. SineWaveSound() = default;
  172. bool appliesToNote (int /*midiNoteNumber*/) override { return true; }
  173. bool appliesToChannel (int /*midiChannel*/) override { return true; }
  174. };
  175. struct SineWaveVoice : public SynthesiserVoice
  176. {
  177. SineWaveVoice() = default;
  178. bool canPlaySound (SynthesiserSound* sound) override
  179. {
  180. return dynamic_cast<SineWaveSound*> (sound) != nullptr;
  181. }
  182. void startNote (int midiNoteNumber, float velocity,
  183. SynthesiserSound* /*sound*/,
  184. int /*currentPitchWheelPosition*/) override
  185. {
  186. currentAngle = 0.0;
  187. level = velocity * 0.15;
  188. tailOff = 0.0;
  189. double cyclesPerSecond = MidiMessage::getMidiNoteInHertz (midiNoteNumber);
  190. double cyclesPerSample = cyclesPerSecond / getSampleRate();
  191. angleDelta = cyclesPerSample * 2.0 * double_Pi;
  192. }
  193. void stopNote (float /*velocity*/, bool allowTailOff) override
  194. {
  195. if (allowTailOff)
  196. {
  197. // start a tail-off by setting this flag. The render callback will pick up on
  198. // this and do a fade out, calling clearCurrentNote() when it's finished.
  199. if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the
  200. // stopNote method could be called more than once.
  201. tailOff = 1.0;
  202. }
  203. else
  204. {
  205. // we're being told to stop playing immediately, so reset everything..
  206. clearCurrentNote();
  207. angleDelta = 0.0;
  208. }
  209. }
  210. void pitchWheelMoved (int /*newValue*/) override
  211. {
  212. // not implemented for the purposes of this demo!
  213. }
  214. void controllerMoved (int /*controllerNumber*/, int /*newValue*/) override
  215. {
  216. // not implemented for the purposes of this demo!
  217. }
  218. void renderNextBlock (AudioBuffer<float>& outputBuffer, int startSample, int numSamples) override
  219. {
  220. if (angleDelta != 0.0)
  221. {
  222. if (tailOff > 0)
  223. {
  224. while (--numSamples >= 0)
  225. {
  226. const float currentSample = (float) (sin (currentAngle) * level * tailOff);
  227. for (int i = outputBuffer.getNumChannels(); --i >= 0;)
  228. outputBuffer.addSample (i, startSample, currentSample);
  229. currentAngle += angleDelta;
  230. ++startSample;
  231. tailOff *= 0.99;
  232. if (tailOff <= 0.005)
  233. {
  234. // tells the synth that this voice has stopped
  235. clearCurrentNote();
  236. angleDelta = 0.0;
  237. break;
  238. }
  239. }
  240. }
  241. else
  242. {
  243. while (--numSamples >= 0)
  244. {
  245. const float currentSample = (float) (sin (currentAngle) * level);
  246. for (int i = outputBuffer.getNumChannels(); --i >= 0;)
  247. outputBuffer.addSample (i, startSample, currentSample);
  248. currentAngle += angleDelta;
  249. ++startSample;
  250. }
  251. }
  252. }
  253. }
  254. using SynthesiserVoice::renderNextBlock;
  255. private:
  256. double currentAngle = 0, angleDelta = 0, level = 0, tailOff = 0;
  257. };
  258. //==============================================================================
  259. Synthesiser synth;
  260. //==============================================================================
  261. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SineWaveSynth)
  262. };
  263. //==============================================================================
  264. class ReverbPlugin : public AudioProcessor
  265. {
  266. public:
  267. ReverbPlugin()
  268. : AudioProcessor (BusesProperties().withInput ("Input", AudioChannelSet::stereo())
  269. .withOutput ("Output", AudioChannelSet::stereo()))
  270. {}
  271. static String getIdentifier()
  272. {
  273. return "Reverb";
  274. }
  275. void prepareToPlay (double newSampleRate, int) override
  276. {
  277. reverb.setSampleRate (newSampleRate);
  278. }
  279. void reset() override
  280. {
  281. reverb.reset();
  282. }
  283. void releaseResources() override {}
  284. void processBlock (AudioBuffer<float>& buffer, MidiBuffer&) override
  285. {
  286. auto numChannels = buffer.getNumChannels();
  287. if (numChannels == 1)
  288. reverb.processMono (buffer.getWritePointer (0), buffer.getNumSamples());
  289. else
  290. reverb.processStereo (buffer.getWritePointer (0),
  291. buffer.getWritePointer (1),
  292. buffer.getNumSamples());
  293. for (int ch = 2; ch < numChannels; ++ch)
  294. buffer.clear (ch, 0, buffer.getNumSamples());
  295. }
  296. using AudioProcessor::processBlock;
  297. const String getName() const override { return getIdentifier(); }
  298. double getTailLengthSeconds() const override { return 0.0; }
  299. bool acceptsMidi() const override { return false; }
  300. bool producesMidi() const override { return false; }
  301. AudioProcessorEditor* createEditor() override { return nullptr; }
  302. bool hasEditor() const override { return false; }
  303. int getNumPrograms() override { return 1; }
  304. int getCurrentProgram() override { return 0; }
  305. void setCurrentProgram (int) override {}
  306. const String getProgramName (int) override { return {}; }
  307. void changeProgramName (int, const String&) override {}
  308. void getStateInformation (juce::MemoryBlock&) override {}
  309. void setStateInformation (const void*, int) override {}
  310. private:
  311. Reverb reverb;
  312. };
  313. //==============================================================================
  314. InternalPluginFormat::InternalPluginFactory::InternalPluginFactory (const std::initializer_list<Constructor>& constructorsIn)
  315. : constructors (constructorsIn),
  316. descriptions ([&]
  317. {
  318. std::vector<PluginDescription> result;
  319. for (const auto& constructor : constructors)
  320. result.push_back (constructor()->getPluginDescription());
  321. return result;
  322. }())
  323. {}
  324. std::unique_ptr<AudioPluginInstance> InternalPluginFormat::InternalPluginFactory::createInstance (const String& name) const
  325. {
  326. const auto begin = descriptions.begin();
  327. const auto it = std::find_if (begin,
  328. descriptions.end(),
  329. [&] (const PluginDescription& desc) { return name == desc.name; });
  330. if (it == descriptions.end())
  331. return nullptr;
  332. const auto index = (size_t) std::distance (begin, it);
  333. return constructors[index]();
  334. }
  335. InternalPluginFormat::InternalPluginFormat()
  336. : factory {
  337. [] { return std::make_unique<AudioProcessorGraph::AudioGraphIOProcessor> (AudioProcessorGraph::AudioGraphIOProcessor::audioInputNode); },
  338. [] { return std::make_unique<AudioProcessorGraph::AudioGraphIOProcessor> (AudioProcessorGraph::AudioGraphIOProcessor::midiInputNode); },
  339. [] { return std::make_unique<AudioProcessorGraph::AudioGraphIOProcessor> (AudioProcessorGraph::AudioGraphIOProcessor::audioOutputNode); },
  340. [] { return std::make_unique<AudioProcessorGraph::AudioGraphIOProcessor> (AudioProcessorGraph::AudioGraphIOProcessor::midiOutputNode); },
  341. [] { return std::make_unique<InternalPlugin> (std::make_unique<SineWaveSynth>()); },
  342. [] { return std::make_unique<InternalPlugin> (std::make_unique<ReverbPlugin>()); },
  343. [] { return std::make_unique<InternalPlugin> (std::make_unique<AUv3SynthProcessor>()); },
  344. [] { return std::make_unique<InternalPlugin> (std::make_unique<Arpeggiator>()); },
  345. [] { return std::make_unique<InternalPlugin> (std::make_unique<DspModulePluginDemoAudioProcessor>()); },
  346. [] { return std::make_unique<InternalPlugin> (std::make_unique<GainProcessor>()); },
  347. [] { return std::make_unique<InternalPlugin> (std::make_unique<JuceDemoPluginAudioProcessor>()); },
  348. [] { return std::make_unique<InternalPlugin> (std::make_unique<MidiLoggerPluginDemoProcessor>()); },
  349. [] { return std::make_unique<InternalPlugin> (std::make_unique<MultiOutSynth>()); },
  350. [] { return std::make_unique<InternalPlugin> (std::make_unique<NoiseGate>()); },
  351. [] { return std::make_unique<InternalPlugin> (std::make_unique<SamplerAudioProcessor>()); },
  352. [] { return std::make_unique<InternalPlugin> (std::make_unique<SurroundProcessor>()); }
  353. }
  354. {
  355. }
  356. std::unique_ptr<AudioPluginInstance> InternalPluginFormat::createInstance (const String& name)
  357. {
  358. return factory.createInstance (name);
  359. }
  360. void InternalPluginFormat::createPluginInstance (const PluginDescription& desc,
  361. double /*initialSampleRate*/, int /*initialBufferSize*/,
  362. PluginCreationCallback callback)
  363. {
  364. if (auto p = createInstance (desc.name))
  365. callback (std::move (p), {});
  366. else
  367. callback (nullptr, NEEDS_TRANS ("Invalid internal plugin name"));
  368. }
  369. bool InternalPluginFormat::requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const
  370. {
  371. return false;
  372. }
  373. const std::vector<PluginDescription>& InternalPluginFormat::getAllTypes() const
  374. {
  375. return factory.getDescriptions();
  376. }