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.

195 lines
7.9KB

  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 "AUv3SynthEditor.h"
  21. class AUv3SynthProcessor : public AudioProcessor
  22. {
  23. public:
  24. AUv3SynthProcessor ()
  25. : AudioProcessor (BusesProperties().withOutput ("Output", AudioChannelSet::stereo(), true)),
  26. currentRecording (1, 1), currentProgram (0)
  27. {
  28. // initialize parameters
  29. addParameter (isRecordingParam = new AudioParameterBool ("isRecording", "Is Recording", false));
  30. addParameter (roomSizeParam = new AudioParameterFloat ("roomSize", "Room Size", 0.0f, 1.0f, 0.5f));
  31. formatManager.registerBasicFormats();
  32. for (int i = 0; i < maxNumVoices; ++i)
  33. synth.addVoice (new SamplerVoice());
  34. loadNewSample (BinaryData::singing_ogg, BinaryData::singing_oggSize, "ogg");
  35. }
  36. //==============================================================================
  37. bool isBusesLayoutSupported (const BusesLayout& layouts) const override
  38. {
  39. return (layouts.getMainOutputChannels() == 2);
  40. }
  41. void prepareToPlay (double sampleRate, int estimatedMaxSizeOfBuffer) override
  42. {
  43. ignoreUnused (estimatedMaxSizeOfBuffer);
  44. lastSampleRate = sampleRate;
  45. currentRecording.setSize (1, static_cast<int> (std::ceil (kMaxDurationOfRecording * lastSampleRate)));
  46. samplesRecorded = 0;
  47. synth.setCurrentPlaybackSampleRate (lastSampleRate);
  48. reverb.setSampleRate (lastSampleRate);
  49. }
  50. void processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages) override
  51. {
  52. Reverb::Parameters reverbParameters;
  53. reverbParameters.roomSize = roomSizeParam->get();
  54. reverb.setParameters (reverbParameters);
  55. synth.renderNextBlock (buffer, midiMessages, 0, buffer.getNumSamples());
  56. if (getMainBusNumOutputChannels() == 1)
  57. reverb.processMono (buffer.getWritePointer (0), buffer.getNumSamples());
  58. else if (getMainBusNumOutputChannels() == 2)
  59. reverb.processStereo (buffer.getWritePointer (0), buffer.getWritePointer (1), buffer.getNumSamples());
  60. }
  61. //==============================================================================
  62. void releaseResources() override { currentRecording.setSize (1, 1); }
  63. //==============================================================================
  64. bool acceptsMidi() const override { return true; }
  65. bool producesMidi() const override { return false; }
  66. bool silenceInProducesSilenceOut() const override { return false; }
  67. double getTailLengthSeconds() const override { return 0.0; }
  68. //==============================================================================
  69. AudioProcessorEditor* createEditor() override { return new AUv3SynthEditor (*this); }
  70. bool hasEditor() const override { return true; }
  71. //==============================================================================
  72. const String getName() const override { return "AUv3 Synth"; }
  73. int getNumPrograms() override { return 4; }
  74. int getCurrentProgram() override { return currentProgram; }
  75. void setCurrentProgram (int index) override { currentProgram = index; }
  76. const String getProgramName (int index) override
  77. {
  78. switch (index)
  79. {
  80. case 0: return "Piano";
  81. case 1: return "Singing";
  82. case 2: return "Pinched Balloon";
  83. case 3: return "Gazeebo";
  84. }
  85. return "<Unknown>";
  86. }
  87. //==============================================================================
  88. void changeProgramName (int /*index*/, const String& /*name*/) override {}
  89. //==============================================================================
  90. void getStateInformation (MemoryBlock& destData) override
  91. {
  92. MemoryOutputStream stream (destData, true);
  93. stream.writeFloat (*isRecordingParam);
  94. stream.writeFloat (*roomSizeParam);
  95. }
  96. void setStateInformation (const void* data, int sizeInBytes) override
  97. {
  98. MemoryInputStream stream (data, static_cast<size_t> (sizeInBytes), false);
  99. isRecordingParam->setValueNotifyingHost (stream.readFloat());
  100. roomSizeParam->setValueNotifyingHost (stream.readFloat());
  101. }
  102. private:
  103. //==============================================================================
  104. void loadNewSample (const void* data, int dataSize, const char* format)
  105. {
  106. MemoryInputStream* soundBuffer = new MemoryInputStream (data, static_cast<std::size_t> (dataSize), false);
  107. ScopedPointer<AudioFormatReader> formatReader (formatManager.findFormatForFileExtension (format)->createReaderFor (soundBuffer, true));
  108. BigInteger midiNotes;
  109. midiNotes.setRange (0, 126, true);
  110. SynthesiserSound::Ptr newSound = new SamplerSound ("Voice", *formatReader, midiNotes, 0x40, 0.0, 0.0, 10.0);
  111. synth.removeSound (0);
  112. sound = newSound;
  113. synth.addSound (sound);
  114. }
  115. void swapSamples()
  116. {
  117. MemoryBlock mb;
  118. MemoryOutputStream* stream = new MemoryOutputStream (mb, true);
  119. {
  120. ScopedPointer<AudioFormatWriter> writer (formatManager.findFormatForFileExtension ("wav")->createWriterFor (stream, lastSampleRate, 1, 16,
  121. StringPairArray(), 0));
  122. writer->writeFromAudioSampleBuffer (currentRecording, 0, currentRecording.getNumSamples());
  123. writer->flush();
  124. stream->flush();
  125. }
  126. loadNewSample (mb.getData(), static_cast<int> (mb.getSize()), "wav");
  127. }
  128. //==============================================================================
  129. static constexpr int maxNumVoices = 5;
  130. static constexpr double kMaxDurationOfRecording = 1.0;
  131. //==============================================================================
  132. AudioFormatManager formatManager;
  133. int samplesRecorded;
  134. double lastSampleRate;
  135. AudioBuffer<float> currentRecording;
  136. Reverb reverb;
  137. Synthesiser synth;
  138. SynthesiserSound::Ptr sound;
  139. AudioParameterBool* isRecordingParam;
  140. AudioParameterFloat* roomSizeParam;
  141. int currentProgram;
  142. //==============================================================================
  143. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AUv3SynthProcessor)
  144. };
  145. //==============================================================================
  146. // This creates new instances of the plugin..
  147. AudioProcessor* JUCE_CALLTYPE createPluginFilter()
  148. {
  149. return new AUv3SynthProcessor();
  150. }