Add drag to reorder fx

This commit is contained in:
Roland Rabien 2023-10-08 14:31:14 -07:00
commit 8a793ba5b4
7 changed files with 179 additions and 55 deletions

@ -1 +1 @@
Subproject commit 33d8c95b10958b79c2a018ba4cb73e99c2e2b528 Subproject commit f79efd9b83a7a546df4ba8c437cc7d487144aa89

View file

@ -104,7 +104,9 @@
{ "id": "matrix", "x": 0, "y": 23, "r": "parW()", "b": "parH()" } { "id": "matrix", "x": 0, "y": 23, "r": "parW()", "b": "parH()" }
] ]
}, },
{ "id": "gate", "x": "0", "y": "prevB()+1", "w": 290, "h": 137, "children": { "id": "fx", "x": 0, "y": "prevB()+1", "w": "parW() - 169", "h": 137, "children":
[
{ "id": "gate", "x": "0", "y": 0, "w": 290, "h": 137, "children":
[ [
{ "id": "Beat", "x": 61, "y": 30, "w": 42, "h": 57 }, { "id": "Beat", "x": 61, "y": 30, "w": 42, "h": 57 },
{ "id": "Length", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, { "id": "Length", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 },
@ -144,7 +146,10 @@
{ "id": "Damping", "x": 0, "y": "prevB()", "w": 42, "h": 57 }, { "id": "Damping", "x": 0, "y": "prevB()", "w": 42, "h": 57 },
{ "id": "Predelay", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, { "id": "Predelay", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 },
{ "id": "Mix", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 } { "id": "Mix", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }
] }, ]
}
]
},
{ "id": "global", "x": "prevR()+1", "y": "prevY()", "w": 168, "h": 137, "children": { "id": "global", "x": "prevR()+1", "y": "prevY()", "w": 168, "h": 137, "children":
[ [
{ "id": "Mono", "x": 0, "y": 23, "w": 42, "h": 57 }, { "id": "Mono", "x": 0, "y": 23, "w": 42, "h": 57 },
@ -154,6 +159,7 @@
{ "id": "PB Range", "x": 0, "y": "prevB()", "w": 42, "h": 57 }, { "id": "PB Range", "x": 0, "y": "prevB()", "w": 42, "h": 57 },
{ "id": "Voices", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, { "id": "Voices", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 },
{ "id": "Level", "x": "prevR() + 42", "y": "prevY()", "w": 42, "h": 57 } { "id": "Level", "x": "prevR() + 42", "y": "prevY()", "w": 42, "h": 57 }
] } ]
}
] ]
} }

View file

