diff --git a/src/dsp/Brickwall/BrickwallProcessor.cpp b/src/dsp/Brickwall/BrickwallProcessor.cpp index cf9d791..c44b6f4 100644 --- a/src/dsp/Brickwall/BrickwallProcessor.cpp +++ b/src/dsp/Brickwall/BrickwallProcessor.cpp @@ -6,6 +6,7 @@ void BrickwallProcessor::prepare (const juce::dsp::ProcessSpec& spec) { filter.prepare (spec); filter.setQValue (chowdsp::CoefficientCalculators::butterworthQ); + postSpectrumAnalyserTask.prepareToPlay (spec.sampleRate, (int) spec.maximumBlockSize, (int) spec.numChannels); } void BrickwallProcessor::reset() @@ -20,6 +21,9 @@ void BrickwallProcessor::processBlock (const chowdsp::BufferView& buffer) filter.setFilterType (getFilterTypeIndex()); filter.setCutoffFrequency (*params.cutoff); filter.processBlock (buffer); + + if (extraState.isEditorOpen.load() && extraState.showPostSpectrum.get()) + postSpectrumAnalyserTask.processBlockInput (buffer.toAudioBuffer()); } int BrickwallProcessor::getFilterTypeIndex() const diff --git a/src/dsp/Brickwall/BrickwallProcessor.h b/src/dsp/Brickwall/BrickwallProcessor.h index f6c6ae2..f654b41 100644 --- a/src/dsp/Brickwall/BrickwallProcessor.h +++ b/src/dsp/Brickwall/BrickwallProcessor.h @@ -1,5 +1,6 @@ #pragma once +#include "gui/Shared/SpectrumAnalyserTask.h" #include namespace dsp::brickwall @@ -28,6 +29,13 @@ enum class FilterType ChebyshevII = 2, Elliptic = 4, }; + +struct ExtraState +{ + std::atomic isEditorOpen { false }; + chowdsp::StateValue showPostSpectrum { "brickwall_show_post_spectrum", true }; +}; + } // namespace dsp::brickwall template <> @@ -98,16 +106,26 @@ struct Params : chowdsp::ParamHolder class BrickwallProcessor { public: - explicit BrickwallProcessor (const Params& brickwallParams) : params (brickwallParams) {} + explicit BrickwallProcessor (const Params& brickwallParams, const dsp::brickwall::ExtraState& es) : params (brickwallParams), extraState(es){} void prepare (const juce::dsp::ProcessSpec& spec); void reset(); void processBlock (const chowdsp::BufferView& buffer) noexcept; + using optionalSpectrumBackgroundTask = std::optional>; + + std::pair getSpectrumAnalyserTasks() + { + return {std::nullopt, std::ref(postSpectrumAnalyserTask.SpectrumAnalyserUITask)}; + } +// gui::SpectrumAnalyserTask::SpectrumAnalyserBackgroundTask& getSpectrumAnalyserTasks() { return postSpectrumAnalyserTask.SpectrumAnalyserUITask; } + + private: int getFilterTypeIndex() const; const Params& params; + const dsp::brickwall::ExtraState& extraState; using EQBand = chowdsp::EQ::EQBand< float, @@ -161,6 +179,8 @@ class BrickwallProcessor chowdsp::EllipticFilter<16, chowdsp::EllipticFilterType::Highpass>>; EQBand filter; + gui::SpectrumAnalyserTask postSpectrumAnalyserTask; + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BrickwallProcessor) }; } // namespace dsp::brickwall diff --git a/src/dsp/EQ/EQProcessor.h b/src/dsp/EQ/EQProcessor.h index cab2c45..cefd706 100644 --- a/src/dsp/EQ/EQProcessor.h +++ b/src/dsp/EQ/EQProcessor.h @@ -116,13 +116,20 @@ struct ExtraState class EQProcessor { public: + EQProcessor (const EQToolParams& eqParams, const ExtraState& extraState); void prepare (const juce::dsp::ProcessSpec& spec); void processBlock (const chowdsp::BufferView& buffer); int getLatencySamples() const; - std::pair getSpectrumAnalyserTasks() { return { preSpectrumAnalyserTask, postSpectrumAnalyserTask }; } + + using optionalSpectrumBackgroundTask = std::optional>; + + std::pair getSpectrumAnalyserTasks() + { + return {std::ref(preSpectrumAnalyserTask.SpectrumAnalyserUITask), std::ref(postSpectrumAnalyserTask.SpectrumAnalyserUITask)}; + } private: const EQToolParams& params; diff --git a/src/dsp/MultiToolProcessor.cpp b/src/dsp/MultiToolProcessor.cpp index 094a68a..0e37b63 100644 --- a/src/dsp/MultiToolProcessor.cpp +++ b/src/dsp/MultiToolProcessor.cpp @@ -38,8 +38,8 @@ namespace detail { return analog_eq::AnalogEQProcessor { *params.analogEQParams }; }), tool_maker ([¶ms] { return band_splitter::BandSplitterProcessor { *params.bandSplitParams }; }), - tool_maker ([¶ms] - { return brickwall::BrickwallProcessor { *params.brickwallParams }; }), + tool_maker ([¶ms, &pluginState] + { return brickwall::BrickwallProcessor { *params.brickwallParams, *pluginState.nonParams.brickwallExtraState }; }), tool_maker ([¶ms] { return svf::SVFProcessor { *params.svfParams }; }) }; diff --git a/src/gui/Brickwall/BrickwallEditor.cpp b/src/gui/Brickwall/BrickwallEditor.cpp index 5ee0d44..d73fef1 100644 --- a/src/gui/Brickwall/BrickwallEditor.cpp +++ b/src/gui/Brickwall/BrickwallEditor.cpp @@ -1,16 +1,66 @@ #include "BrickwallEditor.h" #include "BottomBar.h" #include "gui/Shared/Colours.h" +#include "gui/Shared/LookAndFeels.h" + + namespace gui::brickwall { -BrickwallEditor::BrickwallEditor (State& pluginState, dsp::brickwall::Params& params, const chowdsp::HostContextProvider& hcp) - : plot (pluginState, params, hcp) +BrickwallEditor::BrickwallEditor (State& pluginState, + dsp::brickwall::Params& params, + dsp::brickwall::ExtraState& brickwallExtraState, + const chowdsp::HostContextProvider& hcp, + std::pair spectrumAnalyserTasks) + : extraState(brickwallExtraState), + plot (pluginState, params, hcp), + spectrumAnalyser(plot, spectrumAnalyserTasks) { + addMouseListener (this, true); + extraState.isEditorOpen.store (true); + spectrumAnalyser.setShowPostEQ (extraState.showPostSpectrum.get()); + callbacks += { + extraState.showPostSpectrum.changeBroadcaster.connect ([this] + { + spectrumAnalyser.setShowPostEQ(extraState.showPostSpectrum.get()); + spectrumAnalyser.repaint(); }), + }; + bottomBar = std::make_unique (pluginState, params); addAndMakeVisible (plot); addAndMakeVisible (bottomBar.get()); + addAndMakeVisible (spectrumAnalyser); + spectrumAnalyser.toBehind(bottomBar.get()); +// spectrumAnalyser.toBehind(&plot.getCutoffSlider()); +} + +BrickwallEditor::~BrickwallEditor() +{ + removeMouseListener (this); + extraState.isEditorOpen.store (false); +} + +void BrickwallEditor::mouseDown (const juce::MouseEvent& event) +{ + if (event.mods.isPopupMenu()) + { + chowdsp::SharedLNFAllocator lnfAllocator; + juce::PopupMenu menu; + + juce::PopupMenu::Item postSpectrumItem; + postSpectrumItem.itemID = 100; + postSpectrumItem.text = extraState.showPostSpectrum.get() ? "Disable Post-EQ Visualizer" : "Enable Post-EQ Visualizer"; + postSpectrumItem.action = [this] + { + extraState.showPostSpectrum.set (! extraState.showPostSpectrum.get()); + }; + menu.addItem (postSpectrumItem); + + menu.setLookAndFeel (lnfAllocator->getLookAndFeel()); + menu.showMenuAsync (juce::PopupMenu::Options {} + .withParentComponent (getParentComponent())); + } } void BrickwallEditor::paint (juce::Graphics& g) @@ -28,5 +78,6 @@ void BrickwallEditor::resized() auto bounds = getLocalBounds(); plot.setBounds (bounds); bottomBar->setBounds (bounds.removeFromBottom (proportionOfHeight (0.075f))); + spectrumAnalyser.setBounds (getLocalBounds()); } } // namespace gui::brickwall diff --git a/src/gui/Brickwall/BrickwallEditor.h b/src/gui/Brickwall/BrickwallEditor.h index 8014e7a..db544b2 100644 --- a/src/gui/Brickwall/BrickwallEditor.h +++ b/src/gui/Brickwall/BrickwallEditor.h @@ -1,20 +1,36 @@ #pragma once #include "BrickwallPlot.h" +#include "gui/Shared/SpectrumAnalyser.h" + +using optionalSpectrumBackgroundTask = std::optional>; namespace gui::brickwall { class BrickwallEditor : public juce::Component { public: - BrickwallEditor (State& pluginState, dsp::brickwall::Params& params, const chowdsp::HostContextProvider& hcp); + BrickwallEditor (State& pluginState, + dsp::brickwall::Params& params, + dsp::brickwall::ExtraState& brickwallExtraState, + const chowdsp::HostContextProvider& hcp, + std::pair spectrumAnalyserTasks); + + ~BrickwallEditor(); void paint (juce::Graphics& g) override; void resized() override; + void mouseDown (const juce::MouseEvent& event) override; + private: + + dsp::brickwall::ExtraState& extraState; + chowdsp::ScopedCallbackList callbacks; + BrickwallPlot plot; std::unique_ptr bottomBar; + SpectrumAnalyser spectrumAnalyser; JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BrickwallEditor) }; diff --git a/src/gui/Brickwall/BrickwallPlot.cpp b/src/gui/Brickwall/BrickwallPlot.cpp index 2696ca5..b022e8e 100644 --- a/src/gui/Brickwall/BrickwallPlot.cpp +++ b/src/gui/Brickwall/BrickwallPlot.cpp @@ -98,7 +98,7 @@ BrickwallPlot::BrickwallPlot (State& pluginState, dsp::brickwall::Params& brickw .sampleRate = sampleRate, .fftOrder = fftOrder, }), - brickwall (brickwallParams), + brickwall (brickwallParams, *pluginState.nonParams.brickwallExtraState), cutoffSlider (*brickwallParams.cutoff, *this, pluginState, hcp), chyron (pluginState, brickwallParams, hcp) { diff --git a/src/gui/Brickwall/BrickwallPlot.h b/src/gui/Brickwall/BrickwallPlot.h index b955ff1..367984c 100644 --- a/src/gui/Brickwall/BrickwallPlot.h +++ b/src/gui/Brickwall/BrickwallPlot.h @@ -14,6 +14,7 @@ class BrickwallPlot : public chowdsp::SpectrumPlotBase void paint (juce::Graphics& g) override; void paintOverChildren (juce::Graphics& g) override; void resized() override; +// juce::Slider& getCutoffSlider(){ return cutoffSlider ;} private: void updatePlot(); diff --git a/src/gui/EQ/EQEditor.cpp b/src/gui/EQ/EQEditor.cpp index f39bdf1..30556c2 100644 --- a/src/gui/EQ/EQEditor.cpp +++ b/src/gui/EQ/EQEditor.cpp @@ -9,7 +9,7 @@ EQEditor::EQEditor (State& pluginState, dsp::eq::EQToolParams& eqParams, dsp::eq::ExtraState& eqExtraState, const chowdsp::HostContextProvider& hcp, - std::pair spectrumAnalyserTasks) + std::pair spectrumAnalyserTasks) : params (eqParams), extraState (eqExtraState), plot (pluginState, eqParams.eqParams, hcp), diff --git a/src/gui/EQ/EQEditor.h b/src/gui/EQ/EQEditor.h index 50246c0..c4de033 100644 --- a/src/gui/EQ/EQEditor.h +++ b/src/gui/EQ/EQEditor.h @@ -8,6 +8,8 @@ // - Figure out type-in values for chyron // - Better controls for Q values +using optionalSpectrumBackgroundTask = std::optional>; + namespace gui::eq { class EQEditor : public juce::Component @@ -17,7 +19,7 @@ class EQEditor : public juce::Component dsp::eq::EQToolParams& eqParams, dsp::eq::ExtraState& extraState, const chowdsp::HostContextProvider& hcp, - std::pair spectrumAnalyserTasks); + std::pair spectrumAnalyserTasks); ~EQEditor() override; void paint (juce::Graphics& g) override; diff --git a/src/gui/PluginEditor.cpp b/src/gui/PluginEditor.cpp index 1c7a843..7cadb69 100644 --- a/src/gui/PluginEditor.cpp +++ b/src/gui/PluginEditor.cpp @@ -124,7 +124,11 @@ void PluginEditor::refreshEditor() else if constexpr (std::is_same_v) editorComponent = std::make_unique (pluginState, *pluginState.params.bandSplitParams, hostContextProvider); else if constexpr (std::is_same_v) - editorComponent = std::make_unique (pluginState, *pluginState.params.brickwallParams, hostContextProvider); + editorComponent = std::make_unique (pluginState, + *pluginState.params.brickwallParams, + *pluginState.nonParams.brickwallExtraState, + hostContextProvider, + std::get (plugin.getProcessor().getTools()).getSpectrumAnalyserTasks()); else if constexpr (std::is_same_v) editorComponent = std::make_unique (pluginState, *pluginState.params.svfParams, hostContextProvider); }); diff --git a/src/gui/Shared/SpectrumAnalyser.cpp b/src/gui/Shared/SpectrumAnalyser.cpp index 18096a3..70f3cf4 100644 --- a/src/gui/Shared/SpectrumAnalyser.cpp +++ b/src/gui/Shared/SpectrumAnalyser.cpp @@ -1,25 +1,25 @@ #include "SpectrumAnalyser.h" #include "gui/Shared/Colours.h" -SpectrumAnalyser::SpectrumAnalyser (const chowdsp::SpectrumPlotBase& eqPlot, std::pair spectrumAnalyserTasks) +SpectrumAnalyser::SpectrumAnalyser (const chowdsp::SpectrumPlotBase& eqPlot, std::pair spectrumAnalyserTasks) : eqPlot (eqPlot), - preTask (spectrumAnalyserTasks.first.SpectrumAnalyserUITask), - postTask (spectrumAnalyserTasks.second.SpectrumAnalyserUITask) + preTask (spectrumAnalyserTasks.first.has_value() ? std::ref(spectrumAnalyserTasks.first).get() : std::nullopt), + postTask (spectrumAnalyserTasks.second.has_value() ? std::ref(spectrumAnalyserTasks.second).get() : std::nullopt) { } SpectrumAnalyser::~SpectrumAnalyser() { - if (preTask.isTaskRunning()) - preTask.setShouldBeRunning (false); - if (postTask.isTaskRunning()) - postTask.setShouldBeRunning (false); + if (preTask && preTask->get().isTaskRunning()) + preTask->get().setShouldBeRunning (false); + if (postTask && postTask->get().isTaskRunning()) + postTask->get().setShouldBeRunning (false); } void SpectrumAnalyser::paint (juce::Graphics& g) { - // g.fillAll(juce::Colours::whitesmoke.withAlpha(0.4f)); +// g.fillAll(juce::Colours::whitesmoke.withAlpha(0.4f)); if (showPreEQ) { @@ -41,24 +41,28 @@ void SpectrumAnalyser::visibilityChanged() { if (isVisible()) { - preTask.setShouldBeRunning (showPreEQ); - postTask.setShouldBeRunning (showPostEQ); + if (preTask) + preTask->get().setShouldBeRunning (showPreEQ); + if (postTask) + postTask->get().setShouldBeRunning (showPostEQ); startTimerHz (32); } else { - preTask.setShouldBeRunning (false); - postTask.setShouldBeRunning (false); + if (preTask) + preTask->get().setShouldBeRunning (false); + if (postTask) + postTask->get().setShouldBeRunning (false); stopTimer(); } } void SpectrumAnalyser::timerCallback() { - if (showPreEQ) - updatePlotPath (prePath, preTask); - if (showPostEQ) - updatePlotPath (postPath, postTask); + if (preTask && showPreEQ) + updatePlotPath (prePath, preTask->get()); + if (postTask && showPostEQ) + updatePlotPath (postPath, postTask->get()); } void SpectrumAnalyser::updatePlotPath (juce::Path& pathToUpdate, gui::SpectrumAnalyserTask::SpectrumAnalyserBackgroundTask& taskToUpdate) diff --git a/src/gui/Shared/SpectrumAnalyser.h b/src/gui/Shared/SpectrumAnalyser.h index 80da22f..32aacd3 100644 --- a/src/gui/Shared/SpectrumAnalyser.h +++ b/src/gui/Shared/SpectrumAnalyser.h @@ -2,11 +2,13 @@ #include "SpectrumAnalyserTask.h" #include "dsp/MultiToolProcessor.h" +using optionalSpectrumBackgroundTask = std::optional>; + class SpectrumAnalyser : public juce::Component, public juce::Timer { public: - SpectrumAnalyser (const chowdsp::SpectrumPlotBase& eqPlot, std::pair spectrumAnalyserTasks); + SpectrumAnalyser (const chowdsp::SpectrumPlotBase& eqPlot, std::pair spectrumAnalyserTasks); ~SpectrumAnalyser() override; void paint (juce::Graphics& g) override; void visibilityChanged() override; @@ -18,11 +20,12 @@ class SpectrumAnalyser : public juce::Component, void setShowPostEQ (bool showPostSpectrum) { showPostEQ = showPostSpectrum; } private: + using optionalBackgroundTask = std::optional>; juce::Path prePath; juce::Path postPath; const chowdsp::SpectrumPlotBase& eqPlot; - gui::SpectrumAnalyserTask::SpectrumAnalyserBackgroundTask& preTask; - gui::SpectrumAnalyserTask::SpectrumAnalyserBackgroundTask& postTask; + optionalBackgroundTask preTask; + optionalBackgroundTask postTask; bool showPreEQ = true; bool showPostEQ = true; diff --git a/src/state/PluginState.cpp b/src/state/PluginState.cpp index e167529..7ee4e54 100644 --- a/src/state/PluginState.cpp +++ b/src/state/PluginState.cpp @@ -48,12 +48,14 @@ PluginExtraState::PluginExtraState() { waveshaperExtraState = std::make_unique(); eqExtraState.emplace(); + brickwallExtraState.emplace(); addStateValues ({ &waveshaperExtraState->freeDrawState, &waveshaperExtraState->mathState, &waveshaperExtraState->pointsState, &eqExtraState->showPreSpectrum, &eqExtraState->showPostSpectrum, + &brickwallExtraState->showPostSpectrum, &editorBounds }); } diff --git a/src/state/PluginState.h b/src/state/PluginState.h index 5257ffd..fd74ed1 100644 --- a/src/state/PluginState.h +++ b/src/state/PluginState.h @@ -29,6 +29,7 @@ namespace band_splitter namespace brickwall { struct Params; + struct ExtraState; } namespace svf { @@ -75,6 +76,7 @@ struct PluginExtraState : chowdsp::NonParamState std::unique_ptr waveshaperExtraState; chowdsp::LocalPointer eqExtraState; + chowdsp::LocalPointer brickwallExtraState; chowdsp::StateValue> editorBounds { "editor_bounds", { 750, 500 } }; }; } // namespace state