OpenShot Audio Library | OpenShotAudio 0.3.2
Loading...
Searching...
No Matches
juce_ProcessorChain.h
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2017 - ROLI Ltd.
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 5 End-User License
11 Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
12 27th April 2017).
13
14 End User License Agreement: www.juce.com/juce-5-licence
15 Privacy Policy: www.juce.com/juce-5-privacy-policy
16
17 Or: You may also use this code under the terms of the GPL v3 (see
18 www.gnu.org/licenses).
19
20 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22 DISCLAIMED.
23
24 ==============================================================================
25*/
26
27namespace juce
28{
29namespace dsp
30{
31
32#ifndef DOXYGEN
33namespace ProcessorHelpers // Internal helper classes used in building the ProcessorChain
34{
35 template <int arg>
36 struct AccessHelper
37 {
38 template <typename ProcessorType>
39 static auto& get (ProcessorType& a) noexcept { return AccessHelper<arg - 1>::get (a.processors); }
40
41 template <typename ProcessorType>
42 static const auto& get (const ProcessorType& a) noexcept { return AccessHelper<arg - 1>::get (a.processors); }
43
44 template <typename ProcessorType>
45 static void setBypassed (ProcessorType& a, bool bypassed) { AccessHelper<arg - 1>::setBypassed (a.processors, bypassed); }
46 };
47
48 template <>
49 struct AccessHelper<0>
50 {
51 template <typename ProcessorType>
52 static auto& get (ProcessorType& a) noexcept { return a.getProcessor(); }
53
54 template <typename ProcessorType>
55 static const auto& get (const ProcessorType& a) noexcept { return a.getProcessor(); }
56
57 template <typename ProcessorType>
58 static void setBypassed (ProcessorType& a, bool bypassed) { a.isBypassed = bypassed; }
59 };
60
61 //==============================================================================
62 template <bool isFirst, typename Processor, typename Subclass>
63 struct ChainElement
64 {
65 void prepare (const ProcessSpec& spec)
66 {
67 processor.prepare (spec);
68 }
69
70 template <typename ProcessContext>
71 void process (const ProcessContext& context) noexcept
72 {
73 if (context.usesSeparateInputAndOutputBlocks() && ! isFirst)
74 {
75 jassert (context.getOutputBlock().getNumChannels() == context.getInputBlock().getNumChannels());
76 ProcessContextReplacing<typename ProcessContext::SampleType> replacingContext (context.getOutputBlock());
77 replacingContext.isBypassed = (isBypassed || context.isBypassed);
78
79 processor.process (replacingContext);
80 }
81 else
82 {
83 ProcessContext contextCopy (context);
84 contextCopy.isBypassed = (isBypassed || context.isBypassed);
85
86 processor.process (contextCopy);
87 }
88 }
89
90 void reset()
91 {
92 processor.reset();
93 }
94
95 bool isBypassed = false;
96 Processor processor;
97
98 Processor& getProcessor() noexcept { return processor; }
99 const Processor& getProcessor() const noexcept { return processor; }
100 Subclass& getThis() noexcept { return *static_cast<Subclass*> (this); }
101 const Subclass& getThis() const noexcept { return *static_cast<const Subclass*> (this); }
102
103 template <int arg> auto& get() noexcept { return AccessHelper<arg>::get (getThis()); }
104 template <int arg> const auto& get() const noexcept { return AccessHelper<arg>::get (getThis()); }
105 template <int arg> void setBypassed (bool bypassed) noexcept { AccessHelper<arg>::setBypassed (getThis(), bypassed); }
106 };
107
108 //==============================================================================
109 template <bool isFirst, typename FirstProcessor, typename... SubsequentProcessors>
110 struct ChainBase : public ChainElement<isFirst, FirstProcessor, ChainBase<isFirst, FirstProcessor, SubsequentProcessors...>>
111 {
112 using Base = ChainElement<isFirst, FirstProcessor, ChainBase<isFirst, FirstProcessor, SubsequentProcessors...>>;
113
114 template <typename ProcessContext>
115 void process (const ProcessContext& context) noexcept { Base::process (context); processors.process (context); }
116 void prepare (const ProcessSpec& spec) { Base::prepare (spec); processors.prepare (spec); }
117 void reset() { Base::reset(); processors.reset(); }
118
119 ChainBase<false, SubsequentProcessors...> processors;
120 };
121
122 template <bool isFirst, typename ProcessorType>
123 struct ChainBase<isFirst, ProcessorType> : public ChainElement<isFirst, ProcessorType, ChainBase<isFirst, ProcessorType>> {};
124}
125#endif
126
127
128//==============================================================================
133template <typename... Processors>
134using ProcessorChain = ProcessorHelpers::ChainBase<true, Processors...>;
135
136} // namespace dsp
137} // namespace juce