From 123e050991ff73cc1ab14ec8959765e20de57c8f Mon Sep 17 00:00:00 2001 From: Dominik Kaiser Date: Wed, 24 Sep 2025 12:48:19 +0200 Subject: Add JUCE boilerplate --- src/PluginProcessor.cpp | 188 ++++++++++++++++++++++++++++++++++++++++++++++++ src/PluginProcessor.h | 48 +++++++++++++ src/UI/PluginEditor.cpp | 33 +++++++++ src/UI/PluginEditor.h | 22 ++++++ 4 files changed, 291 insertions(+) create mode 100644 src/PluginProcessor.cpp create mode 100644 src/PluginProcessor.h create mode 100644 src/UI/PluginEditor.cpp create mode 100644 src/UI/PluginEditor.h diff --git a/src/PluginProcessor.cpp b/src/PluginProcessor.cpp new file mode 100644 index 0000000..825d31a --- /dev/null +++ b/src/PluginProcessor.cpp @@ -0,0 +1,188 @@ +#include "PluginProcessor.h" +#include "UI/PluginEditor.h" + +//============================================================================== +SchroederReverbAudioProcessor::SchroederReverbAudioProcessor() + : AudioProcessor (BusesProperties() + #if ! JucePlugin_IsMidiEffect + #if ! JucePlugin_IsSynth + .withInput ("Input", juce::AudioChannelSet::stereo(), true) + #endif + .withOutput ("Output", juce::AudioChannelSet::stereo(), true) + #endif + ) +{ +} + +SchroederReverbAudioProcessor::~SchroederReverbAudioProcessor() +{ +} + +//============================================================================== +const juce::String SchroederReverbAudioProcessor::getName() const +{ + return JucePlugin_Name; +} + +bool SchroederReverbAudioProcessor::acceptsMidi() const +{ + #if JucePlugin_WantsMidiInput + return true; + #else + return false; + #endif +} + +bool SchroederReverbAudioProcessor::producesMidi() const +{ + #if JucePlugin_ProducesMidiOutput + return true; + #else + return false; + #endif +} + +bool SchroederReverbAudioProcessor::isMidiEffect() const +{ + #if JucePlugin_IsMidiEffect + return true; + #else + return false; + #endif +} + +double SchroederReverbAudioProcessor::getTailLengthSeconds() const +{ + return 0.0; +} + +int SchroederReverbAudioProcessor::getNumPrograms() +{ + return 1; // NB: some hosts don't cope very well if you tell them there are 0 programs, + // so this should be at least 1, even if you're not really implementing programs. +} + +int SchroederReverbAudioProcessor::getCurrentProgram() +{ + return 0; +} + +void SchroederReverbAudioProcessor::setCurrentProgram (int index) +{ + juce::ignoreUnused (index); +} + +const juce::String SchroederReverbAudioProcessor::getProgramName (int index) +{ + juce::ignoreUnused (index); + return {}; +} + +void SchroederReverbAudioProcessor::changeProgramName (int index, const juce::String& newName) +{ + juce::ignoreUnused (index, newName); +} + +//============================================================================== +void SchroederReverbAudioProcessor::prepareToPlay (double sampleRate, int samplesPerBlock) +{ + // Use this method as the place to do any pre-playback + // initialisation that you need.. + juce::ignoreUnused (sampleRate, samplesPerBlock); +} + +void SchroederReverbAudioProcessor::releaseResources() +{ + // When playback stops, you can use this as an opportunity to free up any + // spare memory, etc. +} + +bool SchroederReverbAudioProcessor::isBusesLayoutSupported (const BusesLayout& layouts) const +{ + #if JucePlugin_IsMidiEffect + juce::ignoreUnused (layouts); + return true; + #else + // This is the place where you check if the layout is supported. + // In this template code we only support mono or stereo. + // Some plugin hosts, such as certain GarageBand versions, will only + // load plugins that support stereo bus layouts. + if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::mono() + && layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo()) + return false; + + // This checks if the input layout matches the output layout + #if ! JucePlugin_IsSynth + if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet()) + return false; + #endif + + return true; + #endif +} + +void SchroederReverbAudioProcessor::processBlock (juce::AudioBuffer& buffer, + juce::MidiBuffer& midiMessages) +{ + juce::ignoreUnused (midiMessages); + + juce::ScopedNoDenormals noDenormals; + auto totalNumInputChannels = getTotalNumInputChannels(); + auto totalNumOutputChannels = getTotalNumOutputChannels(); + + // In case we have more outputs than inputs, this code clears any output + // channels that didn't contain input data, (because these aren't + // guaranteed to be empty - they may contain garbage). + // This is here to avoid people getting screaming feedback + // when they first compile a plugin, but obviously you don't need to keep + // this code if your algorithm always overwrites all the output channels. + for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i) + buffer.clear (i, 0, buffer.getNumSamples()); + + // This is the place where you'd normally do the guts of your plugin's + // audio processing... + // Make sure to reset the state if your inner loop is processing + // the samples and the outer loop is handling the channels. + // Alternatively, you can process the samples with the channels + // interleaved by keeping the same state. + for (int channel = 0; channel < totalNumInputChannels; ++channel) + { + auto* channelData = buffer.getWritePointer (channel); + juce::ignoreUnused (channelData); + // ..do something to the data... + } +} + +//============================================================================== +bool SchroederReverbAudioProcessor::hasEditor() const +{ + return true; // (change this to false if you choose to not supply an editor) +} + +juce::AudioProcessorEditor* SchroederReverbAudioProcessor::createEditor() +{ + return new SchroederReverbAudioProcessorEditor (*this); +} + +//============================================================================== +void SchroederReverbAudioProcessor::getStateInformation (juce::MemoryBlock& destData) +{ + // You should use this method to store your parameters in the memory block. + // You could do that either as raw data, or use the XML or ValueTree classes + // as intermediaries to make it easy to save and load complex data. + juce::ignoreUnused (destData); +} + +void SchroederReverbAudioProcessor::setStateInformation (const void* data, int sizeInBytes) +{ + // You should use this method to restore your parameters from this memory block, + // whose contents will have been created by the getStateInformation() call. + juce::ignoreUnused (data, sizeInBytes); +} + +//============================================================================== +// This creates new instances of the plugin.. +juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() +{ + return new SchroederReverbAudioProcessor(); +} diff --git a/src/PluginProcessor.h b/src/PluginProcessor.h new file mode 100644 index 0000000..8fcb1e5 --- /dev/null +++ b/src/PluginProcessor.h @@ -0,0 +1,48 @@ +#pragma once + +#include + +//============================================================================== +class SchroederReverbAudioProcessor final : public juce::AudioProcessor +{ +public: + //============================================================================== + SchroederReverbAudioProcessor(); + ~SchroederReverbAudioProcessor() override; + + //============================================================================== + void prepareToPlay (double sampleRate, int samplesPerBlock) override; + void releaseResources() override; + + bool isBusesLayoutSupported (const BusesLayout& layouts) const override; + + void processBlock (juce::AudioBuffer&, juce::MidiBuffer&) override; + using AudioProcessor::processBlock; + + //============================================================================== + juce::AudioProcessorEditor* createEditor() override; + bool hasEditor() const override; + + //============================================================================== + const juce::String getName() const override; + + bool acceptsMidi() const override; + bool producesMidi() const override; + bool isMidiEffect() const override; + double getTailLengthSeconds() const override; + + //============================================================================== + int getNumPrograms() override; + int getCurrentProgram() override; + void setCurrentProgram (int index) override; + const juce::String getProgramName (int index) override; + void changeProgramName (int index, const juce::String& newName) override; + + //============================================================================== + void getStateInformation (juce::MemoryBlock& destData) override; + void setStateInformation (const void* data, int sizeInBytes) override; + +private: + //============================================================================== + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SchroederReverbAudioProcessor) +}; diff --git a/src/UI/PluginEditor.cpp b/src/UI/PluginEditor.cpp new file mode 100644 index 0000000..1ba07af --- /dev/null +++ b/src/UI/PluginEditor.cpp @@ -0,0 +1,33 @@ +#include "../PluginProcessor.h" +#include "PluginEditor.h" + +//============================================================================== +SchroederReverbAudioProcessorEditor::SchroederReverbAudioProcessorEditor (SchroederReverbAudioProcessor& p) + : AudioProcessorEditor (&p), processorRef (p) +{ + juce::ignoreUnused (processorRef); + // Make sure that before the constructor has finished, you've set the + // editor's size to whatever you need it to be. + setSize (400, 300); +} + +SchroederReverbAudioProcessorEditor::~SchroederReverbAudioProcessorEditor() +{ +} + +//============================================================================== +void SchroederReverbAudioProcessorEditor::paint (juce::Graphics& g) +{ + // (Our component is opaque, so we must completely fill the background with a solid colour) + g.fillAll (getLookAndFeel().findColour (juce::ResizableWindow::backgroundColourId)); + + g.setColour (juce::Colours::white); + g.setFont (15.0f); + g.drawFittedText ("Hello World!", getLocalBounds(), juce::Justification::centred, 1); +} + +void SchroederReverbAudioProcessorEditor::resized() +{ + // This is generally where you'll want to lay out the positions of any + // subcomponents in your editor.. +} diff --git a/src/UI/PluginEditor.h b/src/UI/PluginEditor.h new file mode 100644 index 0000000..1f30a89 --- /dev/null +++ b/src/UI/PluginEditor.h @@ -0,0 +1,22 @@ +#pragma once + +#include "../PluginProcessor.h" + +//============================================================================== +class SchroederReverbAudioProcessorEditor final : public juce::AudioProcessorEditor +{ +public: + explicit SchroederReverbAudioProcessorEditor (SchroederReverbAudioProcessor&); + ~SchroederReverbAudioProcessorEditor() override; + + //============================================================================== + void paint (juce::Graphics&) override; + void resized() override; + +private: + // This reference is provided as a quick way for your editor to + // access the processor object that created it. + SchroederReverbAudioProcessor& processorRef; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (SchroederReverbAudioProcessorEditor) +}; -- cgit v1.2.3