From a69ef9e54cb1feeeb59c2f209e584c0ee60b53a7 Mon Sep 17 00:00:00 2001 From: Roland Rabien Date: Fri, 25 Aug 2023 13:26:25 -0700 Subject: [PATCH] Allow selecting wavetable --- modules/gin | 2 +- plugin/Source/Editor.h | 2 +- plugin/Source/Panels.h | 53 +++++++++++++++++++++- plugin/Source/PluginProcessor.cpp | 73 ++++++++++++++++++++++++++++--- plugin/Source/PluginProcessor.h | 7 ++- 5 files changed, 126 insertions(+), 11 deletions(-) diff --git a/modules/gin b/modules/gin index 3e758af..96f0293 160000 --- a/modules/gin +++ b/modules/gin @@ -1 +1 @@ -Subproject commit 3e758affdb87d98b1699982262082c7b4c755392 +Subproject commit 96f0293857109e8565519b7d0016cead2d03985c diff --git a/plugin/Source/Editor.h b/plugin/Source/Editor.h index 80747fb..4c47ad2 100644 --- a/plugin/Source/Editor.h +++ b/plugin/Source/Editor.h @@ -19,7 +19,7 @@ private: OscillatorBox oscillators[Cfg::numOSCs] { { "oscillator 1", proc, 0 }, { "oscillator 2", proc, 1 } }; - FilterBox filter { "filter 1", proc }; + FilterBox filter { "filter", proc }; FilterADSRArea fltADSR { proc }; diff --git a/plugin/Source/Panels.h b/plugin/Source/Panels.h index 86cd52f..3a2a786 100644 --- a/plugin/Source/Panels.h +++ b/plugin/Source/Panels.h @@ -5,7 +5,8 @@ #include "Cfg.h" //============================================================================== -class OscillatorBox : public gin::ParamBox +class OscillatorBox : public gin::ParamBox, + public Value::Listener { public: OscillatorBox (const juce::String& name, WavetableAudioProcessor& proc_, int idx_) @@ -15,6 +16,12 @@ public: auto& osc = proc.oscParams[idx]; + setTitle (idx == 0 ? proc.osc1Table.toString() : proc.osc2Table.toString()); + if (idx == 0) + proc.osc1Table.addListener (this); + else + proc.osc2Table.addListener (this); + addEnable (osc.enable); addControl (new gin::Knob (osc.pos), 0, 0); @@ -40,6 +47,35 @@ public: { wt->setParams (proc.getLiveWTParams (idx)); }; + + auto& h = getHeader(); + h.addAndMakeVisible (nextButton); + h.addAndMakeVisible (prevButton); + nextButton.onClick = [this] { proc.incWavetable (idx, +1); }; + prevButton.onClick = [this] { proc.incWavetable (idx, -1); }; + } + + ~OscillatorBox() override + { + if (idx == 0) + proc.osc1Table.removeListener (this); + else + proc.osc2Table.removeListener (this); + } + + void resized() override + { + gin::ParamBox::resized(); + + auto& h = getHeader(); + nextButton.setBounds (getWidth() / 2 + 100, h.getHeight() / 2 - 4, 8, 8); + prevButton.setBounds (getWidth() / 2 - 108, h.getHeight() / 2 - 4, 8, 8); + } + + void valueChanged (juce::Value&) override + { + setTitle (idx == 0 ? proc.osc1Table.toString() : proc.osc2Table.toString()); + wt->setWavetables (idx == 0 ? &proc.osc1Tables : &proc.osc2Tables); } void paramChanged() override @@ -59,6 +95,9 @@ public: gin::WavetableComponent* wt; gin::CoalescedTimer timer; + + gin::SVGButton nextButton {"next", "M17.525 36.465l-7.071 7.07c-4.686 4.686-4.686 12.284 0 16.971L205.947 256 10.454 451.494c-4.686 4.686-4.686 12.284 0 16.971l7.071 7.07c4.686 4.686 12.284 4.686 16.97 0l211.051-211.05c4.686-4.686 4.686-12.284 0-16.971L34.495 36.465c-4.686-4.687-12.284-4.687-16.97 0z"}; + gin::SVGButton prevButton {"prev", "M238.475 475.535l7.071-7.07c4.686-4.686 4.686-12.284 0-16.971L50.053 256 245.546 60.506c4.686-4.686 4.686-12.284 0-16.971l-7.071-7.07c-4.686-4.686-12.284-4.686-16.97 0L10.454 247.515c-4.686 4.686-4.686 12.284 0 16.971l211.051 211.05c4.686 4.686 12.284 4.686 16.97-.001z"}; }; //============================================================================== @@ -224,6 +263,8 @@ public: { setName ("gate"); + addEnable (proc.gateParams.enable); + addControl (new gin::Select (proc.gateParams.beat), 0, 0); addControl (new gin::Knob (proc.gateParams.length), 1, 0); addControl (new gin::Knob (proc.gateParams.attack), 0, 1); @@ -274,6 +315,8 @@ public: { setName ("chorus"); + addEnable (proc.chorusParams.enable); + addControl (new gin::Knob (proc.chorusParams.delay), 0, 0); addControl (new gin::Knob (proc.chorusParams.rate), 1, 0); addControl (new gin::Knob (proc.chorusParams.mix), 2, 0); @@ -296,6 +339,8 @@ public: { setName ("distort"); + addEnable (proc.distortionParams.enable); + addControl (new gin::Knob (proc.distortionParams.amount), 0, 0); addControl (new gin::Knob (proc.distortionParams.highpass), 1, 0); addControl (new gin::Knob (proc.distortionParams.output), 0, 1); @@ -316,6 +361,8 @@ public: { setName ("delay"); + addEnable (proc.delayParams.enable); + addControl (t = new gin::Knob (proc.delayParams.time), 0, 0); addControl (b = new gin::Select (proc.delayParams.beat), 0, 0); addControl (new gin::Knob (proc.delayParams.fb), 1, 0); @@ -350,6 +397,8 @@ public: { setName ("reverb"); + addEnable (proc.reverbParams.enable); + addControl (new gin::Knob (proc.reverbParams.size), 0, 0); addControl (new gin::Knob (proc.reverbParams.decay), 1, 0); addControl (new gin::Knob (proc.reverbParams.lowpass), 2, 0); @@ -372,7 +421,7 @@ public: { setName ("scope"); - scope = new gin::TriggeredScope (proc.fifo); + scope = new gin::TriggeredScope (proc.scopeFifo); scope->setNumChannels (2); scope->setTriggerMode (gin::TriggeredScope::TriggerMode::Up); scope->setColour (gin::TriggeredScope::lineColourId, juce::Colours::transparentBlack); diff --git a/plugin/Source/PluginProcessor.cpp b/plugin/Source/PluginProcessor.cpp index 0d77cab..80247b6 100644 --- a/plugin/Source/PluginProcessor.cpp +++ b/plugin/Source/PluginProcessor.cpp @@ -328,9 +328,9 @@ void WavetableAudioProcessor::ReverbParams::setup (WavetableAudioProcessor& p) size = p.addExtParam ("rvbSize", "Size", "", "", {0.0f, 1.0f, 0.0f, 2.0f}, 0.0f, 0.0f); decay = p.addExtParam ("rvbDecay", "Decay", "", "", {0.0f, 1.0f, 0.0f, 1.0f}, 0.0f, 0.0f); - lowpass = p.addExtParam ("rvbLowpass", "Lowpass", "", "", {0.0f, 1.0f, 16.0f, 20000.0f}, 0.0f, 0.0f); - damping = p.addExtParam ("rvbDamping", "Damping", "", "", {0.0f, 1.0f, 16.0f, 20000.0f}, 0.0f, 0.0f); - predelay = p.addExtParam ("rvbPredelay", "Predelay", "", "", {0.0f, 1.0f, 0.0f, 0.1f}, 0.0f, 0.0f); + lowpass = p.addExtParam ("rvbLowpass", "Lowpass", "", "", {16.0f, 20000.0f, 0.0f, 0.3f}, 10000.0f, 0.0f); + damping = p.addExtParam ("rvbDamping", "Damping", "", "", {16.0f, 20000.0f, 0.0f, 0.3f}, 10000.0f, 0.0f); + predelay = p.addExtParam ("rvbPredelay", "Predelay", "", "", {0.0f, 0.1f, 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); } @@ -354,8 +354,10 @@ WavetableAudioProcessor::WavetableAudioProcessor() enableLegacyMode(); setVoiceStealingEnabled (true); - loadWaveTable (osc1Tables, juce::MemoryBlock (BinaryData::Analog_PWM_Square_01_wav, BinaryData::Analog_PWM_Square_01_wavSize)); - loadWaveTable (osc2Tables, juce::MemoryBlock (BinaryData::Analog_PWM_Saw_01_wav, BinaryData::Analog_PWM_Saw_01_wavSize)); + osc1Table = "Analog PWM Square 01"; + osc2Table = "Analog PWM Saw 01"; + + reloadWavetables(); for (int i = 0; i < juce::numElementsInArray (oscParams); i++) oscParams[i].setup (*this, i); @@ -394,15 +396,68 @@ WavetableAudioProcessor::~WavetableAudioProcessor() { } +void WavetableAudioProcessor::reloadWavetables() +{ + auto loadMemory = [&] (const juce::String& name) -> juce::MemoryBlock + { + for (auto i = 0; i < BinaryData::namedResourceListSize; i++) + { + if ((name + ".wav").equalsIgnoreCase (BinaryData::originalFilenames[i])) + { + int sz = 0; + if (auto data = BinaryData::getNamedResource (BinaryData::namedResourceList[i], sz)) + return juce::MemoryBlock (data, sz); + } + } + return {}; + }; + + if (auto mb = loadMemory (osc1Table.toString()); mb.getSize() > 0) + loadWaveTable (osc1Tables, mb); + + if (auto mb = loadMemory (osc2Table.toString()); mb.getSize() > 0) + loadWaveTable (osc2Tables, mb); +} + +void WavetableAudioProcessor::incWavetable (int osc, int delta) +{ + auto& table = osc == 0 ? osc1Table : osc2Table; + + juce::StringArray tables; + for (auto i = 0; i < BinaryData::namedResourceListSize; i++) + if (juce::String (BinaryData::originalFilenames[i]).endsWith (".wav")) + tables.add (juce::String (BinaryData::originalFilenames[i]).upToLastOccurrenceOf (".wav", false, false)); + + tables.sortNatural(); + + auto idx = tables.indexOf (table.toString()); + + idx += delta; + if (idx < 0) idx = tables.size() - 1; + if (idx >= tables.size()) idx = 0; + + table = tables[idx]; + + reloadWavetables(); +} + //============================================================================== void WavetableAudioProcessor::stateUpdated() { modMatrix.stateUpdated (state); + + osc1Table = state.getProperty ("wt1"); + osc2Table = state.getProperty ("wt2"); + + reloadWavetables(); } void WavetableAudioProcessor::updateState() { modMatrix.updateState (state); + + state.setProperty ("wt1", osc1Table, nullptr); + state.setProperty ("wt2", osc2Table, nullptr); } //============================================================================== @@ -469,6 +524,8 @@ void WavetableAudioProcessor::reset() l.reset(); modStepLFO.reset(); + + reloadWavetables(); } void WavetableAudioProcessor::prepareToPlay (double newSampleRate, int newSamplesPerBlock) @@ -489,6 +546,8 @@ void WavetableAudioProcessor::prepareToPlay (double newSampleRate, int newSample l.setSampleRate (newSampleRate); modStepLFO.setSampleRate (newSampleRate); + + reloadWavetables(); } void WavetableAudioProcessor::releaseResources() @@ -535,7 +594,9 @@ void WavetableAudioProcessor::processBlock (juce::AudioBuffer& buffer, ju playHead = nullptr; - fifo.write (buffer); + if (buffer.getNumSamples() <= scopeFifo.getFreeSpace()) + scopeFifo.write (buffer); + endBlock (buffer.getNumSamples()); } diff --git a/plugin/Source/PluginProcessor.h b/plugin/Source/PluginProcessor.h index 1b1106e..1412c02 100644 --- a/plugin/Source/PluginProcessor.h +++ b/plugin/Source/PluginProcessor.h @@ -37,6 +37,9 @@ public: juce::Array getLiveFilterCutoff(); gin::WTOscillator::Params getLiveWTParams (int osc); + void reloadWavetables(); + void incWavetable (int osc, int delta); + void applyEffects (juce::AudioSampleBuffer& buffer); // Voice Params @@ -233,11 +236,13 @@ public: gin::StereoDelay stereoDelay { 120.1 }; gin::PlateReverb reverb; gin::GainProcessor outputGain; - gin::AudioFifo fifo { 2, 44100 }; + gin::AudioFifo scopeFifo { 2, 44100 }; juce::OwnedArray osc1Tables; juce::OwnedArray osc2Tables; + juce::Value osc1Table, osc2Table; + //============================================================================== gin::ModMatrix modMatrix;