-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
b81c4ab
commit 7b763c0
Showing
8 changed files
with
354 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
project(gritwave-gritrack VERSION ${CMAKE_PROJECT_VERSION}) | ||
|
||
FetchContent_Declare(JUCE GIT_REPOSITORY "https://github.com/juce-framework/JUCE" GIT_TAG "develop" GIT_SHALLOW TRUE) | ||
FetchContent_MakeAvailable(JUCE) | ||
|
||
set_directory_properties(PROPERTIES JUCE_COMPANY_COPYRIGHT "Copyright 2024 gritwave. All rights reserved.") | ||
set_directory_properties(PROPERTIES JUCE_COMPANY_NAME "gritwave") | ||
set_directory_properties(PROPERTIES JUCE_VST3_COPY_DIR "${CMAKE_BINARY_DIR}/VST3") | ||
set_directory_properties(PROPERTIES JUCE_AU_COPY_DIR "${CMAKE_BINARY_DIR}/AU") | ||
|
||
juce_add_plugin(Gritrack | ||
PRODUCT_NAME "Gritrack" # The name of the final executable, which can differ from the target name | ||
BUNDLE_ID "com.gritwave.gritrack" # Should uniquely identify this target | ||
PLUGIN_CODE Grtr # A unique four-character plugin id with exactly one upper-case character | ||
PLUGIN_MANUFACTURER_CODE Grtw # A four-character manufacturer id with at least one upper-case character | ||
FORMATS AU VST3 Standalone # The formats to build. Other valid formats are: AAX Unity VST AU AUv3 | ||
HARDENED_RUNTIME_ENABLED TRUE # Enables macOS' hardened runtime for this target. Required for notarisation. | ||
COPY_PLUGIN_AFTER_BUILD TRUE # Should the plugin be installed to a default location after building? | ||
IS_SYNTH FALSE # Is this a synth or an effect? | ||
NEEDS_MIDI_INPUT FALSE # Does the plugin need midi input? | ||
NEEDS_MIDI_OUTPUT FALSE # Does the plugin need midi output? | ||
IS_MIDI_EFFECT FALSE # Is this plugin a MIDI effect? | ||
EDITOR_WANTS_KEYBOARD_FOCUS FALSE # Does the editor need keyboard focus? | ||
) | ||
|
||
set(Gritrack_Sources | ||
"src/PluginEditor.hpp" | ||
"src/PluginEditor.cpp" | ||
"src/PluginParameter.hpp" | ||
"src/PluginParameter.cpp" | ||
"src/PluginProcessor.hpp" | ||
"src/PluginProcessor.cpp" | ||
) | ||
|
||
target_sources(Gritrack PRIVATE ${Gritrack_Sources}) | ||
set_target_properties(Gritrack PROPERTIES UNITY_BUILD ON UNITY_BUILD_MODE GROUP) | ||
set_source_files_properties(Gritrack ${Gritrack_Sources} PROPERTIES UNITY_GROUP "src") | ||
|
||
target_compile_definitions(Gritrack | ||
PUBLIC | ||
JUCE_WEB_BROWSER=0 | ||
JUCE_USE_CURL=0 | ||
JUCE_VST3_CAN_REPLACE_VST2=0 | ||
JUCE_USE_MP3AUDIOFORMAT=0 | ||
JUCE_DISPLAY_SPLASH_SCREEN=0 | ||
JUCE_MODAL_LOOPS_PERMITTED=1 | ||
JUCE_REPORT_APP_USAGE=0 | ||
JUCE_DISABLE_JUCE_VERSION_PRINTING=1 | ||
) | ||
|
||
target_include_directories(Gritrack | ||
PUBLIC | ||
${PROJECT_SOURCE_DIR}/src | ||
) | ||
|
||
target_link_libraries(Gritrack | ||
PRIVATE | ||
juce::juce_audio_utils | ||
juce::juce_dsp | ||
|
||
PUBLIC | ||
gritwave::eurorack | ||
juce::juce_recommended_config_flags | ||
# juce::juce_recommended_lto_flags | ||
# juce::juce_recommended_warning_flags | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#include "PluginEditor.hpp" | ||
|
||
PluginEditor::PluginEditor(PluginProcessor& p) : AudioProcessorEditor(&p) | ||
{ | ||
_tooltipWindow->setMillisecondsBeforeTipAppears(750); | ||
setSize(600, 400); | ||
} | ||
|
||
PluginEditor::~PluginEditor() noexcept { setLookAndFeel(nullptr); } | ||
|
||
auto PluginEditor::paint(juce::Graphics& g) -> void | ||
{ | ||
// background | ||
g.fillAll(getLookAndFeel().findColour(juce::ResizableWindow::backgroundColourId)); | ||
} | ||
|
||
auto PluginEditor::resized() -> void {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
#pragma once | ||
|
||
#include "PluginProcessor.hpp" | ||
|
||
#include <juce_gui_extra/juce_gui_extra.h> | ||
|
||
struct PluginEditor final : juce::AudioProcessorEditor | ||
{ | ||
explicit PluginEditor(PluginProcessor& p); | ||
~PluginEditor() noexcept override; | ||
|
||
auto paint(juce::Graphics& g) -> void override; | ||
auto resized() -> void override; | ||
|
||
private: | ||
juce::SharedResourcePointer<juce::TooltipWindow> _tooltipWindow; | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
#include "PluginParameter.hpp" | ||
|
||
namespace gritrack { | ||
|
||
auto createParameters() -> juce::AudioProcessorValueTreeState::ParameterLayout | ||
{ | ||
auto const normalized = juce::NormalisableRange(0.0F, 1.0F); | ||
|
||
return { | ||
std::make_unique<juce::AudioParameterFloat>(juce::ParameterID{ParamID::cv1, 1}, "CV-1", normalized, 0.0F), | ||
std::make_unique<juce::AudioParameterFloat>(juce::ParameterID{ParamID::cv2, 1}, "CV-2", normalized, 0.0F), | ||
std::make_unique<juce::AudioParameterFloat>(juce::ParameterID{ParamID::cv3, 1}, "CV-3", normalized, 0.0F), | ||
std::make_unique<juce::AudioParameterFloat>(juce::ParameterID{ParamID::cv4, 1}, "CV-4", normalized, 0.0F), | ||
std::make_unique<juce::AudioParameterFloat>(juce::ParameterID{ParamID::cv5, 1}, "CV-5", normalized, 0.0F), | ||
std::make_unique<juce::AudioParameterFloat>(juce::ParameterID{ParamID::cv6, 1}, "CV-6", normalized, 0.0F), | ||
std::make_unique<juce::AudioParameterFloat>(juce::ParameterID{ParamID::cv7, 1}, "CV-7", normalized, 0.0F), | ||
std::make_unique<juce::AudioParameterFloat>(juce::ParameterID{ParamID::cv8, 1}, "CV-8", normalized, 0.0F), | ||
}; | ||
} | ||
|
||
} // namespace gritrack |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#pragma once | ||
|
||
#include <juce_audio_processors/juce_audio_processors.h> | ||
#include <juce_data_structures/juce_data_structures.h> | ||
|
||
namespace gritrack { | ||
|
||
struct ParamID | ||
{ | ||
static constexpr char const* cv1 = "cv1"; | ||
static constexpr char const* cv2 = "cv2"; | ||
static constexpr char const* cv3 = "cv3"; | ||
static constexpr char const* cv4 = "cv4"; | ||
static constexpr char const* cv5 = "cv5"; | ||
static constexpr char const* cv6 = "cv6"; | ||
static constexpr char const* cv7 = "cv7"; | ||
static constexpr char const* cv8 = "cv8"; | ||
}; | ||
|
||
auto createParameters() -> juce::AudioProcessorValueTreeState::ParameterLayout; | ||
|
||
} // namespace gritrack |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
|
||
#include "PluginProcessor.hpp" | ||
|
||
#include "PluginEditor.hpp" | ||
#include "PluginParameter.hpp" | ||
|
||
PluginProcessor::PluginProcessor() | ||
: AudioProcessor(BusesProperties() | ||
.withInput("Input", juce::AudioChannelSet::stereo(), true) | ||
.withOutput("Output", juce::AudioChannelSet::stereo(), true)) | ||
, _valueTree{*this, nullptr, juce::Identifier("Gritwave"), gritrack::createParameters()} | ||
, _cv1{*dynamic_cast<juce::AudioParameterFloat*>(_valueTree.getParameter(gritrack::ParamID::cv1))} | ||
, _cv2{*dynamic_cast<juce::AudioParameterFloat*>(_valueTree.getParameter(gritrack::ParamID::cv2))} | ||
, _cv3{*dynamic_cast<juce::AudioParameterFloat*>(_valueTree.getParameter(gritrack::ParamID::cv3))} | ||
, _cv4{*dynamic_cast<juce::AudioParameterFloat*>(_valueTree.getParameter(gritrack::ParamID::cv4))} | ||
, _cv5{*dynamic_cast<juce::AudioParameterFloat*>(_valueTree.getParameter(gritrack::ParamID::cv5))} | ||
, _cv6{*dynamic_cast<juce::AudioParameterFloat*>(_valueTree.getParameter(gritrack::ParamID::cv6))} | ||
, _cv7{*dynamic_cast<juce::AudioParameterFloat*>(_valueTree.getParameter(gritrack::ParamID::cv7))} | ||
, _cv8{*dynamic_cast<juce::AudioParameterFloat*>(_valueTree.getParameter(gritrack::ParamID::cv8))} | ||
{} | ||
|
||
PluginProcessor::~PluginProcessor() = default; | ||
|
||
auto PluginProcessor::getName() const -> juce::String const { return JucePlugin_Name; } | ||
|
||
auto PluginProcessor::acceptsMidi() const -> bool { return false; } | ||
|
||
auto PluginProcessor::producesMidi() const -> bool { return false; } | ||
|
||
auto PluginProcessor::isMidiEffect() const -> bool { return false; } | ||
|
||
auto PluginProcessor::getTailLengthSeconds() const -> double { return 0.0; } | ||
|
||
auto PluginProcessor::getNumPrograms() -> int { return 1; } | ||
|
||
auto PluginProcessor::getCurrentProgram() -> int { return 0; } | ||
|
||
auto PluginProcessor::setCurrentProgram(int index) -> void { juce::ignoreUnused(index); } | ||
|
||
auto PluginProcessor::getProgramName(int index) -> juce::String const | ||
{ | ||
juce::ignoreUnused(index); | ||
return {}; | ||
} | ||
|
||
auto PluginProcessor::changeProgramName(int index, juce::String const& newName) -> void | ||
{ | ||
juce::ignoreUnused(index, newName); | ||
} | ||
|
||
auto PluginProcessor::prepareToPlay(double sampleRate, int samplesPerBlock) -> void | ||
{ | ||
_hades = std::make_unique<grit::Hades>(); | ||
_hades->prepare(sampleRate, static_cast<std::size_t>(samplesPerBlock)); | ||
|
||
_buffer.resize(2U * static_cast<std::size_t>(samplesPerBlock)); | ||
} | ||
|
||
auto PluginProcessor::releaseResources() -> void {} | ||
|
||
auto PluginProcessor::isBusesLayoutSupported(BusesLayout const& layouts) const -> bool | ||
{ | ||
if (layouts.getMainOutputChannelSet() != juce::AudioChannelSet::stereo()) { | ||
return false; | ||
} | ||
|
||
if (layouts.getMainOutputChannelSet() != layouts.getMainInputChannelSet()) { | ||
return false; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
void PluginProcessor::processBlock(juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages) | ||
{ | ||
juce::ignoreUnused(midiMessages); | ||
juce::ScopedNoDenormals const noDenormals; | ||
|
||
for (auto i = getTotalNumInputChannels(); i < getTotalNumOutputChannels(); ++i) { | ||
buffer.clear(i, 0, buffer.getNumSamples()); | ||
} | ||
|
||
auto io = grit::StereoBlock<float>{_buffer.data(), static_cast<etl::size_t>(buffer.getNumSamples())}; | ||
for (auto i = 0; i < buffer.getNumSamples(); ++i) { | ||
io(0, i) = buffer.getSample(0, i); | ||
io(1, i) = buffer.getSample(1, i); | ||
} | ||
|
||
auto const controls = grit::Hades::ControlInput{ | ||
.textureKnob = _cv1, | ||
.morphKnob = _cv2, | ||
.ampKnob = _cv3, | ||
.compressorKnob = _cv4, | ||
.morphCV = _cv5, | ||
.sideChainCV = _cv6, | ||
.attackCV = _cv7, | ||
.releaseCV = _cv8, | ||
.gate1 = false, | ||
.gate2 = false, | ||
}; | ||
|
||
auto const cv = _hades->process(io, controls); | ||
juce::ignoreUnused(cv); | ||
|
||
for (auto i = 0; i < buffer.getNumSamples(); ++i) { | ||
buffer.setSample(0, i, io(0, i)); | ||
buffer.setSample(1, i, io(1, i)); | ||
} | ||
} | ||
|
||
auto PluginProcessor::parameterChanged(juce::String const& parameterID, float newValue) -> void | ||
{ | ||
juce::ignoreUnused(newValue, parameterID); | ||
} | ||
|
||
auto PluginProcessor::hasEditor() const -> bool { return true; } | ||
|
||
auto PluginProcessor::createEditor() -> juce::AudioProcessorEditor* | ||
{ | ||
return new juce::GenericAudioProcessorEditor(*this); | ||
} | ||
|
||
auto PluginProcessor::getStateInformation(juce::MemoryBlock& destData) -> void | ||
{ | ||
juce::MemoryOutputStream stream(destData, false); | ||
_valueTree.state.writeToStream(stream); | ||
} | ||
|
||
auto PluginProcessor::setStateInformation(void const* data, int sizeInBytes) -> void | ||
{ | ||
juce::ValueTree const tree = juce::ValueTree::readFromData(data, static_cast<size_t>(sizeInBytes)); | ||
jassert(tree.isValid()); | ||
if (tree.isValid()) { | ||
_valueTree.state = tree; | ||
} | ||
} | ||
|
||
auto PluginProcessor::getState() noexcept -> juce::AudioProcessorValueTreeState& { return _valueTree; } | ||
|
||
auto PluginProcessor::getState() const noexcept -> juce::AudioProcessorValueTreeState const& { return _valueTree; } | ||
|
||
// This creates new instances of the plugin.. | ||
auto JUCE_CALLTYPE createPluginFilter() -> juce::AudioProcessor* { return new PluginProcessor(); } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
#pragma once | ||
|
||
#include <grit/eurorack/hades.hpp> | ||
|
||
#include <juce_audio_processors/juce_audio_processors.h> | ||
#include <juce_dsp/juce_dsp.h> | ||
#include <juce_gui_extra/juce_gui_extra.h> | ||
|
||
struct PluginProcessor final | ||
: juce::AudioProcessor | ||
, juce::AudioProcessorValueTreeState::Listener | ||
{ | ||
PluginProcessor(); | ||
~PluginProcessor() override; | ||
|
||
auto getName() const -> juce::String const override; | ||
|
||
auto prepareToPlay(double sampleRate, int samplesPerBlock) -> void override; | ||
auto processBlock(juce::AudioBuffer<float>& buffer, juce::MidiBuffer& midiMessages) -> void override; | ||
using juce::AudioProcessor::processBlock; | ||
auto releaseResources() -> void override; | ||
|
||
auto isBusesLayoutSupported(BusesLayout const& layouts) const -> bool override; | ||
|
||
auto createEditor() -> juce::AudioProcessorEditor* override; | ||
auto hasEditor() const -> bool override; | ||
|
||
auto acceptsMidi() const -> bool override; | ||
auto producesMidi() const -> bool override; | ||
auto isMidiEffect() const -> bool override; | ||
auto getTailLengthSeconds() const -> double override; | ||
|
||
auto getNumPrograms() -> int override; | ||
auto getCurrentProgram() -> int override; | ||
void setCurrentProgram(int index) override; | ||
auto getProgramName(int index) -> juce::String const override; | ||
void changeProgramName(int index, juce::String const& newName) override; | ||
|
||
auto getStateInformation(juce::MemoryBlock& destData) -> void override; | ||
auto setStateInformation(void const* data, int sizeInBytes) -> void override; | ||
|
||
auto parameterChanged(juce::String const& parameterID, float newValue) -> void override; | ||
|
||
auto getState() noexcept -> juce::AudioProcessorValueTreeState&; | ||
auto getState() const noexcept -> juce::AudioProcessorValueTreeState const&; | ||
|
||
private: | ||
juce::UndoManager _undoManager{}; | ||
juce::AudioProcessorValueTreeState _valueTree; | ||
|
||
std::vector<float> _buffer{}; | ||
std::unique_ptr<grit::Hades> _hades{nullptr}; | ||
|
||
juce::AudioParameterFloat& _cv1; | ||
juce::AudioParameterFloat& _cv2; | ||
juce::AudioParameterFloat& _cv3; | ||
juce::AudioParameterFloat& _cv4; | ||
juce::AudioParameterFloat& _cv5; | ||
juce::AudioParameterFloat& _cv6; | ||
juce::AudioParameterFloat& _cv7; | ||
juce::AudioParameterFloat& _cv8; | ||
}; |