1 // Copyright 2014 Olivier Gillet.
2 //
3 // Author: Olivier Gillet (ol.gillet@gmail.com)
4 //
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 //
12 // The above copyright notice and this permission notice shall be included in
13 // all copies or substantial portions of the Software.
14 //
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 // THE SOFTWARE.
22 //
23 // See http://creativecommons.org/licenses/MIT/ for more information.
24 //
25 // -----------------------------------------------------------------------------
26 //
27 // Generic class interfacing all dynamics processors.
28 
29 #ifndef STREAMS_PROCESSOR_H_
30 #define STREAMS_PROCESSOR_H_
31 
32 #include <cstdio>
33 
34 #include "stmlib/stmlib.h"
35 
36 #include "streams/compressor.h"
37 #include "streams/envelope.h"
38 #include "streams/filter_controller.h"
39 #include "streams/follower.h"
40 #include "streams/lorenz_generator.h"
41 #include "streams/vactrol.h"
42 
43 namespace streams {
44 
45 enum ProcessorFunction {
46   PROCESSOR_FUNCTION_ENVELOPE,
47   PROCESSOR_FUNCTION_VACTROL,
48   PROCESSOR_FUNCTION_FOLLOWER,
49   PROCESSOR_FUNCTION_COMPRESSOR,
50   PROCESSOR_FUNCTION_FILTER_CONTROLLER,
51   PROCESSOR_FUNCTION_LORENZ_GENERATOR,
52   PROCESSOR_FUNCTION_LAST
53 };
54 
55 #define DECLARE_PROCESSOR(ClassName, variable) \
56   void ClassName ## Init() { \
57     variable.Init(); \
58   } \
59   void ClassName ## Process(int16_t a, int16_t e, uint16_t* g, uint16_t* f) { \
60     variable.Process(a, e, g, f); \
61   } \
62   void ClassName ## Configure(bool a, int32_t* p, int32_t* g) { \
63     variable.Configure(a, p, g); \
64   } \
65   ClassName variable;
66 
67 
68 class Processor {
69  public:
Processor()70   Processor() { }
~Processor()71   ~Processor() { }
72 
73   void Init(uint8_t index);
Init()74   void Init() { Init(0); }
75 
76   typedef void (Processor::*InitFn)();
77   typedef void (Processor::*ProcessFn)(
78       int16_t,
79       int16_t,
80       uint16_t*,
81       uint16_t*);
82   typedef void (Processor::*ConfigureFn)(
83       bool,
84       int32_t*,
85       int32_t*);
86 
87   struct ProcessorCallbacks {
88     InitFn init;
89     ProcessFn process;
90     ConfigureFn configure;
91   };
92 
set_function(ProcessorFunction function)93   inline void set_function(ProcessorFunction function) {
94     function_ = function;
95     callbacks_ = callbacks_table_[function];
96     (this->*callbacks_.init)();
97     dirty_ = true;
98   }
99 
set_alternate(bool alternate)100   inline void set_alternate(bool alternate) {
101     alternate_ = alternate;
102     dirty_ = true;
103   }
104 
set_linked(bool linked)105   inline void set_linked(bool linked) {
106     linked_ = linked;
107     dirty_ = true;
108   }
109 
set_parameter(uint16_t index,uint16_t value)110   inline void set_parameter(uint16_t index, uint16_t value) {
111     parameters_[index] = value;
112     dirty_ = true;
113   }
set_global(uint16_t index,uint16_t value)114   inline void set_global(uint16_t index, uint16_t value) {
115     globals_[index] = value;
116     dirty_ = linked_;
117   }
118 
function()119   inline ProcessorFunction function() const { return function_; }
alternate()120   inline bool alternate() const { return alternate_; }
linked()121   inline bool linked() const { return linked_; }
last_frequency()122   inline uint8_t last_frequency() const { return last_frequency_value_ >> 8; }
last_gain()123   inline uint8_t last_gain() const { return last_gain_value_ >> 8; }
gain_reduction()124   inline int32_t gain_reduction() const { return compressor_.gain_reduction(); }
125 
Process(int16_t audio,int16_t excite,uint16_t * gain,uint16_t * frequency)126   inline void Process(
127       int16_t audio,
128       int16_t excite,
129       uint16_t* gain,
130       uint16_t* frequency) {
131     (this->*callbacks_.process)(audio, excite, gain, frequency);
132     last_gain_value_ = *gain;
133     last_frequency_value_ = *frequency;
134   }
135 
Configure()136   void Configure() {
137     if (!dirty_) {
138       return;
139     }
140     (this->*callbacks_.configure)(
141         alternate_,
142         parameters_,
143         linked_ ? globals_ : NULL);
144     dirty_ = false;
145   }
146 
147  private:
148   uint8_t index_;
149   ProcessorFunction function_;
150   bool linked_;
151   bool alternate_;
152   bool dirty_;
153   int32_t parameters_[2];
154   int32_t globals_[4];
155 
156   uint16_t last_gain_value_;
157   uint16_t last_frequency_value_;
158 
159   ProcessorCallbacks callbacks_;
160   static const ProcessorCallbacks callbacks_table_[PROCESSOR_FUNCTION_LAST];
161 
162   DECLARE_PROCESSOR(Envelope, envelope_);
163   DECLARE_PROCESSOR(Vactrol, vactrol_);
164   DECLARE_PROCESSOR(Follower, follower_);
165   DECLARE_PROCESSOR(Compressor, compressor_);
166   DECLARE_PROCESSOR(FilterController, filter_controller_);
167   DECLARE_PROCESSOR(LorenzGenerator, lorenz_generator_);
168 
169   DISALLOW_COPY_AND_ASSIGN(Processor);
170 };
171 
172 }  // namespace streams
173 
174 #endif  // STREAMS_PROCESSOR_H_
175