Skip to content

Commit

Permalink
Add PS1-Reverb plugin files and update include paths
Browse files Browse the repository at this point in the history
  • Loading branch information
Augnos committed Jan 22, 2024
1 parent cfb3718 commit 4139b50
Show file tree
Hide file tree
Showing 13 changed files with 152 additions and 50 deletions.
26 changes: 21 additions & 5 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
cmake_minimum_required(VERSION 3.22)

# Sets a few variables, like PROJECT_NAME
project(WolfSoundAudioPluginTemplate)
project(PS1-Reverb)

# Always use the newest C++ standard on green-field projects if possible.
set(CMAKE_CXX_STANDARD 23)
Expand All @@ -22,8 +22,8 @@ include(cmake/cpm.cmake)
# This commands downloads AND configures JUCE. It sets up some variables, like JUCE_SOURCE_DIR.
CPMAddPackage(
NAME JUCE
GIT_TAG 7.0.5
VERSION 7.0.5
GIT_TAG 7.0.9
VERSION 7.0.9
GITHUB_REPOSITORY juce-framework/JUCE
SOURCE_DIR ${LIB_DIR}/juce
)
Expand All @@ -32,8 +32,8 @@ CPMAddPackage(
CPMAddPackage(
NAME GOOGLETEST
GITHUB_REPOSITORY google/googletest
GIT_TAG v1.13.0
VERSION 1.13.0
GIT_TAG v1.14.0
VERSION 1.14.0
SOURCE_DIR ${LIB_DIR}/googletest
OPTIONS
"INSTALL_GTEST OFF"
Expand All @@ -56,3 +56,19 @@ add_subdirectory(plugin)

# Adds all the targets configured in the "test" folder.
add_subdirectory(test)


# IR files configuration
set(IR_DIR "${CMAKE_CURRENT_SOURCE_DIR}/source/IR")
set(IR_FILES
"${IR_DIR}/IRChurch.aiff"
"${IR_DIR}/IRDome.aiff"
"${IR_DIR}/IRHall.aiff"
"${IR_DIR}/IRStudio.aiff"
)

# Copy IR files to build directory
foreach(IR_FILE ${IR_FILES})
get_filename_component(IR_FILE_NAME ${IR_FILE} NAME)
configure_file(${IR_FILE} ${CMAKE_BINARY_DIR}/IR/${IR_FILE_NAME} COPYONLY)
endforeach()
37 changes: 28 additions & 9 deletions plugin/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,27 @@ project(AudioPlugin VERSION 0.1.0)

# Adding a directory with the library/application name as a subfolder of the
# include folder is a good practice. It helps avoid name clashes later on.
set(INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/YourPluginName")
set(INCLUDE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include/PS1-Reverb")

# IR files configuration
set(IR_DIR "${CMAKE_CURRENT_SOURCE_DIR}/source/IR")
set(IR_FILES
"${IR_DIR}/IRChurch.aiff"
"${IR_DIR}/IRDome.aiff"
"${IR_DIR}/IRHall.aiff"
"${IR_DIR}/IRStudio.aiff"
)

# Adds a plugin target (that's basically what the Projucer does).
juce_add_plugin(${PROJECT_NAME}
COMPANY_NAME MyCompany # change this
IS_SYNTH FALSE # may change this
NEEDS_MIDI_INPUT FALSE # may change this
NEEDS_MIDI_OUTPUT FALSE # may change this
PLUGIN_MANUFACTURER_CODE MCMP # change this
PLUGIN_CODE EXPL # change this
FORMATS VST3 # may change this
PRODUCT_NAME "YourPluginName" # change this
COMPANY_NAME AugnosMedia
IS_SYNTH FALSE
NEEDS_MIDI_INPUT FALSE
NEEDS_MIDI_OUTPUT FALSE
PLUGIN_MANUFACTURER_CODE AUGN
PLUGIN_CODE PS1R
FORMATS VST3 # Add AAX and AU later
PRODUCT_NAME "PS1 Reverb"
)

# Sets the source files of the plugin project.
Expand All @@ -26,19 +35,22 @@ target_sources(${PROJECT_NAME}
source/PluginProcessor.cpp
${INCLUDE_DIR}/PluginEditor.h
${INCLUDE_DIR}/PluginProcessor.h
${IR_FILES} # Add the IR files to the project
)

# Sets the include directories of the plugin project.
target_include_directories(${PROJECT_NAME}
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/include
${IR_DIR} # Include the IR Directory
)

# Links to all necessary dependencies. The present ones are recommended by JUCE.
# If you use one of the additional modules, like the DSP module, you need to specify it here.
target_link_libraries(${PROJECT_NAME}
PRIVATE
juce::juce_audio_utils
juce::juce_dsp # Add the JUCE DSP module for convolution and other DSP tasks
PUBLIC
juce::juce_recommended_config_flags
juce::juce_recommended_lto_flags
Expand All @@ -51,6 +63,7 @@ target_compile_definitions(${PROJECT_NAME}
JUCE_WEB_BROWSER=0
JUCE_USE_CURL=0
JUCE_VST3_CAN_REPLACE_VST2=0
JucePlugin_Name="${PROJECT_NAME}"
)

# Silences some deprecation warnings that (hopefully) will be fixed in a future release of JUCE.
Expand All @@ -62,3 +75,9 @@ endif()

# In Visual Studio this command provides a nice grouping of source files in "filters".
source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR}/..)

# Copy IR files to build directory
foreach(IR_FILE ${IR_FILES})
get_filename_component(IR_FILE_NAME ${IR_FILE} NAME)
configure_file(${IR_FILE} ${CMAKE_BINARY_DIR}/IR/${IR_FILE_NAME} COPYONLY)
endforeach()
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ namespace audio_plugin {

class AudioPluginAudioProcessorEditor : public juce::AudioProcessorEditor {
public:
explicit AudioPluginAudioProcessorEditor(AudioPluginAudioProcessor &);
explicit AudioPluginAudioProcessorEditor(AudioPluginAudioProcessor&);
~AudioPluginAudioProcessorEditor() override;

void paint(juce::Graphics &) 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.
AudioPluginAudioProcessor &processorRef;
AudioPluginAudioProcessor& processorRef;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AudioPluginAudioProcessorEditor)
};
} // namespace audio_plugin
} // namespace audio_plugin
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <juce_audio_processors/juce_audio_processors.h>
#include <juce_dsp/juce_dsp.h>

namespace audio_plugin {
class AudioPluginAudioProcessor : public juce::AudioProcessor {
Expand All @@ -11,12 +12,12 @@ class AudioPluginAudioProcessor : public juce::AudioProcessor {
void prepareToPlay(double sampleRate, int samplesPerBlock) override;
void releaseResources() override;

bool isBusesLayoutSupported(const BusesLayout &layouts) const override;
bool isBusesLayoutSupported(const BusesLayout& layouts) const override;

void processBlock(juce::AudioBuffer<float> &, juce::MidiBuffer &) override;
void processBlock(juce::AudioBuffer<float>&, juce::MidiBuffer&) override;
using AudioProcessor::processBlock;

juce::AudioProcessorEditor *createEditor() override;
juce::AudioProcessorEditor* createEditor() override;
bool hasEditor() const override;

const juce::String getName() const override;
Expand All @@ -30,12 +31,19 @@ class AudioPluginAudioProcessor : public juce::AudioProcessor {
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 changeProgramName(int index, const juce::String& newName) override;

void getStateInformation(juce::MemoryBlock &destData) override;
void setStateInformation(const void *data, int sizeInBytes) override;
void getStateInformation(juce::MemoryBlock& destData) override;
void setStateInformation(const void* data, int sizeInBytes) override;

void loadImpulseResponse(const juce::String& irFile);

private:
juce::dsp::Convolution convolution;

// Paths to the IR files relative to the binary location
juce::StringArray impulseResponsePaths;

JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AudioPluginAudioProcessor)
};
} // namespace audio_plugin
} // namespace audio_plugin
Binary file added plugin/source/IR/IRChurch.aiff
Binary file not shown.
Binary file added plugin/source/IR/IRDome.aiff
Binary file not shown.
Binary file added plugin/source/IR/IRHall.aiff
Binary file not shown.
Binary file added plugin/source/IR/IRStudio.aiff
Binary file not shown.
Empty file added plugin/source/IRLoader.cpp
Empty file.
10 changes: 5 additions & 5 deletions plugin/source/PluginEditor.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#include "YourPluginName/PluginEditor.h"
#include "YourPluginName/PluginProcessor.h"
#include "PS1-Reverb/PluginEditor.h"
#include "PS1-Reverb/PluginProcessor.h"

namespace audio_plugin {
AudioPluginAudioProcessorEditor::AudioPluginAudioProcessorEditor(
AudioPluginAudioProcessor &p)
AudioPluginAudioProcessor& p)
: AudioProcessorEditor(&p), processorRef(p) {
juce::ignoreUnused(processorRef);
// Make sure that before the constructor has finished, you've set the
Expand All @@ -13,7 +13,7 @@ AudioPluginAudioProcessorEditor::AudioPluginAudioProcessorEditor(

AudioPluginAudioProcessorEditor::~AudioPluginAudioProcessorEditor() {}

void AudioPluginAudioProcessorEditor::paint(juce::Graphics &g) {
void AudioPluginAudioProcessorEditor::paint(juce::Graphics& g) {
// (Our component is opaque, so we must completely fill the background with a
// solid colour)
g.fillAll(
Expand All @@ -29,4 +29,4 @@ void AudioPluginAudioProcessorEditor::resized() {
// This is generally where you'll want to lay out the positions of any
// subcomponents in your editor..
}
} // namespace audio_plugin
} // namespace audio_plugin
95 changes: 77 additions & 18 deletions plugin/source/PluginProcessor.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#include "YourPluginName/PluginProcessor.h"
#include "YourPluginName/PluginEditor.h"
#include "PS1-Reverb/PluginProcessor.h"
#include "PS1-Reverb/PluginEditor.h"

namespace audio_plugin {
AudioPluginAudioProcessor::AudioPluginAudioProcessor()
Expand All @@ -12,6 +12,61 @@ AudioPluginAudioProcessor::AudioPluginAudioProcessor()
.withOutput("Output", juce::AudioChannelSet::stereo(), true)
#endif
) {

// Initialize the impulse response paths
impulseResponsePaths = {"IR/IRStudio.aiff", "IR/IRChurch.aiff",
"IR/IRDome.aiff", "IR/IRHall.aiff"};

// Load the first impulse response by default (this should be handled more
// dynamically)
loadImpulseResponse(impulseResponsePaths[0]);
}

void AudioPluginAudioProcessor::prepareToPlay(double sampleRate,
int samplesPerBlock) {
// Prepare the convolution engine
juce::dsp::ProcessSpec spec;
spec.sampleRate = sampleRate;
spec.maximumBlockSize = samplesPerBlock;
spec.numChannels = getTotalNumOutputChannels();

convolution.prepare(spec);
}

void AudioPluginAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer,
juce::MidiBuffer& midiMessages) {
juce::ScopedNoDenormals noDenormals;
auto totalNumInputChannels = getTotalNumInputChannels();
auto totalNumOutputChannels = getTotalNumOutputChannels();

// ... (clearing buffers, etc.)

// Apply the convolution reverb to each sample
juce::dsp::AudioBlock<float> block(buffer);
convolution.process(juce::dsp::ProcessContextReplacing<float>(block));

// Process the audio block with the convolution engine
juce::dsp::AudioBlock<float> block(buffer);
juce::dsp::ProcessContextReplacing<float> context(block);
convolution.process(context);
}

void AudioPluginAudioProcessor::loadImpulseResponse(
const juce::String& irFile) {
// Assuming the file path is relative to the executable's location
auto file = juce::File::getSpecialLocation(juce::File::currentExecutableFile)
.getSiblingFile(irFile);

// Check if the file exists at the specified path
if (!file.existsAsFile()) {
jassertfalse; // File not found, you may want to handle this more
// gracefully
return;
}

// Load the impulse response file into the convolution engine
convolution.loadImpulseResponse(file, juce::dsp::Convolution::Stereo::yes,
juce::dsp::Convolution::Trim::no, 0);
}

AudioPluginAudioProcessor::~AudioPluginAudioProcessor() {}
Expand Down Expand Up @@ -44,15 +99,19 @@ bool AudioPluginAudioProcessor::isMidiEffect() const {
#endif
}

double AudioPluginAudioProcessor::getTailLengthSeconds() const { return 0.0; }
double AudioPluginAudioProcessor::getTailLengthSeconds() const {
return 0.0;
}

int AudioPluginAudioProcessor::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.
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 AudioPluginAudioProcessor::getCurrentProgram() { return 0; }
int AudioPluginAudioProcessor::getCurrentProgram() {
return 0;
}

void AudioPluginAudioProcessor::setCurrentProgram(int index) {
juce::ignoreUnused(index);
Expand All @@ -64,7 +123,7 @@ const juce::String AudioPluginAudioProcessor::getProgramName(int index) {
}

void AudioPluginAudioProcessor::changeProgramName(int index,
const juce::String &newName) {
const juce::String& newName) {
juce::ignoreUnused(index, newName);
}

Expand All @@ -81,7 +140,7 @@ void AudioPluginAudioProcessor::releaseResources() {
}

bool AudioPluginAudioProcessor::isBusesLayoutSupported(
const BusesLayout &layouts) const {
const BusesLayout& layouts) const {
#if JucePlugin_IsMidiEffect
juce::ignoreUnused(layouts);
return true;
Expand All @@ -104,8 +163,8 @@ bool AudioPluginAudioProcessor::isBusesLayoutSupported(
#endif
}

void AudioPluginAudioProcessor::processBlock(juce::AudioBuffer<float> &buffer,
juce::MidiBuffer &midiMessages) {
void AudioPluginAudioProcessor::processBlock(juce::AudioBuffer<float>& buffer,
juce::MidiBuffer& midiMessages) {
juce::ignoreUnused(midiMessages);

juce::ScopedNoDenormals noDenormals;
Expand All @@ -128,39 +187,39 @@ void AudioPluginAudioProcessor::processBlock(juce::AudioBuffer<float> &buffer,
// 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);
auto* channelData = buffer.getWritePointer(channel);
juce::ignoreUnused(channelData);
// ..do something to the data...
}
}

bool AudioPluginAudioProcessor::hasEditor() const {
return true; // (change this to false if you choose to not supply an editor)
return true; // (change this to false if you choose to not supply an editor)
}

juce::AudioProcessorEditor *AudioPluginAudioProcessor::createEditor() {
juce::AudioProcessorEditor* AudioPluginAudioProcessor::createEditor() {
return new AudioPluginAudioProcessorEditor(*this);
}

void AudioPluginAudioProcessor::getStateInformation(
juce::MemoryBlock &destData) {
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 AudioPluginAudioProcessor::setStateInformation(const void *data,
void AudioPluginAudioProcessor::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);
}
} // namespace audio_plugin
} // namespace audio_plugin

// This creates new instances of the plugin.
// This function definition must be in the global namespace.
juce::AudioProcessor *JUCE_CALLTYPE createPluginFilter() {
juce::AudioProcessor* JUCE_CALLTYPE createPluginFilter() {
return new audio_plugin::AudioPluginAudioProcessor();
}
Loading

0 comments on commit 4139b50

Please sign in to comment.