@ -1,7 +1,7 @@
#include "Editor.h" #include "Editor.h"
Editor::Editor (WavetableAudioProcessor& proc_) Editor::Editor (WavetableAudioProcessor& proc_)
: proc ( proc_ ) : proc (proc_)
{ {
for (auto& o : oscillators) addAndMakeVisible (o); for (auto& o : oscillators) addAndMakeVisible (o);
for (auto& l : lfos) addAndMakeVisible (l); for (auto& l : lfos) addAndMakeVisible (l);
@ -15,13 +15,78 @@ Editor::Editor (WavetableAudioProcessor& proc_)
addAndMakeVisible (mod); addAndMakeVisible (mod);
addAndMakeVisible (mtx); addAndMakeVisible (mtx);
addAndMakeVisible (global); addAndMakeVisible (global);
addAndMakeVisible (gate);
addAndMakeVisible (chorus); fx.addAndMakeVisible (gate);
addAndMakeVisible (distort); fx.addAndMakeVisible (chorus);
addAndMakeVisible (delay); fx.addAndMakeVisible (distort);
addAndMakeVisible (reverb); fx.addAndMakeVisible (delay);
fx.addAndMakeVisible (reverb);
fx.onDragStart = [] (const juce::MouseEvent& e)
{
if (dynamic_cast<gin::ParamHeader*> (e.originalComponent))
return true;
return false;
};
fx.onOrderChanged = [this]
{
proc.fxParams.fx1->setUserValue (fx.getChildComponent(0)->getProperties()["fxId"]);
proc.fxParams.fx2->setUserValue (fx.getChildComponent(1)->getProperties()["fxId"]);
proc.fxParams.fx3->setUserValue (fx.getChildComponent(2)->getProperties()["fxId"]);
proc.fxParams.fx4->setUserValue (fx.getChildComponent(3)->getProperties()["fxId"]);
proc.fxParams.fx5->setUserValue (fx.getChildComponent(4)->getProperties()["fxId"]);
handleAsyncUpdate();
};
proc.fxParams.fx1->addListener (this);
proc.fxParams.fx2->addListener (this);
proc.fxParams.fx3->addListener (this);
proc.fxParams.fx4->addListener (this);
proc.fxParams.fx5->addListener (this);
addAndMakeVisible (fx);
setupCallbacks(); setupCallbacks();
handleAsyncUpdate();
}
Editor::~Editor()
{
proc.fxParams.fx1->removeListener (this);
proc.fxParams.fx2->removeListener (this);
proc.fxParams.fx3->removeListener (this);
proc.fxParams.fx4->removeListener (this);
proc.fxParams.fx5->removeListener (this);
}
void Editor::handleAsyncUpdate()
{
if (fx.isDragInProgress())
return;
fx.removeAllChildren();
auto getComp = [this] (int fxId) -> juce::Component*
{
if (fxId == fxGate) return &gate;
if (fxId == fxChorus) return &chorus;
if (fxId == fxDistort) return &distort;
if (fxId == fxDelay) return &delay;
if (fxId == fxReverb) return &reverb;
jassertfalse;
return nullptr;
};
fx.addAndMakeVisible (getComp (proc.fxParams.fx1->getUserValueInt()));
fx.addAndMakeVisible (getComp (proc.fxParams.fx2->getUserValueInt()));
fx.addAndMakeVisible (getComp (proc.fxParams.fx3->getUserValueInt()));
fx.addAndMakeVisible (getComp (proc.fxParams.fx4->getUserValueInt()));
fx.addAndMakeVisible (getComp (proc.fxParams.fx5->getUserValueInt()));
if (fx.getWidth() > 0)
fx.resized();
} }
void Editor::setupCallbacks() void Editor::setupCallbacks()

View file

@ -5,15 +5,21 @@
#include "Panels.h" #include "Panels.h"
//============================================================================== //==============================================================================
class Editor : public juce::Component class Editor : public juce::Component,
private gin::Parameter::ParameterListener,
private juce::AsyncUpdater
{ {
public: public:
Editor (WavetableAudioProcessor& proc_); Editor (WavetableAudioProcessor& proc_);
~Editor() override;
void setupCallbacks(); void setupCallbacks();
void resized() override; void resized() override;
private: private:
void valueUpdated (gin::Parameter*) override { triggerAsyncUpdate(); }
void handleAsyncUpdate() override;
WavetableAudioProcessor& proc; WavetableAudioProcessor& proc;
OscillatorBox oscillators[Cfg::numOSCs] { { "oscillator 1", proc, 0 }, { "oscillator 2", proc, 1 } }; OscillatorBox oscillators[Cfg::numOSCs] { { "oscillator 1", proc, 0 }, { "oscillator 2", proc, 1 } };
@ -36,5 +42,7 @@ private:
DelayBox delay { proc }; DelayBox delay { proc };
ReverbBox reverb { proc }; ReverbBox reverb { proc };
gin::ComponentGrid fx { "fx" };
gin::Layout layout { *this }; gin::Layout layout { *this };
}; };

View file

