From 52ad1d61ad690edfc2380267f9d9304663efaa2d Mon Sep 17 00:00:00 2001
From: zsliu98 <zsliu98@gmail.com>
Date: Sun, 27 Aug 2023 23:53:14 -0400
Subject: [PATCH] fix: add process lock

---
 Source/DSP/ShaperFunctions.h |  8 +++----
 Source/DSP/WaveShaper.h      | 36 ++++++++++-------------------
 Source/PluginProcessor.cpp   | 44 +++++++++++++++++++++---------------
 Source/PluginProcessor.h     | 14 +++---------
 4 files changed, 45 insertions(+), 57 deletions(-)

diff --git a/Source/DSP/ShaperFunctions.h b/Source/DSP/ShaperFunctions.h
index 139e6df..1a84b5d 100644
--- a/Source/DSP/ShaperFunctions.h
+++ b/Source/DSP/ShaperFunctions.h
@@ -101,16 +101,16 @@ namespace shaper {
     class SigmodShaper : public Shaper<FloatType> {
     public:
         void setParameters(FloatType curve) override {
-            trueCurve = curve * 2.5 + 0.5;
+            trueCurve = curve * FloatType(2.5) + FloatType(0.5);
             b = -basic(0);
-            k = static_cast<FloatType>(1) / (basic(1) + b);
+            k = FloatType(1) / (basic(1) + b);
         }
 
     private:
         FloatType trueCurve, k, b;
 
         FloatType basic(FloatType x) const override {
-            return static_cast<FloatType>(1) / (1 + std::exp(-trueCurve * x));
+            return FloatType(1) / (1 + std::exp(-trueCurve * x));
         }
 
         FloatType shape(FloatType x) const override {
@@ -125,7 +125,7 @@ namespace shaper {
             trueCurve = (curve * static_cast<FloatType>(0.999) + static_cast<FloatType>(0.001)) *
                         juce::MathConstants<FloatType>::pi / 2;
             b = -basic(0);
-            k = static_cast<FloatType>(1) / (basic(1) + b);
+            k = FloatType(1) / (basic(1) + b);
         }
 
     private:
diff --git a/Source/DSP/WaveShaper.h b/Source/DSP/WaveShaper.h
index 816fa07..deb0796 100644
--- a/Source/DSP/WaveShaper.h
+++ b/Source/DSP/WaveShaper.h
@@ -22,7 +22,7 @@ You should have received a copy of the GNU General Public License along with ZLI
 template<typename FloatType>
 class WaveHelper {
 public:
-    WaveHelper(){
+    WaveHelper() {
         setWet(static_cast<FloatType>(zldsp::wet::formatV(zldsp::wet::defaultV)));
     }
 
@@ -41,7 +41,7 @@ class WaveHelper {
 
     FloatType operator()(FloatType x) const { return shape(x); }
 
-    shaper::ShaperMixer<FloatType>* getShaper() {return &shaperMixer;}
+    shaper::ShaperMixer<FloatType> *getShaper() { return &shaperMixer; }
 
 private:
     static constexpr FloatType clip = static_cast<FloatType>(1);
@@ -127,12 +127,13 @@ class LRFilters {
 template<typename FloatType>
 class WaveShaper {
 public:
-    WaveShaper() {
+    explicit WaveShaper(juce::AudioProcessor &processor) {
+        processorRef = &processor;
         filters[0].setCutoffFrequency(zldsp::lowSplit::defaultV);
         filters[1].setCutoffFrequency(zldsp::highSplit::defaultV);
     }
 
-    shaper::ShaperMixer<FloatType>* getShaper() {return helper.getShaper();}
+    shaper::ShaperMixer<FloatType> *getShaper() { return helper.getShaper(); }
 
     void setWet(FloatType wet) {
         helper.setWet(wet);
@@ -143,6 +144,7 @@ class WaveShaper {
     }
 
     void setCutoffFrequency(FloatType lowFreq, FloatType highFreq) {
+        const juce::GenericScopedLock<juce::CriticalSection> processLock(processorRef->getCallbackLock());
         filters[0].setCutoffFrequency(lowFreq);
         filters[1].setCutoffFrequency(highFreq);
     }
@@ -156,30 +158,18 @@ class WaveShaper {
     }
 
     void setOverSampleFactor(int overSampleFactor) {
+        const juce::GenericScopedLock<juce::CriticalSection> processLock(processorRef->getCallbackLock());
         idxSampler = static_cast<size_t>(std::min(overSampleFactor, numSamplers - 1));
         for (size_t i = 0; i < numBands - 1; ++i) {
             filters[i].update(overSampleFactor);
         }
+        processorRef->setLatencySamples(overSamplers[idxSampler]->getLatencyInSamples());
     }
 
     void setTypes(size_t type1, size_t type2) {
         helper.setTypes(type1, type2);
     }
 
-    void setParameters(bool clipFlag, bool effectFlag, float curve,
-                       float wetWeight, bool bandSplit, float low_split,
-                       float high_split, int overSampleFactor) {
-        helper.setParameters(clipFlag, curve, wetWeight);
-        effect = effectFlag;
-        split = bandSplit;
-        idxSampler = (unsigned int) std::min(overSampleFactor, numSamplers - 1);
-        filters[0].setCutoffFrequency(low_split);
-        filters[1].setCutoffFrequency(high_split);
-        for (size_t i = 0; i < numBands - 1; ++i) {
-            filters[i].update(idxSampler);
-        }
-    }
-
     void reset() noexcept {
         for (size_t i = 0; i < numBands - 1; ++i) {
             filters[i].reset();
@@ -190,10 +180,6 @@ class WaveShaper {
         }
     }
 
-    float getLatencyInSamples() {
-        return overSamplers[idxSampler]->getLatencyInSamples();
-    }
-
     template<typename SampleType>
     SampleType JUCE_VECTOR_CALLTYPE
     processSample(SampleType s) noexcept {
@@ -216,8 +202,9 @@ class WaveShaper {
             if (split) {
                 auto sepBlock =
                         juce::dsp::AudioBlock<FloatType>(bufferSeparation)
-                                .getSubBlock(0, (size_t) ((FloatType) std::pow(2.0, idxSampler) *
-                                                          (FloatType) numSamples));
+                                .getSubBlock(0, static_cast<size_t> (
+                                        std::pow(FloatType(2), static_cast<FloatType>(idxSampler)) *
+                                        static_cast<FloatType>(numSamples)));
                 juce::dsp::AudioBlock<FloatType> blocks[numBands];
                 std::vector<juce::dsp::ProcessContextReplacing<FloatType>> contexts;
                 for (size_t i = 0; i < numBands; ++i) {
@@ -280,6 +267,7 @@ class WaveShaper {
     }
 
 private:
+    juce::AudioProcessor *processorRef;
     constexpr static const int numSamplers = 5, numBands = 3;
     std::atomic<double> sampleRate;
     WaveHelper<FloatType> helper;
diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp
index 1d28e3c..04b891d 100644
--- a/Source/PluginProcessor.cpp
+++ b/Source/PluginProcessor.cpp
@@ -28,9 +28,10 @@ ZLInflatorAudioProcessor::ZLInflatorAudioProcessor()
 #endif
           parameters(*this, nullptr, juce::Identifier("ZLInflatorParameters"), zldsp::getParameterLayout()),
           states(*this, nullptr, juce::Identifier("ZLInflatorStates"), zlstate::getParameterLayout()),
-          waveShaperAttach(chain.get<waveShaper>(), parameters) {
-    chain.get<gain1>().setGainDecibels(zldsp::inputGain::defaultV);
-    chain.get<gain2>().setGainDecibels(zldsp::outputGain::defaultV);
+          waveShaper(*this),
+          waveShaperAttach(waveShaper, parameters) {
+    inGain.setGainDecibels(zldsp::inputGain::defaultV);
+    outGain.setGainDecibels(zldsp::outputGain::defaultV);
     parameters.addParameterListener(zldsp::inputGain::ID, this);
     parameters.addParameterListener(zldsp::outputGain::ID, this);
     waveShaperAttach.addListeners();
@@ -97,12 +98,20 @@ void ZLInflatorAudioProcessor::prepareToPlay(double sampleRate,
     reset();
     auto channels = static_cast<juce::uint32> (juce::jmin(getMainBusNumInputChannels(), getMainBusNumOutputChannels()));
     juce::dsp::ProcessSpec spec{sampleRate, static_cast<juce::uint32> (samplesPerBlock), channels};
-    chain.prepare(spec);
-    updateParameters();
+
+    inGain.prepare(spec);
+    outGain.prepare(spec);
+    meterIn.prepare(spec);
+    meterOut.prepare(spec);
+    waveShaper.prepare(spec);
 }
 
 void ZLInflatorAudioProcessor::reset() {
-    chain.reset();
+    inGain.reset();
+    outGain.reset();
+    meterIn.reset();
+    meterOut.reset();
+    waveShaper.reset();
 }
 
 void ZLInflatorAudioProcessor::releaseResources() {
@@ -127,20 +136,19 @@ bool ZLInflatorAudioProcessor::isBusesLayoutSupported(
 void ZLInflatorAudioProcessor::processBlock(juce::AudioBuffer<float> &buffer,
                                             juce::MidiBuffer &midiMessages) {
     juce::ScopedNoDenormals noDenormals;
+    juce::ignoreUnused(midiMessages);
     auto totalNumInputChannels = getTotalNumInputChannels();
     auto totalNumOutputChannels = getTotalNumOutputChannels();
 
     for (auto i = totalNumInputChannels; i < totalNumOutputChannels; ++i)
         buffer.clear(i, 0, buffer.getNumSamples());
 
-    updateParameters();
-
     juce::dsp::AudioBlock<float> block(buffer);
-    chain.process(juce::dsp::ProcessContextReplacing<float>(block));
-}
-
-void ZLInflatorAudioProcessor::updateParameters() {
-    setLatencySamples(static_cast<int>(chain.get<waveShaper>().getLatencyInSamples()));
+    inGain.process(juce::dsp::ProcessContextReplacing<float>(block));
+    meterIn.process(juce::dsp::ProcessContextReplacing<float>(block));
+    waveShaper.process(juce::dsp::ProcessContextReplacing<float>(block));
+    outGain.process(juce::dsp::ProcessContextReplacing<float>(block));
+    meterOut.process(juce::dsp::ProcessContextReplacing<float>(block));
 }
 
 //==============================================================================
@@ -180,21 +188,21 @@ juce::AudioProcessor *JUCE_CALLTYPE createPluginFilter() {
 }
 
 MeterSource<float> *ZLInflatorAudioProcessor::getInputMeterSource() {
-    return &chain.get<meter1>();
+    return &meterIn;
 }
 
 MeterSource<float> *ZLInflatorAudioProcessor::getOutputMeterSource() {
-    return &chain.get<meter2>();
+    return &meterOut;
 }
 
 shaper::ShaperMixer<float> *ZLInflatorAudioProcessor::getShaperMixer() {
-    return chain.get<waveShaper>().getShaper();
+    return waveShaper.getShaper();
 }
 
 void ZLInflatorAudioProcessor::parameterChanged(const juce::String &parameterID, float newValue) {
     if (parameterID.equalsIgnoreCase(zldsp::inputGain::ID)) {
-        chain.get<gain1>().setGainDecibels(newValue);
+        inGain.setGainDecibels(newValue);
     } else if (parameterID.equalsIgnoreCase(zldsp::outputGain::ID)) {
-        chain.get<gain2>().setGainDecibels(newValue);
+        outGain.setGainDecibels(newValue);
     }
 }
\ No newline at end of file
diff --git a/Source/PluginProcessor.h b/Source/PluginProcessor.h
index 397e465..96435b1 100644
--- a/Source/PluginProcessor.h
+++ b/Source/PluginProcessor.h
@@ -101,16 +101,8 @@ class ZLInflatorAudioProcessor : public juce::AudioProcessor,
     //==============================================================================
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ZLInflatorAudioProcessor)
 
-    enum {
-        gain1,
-        meter1,
-        waveShaper,
-        gain2,
-        meter2
-    };
-
-    using Gain = juce::dsp::Gain<float>;
-    juce::dsp::ProcessorChain<Gain, MeterSource<float>, WaveShaper<float>, Gain, MeterSource<float>> chain;
+    juce::dsp::Gain<float> inGain, outGain;
+    MeterSource<float> meterIn, meterOut;
+    WaveShaper<float> waveShaper;
     WaveShaperAttach<float> waveShaperAttach;
-    void updateParameters();
 };