BypassProcessor.h (2104B)
1 #ifndef BYPASSPROCESSOR_H_INCLUDED 2 #define BYPASSPROCESSOR_H_INCLUDED 3 4 #include <JuceHeader.h> 5 6 /** Utility class for *smoothly* bypassing a processor */ 7 class BypassProcessor 8 { 9 public: 10 BypassProcessor() = default; 11 12 static bool toBool (const std::atomic<float>* param) 13 { 14 return static_cast<bool> (param->load()); 15 } 16 17 void prepare (int samplesPerBlock, int numChannels, bool onOffParam) 18 { 19 prevOnOffParam = onOffParam; 20 fadeBuffer.setSize (numChannels, samplesPerBlock); 21 bufferCopied = false; 22 } 23 24 /** 25 * Call this at the start of your processBlock(). 26 * If it returns false, you can safely skip all other 27 * processing. 28 */ 29 bool processBlockIn (AudioBuffer<float>& block, bool onOffParam) 30 { 31 if (! onOffParam && ! prevOnOffParam) 32 return false; // NOLINT 33 34 if (onOffParam != prevOnOffParam) 35 { 36 fadeBuffer.makeCopyOf (block, true); 37 bufferCopied = true; 38 } 39 40 return true; 41 } 42 43 void processBlockOut (AudioBuffer<float>& block, bool onOffParam) 44 { 45 if (onOffParam == prevOnOffParam) 46 return; 47 48 if (! bufferCopied) 49 return; // parameter was changed in the middle of the buffer, let's wait for the next one! 50 51 const auto numChannels = block.getNumChannels(); 52 const auto numSamples = block.getNumSamples(); 53 54 float startGain = ! onOffParam ? 1.0f // fade out 55 : 0.0f; // fade in 56 float endGain = 1.0f - startGain; 57 58 block.applyGainRamp (0, numSamples, startGain, endGain); 59 for (int ch = 0; ch < numChannels; ++ch) 60 block.addFromWithRamp (ch, 0, fadeBuffer.getReadPointer (ch), numSamples, 1.0f - startGain, 1.0f - endGain); 61 62 prevOnOffParam = onOffParam; 63 bufferCopied = false; 64 } 65 66 private: 67 bool prevOnOffParam = false; 68 bool bufferCopied = false; 69 AudioBuffer<float> fadeBuffer; 70 71 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (BypassProcessor) 72 }; 73 74 #endif // BYPASSPROCESSOR_H_INCLUDED