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.

198 lines
8.0KB

  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.getMainInputChannels() == 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:
  81. return "Piano";
  82. case 1:
  83. return "Singing";
  84. case 2:
  85. return "Pinched Balloon";
  86. case 3:
  87. return "Gazeebo";
  88. }
  89. return "<Unknown>";
  90. }
  91. //==============================================================================
  92. void changeProgramName (int /*index*/, const String& /*name*/) override {}
  93. //==============================================================================
  94. void getStateInformation (MemoryBlock& destData) override
  95. {
  96. MemoryOutputStream stream (destData, true);
  97. stream.writeFloat (*isRecordingParam);
  98. stream.writeFloat (*roomSizeParam);
  99. }
  100. void setStateInformation (const void* data, int sizeInBytes) override
  101. {
  102. MemoryInputStream stream (data, static_cast<size_t> (sizeInBytes), false);
  103. isRecordingParam->setValueNotifyingHost (stream.readFloat());
  104. roomSizeParam->setValueNotifyingHost (stream.readFloat());
  105. }
  106. private:
  107. //==============================================================================
  108. void loadNewSample (const void* data, int dataSize, const char* format)
  109. {
  110. MemoryInputStream* soundBuffer = new MemoryInputStream (data, static_cast<std::size_t> (dataSize), false);
  111. ScopedPointer<AudioFormatReader> formatReader (formatManager.findFormatForFileExtension (format)->createReaderFor (soundBuffer, true));
  112. BigInteger midiNotes;
  113. midiNotes.setRange (0, 126, true);
  114. SynthesiserSound::Ptr newSound = new SamplerSound ("Voice", *formatReader, midiNotes, 0x40, 0.0, 0.0, 10.0);
  115. synth.removeSound (0);
  116. sound = newSound;
  117. synth.addSound (sound);
  118. }
  119. void swapSamples()
  120. {
  121. MemoryBlock mb;
  122. MemoryOutputStream* stream = new MemoryOutputStream (mb, true);
  123. {
  124. ScopedPointer<AudioFormatWriter> writer (formatManager.findFormatForFileExtension ("wav")->createWriterFor (stream, lastSampleRate, 1, 16,
  125. StringPairArray(), 0));
  126. writer->writeFromAudioSampleBuffer (currentRecording, 0, currentRecording.getNumSamples());
  127. writer->flush();
  128. stream->flush();
  129. }
  130. loadNewSample (mb.getData(), static_cast<int> (mb.getSize()), "wav");
  131. }
  132. //==============================================================================
  133. static constexpr int maxNumVoices = 5;
  134. static constexpr double kMaxDurationOfRecording = 1.0;
  135. //==============================================================================
  136. AudioFormatManager formatManager;
  137. int samplesRecorded;
  138. double lastSampleRate;
  139. AudioBuffer<float> currentRecording;
  140. Reverb reverb;
  141. Synthesiser synth;
  142. SynthesiserSound::Ptr sound;
  143. AudioParameterBool* isRecordingParam;
  144. AudioParameterFloat* roomSizeParam;
  145. int currentProgram;
  146. //==============================================================================
  147. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AUv3SynthProcessor)
  148. };
  149. //==============================================================================
  150. // This creates new instances of the plugin..
  151. AudioProcessor* JUCE_CALLTYPE createPluginFilter()
  152. {
  153. return new AUv3SynthProcessor();
  154. }