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.

482 lines
22KB

  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. #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 (BinaryData::originalFilenames[i] == 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 canAddBus (bool) const override { return true; }
  97. bool canRemoveBus (bool) const override { return true; }
  98. //==============================================================================
  99. void fillInPluginDescription (PluginDescription& description) const override
  100. {
  101. description = getPluginDescription (*inner);
  102. }
  103. private:
  104. static PluginDescription getPluginDescription (const AudioProcessor& proc)
  105. {
  106. const auto ins = proc.getTotalNumInputChannels();
  107. const auto outs = proc.getTotalNumOutputChannels();
  108. const auto identifier = proc.getName();
  109. const auto registerAsGenerator = ins == 0;
  110. const auto acceptsMidi = proc.acceptsMidi();
  111. PluginDescription descr;
  112. descr.name = identifier;
  113. descr.descriptiveName = identifier;
  114. descr.pluginFormatName = InternalPluginFormat::getIdentifier();
  115. descr.category = (registerAsGenerator ? (acceptsMidi ? "Synth" : "Generator") : "Effect");
  116. descr.manufacturerName = "JUCE";
  117. descr.version = ProjectInfo::versionString;
  118. descr.fileOrIdentifier = identifier;
  119. descr.isInstrument = (acceptsMidi && registerAsGenerator);
  120. descr.numInputChannels = ins;
  121. descr.numOutputChannels = outs;
  122. descr.uniqueId = descr.deprecatedUid = identifier.hashCode();
  123. return descr;
  124. }
  125. void matchChannels (bool isInput)
  126. {
  127. const auto inBuses = inner->getBusCount (isInput);
  128. while (getBusCount (isInput) < inBuses)
  129. addBus (isInput);
  130. while (inBuses < getBusCount (isInput))
  131. removeBus (isInput);
  132. }
  133. std::unique_ptr<AudioProcessor> inner;
  134. //==============================================================================
  135. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (InternalPlugin)
  136. };
  137. //==============================================================================
  138. class SineWaveSynth : public AudioProcessor
  139. {
  140. public:
  141. SineWaveSynth()
  142. : AudioProcessor (BusesProperties().withOutput ("Output", AudioChannelSet::stereo()))
  143. {
  144. const int numVoices = 8;
  145. // Add some voices...
  146. for (int i = numVoices; --i >= 0;)
  147. synth.addVoice (new SineWaveVoice());
  148. // ..and give the synth a sound to play
  149. synth.addSound (new SineWaveSound());
  150. }
  151. static String getIdentifier()
  152. {
  153. return "Sine Wave Synth";
  154. }
  155. //==============================================================================
  156. void prepareToPlay (double newSampleRate, int) override
  157. {
  158. synth.setCurrentPlaybackSampleRate (newSampleRate);
  159. }
  160. void releaseResources() override {}
  161. //==============================================================================
  162. void processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages) override
  163. {
  164. const int numSamples = buffer.getNumSamples();
  165. buffer.clear();
  166. synth.renderNextBlock (buffer, midiMessages, 0, numSamples);
  167. buffer.applyGain (0.8f);
  168. }
  169. using AudioProcessor::processBlock;
  170. const String getName() const override { return getIdentifier(); }
  171. double getTailLengthSeconds() const override { return 0.0; }
  172. bool acceptsMidi() const override { return true; }
  173. bool producesMidi() const override { return true; }
  174. AudioProcessorEditor* createEditor() override { return nullptr; }
  175. bool hasEditor() const override { return false; }
  176. int getNumPrograms() override { return 1; }
  177. int getCurrentProgram() override { return 0; }
  178. void setCurrentProgram (int) override {}
  179. const String getProgramName (int) override { return {}; }
  180. void changeProgramName (int, const String&) override {}
  181. void getStateInformation (juce::MemoryBlock&) override {}
  182. void setStateInformation (const void*, int) override {}
  183. private:
  184. //==============================================================================
  185. struct SineWaveSound : public SynthesiserSound
  186. {
  187. SineWaveSound() = default;
  188. bool appliesToNote (int /*midiNoteNumber*/) override { return true; }
  189. bool appliesToChannel (int /*midiChannel*/) override { return true; }
  190. };
  191. struct SineWaveVoice : public SynthesiserVoice
  192. {
  193. SineWaveVoice() = default;
  194. bool canPlaySound (SynthesiserSound* sound) override
  195. {
  196. return dynamic_cast<SineWaveSound*> (sound) != nullptr;
  197. }
  198. void startNote (int midiNoteNumber, float velocity,
  199. SynthesiserSound* /*sound*/,
  200. int /*currentPitchWheelPosition*/) override
  201. {
  202. currentAngle = 0.0;
  203. level = velocity * 0.15;
  204. tailOff = 0.0;
  205. double cyclesPerSecond = MidiMessage::getMidiNoteInHertz (midiNoteNumber);
  206. double cyclesPerSample = cyclesPerSecond / getSampleRate();
  207. angleDelta = cyclesPerSample * 2.0 * MathConstants<double>::pi;
  208. }
  209. void stopNote (float /*velocity*/, bool allowTailOff) override
  210. {
  211. if (allowTailOff)
  212. {
  213. // start a tail-off by setting this flag. The render callback will pick up on
  214. // this and do a fade out, calling clearCurrentNote() when it's finished.
  215. if (tailOff == 0.0) // we only need to begin a tail-off if it's not already doing so - the
  216. // stopNote method could be called more than once.
  217. tailOff = 1.0;
  218. }
  219. else
  220. {
  221. // we're being told to stop playing immediately, so reset everything..
  222. clearCurrentNote();
  223. angleDelta = 0.0;
  224. }
  225. }
  226. void pitchWheelMoved (int /*newValue*/) override
  227. {
  228. // not implemented for the purposes of this demo!
  229. }
  230. void controllerMoved (int /*controllerNumber*/, int /*newValue*/) override
  231. {
  232. // not implemented for the purposes of this demo!
  233. }
  234. void renderNextBlock (AudioBuffer<float>& outputBuffer, int startSample, int numSamples) override
  235. {
  236. if (angleDelta != 0.0)
  237. {
  238. if (tailOff > 0)
  239. {
  240. while (--numSamples >= 0)
  241. {
  242. const float currentSample = (float) (sin (currentAngle) * level * tailOff);
  243. for (int i = outputBuffer.getNumChannels(); --i >= 0;)
  244. outputBuffer.addSample (i, startSample, currentSample);
  245. currentAngle += angleDelta;
  246. ++startSample;
  247. tailOff *= 0.99;
  248. if (tailOff <= 0.005)
  249. {
  250. // tells the synth that this voice has stopped
  251. clearCurrentNote();
  252. angleDelta = 0.0;
  253. break;
  254. }
  255. }
  256. }
  257. else
  258. {
  259. while (--numSamples >= 0)
  260. {
  261. const float currentSample = (float) (sin (currentAngle) * level);
  262. for (int i = outputBuffer.getNumChannels(); --i >= 0;)
  263. outputBuffer.addSample (i, startSample, currentSample);
  264. currentAngle += angleDelta;
  265. ++startSample;
  266. }
  267. }
  268. }
  269. }
  270. using SynthesiserVoice::renderNextBlock;
  271. private:
  272. double currentAngle = 0, angleDelta = 0, level = 0, tailOff = 0;
  273. };
  274. //==============================================================================
  275. Synthesiser synth;
  276. //==============================================================================
  277. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SineWaveSynth)
  278. };
  279. //==============================================================================
  280. class ReverbPlugin : public AudioProcessor
  281. {
  282. public:
  283. ReverbPlugin()
  284. : AudioProcessor (BusesProperties().withInput ("Input", AudioChannelSet::stereo())
  285. .withOutput ("Output", AudioChannelSet::stereo()))
  286. {}
  287. static String getIdentifier()
  288. {
  289. return "Reverb";
  290. }
  291. void prepareToPlay (double newSampleRate, int) override
  292. {
  293. reverb.setSampleRate (newSampleRate);
  294. }
  295. void reset() override
  296. {
  297. reverb.reset();
  298. }
  299. void releaseResources() override {}
  300. void processBlock (AudioBuffer<float>& buffer, MidiBuffer&) override
  301. {
  302. auto numChannels = buffer.getNumChannels();
  303. if (numChannels == 1)
  304. reverb.processMono (buffer.getWritePointer (0), buffer.getNumSamples());
  305. else
  306. reverb.processStereo (buffer.getWritePointer (0),
  307. buffer.getWritePointer (1),
  308. buffer.getNumSamples());
  309. for (int ch = 2; ch < numChannels; ++ch)
  310. buffer.clear (ch, 0, buffer.getNumSamples());
  311. }
  312. using AudioProcessor::processBlock;
  313. const String getName() const override { return getIdentifier(); }
  314. double getTailLengthSeconds() const override { return 0.0; }
  315. bool acceptsMidi() const override { return false; }
  316. bool producesMidi() const override { return false; }
  317. AudioProcessorEditor* createEditor() override { return nullptr; }
  318. bool hasEditor() const override { return false; }
  319. int getNumPrograms() override { return 1; }
  320. int getCurrentProgram() override { return 0; }
  321. void setCurrentProgram (int) override {}
  322. const String getProgramName (int) override { return {}; }
  323. void changeProgramName (int, const String&) override {}
  324. void getStateInformation (juce::MemoryBlock&) override {}
  325. void setStateInformation (const void*, int) override {}
  326. private:
  327. Reverb reverb;
  328. };
  329. //==============================================================================
  330. InternalPluginFormat::InternalPluginFactory::InternalPluginFactory (const std::initializer_list<Constructor>& constructorsIn)
  331. : constructors (constructorsIn),
  332. descriptions ([&]
  333. {
  334. std::vector<PluginDescription> result;
  335. for (const auto& constructor : constructors)
  336. result.push_back (constructor()->getPluginDescription());
  337. return result;
  338. }())
  339. {}
  340. std::unique_ptr<AudioPluginInstance> InternalPluginFormat::InternalPluginFactory::createInstance (const String& name) const
  341. {
  342. const auto begin = descriptions.begin();
  343. const auto it = std::find_if (begin,
  344. descriptions.end(),
  345. [&] (const PluginDescription& desc) { return name.equalsIgnoreCase (desc.name); });
  346. if (it == descriptions.end())
  347. return nullptr;
  348. const auto index = (size_t) std::distance (begin, it);
  349. return constructors[index]();
  350. }
  351. InternalPluginFormat::InternalPluginFormat()
  352. : factory {
  353. [] { return std::make_unique<AudioProcessorGraph::AudioGraphIOProcessor> (AudioProcessorGraph::AudioGraphIOProcessor::audioInputNode); },
  354. [] { return std::make_unique<AudioProcessorGraph::AudioGraphIOProcessor> (AudioProcessorGraph::AudioGraphIOProcessor::midiInputNode); },
  355. [] { return std::make_unique<AudioProcessorGraph::AudioGraphIOProcessor> (AudioProcessorGraph::AudioGraphIOProcessor::audioOutputNode); },
  356. [] { return std::make_unique<AudioProcessorGraph::AudioGraphIOProcessor> (AudioProcessorGraph::AudioGraphIOProcessor::midiOutputNode); },
  357. [] { return std::make_unique<InternalPlugin> (std::make_unique<SineWaveSynth>()); },
  358. [] { return std::make_unique<InternalPlugin> (std::make_unique<ReverbPlugin>()); },
  359. [] { return std::make_unique<InternalPlugin> (std::make_unique<AUv3SynthProcessor>()); },
  360. [] { return std::make_unique<InternalPlugin> (std::make_unique<Arpeggiator>()); },
  361. [] { return std::make_unique<InternalPlugin> (std::make_unique<DspModulePluginDemoAudioProcessor>()); },
  362. [] { return std::make_unique<InternalPlugin> (std::make_unique<GainProcessor>()); },
  363. [] { return std::make_unique<InternalPlugin> (std::make_unique<JuceDemoPluginAudioProcessor>()); },
  364. [] { return std::make_unique<InternalPlugin> (std::make_unique<MidiLoggerPluginDemoProcessor>()); },
  365. [] { return std::make_unique<InternalPlugin> (std::make_unique<MultiOutSynth>()); },
  366. [] { return std::make_unique<InternalPlugin> (std::make_unique<NoiseGate>()); },
  367. [] { return std::make_unique<InternalPlugin> (std::make_unique<SamplerAudioProcessor>()); },
  368. [] { return std::make_unique<InternalPlugin> (std::make_unique<SurroundProcessor>()); }
  369. }
  370. {
  371. }
  372. std::unique_ptr<AudioPluginInstance> InternalPluginFormat::createInstance (const String& name)
  373. {
  374. return factory.createInstance (name);
  375. }
  376. void InternalPluginFormat::createPluginInstance (const PluginDescription& desc,
  377. double /*initialSampleRate*/, int /*initialBufferSize*/,
  378. PluginCreationCallback callback)
  379. {
  380. if (auto p = createInstance (desc.name))
  381. callback (std::move (p), {});
  382. else
  383. callback (nullptr, NEEDS_TRANS ("Invalid internal plugin name"));
  384. }
  385. bool InternalPluginFormat::requiresUnblockedMessageThreadDuringCreation (const PluginDescription&) const
  386. {
  387. return false;
  388. }
  389. const std::vector<PluginDescription>& InternalPluginFormat::getAllTypes() const
  390. {
  391. return factory.getDescriptions();
  392. }