1 /*
2 ** Surge Synthesizer is Free and Open Source Software
3 **
4 ** Surge is made available under the Gnu General Public License, v3.0
5 ** https://www.gnu.org/licenses/gpl-3.0.en.html
6 **
7 ** Copyright 2004-2020 by various individuals as described by the Git transaction log
8 **
9 ** All source at: https://github.com/surge-synthesizer/surge.git
10 **
11 ** Surge was a commercial product from 2004-2018, with Copyright and ownership
12 ** in that period held by Claes Johanson at Vember Audio. Claes made Surge
13 ** open source in September 2018.
14 */
15 
16 #pragma once
17 
18 #include <random>
19 
20 enum modsrctype
21 {
22     mst_undefined = 0,
23     mst_controller,
24     mst_adsr,
25     mst_lfo,
26     mst_stepseq,
27 };
28 
29 enum modsources
30 {
31     ms_original = 0,
32     ms_velocity,
33     ms_keytrack,
34     ms_polyaftertouch,
35     ms_aftertouch,
36     ms_pitchbend,
37     ms_modwheel,
38     ms_ctrl1,
39     ms_ctrl2,
40     ms_ctrl3,
41     ms_ctrl4,
42     ms_ctrl5,
43     ms_ctrl6,
44     ms_ctrl7,
45     ms_ctrl8,
46     ms_ampeg,
47     ms_filtereg,
48     ms_lfo1,
49     ms_lfo2,
50     ms_lfo3,
51     ms_lfo4,
52     ms_lfo5,
53     ms_lfo6,
54     ms_slfo1,
55     ms_slfo2,
56     ms_slfo3,
57     ms_slfo4,
58     ms_slfo5,
59     ms_slfo6,
60     ms_timbre,
61     ms_releasevelocity,
62     ms_random_bipolar,
63     ms_random_unipolar,
64     ms_alternate_bipolar,
65     ms_alternate_unipolar,
66     ms_breath,
67     ms_expression,
68     ms_sustain,
69     ms_lowest_key,
70     ms_highest_key,
71     ms_latest_key,
72     n_modsources,
73 };
74 
75 const int modsource_display_order[n_modsources] = {
76     ms_original,
77     ms_velocity,
78     ms_releasevelocity,
79     ms_keytrack,
80     ms_lowest_key,
81     ms_highest_key,
82     ms_latest_key,
83     ms_polyaftertouch,
84     ms_aftertouch,
85     ms_modwheel,
86     ms_breath,
87     ms_expression,
88     ms_sustain,
89     ms_pitchbend,
90     ms_timbre,
91     ms_alternate_bipolar,
92     ms_alternate_unipolar,
93     ms_random_bipolar,
94     ms_random_unipolar,
95     ms_filtereg,
96     ms_ampeg,
97     ms_lfo1,
98     ms_lfo2,
99     ms_lfo3,
100     ms_lfo4,
101     ms_lfo5,
102     ms_lfo6,
103     ms_slfo1,
104     ms_slfo2,
105     ms_slfo3,
106     ms_slfo4,
107     ms_slfo5,
108     ms_slfo6,
109     ms_ctrl1,
110     ms_ctrl2,
111     ms_ctrl3,
112     ms_ctrl4,
113     ms_ctrl5,
114     ms_ctrl6,
115     ms_ctrl7,
116     ms_ctrl8,
117 };
118 
119 const int n_customcontrollers = 8;
120 const int num_metaparameters = n_customcontrollers;
121 extern float samplerate_inv;
122 extern float samplerate;
123 
124 const char modsource_names_button[n_modsources][32] = {
125     "Off",          "Velocity", "Keytrack",   "Poly AT",     "Channel AT",    "Pitch Bend",
126     "Modwheel",     "Macro 1",  "Macro 2",    "Macro 3",     "Macro 4",       "Macro 5",
127     "Macro 6",      "Macro 7",  "Macro 8",    "Amp EG",      "Filter EG",     "LFO 1",
128     "LFO 2",        "LFO 3",    "LFO 4",      "LFO 5",       "LFO 6",         "S-LFO 1",
129     "S-LFO 2",      "S-LFO 3",  "S-LFO 4",    "S-LFO 5",     "S-LFO 6",       "MPE Timbre",
130     "Rel Velocity", "Random",   "Random Uni", "Alternate",   "Alternate Uni", "Breath",
131     "Expression",   "Sustain",  "Lowest Key", "Highest Key", "Latest Key",
132 };
133 
134 const char modsource_names[n_modsources][32] = {
135     "Off",
136     "Velocity",
137     "Keytrack",
138     "Polyphonic Aftertouch",
139     "Channel Aftertouch",
140     "Pitch Bend",
141     "Modulation Wheel",
142     "Macro 1",
143     "Macro 2",
144     "Macro 3",
145     "Macro 4",
146     "Macro 5",
147     "Macro 6",
148     "Macro 7",
149     "Macro 8",
150     "Amp EG",
151     "Filter EG",
152     "Voice LFO 1",
153     "Voice LFO 2",
154     "Voice LFO 3",
155     "Voice LFO 4",
156     "Voice LFO 5",
157     "Voice LFO 6",
158     "Scene LFO 1",
159     "Scene LFO 2",
160     "Scene LFO 3",
161     "Scene LFO 4",
162     "Scene LFO 5",
163     "Scene LFO 6",
164     "MPE Timbre",
165     "Release Velocity",
166     "Random Bipolar",
167     "Random Unipolar",
168     "Alternate Bipolar",
169     "Alternate Unipolar",
170     "Breath",
171     "Expression",
172     "Sustain Pedal",
173     "Lowest Key",
174     "Highest Key",
175     "Latest Key",
176 };
177 
178 const char modsource_names_tag[n_modsources][32] = {
179     "off",    "vel",    "keytrack",    "poly_at",    "chan_at",     "pbend",      "mwheel",
180     "macro1", "macro2", "macro3",      "macro4",     "macro5",      "macro6",     "macro7",
181     "macro8", "amp_eg", "filter_eg",   "lfo1",       "lfo2",        "lfo3",       "lfo4",
182     "lfo5",   "lfo6",   "slfo1",       "slfo2",      "slfo3",       "slfo4",      "slfo5",
183     "slfo6",  "timbre", "release_vel", "random",     "random_uni",  "alt",        "alt_uni",
184     "breath", "expr",   "sustain",     "lowest_key", "highest_key", "latest_key",
185 };
186 
187 const int modsource_grid_xy[n_modsources][2] = {
188     {0, 0}, // Velocity
189     {0, 3}, // Keytrack
190     {6, 7}, // Poly AT
191     {2, 3}, // Channel
192     {3, 3}, // AT
193     {4, 3}, // Pitch Bend
194     {5, 3}, // Modwheel
195     {0, 0}, // Macro 1
196     {1, 0}, // Macro 2
197     {2, 0}, // Macro 3
198     {3, 0}, // Macro 4
199     {4, 0}, // Macro 5
200     {5, 0}, // Macro 6
201     {6, 0}, // Macro 7
202     {7, 0}, // Macro 8
203     {7, 5}, // AEG
204     {6, 5}, // FEG
205     {0, 5}, // LFO 1
206     {1, 5}, // LFO 2
207     {2, 5}, // LFO 3
208     {3, 5}, // LFO 4
209     {4, 5}, // LFO 5
210     {5, 5}, // LFO 6
211     {0, 7}, // S-LFO 1
212     {1, 7}, // S-LFO 2
213     {2, 7}, // S-LFO 3
214     {3, 7}, // S-LFO 4
215     {4, 7}, // S-LFO 5
216     {5, 7}, // S-LFO 6
217     {9, 3}, // Timbre
218     {1, 3}, // Release Velocity
219     {8, 5}, // Random Bi
220     {8, 5}, // Random Uni
221     {9, 5}, // Alternate Bi
222     {9, 5}, // Alternate Uni
223     {6, 3}, // Breath
224     {7, 3}, // Expression
225     {8, 3}, // Sustain
226     {7, 7}, // Lowest Key
227     {8, 7}, // Highest Key
228     {9, 7}, // Latest Key
229 };
230 
isScenelevel(modsources ms)231 inline bool isScenelevel(modsources ms)
232 {
233     return (((ms <= ms_ctrl8) || ((ms >= ms_slfo1) && (ms <= ms_slfo6))) &&
234             ((ms != ms_velocity) && (ms != ms_keytrack) && (ms != ms_polyaftertouch) &&
235              (ms != ms_releasevelocity))) ||
236            ((ms >= ms_breath) && (ms <= ms_latest_key));
237 }
238 
canModulateMonophonicTarget(modsources ms)239 inline bool canModulateMonophonicTarget(modsources ms)
240 {
241     return isScenelevel(ms) || ms == ms_aftertouch;
242 }
243 
isCustomController(modsources ms)244 inline bool isCustomController(modsources ms) { return (ms >= ms_ctrl1) && (ms <= ms_ctrl8); }
245 
isEnvelope(modsources ms)246 inline bool isEnvelope(modsources ms) { return (ms == ms_ampeg) || (ms == ms_filtereg); }
247 
isLFO(modsources ms)248 inline bool isLFO(modsources ms) { return (ms >= ms_lfo1) && (ms <= ms_slfo6); }
249 
canModulateModulators(modsources ms)250 inline bool canModulateModulators(modsources ms) { return (ms != ms_ampeg) && (ms != ms_filtereg); }
251 
isVoiceModulator(modsources ms)252 inline bool isVoiceModulator(modsources ms) { return !((ms >= ms_slfo1) && (ms <= ms_slfo6)); }
253 
canModulateVoiceModulators(modsources ms)254 inline bool canModulateVoiceModulators(modsources ms)
255 {
256     return (ms <= ms_ctrl8) || ms == ms_timbre;
257 }
258 
259 struct ModulationRouting
260 {
261     int source_id;
262     int destination_id;
263     float depth;
264 };
265 
266 class ModulationSource
267 {
268   public:
ModulationSource()269     ModulationSource() {}
~ModulationSource()270     virtual ~ModulationSource() {}
get_title()271     virtual const char *get_title() { return 0; }
get_type()272     virtual int get_type() { return mst_undefined; }
process_block()273     virtual void process_block() {}
attack()274     virtual void attack(){};
release()275     virtual void release(){};
reset()276     virtual void reset(){};
get_output()277     virtual float get_output() { return output; }
get_output01()278     virtual float get_output01() { return output; }
per_voice()279     virtual bool per_voice() { return false; }
is_bipolar()280     virtual bool is_bipolar() { return false; }
set_bipolar(bool b)281     virtual void set_bipolar(bool b) {}
282     float output;
283 };
284 
285 class ControllerModulationSource : public ModulationSource
286 {
287   public:
288     // Smoothing and Shaping Behaviors
289     enum SmoothingMode
290     {
291         LEGACY = -1, // This is (1) the exponential backoff and (2) not streamed.
292         SLOW_EXP,    // Legacy with a sigma clamp
293         FAST_EXP,    // Faster Legacy with a sigma clamp
294         FAST_LINE,   // Linearly move
295         DIRECT       // Apply the value directly
296     } smoothingMode = LEGACY;
297 
ControllerModulationSource()298     ControllerModulationSource()
299     {
300         target = 0.f;
301         output = 0.f;
302         bipolar = false;
303         changed = true;
304         smoothingMode = LEGACY;
305     }
ControllerModulationSource(SmoothingMode mode)306     ControllerModulationSource(SmoothingMode mode) : ControllerModulationSource()
307     {
308         smoothingMode = mode;
309     }
310 
~ControllerModulationSource()311     virtual ~ControllerModulationSource() {}
set_target(float f)312     void set_target(float f)
313     {
314         target = f;
315         startingpoint = output;
316         changed = true;
317     }
318 
init(float f)319     void init(float f)
320     {
321         target = f;
322         output = f;
323         startingpoint = f;
324         changed = true;
325     }
326 
327     void set_target01(float f, bool updatechanged = true)
328     {
329         if (bipolar)
330             target = 2.f * f - 1.f;
331         else
332             target = f;
333         startingpoint = output;
334         if (updatechanged)
335             changed = true;
336     }
337 
get_output01()338     virtual float get_output01() override
339     {
340         if (bipolar)
341             return 0.5f + 0.5f * output;
342         return output;
343     }
344 
get_target01()345     virtual float get_target01()
346     {
347         if (bipolar)
348             return 0.5f + 0.5f * target;
349         return target;
350     }
351 
has_changed(bool reset)352     virtual bool has_changed(bool reset)
353     {
354         if (changed)
355         {
356             if (reset)
357                 changed = false;
358             return true;
359         }
360         return false;
361     }
362 
reset()363     virtual void reset() override
364     {
365         target = 0.f;
366         output = 0.f;
367         bipolar = false;
368     }
processSmoothing(SmoothingMode mode,float sigma)369     inline void processSmoothing(SmoothingMode mode, float sigma)
370     {
371         if (mode == LEGACY || mode == SLOW_EXP || mode == FAST_EXP)
372         {
373             float b = fabs(target - output);
374             if (b < sigma && mode != LEGACY)
375             {
376                 output = target;
377             }
378             else
379             {
380                 float a = (mode == FAST_EXP ? 0.99f : 0.9f) * 44100 * samplerate_inv * b;
381                 output = (1 - a) * output + a * target;
382             }
383             return;
384         };
385         if (mode == FAST_LINE)
386         {
387             /*
388              * Apply a constant change until we get there.
389              * Rate is set so we cover the entire range (0,1)
390              * in 50 blocks at 44k
391              */
392             float sampf = samplerate / 44100;
393             float da = (target - startingpoint) / (50 * sampf);
394             float b = target - output;
395             if (fabs(b) < fabs(da))
396             {
397                 output = target;
398             }
399             else
400             {
401                 output += da;
402             }
403         }
404         if (mode == DIRECT)
405         {
406             output = target;
407         }
408     }
process_block()409     virtual void process_block() override
410     {
411         processSmoothing(smoothingMode, smoothingMode == FAST_EXP ? 0.005f : 0.0025f);
412     }
413 
process_block_until_close(float sigma)414     virtual bool process_block_until_close(float sigma)
415     {
416         if (smoothingMode == LEGACY)
417             processSmoothing(SLOW_EXP, sigma);
418         else
419             processSmoothing(smoothingMode, sigma);
420 
421         return (output != target); // continue
422     }
423 
is_bipolar()424     virtual bool is_bipolar() override { return bipolar; }
set_bipolar(bool b)425     virtual void set_bipolar(bool b) override { bipolar = b; }
426 
427     float target, startingpoint;
428     int id; // can be used to assign the controller to a parameter id
429     bool bipolar;
430     bool changed;
431 };
432 
433 class RandomModulationSource : public ModulationSource
434 {
435   public:
RandomModulationSource(bool bp)436     RandomModulationSource(bool bp) : bipolar(bp)
437     {
438         std::random_device rd;
439         gen = std::minstd_rand(rd());
440         if (bp)
441             dis = std::uniform_real_distribution<float>(-1.0, 1.0);
442         else
443             dis = std::uniform_real_distribution<float>(0.0, 1.0);
444     }
445 
attack()446     virtual void attack() override { output = dis(gen); }
447 
448     bool bipolar;
449     std::minstd_rand gen;
450     std::uniform_real_distribution<float> dis;
451 };
452 
453 class AlternateModulationSource : public ModulationSource
454 {
455   public:
AlternateModulationSource(bool bp)456     AlternateModulationSource(bool bp) : state(false)
457     {
458         if (bp)
459             nv = -1;
460         else
461             nv = 0;
462 
463         pv = 1;
464     }
465 
attack()466     virtual void attack() override
467     {
468         if (state)
469             output = pv;
470         else
471             output = nv;
472         state = !state;
473     }
474 
475     bool state;
476     float nv, pv;
477 };
478