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.

476 lines
22KB

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