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