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. //==============================================================================
  21. /**
  22. */
  23. class MultiOutSynth : public AudioProcessor
  24. {
  25. public:
  26. enum
  27. {
  28. maxMidiChannel = 16,
  29. maxNumberOfVoices = 5
  30. };
  31. //==============================================================================
  32. MultiOutSynth()
  33. : AudioProcessor (BusesProperties()
  34. .withOutput ("Output #1", AudioChannelSet::stereo(), true)
  35. .withOutput ("Output #2", AudioChannelSet::stereo(), false)
  36. .withOutput ("Output #3", AudioChannelSet::stereo(), false)
  37. .withOutput ("Output #4", AudioChannelSet::stereo(), false)
  38. .withOutput ("Output #5", AudioChannelSet::stereo(), false)
  39. .withOutput ("Output #6", AudioChannelSet::stereo(), false)
  40. .withOutput ("Output #7", AudioChannelSet::stereo(), false)
  41. .withOutput ("Output #8", AudioChannelSet::stereo(), false)
  42. .withOutput ("Output #9", AudioChannelSet::stereo(), false)
  43. .withOutput ("Output #10", AudioChannelSet::stereo(), false)
  44. .withOutput ("Output #11", AudioChannelSet::stereo(), false)
  45. .withOutput ("Output #12", AudioChannelSet::stereo(), false)
  46. .withOutput ("Output #13", AudioChannelSet::stereo(), false)
  47. .withOutput ("Output #14", AudioChannelSet::stereo(), false)
  48. .withOutput ("Output #15", AudioChannelSet::stereo(), false)
  49. .withOutput ("Output #16", AudioChannelSet::stereo(), false))
  50. {
  51. // initialize other stuff (not related to buses)
  52. formatManager.registerBasicFormats();
  53. for (int midiChannel = 0; midiChannel < maxMidiChannel; ++midiChannel)
  54. {
  55. synth.add (new Synthesiser());
  56. for (int i = 0; i < maxNumberOfVoices; ++i)
  57. synth[midiChannel]->addVoice (new SamplerVoice());
  58. }
  59. loadNewSample (BinaryData::singing_ogg, BinaryData::singing_oggSize);
  60. }
  61. ~MultiOutSynth() {}
  62. //==============================================================================
  63. bool canAddBus (bool isInput) const override { return (! isInput && getBusCount (false) < maxMidiChannel); }
  64. bool canRemoveBus (bool isInput) const override { return (! isInput && getBusCount (false) > 1); }
  65. //==============================================================================
  66. void prepareToPlay (double newSampleRate, int samplesPerBlock) override
  67. {
  68. ignoreUnused (samplesPerBlock);
  69. for (int midiChannel = 0; midiChannel < maxMidiChannel; ++midiChannel)
  70. synth[midiChannel]->setCurrentPlaybackSampleRate (newSampleRate);
  71. }
  72. void releaseResources() override {}
  73. void processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiBuffer) override
  74. {
  75. auto busCount = getBusCount (false);
  76. for (int busNr = 0; busNr < busCount; ++busNr)
  77. {
  78. MidiBuffer midiChannelBuffer = filterMidiMessagesForChannel (midiBuffer, busNr + 1);
  79. auto audioBusBuffer = getBusBuffer (buffer, false, busNr);
  80. synth [busNr]->renderNextBlock (audioBusBuffer, midiChannelBuffer, 0, audioBusBuffer.getNumSamples());
  81. }
  82. }
  83. //==============================================================================
  84. AudioProcessorEditor* createEditor() override { return new GenericAudioProcessorEditor (this); }
  85. bool hasEditor() const override { return true; }
  86. //==============================================================================
  87. const String getName() const override { return "Gain PlugIn"; }
  88. bool acceptsMidi() const override { return false; }
  89. bool producesMidi() const override { return false; }
  90. double getTailLengthSeconds() const override { return 0; }
  91. int getNumPrograms() override { return 1; }
  92. int getCurrentProgram() override { return 0; }
  93. void setCurrentProgram (int) override {}
  94. const String getProgramName (int) override { return String(); }
  95. void changeProgramName (int , const String& ) override { }
  96. //==============================================================================
  97. void getStateInformation (MemoryBlock&) override {}
  98. void setStateInformation (const void*, int) override {}
  99. private:
  100. //==============================================================================
  101. static MidiBuffer filterMidiMessagesForChannel (const MidiBuffer& input, int channel)
  102. {
  103. MidiMessage msg;
  104. int samplePosition;
  105. MidiBuffer output;
  106. for (MidiBuffer::Iterator it (input); it.getNextEvent (msg, samplePosition);)
  107. if (msg.getChannel() == channel) output.addEvent (msg, samplePosition);
  108. return output;
  109. }
  110. void loadNewSample (const void* data, int dataSize)
  111. {
  112. MemoryInputStream* soundBuffer = new MemoryInputStream (data, static_cast<std::size_t> (dataSize), false);
  113. ScopedPointer<AudioFormatReader> formatReader (formatManager.findFormatForFileExtension ("ogg")->createReaderFor (soundBuffer, true));
  114. BigInteger midiNotes;
  115. midiNotes.setRange (0, 126, true);
  116. SynthesiserSound::Ptr newSound = new SamplerSound ("Voice", *formatReader, midiNotes, 0x40, 0.0, 0.0, 10.0);
  117. for (int channel = 0; channel < maxMidiChannel; ++channel)
  118. synth[channel]->removeSound (0);
  119. sound = newSound;
  120. for (int channel = 0; channel < maxMidiChannel; ++channel)
  121. synth[channel]->addSound (sound);
  122. }
  123. //==============================================================================
  124. AudioFormatManager formatManager;
  125. OwnedArray<Synthesiser> synth;
  126. SynthesiserSound::Ptr sound;
  127. //==============================================================================
  128. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MultiOutSynth)
  129. };
  130. //==============================================================================
  131. // This creates new instances of the plugin..
  132. AudioProcessor* JUCE_CALLTYPE createPluginFilter()
  133. {
  134. return new MultiOutSynth();
  135. }