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.

483 lines
22KB

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