| 
							- /*
 -   ==============================================================================
 - 
 -    This file is part of the JUCE examples.
 -    Copyright (c) 2017 - ROLI Ltd.
 - 
 -    The code included in this file is provided under the terms of the ISC license
 -    http://www.isc.org/downloads/software-support-policy/isc-license. Permission
 -    To use, copy, modify, and/or distribute this software for any purpose with or
 -    without fee is hereby granted provided that the above copyright notice and
 -    this permission notice appear in all copies.
 - 
 -    THE SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES,
 -    WHETHER EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR
 -    PURPOSE, ARE DISCLAIMED.
 - 
 -   ==============================================================================
 - */
 - 
 - /*******************************************************************************
 -  The block below describes the properties of this PIP. A PIP is a short snippet
 -  of code that can be read by the Projucer and used to generate a JUCE project.
 - 
 -  BEGIN_JUCE_PIP_METADATA
 - 
 -  name:             AUv3SynthPlugin
 -  version:          1.0.0
 -  vendor:           JUCE
 -  website:          http://juce.com
 -  description:      AUv3 synthesiser audio plugin.
 - 
 -  dependencies:     juce_audio_basics, juce_audio_devices, juce_audio_formats,
 -                    juce_audio_plugin_client, juce_audio_processors,
 -                    juce_audio_utils, juce_core, juce_data_structures,
 -                    juce_events, juce_graphics, juce_gui_basics, juce_gui_extra
 -  exporters:        xcode_mac, xcode_iphone
 - 
 -  moduleFlags:      JUCE_STRICT_REFCOUNTEDPOINTER=1
 - 
 -  type:             AudioProcessor
 -  mainClass:        AUv3SynthProcessor
 - 
 -  useLocalCopy:     1
 - 
 -  END_JUCE_PIP_METADATA
 - 
 - *******************************************************************************/
 - 
 - #pragma once
 - 
 - #include "../Assets/DemoUtilities.h"
 - 
 - //==============================================================================
 - class MaterialLookAndFeel : public LookAndFeel_V4
 - {
 - public:
 -     //==============================================================================
 -     MaterialLookAndFeel()
 -     {
 -         setColour (ResizableWindow::backgroundColourId, windowBackgroundColour);
 -         setColour (TextButton::buttonOnColourId,        brightButtonColour);
 -         setColour (TextButton::buttonColourId,          disabledButtonColour);
 -     }
 - 
 -     //==============================================================================
 -     void drawButtonBackground (Graphics& g,
 -                                Button& button,
 -                                const Colour& /*backgroundColour*/,
 -                                bool /*isMouseOverButton*/,
 -                                bool isButtonDown) override
 -     {
 -         auto buttonRect = button.getLocalBounds().toFloat();
 - 
 -         if (isButtonDown)
 -             g.setColour (brightButtonColour.withAlpha (0.7f));
 -         else if (! button.isEnabled())
 -             g.setColour (disabledButtonColour);
 -         else
 -             g.setColour (brightButtonColour);
 - 
 -         g.fillRoundedRectangle (buttonRect, 5.0f);
 -     }
 - 
 -     //==============================================================================
 -     void drawButtonText (Graphics& g, TextButton& button, bool isMouseOverButton, bool isButtonDown) override
 -     {
 -         ignoreUnused (isMouseOverButton, isButtonDown);
 - 
 -         Font font (getTextButtonFont (button, button.getHeight()));
 -         g.setFont (font);
 - 
 -         if (button.isEnabled())
 -             g.setColour (Colours::white);
 -         else
 -             g.setColour (backgroundColour);
 - 
 -         g.drawFittedText (button.getButtonText(), 0, 0,
 -                           button.getWidth(),
 -                           button.getHeight(),
 -                           Justification::centred, 2);
 -     }
 - 
 -     //==============================================================================
 -     void drawLinearSlider (Graphics& g, int x, int y, int width, int height,
 -                            float sliderPos, float minSliderPos, float maxSliderPos,
 -                            const Slider::SliderStyle style, Slider& slider) override
 -     {
 -         ignoreUnused (style, minSliderPos, maxSliderPos);
 - 
 -         auto r = Rectangle<int> (x + haloRadius, y, width - (haloRadius * 2), height);
 -         auto backgroundBar = r.withSizeKeepingCentre(r.getWidth(), 2);
 - 
 -         sliderPos = (sliderPos - minSliderPos) / static_cast<float> (width);
 - 
 -         auto knobPos = static_cast<int> (sliderPos * r.getWidth());
 - 
 -         g.setColour (sliderActivePart);
 -         g.fillRect (backgroundBar.removeFromLeft (knobPos));
 - 
 -         g.setColour (sliderInactivePart);
 -         g.fillRect (backgroundBar);
 - 
 -         if (slider.isMouseOverOrDragging())
 -         {
 -             auto haloBounds = r.withTrimmedLeft (knobPos - haloRadius)
 -                                .withWidth (haloRadius * 2)
 -                                .withSizeKeepingCentre (haloRadius * 2, haloRadius * 2);
 - 
 -             g.setColour (sliderActivePart.withAlpha (0.5f));
 -             g.fillEllipse (haloBounds.toFloat());
 -         }
 - 
 -         auto knobRadius = slider.isMouseOverOrDragging() ? knobActiveRadius : knobInActiveRadius;
 -         auto knobBounds = r.withTrimmedLeft (knobPos - knobRadius)
 -                            .withWidth (knobRadius * 2)
 -                            .withSizeKeepingCentre (knobRadius * 2, knobRadius * 2);
 - 
 -         g.setColour (sliderActivePart);
 -         g.fillEllipse (knobBounds.toFloat());
 -     }
 - 
 -     //==============================================================================
 -     Font getTextButtonFont (TextButton& button, int buttonHeight) override
 -     {
 -         return LookAndFeel_V3::getTextButtonFont (button, buttonHeight).withHeight (buttonFontSize);
 -     }
 - 
 -     Font getLabelFont (Label& label) override
 -     {
 -         return LookAndFeel_V3::getLabelFont (label).withHeight (labelFontSize);
 -     }
 - 
 -     //==============================================================================
 -     enum
 -     {
 -         labelFontSize  = 12,
 -         buttonFontSize = 15
 -     };
 - 
 -     //==============================================================================
 -     enum
 -     {
 -         knobActiveRadius   = 12,
 -         knobInActiveRadius = 8,
 -         haloRadius         = 18
 -     };
 - 
 -     //==============================================================================
 -     const Colour windowBackgroundColour = Colour (0xff262328);
 -     const Colour backgroundColour       = Colour (0xff4d4d4d);
 -     const Colour brightButtonColour     = Colour (0xff80cbc4);
 -     const Colour disabledButtonColour   = Colour (0xffe4e4e4);
 -     const Colour sliderInactivePart     = Colour (0xff545d62);
 -     const Colour sliderActivePart       = Colour (0xff80cbc4);
 - };
 - 
 - //==============================================================================
 - class AUv3SynthEditor   : public AudioProcessorEditor,
 -                           private Timer
 - {
 - public:
 -     //==============================================================================
 -     AUv3SynthEditor (AudioProcessor& processorIn)
 -         : AudioProcessorEditor (processorIn),
 -           roomSizeSlider (Slider::LinearHorizontal, Slider::NoTextBox)
 -     {
 -         LookAndFeel::setDefaultLookAndFeel (&materialLookAndFeel);
 - 
 -         roomSizeSlider.setValue (getParameterValue ("roomSize"), NotificationType::dontSendNotification);
 - 
 -         recordButton.onClick = [this] { startRecording(); };
 -         addAndMakeVisible (recordButton);
 - 
 -         roomSizeSlider.onValueChange = [this] { setParameterValue ("roomSize", (float) roomSizeSlider.getValue()); };
 -         roomSizeSlider.setRange (0.0, 1.0);
 -         addAndMakeVisible (roomSizeSlider);
 - 
 -         if (auto fileStream = createAssetInputStream ("proaudio.path"))
 -         {
 -             Path proAudioPath;
 -             proAudioPath.loadPathFromStream (*fileStream);
 -             proAudioIcon.setPath (proAudioPath);
 -             addAndMakeVisible (proAudioIcon);
 - 
 -             auto proAudioIconColour = findColour (TextButton::buttonOnColourId);
 -             proAudioIcon.setFill (FillType (proAudioIconColour));
 -         }
 - 
 -         setSize (600, 400);
 -         startTimer (100);
 -     }
 - 
 -     //==============================================================================
 -     void paint (Graphics& g) override
 -     {
 -         g.fillAll (findColour (ResizableWindow::backgroundColourId));
 -     }
 - 
 -     void resized() override
 -     {
 -         auto r = getLocalBounds();
 - 
 -         auto guiElementAreaHeight = r.getHeight() / 3;
 - 
 -         proAudioIcon.setTransformToFit (r.removeFromLeft (proportionOfWidth (0.25))
 -                                          .withSizeKeepingCentre (guiElementAreaHeight, guiElementAreaHeight)
 -                                          .toFloat(),
 -                                         RectanglePlacement::fillDestination);
 - 
 -         auto margin = guiElementAreaHeight / 4;
 -         r.reduce (margin, margin);
 - 
 -         auto buttonHeight = guiElementAreaHeight - margin;
 - 
 -         recordButton  .setBounds (r.removeFromTop (guiElementAreaHeight).withSizeKeepingCentre (r.getWidth(), buttonHeight));
 -         roomSizeSlider.setBounds (r.removeFromTop (guiElementAreaHeight).withSizeKeepingCentre (r.getWidth(), buttonHeight));
 -     }
 - 
 -     //==============================================================================
 -     void startRecording()
 -     {
 -         recordButton.setEnabled (false);
 -         setParameterValue ("isRecording", 1.0f);
 -     }
 - 
 - private:
 -     //==============================================================================
 -     void timerCallback() override
 -     {
 -         auto isRecordingNow = (getParameterValue ("isRecording") >= 0.5f);
 - 
 -         recordButton.setEnabled (! isRecordingNow);
 -         roomSizeSlider.setValue (getParameterValue ("roomSize"), NotificationType::dontSendNotification);
 -     }
 - 
 -     //==============================================================================
 -     AudioProcessorParameter* getParameter (const String& paramId)
 -     {
 -         if (auto* processor = getAudioProcessor())
 -         {
 -             auto& params = processor->getParameters();
 - 
 -             for (auto p : params)
 -             {
 -                 if (auto* param = dynamic_cast<AudioProcessorParameterWithID*> (p))
 -                 {
 -                     if (param->paramID == paramId)
 -                         return param;
 -                 }
 -             }
 -         }
 - 
 -         return nullptr;
 -     }
 - 
 -     //==============================================================================
 -     float getParameterValue (const String& paramId)
 -     {
 -         if (auto* param = getParameter (paramId))
 -             return param->getValue();
 - 
 -         return 0.0f;
 -     }
 - 
 -     void setParameterValue (const String& paramId, float value)
 -     {
 -         if (auto* param = getParameter (paramId))
 -             param->setValueNotifyingHost (value);
 -     }
 - 
 -     //==============================================================================
 -     MaterialLookAndFeel materialLookAndFeel;
 - 
 -     //==============================================================================
 -     TextButton recordButton { "Record" };
 -     Slider roomSizeSlider;
 -     DrawablePath proAudioIcon;
 - 
 -     //==============================================================================
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AUv3SynthEditor)
 - };
 - 
 - //==============================================================================
 - class AUv3SynthProcessor : public AudioProcessor
 - {
 - public:
 -     AUv3SynthProcessor ()
 -         : AudioProcessor (BusesProperties().withOutput ("Output", AudioChannelSet::stereo(), true)),
 -           currentRecording (1, 1), currentProgram (0)
 -     {
 -         // initialize parameters
 -         addParameter (isRecordingParam = new AudioParameterBool  ("isRecording", "Is Recording", false));
 -         addParameter (roomSizeParam    = new AudioParameterFloat ("roomSize", "Room Size", 0.0f, 1.0f, 0.5f));
 - 
 -         formatManager.registerBasicFormats();
 - 
 -         for (auto i = 0; i < maxNumVoices; ++i)
 -             synth.addVoice (new SamplerVoice());
 - 
 -         loadNewSample (createAssetInputStream ("singing.ogg"), "ogg");
 -     }
 - 
 -     //==============================================================================
 -     bool isBusesLayoutSupported (const BusesLayout& layouts) const override
 -     {
 -         return (layouts.getMainOutputChannels() <= 2);
 -     }
 - 
 -     void prepareToPlay (double sampleRate, int estimatedMaxSizeOfBuffer) override
 -     {
 -         ignoreUnused (estimatedMaxSizeOfBuffer);
 - 
 -         lastSampleRate = sampleRate;
 - 
 -         currentRecording.setSize (1, static_cast<int> (std::ceil (maxDurationOfRecording * lastSampleRate)));
 -         samplesRecorded = 0;
 - 
 -         synth.setCurrentPlaybackSampleRate (lastSampleRate);
 -         reverb.setSampleRate (lastSampleRate);
 -     }
 - 
 -     void processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages) override
 -     {
 -         Reverb::Parameters reverbParameters;
 -         reverbParameters.roomSize = roomSizeParam->get();
 - 
 -         reverb.setParameters (reverbParameters);
 -         synth.renderNextBlock (buffer, midiMessages, 0, buffer.getNumSamples());
 - 
 -         if (getMainBusNumOutputChannels() == 1)
 -             reverb.processMono (buffer.getWritePointer (0), buffer.getNumSamples());
 -         else if (getMainBusNumOutputChannels() == 2)
 -             reverb.processStereo (buffer.getWritePointer (0), buffer.getWritePointer (1), buffer.getNumSamples());
 -     }
 - 
 -     //==============================================================================
 -     void releaseResources() override                                            { currentRecording.setSize (1, 1); }
 - 
 -     //==============================================================================
 -     bool acceptsMidi() const override                                           { return true; }
 -     bool producesMidi() const override                                          { return false; }
 -     bool silenceInProducesSilenceOut() const override                           { return false; }
 -     double getTailLengthSeconds() const override                                { return 0.0; }
 - 
 -     //==============================================================================
 -     AudioProcessorEditor* createEditor() override                               { return new AUv3SynthEditor (*this); }
 -     bool hasEditor() const override                                             { return true; }
 - 
 -     //==============================================================================
 -     const String getName() const override                                       { return "AUv3 Synth"; }
 -     int getNumPrograms() override                                               { return 4; }
 -     int getCurrentProgram() override                                            { return currentProgram; }
 -     void setCurrentProgram (int index) override                                 { currentProgram = index; }
 - 
 -     const String getProgramName (int index) override
 -     {
 -         switch (index)
 -         {
 -             case 0:  return "Piano";
 -             case 1:  return "Singing";
 -             case 2:  return "Pinched Balloon";
 -             case 3:  return "Gazeebo";
 -         }
 - 
 -         return "<Unknown>";
 -     }
 - 
 -     //==============================================================================
 -     void changeProgramName (int /*index*/, const String& /*name*/) override     {}
 - 
 -     //==============================================================================
 -     void getStateInformation (MemoryBlock& destData) override
 -     {
 -         MemoryOutputStream stream (destData, true);
 - 
 -         stream.writeFloat (*isRecordingParam);
 -         stream.writeFloat (*roomSizeParam);
 -     }
 - 
 -     void setStateInformation (const void* data, int sizeInBytes) override
 -     {
 -         MemoryInputStream stream (data, static_cast<size_t> (sizeInBytes), false);
 - 
 -         isRecordingParam->setValueNotifyingHost (stream.readFloat());
 -         roomSizeParam->setValueNotifyingHost    (stream.readFloat());
 - 
 -     }
 - private:
 -     //==============================================================================
 -     void loadNewSampleBinary (const void* data, int dataSize, const char* format)
 -     {
 -         auto soundBuffer = std::make_unique<MemoryInputStream> (data, static_cast<std::size_t> (dataSize), false);
 -         loadNewSample (std::move (soundBuffer), format);
 -     }
 - 
 -     void loadNewSample (std::unique_ptr<InputStream> soundBuffer, const char* format)
 -     {
 -         std::unique_ptr<AudioFormatReader> formatReader (formatManager.findFormatForFileExtension (format)->createReaderFor (soundBuffer.release(), true));
 - 
 -         BigInteger midiNotes;
 -         midiNotes.setRange (0, 126, true);
 -         SynthesiserSound::Ptr newSound = new SamplerSound ("Voice", *formatReader, midiNotes, 0x40, 0.0, 0.0, 10.0);
 -         synth.removeSound (0);
 -         sound = newSound;
 -         synth.addSound (sound);
 -     }
 - 
 -     void swapSamples()
 -     {
 -         MemoryBlock mb;
 -         auto* stream = new MemoryOutputStream (mb, true);
 - 
 -         {
 -             std::unique_ptr<AudioFormatWriter> writer (formatManager.findFormatForFileExtension ("wav")->createWriterFor (stream, lastSampleRate, 1, 16,
 -                                                                                                                           StringPairArray(), 0));
 -             writer->writeFromAudioSampleBuffer (currentRecording, 0, currentRecording.getNumSamples());
 -             writer->flush();
 -             stream->flush();
 -         }
 - 
 -         loadNewSampleBinary (mb.getData(), static_cast<int> (mb.getSize()), "wav");
 -     }
 - 
 -     //==============================================================================
 -     static constexpr int maxNumVoices = 5;
 -     static constexpr double maxDurationOfRecording = 1.0;
 - 
 -     //==============================================================================
 -     AudioFormatManager formatManager;
 - 
 -     int samplesRecorded;
 -     double lastSampleRate;
 -     AudioBuffer<float> currentRecording;
 - 
 -     Reverb reverb;
 -     Synthesiser synth;
 -     SynthesiserSound::Ptr sound;
 - 
 -     AudioParameterBool* isRecordingParam;
 -     AudioParameterFloat* roomSizeParam;
 - 
 -     int currentProgram;
 - 
 -     //==============================================================================
 -     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AUv3SynthProcessor)
 - };
 
 
  |