1 // Copyright 2013 Emilie Gillet.
2 //
3 // Author: Emilie Gillet (emilie.o.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 // This is the common entry points for all types of modulation sources!
28 
29 #ifndef PEAKS_PROCESSORS_H_
30 #define PEAKS_PROCESSORS_H_
31 
32 #include "stmlib/stmlib.h"
33 
34 #include <algorithm>
35 
36 #include "peaks/drums/bass_drum.h"
37 #include "peaks/drums/fm_drum.h"
38 #include "peaks/drums/snare_drum.h"
39 #include "peaks/drums/high_hat.h"
40 #include "peaks/modulations/bouncing_ball.h"
41 #include "peaks/modulations/lfo.h"
42 #include "peaks/modulations/mini_sequencer.h"
43 #include "peaks/modulations/multistage_envelope.h"
44 #include "peaks/number_station/number_station.h"
45 #include "peaks/pulse_processor/pulse_shaper.h"
46 #include "peaks/pulse_processor/pulse_randomizer.h"
47 
48 #include "peaks/gate_processor.h"
49 
50 namespace peaks {
51 
52 enum ProcessorFunction {
53   PROCESSOR_FUNCTION_ENVELOPE,
54   PROCESSOR_FUNCTION_LFO,
55   PROCESSOR_FUNCTION_TAP_LFO,
56   PROCESSOR_FUNCTION_BASS_DRUM,
57   PROCESSOR_FUNCTION_SNARE_DRUM,
58   PROCESSOR_FUNCTION_HIGH_HAT,
59   PROCESSOR_FUNCTION_FM_DRUM,
60   PROCESSOR_FUNCTION_PULSE_SHAPER,
61   PROCESSOR_FUNCTION_PULSE_RANDOMIZER,
62   PROCESSOR_FUNCTION_BOUNCING_BALL,
63   PROCESSOR_FUNCTION_MINI_SEQUENCER,
64   PROCESSOR_FUNCTION_NUMBER_STATION,
65   PROCESSOR_FUNCTION_LAST
66 };
67 
68 #define DECLARE_PROCESSOR(ClassName, variable) \
69   void ClassName ## Init() { \
70     variable.Init(); \
71   } \
72   void ClassName ## Process(const GateFlags* gate_flags, int16_t* out, size_t size) { \
73     variable.Process(gate_flags, out, size); \
74   } \
75   void ClassName ## Configure(uint16_t* p, ControlMode control_mode) { \
76     variable.Configure(p, control_mode); \
77   } \
78   ClassName variable;
79 
80 class Processors {
81  public:
Processors()82   Processors() { }
~Processors()83   ~Processors() { }
84 
85   void Init(uint8_t index);
86 
87   typedef void (Processors::*InitFn)();
88   typedef void (Processors::*ProcessFn)(const GateFlags*, int16_t*, size_t);
89   typedef void (Processors::*ConfigureFn)(uint16_t*, ControlMode);
90 
91   struct ProcessorCallbacks {
92     InitFn init_fn;
93     ProcessFn process_fn;
94     ConfigureFn configure_fn;
95   };
96 
set_control_mode(ControlMode control_mode)97   inline void set_control_mode(ControlMode control_mode) {
98     control_mode_ = control_mode;
99     Configure();
100   }
101 
set_parameter(uint8_t index,uint16_t parameter)102   inline void set_parameter(uint8_t index, uint16_t parameter) {
103     parameter_[index] = parameter;
104     Configure();
105   }
106 
CopyParameters(uint16_t * parameters,uint16_t size)107   inline void CopyParameters(uint16_t* parameters, uint16_t size) {
108     std::copy(&parameters[0], &parameters[size], &parameter_[0]);
109   }
110 
set_function(ProcessorFunction function)111   inline void set_function(ProcessorFunction function) {
112     function_ = function;
113     lfo_.set_sync(function == PROCESSOR_FUNCTION_TAP_LFO);
114     callbacks_ = callbacks_table_[function];
115     if (function != PROCESSOR_FUNCTION_TAP_LFO) {
116       (this->*callbacks_.init_fn)();
117     }
118     Configure();
119   }
120 
function()121   inline ProcessorFunction function() const { return function_; }
122 
Process(const GateFlags * gate_flags,int16_t * output,size_t size)123   inline void Process(const GateFlags* gate_flags, int16_t* output, size_t size) {
124     (this->*callbacks_.process_fn)(gate_flags, output, size);
125   }
126 
number_station()127   inline const NumberStation& number_station() const { return number_station_; }
128 
129  private:
Configure()130   void Configure() {
131     if (function_ == PROCESSOR_FUNCTION_SNARE_DRUM ||
132         function_ == PROCESSOR_FUNCTION_HIGH_HAT) {
133       uint16_t tone_parameter = control_mode_ == CONTROL_MODE_FULL
134           ? parameter_[1] : parameter_[0];
135       uint16_t snappy_parameter = control_mode_ == CONTROL_MODE_FULL
136           ? parameter_[2] : parameter_[1];
137       if (tone_parameter >= 65000 && snappy_parameter >= 65000) {
138         if (function_ != PROCESSOR_FUNCTION_HIGH_HAT) {
139           set_function(PROCESSOR_FUNCTION_HIGH_HAT);
140         }
141       } else if (tone_parameter <= 64500 || snappy_parameter <= 64500) {
142         if (function_ != PROCESSOR_FUNCTION_SNARE_DRUM) {
143           set_function(PROCESSOR_FUNCTION_SNARE_DRUM);
144         }
145       }
146     }
147     (this->*callbacks_.configure_fn)(&parameter_[0], control_mode_);
148   }
149 
150   ControlMode control_mode_;
151   ProcessorFunction function_;
152   uint16_t parameter_[4];
153 
154   ProcessorCallbacks callbacks_;
155   static const ProcessorCallbacks callbacks_table_[PROCESSOR_FUNCTION_LAST];
156 
157   DECLARE_PROCESSOR(MultistageEnvelope, envelope_);
158   DECLARE_PROCESSOR(Lfo, lfo_);
159   DECLARE_PROCESSOR(BassDrum, bass_drum_);
160   DECLARE_PROCESSOR(SnareDrum, snare_drum_);
161   DECLARE_PROCESSOR(HighHat, high_hat_);
162   DECLARE_PROCESSOR(FmDrum, fm_drum_);
163   DECLARE_PROCESSOR(PulseShaper, pulse_shaper_);
164   DECLARE_PROCESSOR(PulseRandomizer, pulse_randomizer_);
165   DECLARE_PROCESSOR(BouncingBall, bouncing_ball_);
166   DECLARE_PROCESSOR(MiniSequencer, mini_sequencer_);
167   DECLARE_PROCESSOR(NumberStation, number_station_);
168 
169   DISALLOW_COPY_AND_ASSIGN(Processors);
170 };
171 
172 extern Processors processors[2];
173 
174 }  // namespace peaks
175 
176 #endif  // PEAKS_PROCESSORS_H_
177