diff --git a/CMakeLists.txt b/CMakeLists.txt index 664bbfb..f4d01d1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -4,7 +4,7 @@ cmake_minimum_required (VERSION 3.24.0 FATAL_ERROR) # Set for each plugin # set (PLUGIN_NAME Wavetable) -set (PLUGIN_VERSION 1.0.0) +set (PLUGIN_VERSION 0.0.1) set (BUNDLE_ID com.socalabs.Wavetable) set (AU_ID WavetableAU) set (LV2_URI "https://socalabs.com/wavetable/") @@ -96,6 +96,7 @@ set_property (DIRECTORY APPEND PROPERTY LABELS Assets) juce_add_binary_data (${PLUGIN_NAME}_Assets SOURCES "./plugin/Resources/layout.json" + "./plugin/Resources/Wavetables/Analog/Analog Classic.wav" "./plugin/Resources/Wavetables/Analog/Analog PWM Square 03.wav" "./plugin/Resources/Wavetables/Analog/Analog PWM Sub 06.wav" "./plugin/Resources/Wavetables/Analog/Analog PWM Sub 07.wav" diff --git a/modules/gin b/modules/gin index 61a4618..3ed8ab1 160000 --- a/modules/gin +++ b/modules/gin @@ -1 +1 @@ -Subproject commit 61a4618d11e8049365000a0027e57edd24de86cf +Subproject commit 3ed8ab15c16bbee9ddf6f96612fe1999baa395d6 diff --git a/plugin/Resources/Wavetables/Analog/Analog Classic.wav b/plugin/Resources/Wavetables/Analog/Analog Classic.wav new file mode 100644 index 0000000..31df890 Binary files /dev/null and b/plugin/Resources/Wavetables/Analog/Analog Classic.wav differ diff --git a/plugin/Resources/layout.json b/plugin/Resources/layout.json index 543bcd4..f8aa77e 100644 --- a/plugin/Resources/layout.json +++ b/plugin/Resources/layout.json @@ -2,27 +2,128 @@ "children": [ { "id": "osc[1..2]", "x": "0,prevR()+1", "y": 0, "w": "parW()/2", "h": 163 }, - { "id": "flt", "x": "0", "y": "prevB()+1", "w": 400, "h": 163, "children": + { "id": "noise", "x": "0", "y": "prevB()+1", "w": 120, "h": 163, "children": + [ + { "id": "Level", "x": 0, "y": "23 + 35", "w": 56, "h": 70 }, + { "id": "Pan", "x": "prevR()", "y": "prevY()", "w": 56, "h": 70 } + ] + }, + { "id": "sub", "x": "prevR()+1", "y": "prevY()", "w": 112, "h": 163, "children": + [ + { "id": "Wave", "x": 0, "y": 23, "w": 56, "h": 70 }, + { "id": "Tune", "x": "prevR()", "y": 23, "w": 56, "h": 70 }, + { "id": "Level", "x": 0, "y": "prevB()", "w": 56, "h": 70 }, + { "id": "Pan", "x": "prevR()", "y": "prevY()", "w": 56, "h": 70 } + ] + }, + { "id": "flt", "x": "prevR()+1", "y": "prevY()", "w": 336, "h": 163, "children": [ { "id": "FLT WT1", "x": 24, "y": 6, "w": 12, "h": 12 }, { "id": "FLT WT2", "x": "prevR()+6", "y": 6, "w": 12, "h": 12 }, { "id": "FLT sub", "x": "prevR()+6", "y": 6, "w": 12, "h": 12 }, - { "id": "FLT noise", "x": "prevR()+6", "y": 6, "w": 12, "h": 12 } + { "id": "FLT noise", "x": "prevR()+6", "y": 6, "w": 12, "h": 12 }, + { "id": "Type", "x": 0, "y": 23, "w": 56, "h": 70 }, + { "id": "Freq", "x": "prevR()", "y": 23, "w": 56, "h": 70 }, + { "id": "Res", "x": "prevR()", "y": 23, "w": 56, "h": 70 }, + { "id": "Key", "x": 0, "y": "prevB()", "w": 56, "h": 70 }, + { "id": "Vel", "x": "prevR()", "y": "prevY()", "w": 56, "h": 70 }, + { "id": "Amnt", "x": "prevR()", "y": "prevY()", "w": 56, "h": 70 }, + { "id": "A", "x": "prevR()", "y": "prevY() + 13", "w": 42, "h": 57 }, + { "id": "D", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "S", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "R", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "adsr", "x": "getX('A')", "y": "getY('Res')", "r": "getR('R')", "b": "getY('A')" } ] }, - { "id": "adsr", "x": "prevR()+1", "y": "prevY()", "w": 240, "h": 163 }, - { "id": "noise", "x": "prevR()+1", "y": "prevY()", "w": 120, "h": 163 }, - { "id": "sub", "x": "prevR()+1", "y": "prevY()", "w": 120, "h": 163 }, - { "id": "lfo[1..3]", "x": 0, "y": "prevB()+1,prevY()", "w": 340, "h": 163 }, - { "id": "env[1..3]", "x": "getR('lfo1')+1", "y": "prevY()", "w": 240, "h": 163 }, - { "id": "step", "x": "prevR()+1", "y": "prevY()", "w": 240, "h": 163 }, - { "id": "mod", "x": "prevR()+1", "y": "prevY()", "w": 240, "h": 163 }, - { "id": "gate", "x": "0", "y": "prevB()+1", "w": 240, "h": 163 }, - { "id": "chorus", "x": "prevR()+1", "y": "prevY()", "w": 175, "h": 163 }, - { "id": "distort", "x": "prevR()+1", "y": "prevY()", "w": 100, "h": 163 }, - { "id": "delay", "x": "prevR()+1", "y": "prevY()", "w": 175, "h": 163 }, - { "id": "reverb", "x": "prevR()+1", "y": "prevY()", "w": 175, "h": 163 }, - { "id": "global", "x": "prevR()+1", "y": "prevY()", "w": 175, "h": 163 }, - { "id": "scope", "x": 0, "y": "prevB()+1", "w": "parW()-2", "b": "parH()-1" } + { "id": "adsr", "x": "prevR()+1", "y": "prevY()", "w": "210 + 118", "h": 163, "children": + [ + { "id": "A", "x": "118/2", "y": 106, "w": 42, "h": 57 }, + { "id": "D", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "S", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "R", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "Vel", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "adsr", "x": 0, "y": 23, "r": "parW()", "b": "getY('A')" } + ] }, + { "id": "lfo[1..3]", "x": 0, "y": "prevB()+1,prevY()", "w": 280, "h": 163, "children": + [ + { "id": "Sync", "x": 0, "y": 23, "w": 56, "h": 70 }, + { "id": "Beat", "x": "prevR()", "y": 23, "w": 56, "h": 70 }, + { "id": "Rate", "x": "prevX()", "y": 23, "w": 56, "h": 70 }, + { "id": "Wave", "x": 0, "y": "prevB()", "w": 56, "h": 70 }, + { "id": "Depth", "x": "prevR()", "y": "prevY()", "w": 56, "h": 70 }, + { "id": "Offset", "x": "prevR()", "y": "prevY() + 13", "w": 42, "h": 57 }, + { "id": "Phase", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "Delay", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "Fade", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "lfo", "x": "getX('Offset')", "y": "getY('Rate')", "r": "getR('Fade')", "b": "getY('Fade')" } + ] }, + { "id": "env[1..3]", "x": "getR('lfo1')+1", "y": "prevY()", "w": "168 + 50", "h": 163, "children": + [ + { "id": "A", "x": 25, "y": 106, "w": 42, "h": 57 }, + { "id": "D", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "S", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "R", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "adsr", "x": 0, "y": 23, "r": "parW()", "b": "getY('A')" } + ] }, + { "id": "step", "x": "prevR()+1", "y": "prevY()", "w": 218, "h": 163, "children": + [ + { "id": "step", "x": 0, "y": 23, "r": "parW()", "h": 83 }, + { "id": "Beat", "x": 67, "y": 106, "w": 42, "h": 57 }, + { "id": "Length", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 } + ] }, + { "id": "mod", "x": "prevR()+1", "y": "prevY()", "r": "parW()", "h": 163, "children": + [ + { "id": "modlist", "x": 0, "y": 23, "r": "parW()", "b": "parH()" } + ] }, + { "id": "gate", "x": "0", "y": "prevB()+1", "w": 290, "h": 137, "children": + [ + { "id": "Beat", "x": 61, "y": 30, "w": 42, "h": 57 }, + { "id": "Length", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "A", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "R", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "pattern", "x": 2, "y": "prevB() + 5", "w": "parW() - 6", "b": "parH() - 15" } + ] + }, + { "id": "chorus", "x": "prevR()+1", "y": "prevY()", "w": 126, "h": 137, "children": + [ + { "id": "Delay", "x": 0, "y": 23, "w": 42, "h": 57 }, + { "id": "Speed", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "Mix", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "Depth", "x": 21, "y": "prevB()", "w": 42, "h": 57 }, + { "id": "Width", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 } + ] + }, + { "id": "distort", "x": "prevR()+1", "y": "prevY()", "w": 100, "h": 137, "children": + [ + { "id": "Amount", "x": 22, "y": "23 + 22", "w": 56, "h": 70 } + ] + }, + { "id": "delay", "x": "prevR()+1", "y": "prevY()", "w": 126, "h": 137, "children": + [ + { "id": "Sync", "x": 0, "y": 23, "w": 42, "h": 57 }, + { "id": "Delay1", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "Delay2", "x": "prevX()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "Mix", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "FB", "x": 21, "y": "prevB()", "w": 42, "h": 57 }, + { "id": "CF", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 } + ] }, + { "id": "reverb", "x": "prevR()+1", "y": "prevY()", "w": 126, "h": 137, "children": + [ + { "id": "Size", "x": 0, "y": 23, "w": 42, "h": 57 }, + { "id": "Decay", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "Lowpass", "x": "prevR()", "y": "prevY()", "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": "Mix", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 } + ] }, + { "id": "global", "x": "prevR()+1", "y": "prevY()", "w": 126, "h": 137, "children": + [ + { "id": "Legato", "x": 0, "y": 23, "w": 42, "h": 57 }, + { "id": "Glide", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "Rate", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "Mono", "x": 0, "y": "prevB()", "w": 42, "h": 57 }, + { "id": "Voices", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 }, + { "id": "Level", "x": "prevR()", "y": "prevY()", "w": 42, "h": 57 } + ] } ] } \ No newline at end of file diff --git a/plugin/Source/Editor.cpp b/plugin/Source/Editor.cpp index f73eb3b..c55a524 100644 --- a/plugin/Source/Editor.cpp +++ b/plugin/Source/Editor.cpp @@ -19,7 +19,6 @@ Editor::Editor (WavetableAudioProcessor& proc_) addAndMakeVisible (distort); addAndMakeVisible (delay); addAndMakeVisible (reverb); - addAndMakeVisible (scope); addAndMakeVisible (effects); diff --git a/plugin/Source/Editor.h b/plugin/Source/Editor.h index dc7730a..f15df64 100644 --- a/plugin/Source/Editor.h +++ b/plugin/Source/Editor.h @@ -35,7 +35,6 @@ private: DistortBox distort { proc }; DelayBox delay { proc }; ReverbBox reverb { proc }; - ScopeArea scope { proc }; gin::BoxArea lfoBox; gin::BoxArea effects; diff --git a/plugin/Source/Panels.h b/plugin/Source/Panels.h index a0d0496..4b4d565 100644 --- a/plugin/Source/Panels.h +++ b/plugin/Source/Panels.h @@ -33,6 +33,8 @@ public: addControl (new gin::Select (osc.voices), 0, 1); addControl (detune = new gin::Knob (osc.detune), 1, 1); addControl (spread = new gin::Knob (osc.spread), 2, 1); + addControl (new gin::Knob (osc.formant, true), 3, 1); + addControl (new gin::Knob (osc.bend, true), 4, 1); watchParam (osc.voices); @@ -95,6 +97,7 @@ public: } juce::PopupMenu m; + m.setLookAndFeel (&getLookAndFeel()); for (auto itr : menus) m.addSubMenu (itr.first, itr.second); @@ -195,10 +198,11 @@ public: adsr->setParams (preset.attack, preset.decay, preset.sustain, preset.release); addControl (adsr, 0, 0, 4, 1); - addControl (a = new gin::Knob (preset.attack), 0, 1); - addControl (d = new gin::Knob (preset.decay), 1, 1); - addControl (s = new gin::Knob (preset.sustain), 2, 1); - addControl (r = new gin::Knob (preset.release), 3, 1); + addControl (new gin::Knob (preset.attack), 0, 1); + addControl (new gin::Knob (preset.decay), 1, 1); + addControl (new gin::Knob (preset.sustain), 2, 1); + addControl (new gin::Knob (preset.release), 3, 1); + addControl (new gin::Knob (preset.velocityTracking), 4, 1); } WavetableAudioProcessor& proc; @@ -385,7 +389,7 @@ public: addModSource (new gin::ModulationSourceButton (proc.modMatrix, proc.modSrcStep, true)); addModSource (new gin::ModulationSourceButton (proc.modMatrix, proc.modSrcMonoStep, false)); - addControl (new gin::Knob (prs.beat), 0, 1); + addControl (new gin::Select (prs.beat), 0, 1); addControl (new gin::Knob (prs.length), 1, 1); auto g = new gin::StepLFOComponent (Cfg::numStepLFOSteps); @@ -524,6 +528,9 @@ public: addControl (new gin::Switch (proc.delayParams.sync), 0, 1); addControl (new gin::Knob (proc.delayParams.mix), 1.5f, 1.0f); + t->setName ("Delay1"); + b->setName ("Delay2"); + watchParam (proc.delayParams.sync); setSize (168, 163); @@ -564,30 +571,3 @@ public: WavetableAudioProcessor& proc; }; - -//============================================================================== -class ScopeArea : public gin::ParamArea -{ -public: - ScopeArea (WavetableAudioProcessor& proc_) - : gin::ParamArea ("Scope"), proc (proc_) - { - setName ("scope"); - - scope = new gin::TriggeredScope (proc.scopeFifo); - scope->setNumChannels (2); - scope->setTriggerMode (gin::TriggeredScope::TriggerMode::Up); - scope->setColour (gin::TriggeredScope::lineColourId, juce::Colours::transparentBlack); - addControl (scope); - - setSize (272, 163); - } - - void resized() override - { - scope->setBounds (getLocalBounds().withSizeKeepingCentre (getWidth(), 140)); - } - - WavetableAudioProcessor& proc; - gin::TriggeredScope* scope; -}; diff --git a/plugin/Source/PluginEditor.cpp b/plugin/Source/PluginEditor.cpp index 5863181..2677275 100644 --- a/plugin/Source/PluginEditor.cpp +++ b/plugin/Source/PluginEditor.cpp @@ -5,9 +5,18 @@ WavetableAudioProcessorEditor::WavetableAudioProcessorEditor (WavetableAudioProcessor& p) : ProcessorEditor (p), vaProc (p) { - addAndMakeVisible (editor); + scope.setName ("scope"); + scope.setNumChannels (2); + scope.setTriggerMode (gin::TriggeredScope::TriggerMode::Up); + scope.setColour (gin::TriggeredScope::traceColourId + 0, findColour(gin::PluginLookAndFeel::accentColourId, true).withAlpha (0.7f)); + scope.setColour (gin::TriggeredScope::traceColourId + 1, findColour(gin::PluginLookAndFeel::accentColourId, true).withAlpha (0.7f)); + scope.setColour (gin::TriggeredScope::lineColourId, juce::Colours::transparentBlack); - setSize (901, 753); + addAndMakeVisible (editor); + addAndMakeVisible (scope); + scope.setBounds (674, 5, 177, 30); + + setSize (901, 671); } WavetableAudioProcessorEditor::~WavetableAudioProcessorEditor() diff --git a/plugin/Source/PluginEditor.h b/plugin/Source/PluginEditor.h index eba4b01..b39cdc9 100644 --- a/plugin/Source/PluginEditor.h +++ b/plugin/Source/PluginEditor.h @@ -21,6 +21,7 @@ public: private: WavetableAudioProcessor& vaProc; + gin::TriggeredScope scope { vaProc.scopeFifo }; Editor editor { vaProc }; #if JUCE_DEBUG diff --git a/plugin/Source/PluginProcessor.cpp b/plugin/Source/PluginProcessor.cpp index 84aa2a1..6ac18e4 100644 --- a/plugin/Source/PluginProcessor.cpp +++ b/plugin/Source/PluginProcessor.cpp @@ -110,6 +110,8 @@ void WavetableAudioProcessor::OSCParams::setup (WavetableAudioProcessor& p, int detune = p.addExtParam (id + "detune", nm + "Detune", "Detune", "", { 0.0, 0.5, 0.0, 1.0 }, 0.0, 0.0f); spread = p.addExtParam (id + "spread", nm + "Spread", "Spread", "%", { -100.0, 100.0, 0.0, 1.0 }, 0.0, 0.0f); pan = p.addExtParam (id + "pan", nm + "Pan", "Pan", "", { -1.0, 1.0, 0.0, 1.0 }, 0.0, 0.0f); + formant = p.addExtParam (id + "formant", nm + "Formant", "Formant", "", { -1.0, 1.0, 0.0, 1.0 }, 0.0, 0.0f); + bend = p.addExtParam (id + "bend", nm + "Bend", "Bend", "", { -1.0, 1.0, 0.0, 1.0 }, 0.0, 0.0f); level->conversionFunction = [] (float in) { return juce::Decibels::decibelsToGain (in); }; } @@ -354,7 +356,7 @@ static bool loadWaveTable (juce::OwnedArray& table, } //============================================================================== -WavetableAudioProcessor::WavetableAudioProcessor() +WavetableAudioProcessor::WavetableAudioProcessor() : gin::Processor (false) { lf = std::make_unique(); @@ -398,6 +400,7 @@ WavetableAudioProcessor::WavetableAudioProcessor() } setupModMatrix(); + init(); } WavetableAudioProcessor::~WavetableAudioProcessor() @@ -683,7 +686,9 @@ gin::WTOscillator::Params WavetableAudioProcessor::getLiveWTParams (int osc) return vav->getLiveWTParams (osc); gin::WTOscillator::Params p; - p.pw = oscParams[osc].pos->getValue(); + p.position = oscParams[osc].pos->getUserValue() / 100.0f; + p.formant = oscParams[osc].formant->getUserValue(); + p.bend = oscParams[osc].bend->getUserValue(); return p; } diff --git a/plugin/Source/PluginProcessor.h b/plugin/Source/PluginProcessor.h index 5fb72bc..12f97d2 100644 --- a/plugin/Source/PluginProcessor.h +++ b/plugin/Source/PluginProcessor.h @@ -48,7 +48,7 @@ public: { OSCParams() = default; - gin::Parameter::Ptr enable, voices, tune, finetune, level, pos, detune, spread, pan; + gin::Parameter::Ptr enable, voices, tune, finetune, level, pos, detune, spread, pan, bend, formant; void setup (WavetableAudioProcessor& p, int idx); diff --git a/plugin/Source/WavetableVoice.cpp b/plugin/Source/WavetableVoice.cpp index a1375a5..1cfa9f3 100644 --- a/plugin/Source/WavetableVoice.cpp +++ b/plugin/Source/WavetableVoice.cpp @@ -211,14 +211,15 @@ void WavetableVoice::updateParams (int blockSize) currentMidiNotes[i] += float (note.totalPitchbendInSemitones); currentMidiNotes[i] += getValue (proc.oscParams[i].tune) + getValue (proc.oscParams[i].finetune) / 100.0f; - oscParams[i].wave = gin::Wave::wavetable; - oscParams[i].voices = int (proc.oscParams[i].voices->getProcValue()); - oscParams[i].vcTrns = 0; - oscParams[i].pw = getValue (proc.oscParams[i].pos) / 100.0f; - oscParams[i].pan = getValue (proc.oscParams[i].pan); - oscParams[i].spread = getValue (proc.oscParams[i].spread) / 100.0f; - oscParams[i].detune = getValue (proc.oscParams[i].detune); - oscParams[i].gain = getValue (proc.oscParams[i].level); + oscParams[i].voices = int (proc.oscParams[i].voices->getProcValue()); + oscParams[i].vcTrns = 0; + oscParams[i].position = getValue (proc.oscParams[i].pos) / 100.0f; + oscParams[i].pan = getValue (proc.oscParams[i].pan); + oscParams[i].spread = getValue (proc.oscParams[i].spread) / 100.0f; + oscParams[i].detune = getValue (proc.oscParams[i].detune); + oscParams[i].gain = getValue (proc.oscParams[i].level); + oscParams[i].formant = getValue (proc.oscParams[i].formant); + oscParams[i].bend = getValue (proc.oscParams[i].bend); } if (proc.subParams.enable->isOn()) @@ -412,6 +413,8 @@ float WavetableVoice::getFilterCutoffNormalized() gin::WTOscillator::Params WavetableVoice::getLiveWTParams (int osc) { gin::WTOscillator::Params p; - p.pw = getValue (proc.oscParams[osc].pos) / 100.0f; + p.position = getValue (proc.oscParams[osc].pos) / 100.0f; + p.formant = getValue (proc.oscParams[osc].formant); + p.bend = getValue (proc.oscParams[osc].bend); return p; } diff --git a/plugin/Source/WavetableVoice.h b/plugin/Source/WavetableVoice.h index 201def8..734c0e5 100644 --- a/plugin/Source/WavetableVoice.h +++ b/plugin/Source/WavetableVoice.h @@ -49,7 +49,7 @@ private: gin::AnalogADSR adsr; float currentMidiNotes[Cfg::numOSCs]; - gin::WTVoicedStereoOscillator::Params oscParams[Cfg::numOSCs]; + gin::WTVoicedStereoOscillatorParams oscParams[Cfg::numOSCs]; float subNote = 0.0f; gin::StereoOscillator::Params subParams;