1 /*
2   ==============================================================================
3 
4    This file is part of the JUCE library.
5    Copyright (c) 2020 - Raw Material Software Limited
6 
7    JUCE is an open source library subject to commercial or open-source
8    licensing.
9 
10    By using JUCE, you agree to the terms of both the JUCE 6 End-User License
11    Agreement and JUCE Privacy Policy (both effective as of the 16th June 2020).
12 
13    End User License Agreement: www.juce.com/juce-6-licence
14    Privacy Policy: www.juce.com/juce-privacy-policy
15 
16    Or: You may also use this code under the terms of the GPL v3 (see
17    www.gnu.org/licenses).
18 
19    JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
20    EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
21    DISCLAIMED.
22 
23   ==============================================================================
24 */
25 
26 namespace juce
27 {
28 namespace dsp
29 {
30 
31 /**
32     A simple limiter with standard threshold and release time controls, featuring
33     two compressors and a hard clipper at 0 dB.
34 
35     @tags{DSP}
36 */
37 template <typename SampleType>
38 class Limiter
39 {
40 public:
41     //==============================================================================
42     /** Constructor. */
43     Limiter() = default;
44 
45     //==============================================================================
46     /** Sets the threshold in dB of the limiter.*/
47     void setThreshold (SampleType newThreshold);
48 
49     /** Sets the release time in milliseconds of the limiter.*/
50     void setRelease (SampleType newRelease);
51 
52     //==============================================================================
53     /** Initialises the processor. */
54     void prepare (const ProcessSpec& spec);
55 
56     /** Resets the internal state variables of the processor. */
57     void reset();
58 
59     //==============================================================================
60     /** Processes the input and output samples supplied in the processing context. */
61     template <typename ProcessContext>
process(const ProcessContext & context)62     void process (const ProcessContext& context) noexcept
63     {
64         const auto& inputBlock = context.getInputBlock();
65         auto& outputBlock      = context.getOutputBlock();
66         const auto numChannels = outputBlock.getNumChannels();
67         const auto numSamples  = outputBlock.getNumSamples();
68 
69         jassert (inputBlock.getNumChannels() == numChannels);
70         jassert (inputBlock.getNumSamples()  == numSamples);
71 
72         if (context.isBypassed)
73         {
74             outputBlock.copyFrom (inputBlock);
75             return;
76         }
77 
78         firstStageCompressor.process (context);
79 
80         auto secondContext = ProcessContextReplacing<SampleType> (outputBlock);
81         secondStageCompressor.process (secondContext);
82 
83         outputBlock.multiplyBy (outputVolume);
84 
85         for (size_t channel = 0; channel < numChannels; ++channel)
86         {
87             FloatVectorOperations::clip (outputBlock.getChannelPointer (channel), outputBlock.getChannelPointer (channel),
88                                          (SampleType) -1.0, (SampleType) 1.0, (int) numSamples);
89         }
90     }
91 
92 private:
93     //==============================================================================
94     void update();
95 
96     //==============================================================================
97     Compressor<SampleType> firstStageCompressor, secondStageCompressor;
98     SmoothedValue<SampleType, ValueSmoothingTypes::Linear> outputVolume;
99 
100     double sampleRate = 44100.0;
101     SampleType thresholddB = -10.0, releaseTime = 100.0;
102 };
103 
104 } // namespace dsp
105 } // namespace juce
106