@ -635,6 +635,7 @@ public:
: gin::ParamBox ("Gate"), proc (proc_) : gin::ParamBox ("Gate"), proc (proc_)
{ {
setName ("gate"); setName ("gate");
getProperties().set ("fxId", fxGate);
addEnable (proc.gateParams.enable); addEnable (proc.gateParams.enable);
@ -659,6 +660,7 @@ public:
: gin::ParamBox ("Chorus"), proc (proc_) : gin::ParamBox ("Chorus"), proc (proc_)
{ {
setName ("chorus"); setName ("chorus");
getProperties().set ("fxId", fxChorus);
addEnable (proc.chorusParams.enable); addEnable (proc.chorusParams.enable);
@ -681,6 +683,7 @@ public:
: gin::ParamBox ("Distort"), proc (proc_) : gin::ParamBox ("Distort"), proc (proc_)
{ {
setName ("distort"); setName ("distort");
getProperties().set ("fxId", fxDistort);
addEnable (proc.distortionParams.enable); addEnable (proc.distortionParams.enable);
@ -698,6 +701,7 @@ public:
: gin::ParamBox ("Delay"), proc (proc_) : gin::ParamBox ("Delay"), proc (proc_)
{ {
setName ("delay"); setName ("delay");
getProperties().set ("fxId", fxDelay);
addEnable (proc.delayParams.enable); addEnable (proc.delayParams.enable);
@ -735,6 +739,7 @@ public:
: gin::ParamBox ("Reverb"), proc (proc_) : gin::ParamBox ("Reverb"), proc (proc_)
{ {
setName ("reverb"); setName ("reverb");
getProperties().set ("fxId", fxReverb);
addEnable (proc.reverbParams.enable); addEnable (proc.reverbParams.enable);

View file

@ -362,6 +362,16 @@ void WavetableAudioProcessor::ReverbParams::setup (WavetableAudioProcessor& p)
mix = p.addExtParam ("rvbMix", "Mix", "", "", {0.0f, 1.0f, 0.0f, 1.0f}, 0.0f, 0.0f); mix = p.addExtParam ("rvbMix", "Mix", "", "", {0.0f, 1.0f, 0.0f, 1.0f}, 0.0f, 0.0f);
} }
//==============================================================================
void WavetableAudioProcessor::FXParams::setup (WavetableAudioProcessor& p)
{
fx1 = p.addIntParam ("fxOrder1", "FX1", "", "", { 0.0, 4.0, 1.0, 1.0 }, fxGate, 0.0f);
fx2 = p.addIntParam ("fxOrder2", "FX2", "", "", { 0.0, 4.0, 1.0, 1.0 }, fxChorus, 0.0f);
fx3 = p.addIntParam ("fxOrder3", "FX3", "", "", { 0.0, 4.0, 1.0, 1.0 }, fxDistort, 0.0f);
fx4 = p.addIntParam ("fxOrder4", "FX4", "", "", { 0.0, 4.0, 1.0, 1.0 }, fxDelay, 0.0f);
fx5 = p.addIntParam ("fxOrder5", "FX5", "", "", { 0.0, 4.0, 1.0, 1.0 }, fxReverb, 0.0f);
}
#if 0 #if 0
void convertWavetables() void convertWavetables()
{ {
@ -498,6 +508,7 @@ WavetableAudioProcessor::WavetableAudioProcessor()
distortionParams.setup (*this); distortionParams.setup (*this);
delayParams.setup (*this); delayParams.setup (*this);
reverbParams.setup (*this); reverbParams.setup (*this);
fxParams.setup (*this);
for (int i = 0; i < 50; i++) for (int i = 0; i < 50; i++)
{ {
@ -861,25 +872,25 @@ gin::WTOscillator::Params WavetableAudioProcessor::getLiveWTParams (int osc)
return p; return p;
} }
void WavetableAudioProcessor::applyEffects (juce::AudioSampleBuffer& buffer) void WavetableAudioProcessor::applyEffect (juce::AudioSampleBuffer& buffer, int fxId)
{ {
// Apply gate // Apply gate
if (gateParams.enable->isOn()) if (fxId == fxGate && gateParams.enable->isOn())
gate.process (buffer, noteOnIndex, noteOffIndex); gate.process (buffer, noteOnIndex, noteOffIndex);
// Apply Chorus // Apply Chorus
if (chorusParams.enable->isOn()) if (fxId == fxChorus && chorusParams.enable->isOn())
chorus.process (buffer); chorus.process (buffer);
// Apply Distortion // Apply Distortion
if (distortionParams.enable->isOn()) if (fxId == fxDistort && distortionParams.enable->isOn())
{ {
auto clip = 1.0f / (2.0f * distortionVal); auto clip = 1.0f / (2.0f * distortionVal);
gin::Distortion::processBlock (buffer, distortionVal, -clip, clip); gin::Distortion::processBlock (buffer, distortionVal, -clip, clip);
} }
// Apply Delay // Apply Delay
if (delayParams.enable->isOn()) if (fxId == fxDelay && delayParams.enable->isOn())
{ {
if (delayParams.sync->isOn()) if (delayParams.sync->isOn())
stereoDelay.process (buffer); stereoDelay.process (buffer);
@ -888,8 +899,17 @@ void WavetableAudioProcessor::applyEffects (juce::AudioSampleBuffer& buffer)
} }
// Apply Reverb // Apply Reverb
if (reverbParams.enable->isOn()) if (fxId == fxReverb && reverbParams.enable->isOn())
reverb.process (buffer.getWritePointer (0), buffer.getWritePointer (1), buffer.getNumSamples ()); reverb.process (buffer.getWritePointer (0), buffer.getWritePointer (1), buffer.getNumSamples ());
}
void WavetableAudioProcessor::applyEffects (juce::AudioSampleBuffer& buffer)
{
applyEffect (buffer, fxParams.fx1->getUserValueInt());
applyEffect (buffer, fxParams.fx2->getUserValueInt());
applyEffect (buffer, fxParams.fx3->getUserValueInt());
applyEffect (buffer, fxParams.fx4->getUserValueInt());
applyEffect (buffer, fxParams.fx5->getUserValueInt());
// Output gain // Output gain
outputGain.process (buffer); outputGain.process (buffer);

View file

@ -4,6 +4,12 @@
#include "WavetableVoice.h" #include "WavetableVoice.h"
constexpr auto fxGate = 0;
constexpr auto fxChorus = 1;
constexpr auto fxDistort = 2;
constexpr auto fxDelay = 3;
constexpr auto fxReverb = 4;
//============================================================================== //==============================================================================
class WavetableAudioProcessor : public gin::Processor, class WavetableAudioProcessor : public gin::Processor,
public gin::Synthesiser public gin::Synthesiser
@ -45,6 +51,8 @@ public:
bool loadUserWavetable (int osc, const juce::File& f, int sz); bool loadUserWavetable (int osc, const juce::File& f, int sz);
void applyEffects (juce::AudioSampleBuffer& buffer); void applyEffects (juce::AudioSampleBuffer& buffer);
void applyEffect (juce::AudioSampleBuffer& buffer, int fxId);
bool loadWaveTable (juce::OwnedArray<gin::BandLimitedLookupTable>& table, double sr, const juce::MemoryBlock& wav, const juce::String& format, int size); bool loadWaveTable (juce::OwnedArray<gin::BandLimitedLookupTable>& table, double sr, const juce::MemoryBlock& wav, const juce::String& format, int size);
// Voice Params // Voice Params
@ -220,6 +228,17 @@ public:
JUCE_DECLARE_NON_COPYABLE (ReverbParams) JUCE_DECLARE_NON_COPYABLE (ReverbParams)
}; };
struct FXParams
{
FXParams() = default;
gin::Parameter::Ptr fx1, fx2, fx3, fx4, fx5;
void setup (WavetableAudioProcessor& p);
JUCE_DECLARE_NON_COPYABLE (FXParams)
};
//============================================================================== //==============================================================================
gin::ModSrcId modSrcPressure, modSrcTimbre, modSrcPitchbend, modScrPitchBend, gin::ModSrcId modSrcPressure, modSrcTimbre, modSrcPitchbend, modScrPitchBend,
modSrcFilter, modSrcNote, modSrcVelocity, modSrcStep, modSrcMonoStep; modSrcFilter, modSrcNote, modSrcVelocity, modSrcStep, modSrcMonoStep;
@ -235,6 +254,7 @@ public:
EnvParams envParams[Cfg::numENVs]; EnvParams envParams[Cfg::numENVs];
LFOParams lfoParams[Cfg::numLFOs]; LFOParams lfoParams[Cfg::numLFOs];
StepLFOParams stepLfoParams; StepLFOParams stepLfoParams;
FXParams fxParams;
ADSRParams adsrParams; ADSRParams adsrParams;