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.

171 lines
7.4KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  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 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. #include "../JuceLibraryCode/JuceHeader.h"
  20. #include "../../GenericEditor.h"
  21. //==============================================================================
  22. /**
  23. */
  24. class MultiOutSynth : public AudioProcessor
  25. {
  26. public:
  27. enum
  28. {
  29. maxMidiChannel = 16,
  30. maxNumberOfVoices = 5
  31. };
  32. //==============================================================================
  33. MultiOutSynth()
  34. : AudioProcessor (BusesProperties()
  35. .withOutput ("Output #1", AudioChannelSet::stereo(), true)
  36. .withOutput ("Output #2", AudioChannelSet::stereo(), false)
  37. .withOutput ("Output #3", AudioChannelSet::stereo(), false)
  38. .withOutput ("Output #4", AudioChannelSet::stereo(), false)
  39. .withOutput ("Output #5", AudioChannelSet::stereo(), false)
  40. .withOutput ("Output #6", AudioChannelSet::stereo(), false)
  41. .withOutput ("Output #7", AudioChannelSet::stereo(), false)
  42. .withOutput ("Output #8", AudioChannelSet::stereo(), false)
  43. .withOutput ("Output #9", AudioChannelSet::stereo(), false)
  44. .withOutput ("Output #10", AudioChannelSet::stereo(), false)
  45. .withOutput ("Output #11", AudioChannelSet::stereo(), false)
  46. .withOutput ("Output #12", AudioChannelSet::stereo(), false)
  47. .withOutput ("Output #13", AudioChannelSet::stereo(), false)
  48. .withOutput ("Output #14", AudioChannelSet::stereo(), false)
  49. .withOutput ("Output #15", AudioChannelSet::stereo(), false)
  50. .withOutput ("Output #16", AudioChannelSet::stereo(), false))
  51. {
  52. // initialize other stuff (not related to buses)
  53. formatManager.registerBasicFormats();
  54. for (int midiChannel = 0; midiChannel < maxMidiChannel; ++midiChannel)
  55. {
  56. synth.add (new Synthesiser());
  57. for (int i = 0; i < maxNumberOfVoices; ++i)
  58. synth[midiChannel]->addVoice (new SamplerVoice());
  59. }
  60. loadNewSample (BinaryData::singing_ogg, BinaryData::singing_oggSize);
  61. }
  62. ~MultiOutSynth() {}
  63. //==============================================================================
  64. bool canAddBus (bool isInput) const override { return (! isInput && getBusCount (false) < maxMidiChannel); }
  65. bool canRemoveBus (bool isInput) const override { return (! isInput && getBusCount (false) > 1); }
  66. //==============================================================================
  67. void prepareToPlay (double newSampleRate, int samplesPerBlock) override
  68. {
  69. ignoreUnused (samplesPerBlock);
  70. for (int midiChannel = 0; midiChannel < maxMidiChannel; ++midiChannel)
  71. synth[midiChannel]->setCurrentPlaybackSampleRate (newSampleRate);
  72. }
  73. void releaseResources() override {}
  74. void processBlock (AudioSampleBuffer& buffer, MidiBuffer& midiBuffer) override
  75. {
  76. const int busCount = getBusCount (false);
  77. for (int busNr = 0; busNr < busCount; ++busNr)
  78. {
  79. MidiBuffer midiChannelBuffer = filterMidiMessagesForChannel (midiBuffer, busNr + 1);
  80. AudioSampleBuffer audioBusBuffer = getBusBuffer (buffer, false, busNr);
  81. synth [busNr]->renderNextBlock (audioBusBuffer, midiChannelBuffer, 0, audioBusBuffer.getNumSamples());
  82. }
  83. }
  84. //==============================================================================
  85. AudioProcessorEditor* createEditor() override { return new GenericEditor (*this); }
  86. bool hasEditor() const override { return true; }
  87. //==============================================================================
  88. const String getName() const override { return "Gain PlugIn"; }
  89. bool acceptsMidi() const override { return false; }
  90. bool producesMidi() const override { return false; }
  91. double getTailLengthSeconds() const override { return 0; }
  92. int getNumPrograms() override { return 1; }
  93. int getCurrentProgram() override { return 0; }
  94. void setCurrentProgram (int) override {}
  95. const String getProgramName (int) override { return String(); }
  96. void changeProgramName (int , const String& ) override { }
  97. //==============================================================================
  98. void getStateInformation (MemoryBlock&) override {}
  99. void setStateInformation (const void*, int) override {}
  100. private:
  101. //==============================================================================
  102. static MidiBuffer filterMidiMessagesForChannel (const MidiBuffer& input, int channel)
  103. {
  104. MidiMessage msg;
  105. int samplePosition;
  106. MidiBuffer output;
  107. for (MidiBuffer::Iterator it (input); it.getNextEvent (msg, samplePosition);)
  108. if (msg.getChannel() == channel) output.addEvent (msg, samplePosition);
  109. return output;
  110. }
  111. void loadNewSample (const void* data, int dataSize)
  112. {
  113. MemoryInputStream* soundBuffer = new MemoryInputStream (data, static_cast<std::size_t> (dataSize), false);
  114. ScopedPointer<AudioFormatReader> formatReader (formatManager.findFormatForFileExtension ("ogg")->createReaderFor (soundBuffer, true));
  115. BigInteger midiNotes;
  116. midiNotes.setRange (0, 126, true);
  117. SynthesiserSound::Ptr newSound = new SamplerSound ("Voice", *formatReader, midiNotes, 0x40, 0.0, 0.0, 10.0);
  118. for (int channel = 0; channel < maxMidiChannel; ++channel)
  119. synth[channel]->removeSound (0);
  120. sound = newSound;
  121. for (int channel = 0; channel < maxMidiChannel; ++channel)
  122. synth[channel]->addSound (sound);
  123. }
  124. //==============================================================================
  125. AudioFormatManager formatManager;
  126. OwnedArray<Synthesiser> synth;
  127. SynthesiserSound::Ptr sound;
  128. //==============================================================================
  129. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MultiOutSynth)
  130. };
  131. //==============================================================================
  132. // This creates new instances of the plugin..
  133. AudioProcessor* JUCE_CALLTYPE createPluginFilter()
  134. {
  135. return new MultiOutSynth();
  136. }