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 #include "SurgeSynthesizer.h"
17 #include "DspUtilities.h"
18 #include <ctime>
19 #if MAC || LINUX
20 #include <pthread.h>
21 #else
22 #include <windows.h>
23 #include <process.h>
24 #endif
25 
26 #if TARGET_AUDIOUNIT
27 #include "aulayer.h"
28 #elif TARGET_VST3
29 #include "SurgeVst3Processor.h"
30 #include "vstgui/plugin-bindings/plugguieditor.h"
31 #elif TARGET_LV2
32 #include "SurgeLv2Wrapper.h"
33 #include "vstgui/plugin-bindings/plugguieditor.h"
34 #elif TARGET_APP
35 #include "PluginLayer.h"
36 #include "vstgui/plugin-bindings/plugguieditor.h"
37 #elif TARGET_JUCE
38 #include "JUCEPluginLayerProxy.h"
39 #elif TARGET_JUCE_UI
40 #include "SurgeSynthProcessor.h"
41 #elif TARGET_HEADLESS
42 #include "HeadlessPluginLayerProxy.h"
43 #else
44 #include "Vst2PluginInstance.h"
45 
46 #if LINUX
47 #include "../linux/linux-aeffguieditor.h"
48 #else
49 #include "vstgui/plugin-bindings/aeffguieditor.h"
50 #endif
51 #endif
52 #include "SurgeParamConfig.h"
53 
54 #include "UserDefaults.h"
55 #include "filesystem/import.h"
56 #include "effect/Effect.h"
57 
58 #include <thread>
59 #include "libMTSClient.h"
60 
61 using namespace std;
62 
SurgeSynthesizer(PluginLayer * parent,std::string suppliedDataPath)63 SurgeSynthesizer::SurgeSynthesizer(PluginLayer *parent, std::string suppliedDataPath)
64     //: halfband_AL(false),halfband_AR(false),halfband_BL(false),halfband_BR(false),
65     : storage(suppliedDataPath), hpA(&storage), hpB(&storage), _parent(parent), halfbandA(6, true),
66       halfbandB(6, true), halfbandIN(6, true)
67 {
68     switch_toggled_queued = false;
69     audio_processing_active = false;
70     halt_engine = false;
71     release_if_latched[0] = true;
72     release_if_latched[1] = true;
73     release_anyway[0] = false;
74     release_anyway[1] = false;
75     load_fx_needed = true;
76     process_input = false; // hosts set this if there are input busses
77 
78     fx_suspend_bitmask = 0;
79 
80     demo_counter = 10;
81 
82     // TODO: FIX NUMBER OF FX ASSUMPTION
83     memset(fx, 0, sizeof(void *) * 8);
84     srand((unsigned)time(nullptr));
85     // TODO: FIX SCENE ASSUMPTION
86     memset(storage.getPatch().scenedata[0], 0, sizeof(pdata) * n_scene_params);
87     memset(storage.getPatch().scenedata[1], 0, sizeof(pdata) * n_scene_params);
88     memset(storage.getPatch().globaldata, 0, sizeof(pdata) * n_global_params);
89     memset(mControlInterpolatorUsed, 0, sizeof(bool) * num_controlinterpolators);
90     memset((void *)fxsync, 0, sizeof(FxStorage) * n_fx_slots);
91 
92     for (int i = 0; i < n_fx_slots; i++)
93     {
94         memcpy((void *)&fxsync[i], (void *)&storage.getPatch().fx[i], sizeof(FxStorage));
95         fx_reload[i] = false;
96         fx_reload_mod[i] = false;
97     }
98 
99     allNotesOff();
100 
101     for (int i = 0; i < MAX_VOICES; i++)
102     {
103         voices_usedby[0][i] = 0;
104         voices_usedby[1][i] = 0;
105     }
106 
107     for (int sc = 0; sc < n_scenes; sc++)
108     {
109         FBQ[sc] = (QuadFilterChainState *)_aligned_malloc(
110             (MAX_VOICES >> 2) * sizeof(QuadFilterChainState), 16);
111 
112         for (int i = 0; i < (MAX_VOICES >> 2); ++i)
113         {
114             InitQuadFilterChainStateToZero(&(FBQ[sc][i]));
115         }
116     }
117 
118     SurgePatch &patch = storage.getPatch();
119 
120     storage.smoothingMode =
121         (ControllerModulationSource::SmoothingMode)(int)Surge::Storage::getUserDefaultValue(
122             &storage, "smoothingMode", (int)(ControllerModulationSource::SmoothingMode::LEGACY));
123     storage.pitchSmoothingMode =
124         (ControllerModulationSource::SmoothingMode)(int)Surge::Storage::getUserDefaultValue(
125             &storage, "pitchSmoothingMode",
126             (int)(ControllerModulationSource::SmoothingMode::DIRECT));
127 
128     patch.polylimit.val.i = DEFAULT_POLYLIMIT;
129 
130     for (int sc = 0; sc < n_scenes; sc++)
131     {
132         SurgeSceneStorage &scene = patch.scene[sc];
133         scene.modsources.resize(n_modsources);
134 
135         for (int i = 0; i < n_modsources; i++)
136         {
137             scene.modsources[i] = 0;
138         }
139         scene.modsources[ms_modwheel] = new ControllerModulationSource(storage.smoothingMode);
140         scene.modsources[ms_breath] = new ControllerModulationSource(storage.smoothingMode);
141         scene.modsources[ms_expression] = new ControllerModulationSource(storage.smoothingMode);
142         scene.modsources[ms_sustain] = new ControllerModulationSource(storage.smoothingMode);
143         scene.modsources[ms_aftertouch] = new ControllerModulationSource(storage.smoothingMode);
144         scene.modsources[ms_pitchbend] = new ControllerModulationSource(storage.smoothingMode);
145         scene.modsources[ms_lowest_key] = new ControllerModulationSource(storage.smoothingMode);
146         scene.modsources[ms_highest_key] = new ControllerModulationSource(storage.smoothingMode);
147         scene.modsources[ms_latest_key] = new ControllerModulationSource(storage.smoothingMode);
148 
149         ((ControllerModulationSource *)scene.modsources[ms_lowest_key])->init(0.f);
150         ((ControllerModulationSource *)scene.modsources[ms_highest_key])->init(0.f);
151         ((ControllerModulationSource *)scene.modsources[ms_latest_key])->init(0.f);
152 
153         scene.modsources[ms_random_bipolar] = new RandomModulationSource(true);
154         scene.modsources[ms_random_unipolar] = new RandomModulationSource(false);
155         scene.modsources[ms_alternate_bipolar] = new AlternateModulationSource(true);
156         scene.modsources[ms_alternate_unipolar] = new AlternateModulationSource(false);
157 
158         for (int osc = 0; osc < n_oscs; osc++)
159         {
160             // p 5 is unison detune
161             scene.osc[osc].p[5].val.f = 0.1f;
162         }
163 
164         for (int i = 0; i < n_filterunits_per_scene; i++)
165         {
166             scene.filterunit[i].type.set_user_data(&patch.patchFilterSelectorMapper);
167         }
168 
169         scene.filterblock_configuration.val.i = fc_wide;
170 
171         for (int l = 0; l < n_lfos_scene; l++)
172         {
173             scene.modsources[ms_slfo1 + l] = new LfoModulationSource();
174             ((LfoModulationSource *)scene.modsources[ms_slfo1 + l])
175                 ->assign(&storage, &scene.lfo[n_lfos_voice + l], storage.getPatch().scenedata[sc],
176                          0, &patch.stepsequences[sc][n_lfos_voice + l],
177                          &patch.msegs[sc][n_lfos_voice + l],
178                          &patch.formulamods[sc][n_lfos_voice + l]);
179         }
180 
181         for (int k = 0; k < 128; ++k)
182             midiKeyPressedForScene[sc][k] = 0;
183     }
184 
185     for (int i = 0; i < n_customcontrollers; i++)
186     {
187         patch.scene[0].modsources[ms_ctrl1 + i] =
188             new ControllerModulationSource(storage.smoothingMode);
189 
190         for (int j = 1; j < n_scenes; j++)
191         {
192             patch.scene[j].modsources[ms_ctrl1 + i] = patch.scene[0].modsources[ms_ctrl1 + i];
193         }
194     }
195 
196     amp.set_blocksize(BLOCK_SIZE);
197     // TODO: FIX SCENE ASSUMPTION
198     FX1.set_blocksize(BLOCK_SIZE);
199     FX2.set_blocksize(BLOCK_SIZE);
200     send[0][0].set_blocksize(BLOCK_SIZE);
201     send[0][1].set_blocksize(BLOCK_SIZE);
202     send[1][0].set_blocksize(BLOCK_SIZE);
203     send[1][1].set_blocksize(BLOCK_SIZE);
204 
205     polydisplay = 0;
206     refresh_editor = false;
207     patch_loaded = false;
208     storage.getPatch().category = "Init";
209     storage.getPatch().name = "Init";
210     storage.getPatch().comment = "";
211     storage.getPatch().author = "Surge Synth Team";
212     midiprogramshavechanged = false;
213 
214     for (int i = 0; i < BLOCK_SIZE; i++)
215     {
216         input[0][i] = 0.f;
217         input[1][i] = 0.f;
218     }
219 
220     masterfade = 1.f;
221     current_category_id = -1;
222     patchid_queue = -1;
223     has_patchid_file = false;
224     patchid_file[0] = 0;
225     patchid = -1;
226     CC0 = 0;
227     CC32 = 0;
228     PCH = 0;
229 
230     for (int i = 0; i < 8; i++)
231     {
232         refresh_ctrl_queue[i] = -1;
233         refresh_parameter_queue[i] = -1;
234     }
235 
236     for (int i = 0; i < 8; i++)
237     {
238         vu_peak[i] = 0.f;
239     }
240 
241     learn_param = -1;
242     learn_custom = -1;
243 
244     for (int i = 0; i < 16; i++)
245     {
246         memset(&channelState[i], 0, sizeof(MidiChannelState));
247     }
248 
249     mpeEnabled = false;
250     mpeVoices = 0;
251     storage.mpePitchBendRange =
252         (float)Surge::Storage::getUserDefaultValue(&storage, "mpePitchBendRange", 48);
253     mpeGlobalPitchBendRange = 0;
254 
255 #if TARGET_VST3 || TARGET_VST2 || TARGET_AUDIOUNIT
256     // If we are in a DAW hosted environment, choose a preset from the preset library
257     // Skip LV2 until we sort out the patch change dynamics there
258     int pid = 0;
259     for (auto p : storage.patch_list)
260     {
261         if (p.name == "Init Saw" && storage.patch_category[p.category].name == "Init")
262         {
263             // patchid_queue = pid;
264             // This is the wrong thing to do. I *think* what we need to do here is to
265             // explicitly load the file directly inline on thread using loadPatchFromFile
266             // and set up the location int rather than defer the load. But do that
267             // later
268             break;
269         }
270         pid++;
271     }
272 #endif
273 }
274 
~SurgeSynthesizer()275 SurgeSynthesizer::~SurgeSynthesizer()
276 {
277     allNotesOff();
278 
279     for (int sc = 0; sc < n_scenes; sc++)
280     {
281         _aligned_free(FBQ[sc]);
282     }
283 
284     for (int sc = 0; sc < n_scenes; sc++)
285     {
286         delete storage.getPatch().scene[sc].modsources[ms_modwheel];
287         delete storage.getPatch().scene[sc].modsources[ms_breath];
288         delete storage.getPatch().scene[sc].modsources[ms_expression];
289         delete storage.getPatch().scene[sc].modsources[ms_sustain];
290         delete storage.getPatch().scene[sc].modsources[ms_aftertouch];
291         delete storage.getPatch().scene[sc].modsources[ms_pitchbend];
292         delete storage.getPatch().scene[sc].modsources[ms_lowest_key];
293         delete storage.getPatch().scene[sc].modsources[ms_highest_key];
294         delete storage.getPatch().scene[sc].modsources[ms_latest_key];
295 
296         delete storage.getPatch().scene[sc].modsources[ms_random_bipolar];
297         delete storage.getPatch().scene[sc].modsources[ms_random_unipolar];
298         delete storage.getPatch().scene[sc].modsources[ms_alternate_bipolar];
299         delete storage.getPatch().scene[sc].modsources[ms_alternate_unipolar];
300 
301         for (int i = 0; i < n_lfos_scene; i++)
302         {
303             delete storage.getPatch().scene[sc].modsources[ms_slfo1 + i];
304         }
305     }
306 
307     for (int i = 0; i < n_customcontrollers; i++)
308     {
309         delete storage.getPatch().scene[0].modsources[ms_ctrl1 + i];
310     }
311 }
312 
calculateChannelMask(int channel,int key)313 int SurgeSynthesizer::calculateChannelMask(int channel, int key)
314 {
315     /*
316     ** Just because I always forget
317     **
318     ** A voice is routed to scene n if channelmask & n. So "1" means scene A, "2" means scene B and
319     *"3" (= 2 | 1 ) = both.
320     */
321     int channelmask = channel;
322 
323     if ((channel == 0) || (channel > 2) || mpeEnabled ||
324         storage.getPatch().scenemode.val.i == sm_chsplit)
325     {
326         switch (storage.getPatch().scenemode.val.i)
327         {
328         case sm_single:
329             //	case sm_morph:
330             if (storage.getPatch().scene_active.val.i == 1)
331                 channelmask = 2;
332             else
333                 channelmask = 1;
334             break;
335         case sm_dual:
336             channelmask = 3;
337             break;
338         case sm_split:
339             if (key < storage.getPatch().splitpoint.val.i)
340                 channelmask = 1;
341             else
342                 channelmask = 2;
343             break;
344         case sm_chsplit:
345             if (channel < ((int)(storage.getPatch().splitpoint.val.i / 8) + 1))
346                 channelmask = 1;
347             else
348                 channelmask = 2;
349 
350             break;
351         }
352     }
353     else if (storage.getPatch().scenemode.val.i == sm_single)
354     {
355         if (storage.getPatch().scene_active.val.i == 1)
356             channelmask = 2;
357         else
358             channelmask = 1;
359     }
360 
361     return channelmask;
362 }
363 
playNote(char channel,char key,char velocity,char detune)364 void SurgeSynthesizer::playNote(char channel, char key, char velocity, char detune)
365 {
366     if (halt_engine)
367         return;
368 
369     if (storage.oddsound_mts_client && storage.oddsound_mts_active)
370     {
371         if (MTS_ShouldFilterNote(storage.oddsound_mts_client, key, channel))
372         {
373             return;
374         }
375     }
376 
377     // For split/dual
378     // MIDI Channel 1 plays the split/dual
379     // MIDI Channel 2 plays A
380     // MIDI Channel 3 plays B
381 
382     int channelmask = calculateChannelMask(channel, key);
383 
384     // TODO: FIX SCENE ASSUMPTION
385     if (channelmask & 1)
386     {
387         midiKeyPressedForScene[0][key] = ++orderedMidiKey;
388         playVoice(0, channel, key, velocity, detune);
389     }
390     if (channelmask & 2)
391     {
392         midiKeyPressedForScene[1][key] = ++orderedMidiKey;
393         playVoice(1, channel, key, velocity, detune);
394     }
395 
396     channelState[channel].keyState[key].keystate = velocity;
397     channelState[channel].keyState[key].lastdetune = detune;
398 
399     /*
400     ** OK so why is there hold stuff here? This is play not release.
401     ** Well if you release a key with the pedal down it goes into the
402     ** 'release me later' buffer. If you press the key again it stays there
403     ** so even with the key held, you end up releasing it when you pedal.
404     **
405     ** Or: NoteOn / Pedal On / Note Off / Note On / Pedal Off should leave the note ringing
406     **
407     ** and right now it doesn't
408     */
409     bool noHold = !channelState[channel].hold;
410     if (mpeEnabled)
411         noHold = noHold && !channelState[0].hold;
412 
413     if (!noHold)
414     {
415         for (int sc = 0; sc < n_scenes; ++sc)
416         {
417             for (auto &h : holdbuffer[sc])
418             {
419                 if (h.first == channel && h.second == key)
420                 {
421                     h.first = -1;
422                     h.second = -1;
423                 }
424             }
425         }
426     }
427 }
428 
softkillVoice(int s)429 void SurgeSynthesizer::softkillVoice(int s)
430 {
431     list<SurgeVoice *>::iterator iter, max_playing, max_released;
432     int max_age = 0, max_age_release = 0;
433     iter = voices[s].begin();
434 
435     while (iter != voices[s].end())
436     {
437         SurgeVoice *v = *iter;
438         assert(v);
439         if (v->state.gate)
440         {
441             if (v->age > max_age)
442             {
443                 max_age = v->age;
444                 max_playing = iter;
445             }
446         }
447         else if (!v->state.uberrelease)
448         {
449             if (v->age_release > max_age_release)
450             {
451                 max_age_release = v->age_release;
452                 max_released = iter;
453             }
454         }
455         iter++;
456     }
457     if (max_age_release)
458         (*max_released)->uber_release();
459     else if (max_age)
460         (*max_playing)->uber_release();
461 }
462 
463 // only allow 'margin' number of voices to be softkilled simultaneously
enforcePolyphonyLimit(int s,int margin)464 void SurgeSynthesizer::enforcePolyphonyLimit(int s, int margin)
465 {
466     list<SurgeVoice *>::iterator iter;
467 
468     if (voices[s].size() > (storage.getPatch().polylimit.val.i + margin))
469     {
470         int excess_voices =
471             max(0, (int)voices[s].size() - (storage.getPatch().polylimit.val.i + margin));
472         iter = voices[s].begin();
473 
474         while (iter != voices[s].end())
475         {
476             if (excess_voices < 1)
477                 break;
478 
479             SurgeVoice *v = *iter;
480             if (v->state.uberrelease)
481             {
482                 excess_voices--;
483                 freeVoice(v);
484                 iter = voices[s].erase(iter);
485             }
486             else
487                 iter++;
488         }
489     }
490 }
491 
getNonUltrareleaseVoices(int s)492 int SurgeSynthesizer::getNonUltrareleaseVoices(int s)
493 {
494     int count = 0;
495 
496     list<SurgeVoice *>::iterator iter;
497     iter = voices[s].begin();
498     while (iter != voices[s].end())
499     {
500         SurgeVoice *v = *iter;
501         assert(v);
502         if (!v->state.uberrelease)
503             count++;
504         iter++;
505     }
506 
507     return count;
508 }
509 
getNonReleasedVoices(int s)510 int SurgeSynthesizer::getNonReleasedVoices(int s)
511 {
512     int count = 0;
513 
514     list<SurgeVoice *>::iterator iter;
515     iter = voices[s].begin();
516     while (iter != voices[s].end())
517     {
518         SurgeVoice *v = *iter;
519         assert(v);
520         if (v->state.gate)
521             count++;
522         iter++;
523     }
524 
525     return count;
526 }
527 
getUnusedVoice(int scene)528 SurgeVoice *SurgeSynthesizer::getUnusedVoice(int scene)
529 {
530     for (int i = 0; i < MAX_VOICES; i++)
531     {
532         if (!voices_usedby[scene][i])
533         {
534             voices_usedby[scene][i] = scene + 1;
535             return &voices_array[scene][i];
536         }
537     }
538     return 0;
539 }
540 
freeVoice(SurgeVoice * v)541 void SurgeSynthesizer::freeVoice(SurgeVoice *v)
542 {
543     for (int i = 0; i < MAX_VOICES; i++)
544     {
545         if (voices_usedby[0][i] && (v == &voices_array[0][i]))
546         {
547             voices_usedby[0][i] = 0;
548         }
549         if (voices_usedby[1][i] && (v == &voices_array[1][i]))
550         {
551             voices_usedby[1][i] = 0;
552         }
553     }
554     v->freeAllocatedElements();
555 }
556 
getMpeMainChannel(int voiceChannel,int key)557 int SurgeSynthesizer::getMpeMainChannel(int voiceChannel, int key)
558 {
559     if (mpeEnabled)
560     {
561         return 0;
562     }
563 
564     return voiceChannel;
565 }
566 
playVoice(int scene,char channel,char key,char velocity,char detune)567 void SurgeSynthesizer::playVoice(int scene, char channel, char key, char velocity, char detune)
568 {
569     if (getNonReleasedVoices(scene) == 0)
570     {
571         for (int l = 0; l < n_lfos_scene; l++)
572         {
573             storage.getPatch().scene[scene].modsources[ms_slfo1 + l]->attack();
574         }
575     }
576 
577     for (int i = ms_random_bipolar; i <= ms_alternate_unipolar; ++i)
578     {
579         storage.getPatch().scene[scene].modsources[i]->attack();
580     }
581 
582     int excessVoices =
583         max(0, (int)getNonUltrareleaseVoices(scene) - storage.getPatch().polylimit.val.i + 1);
584 
585     for (int i = 0; i < excessVoices; i++)
586     {
587         softkillVoice(scene);
588     }
589     enforcePolyphonyLimit(scene, 3);
590 
591     int lowkey = 0, hikey = 127;
592     if (storage.getPatch().scenemode.val.i == sm_split)
593     {
594         if (scene == 0)
595             hikey = storage.getPatch().splitpoint.val.i - 1;
596         else
597             lowkey = storage.getPatch().splitpoint.val.i;
598     }
599 
600     int lowMpeChan = 1; // skip control chan
601     int highMpeChan = 16;
602     if (storage.getPatch().scenemode.val.i == sm_chsplit)
603     {
604         if (scene == 0)
605         {
606             highMpeChan = (int)(storage.getPatch().splitpoint.val.i / 8 + 1);
607         }
608         else
609         {
610             lowMpeChan = (int)(storage.getPatch().splitpoint.val.i / 8 + 1);
611         }
612     }
613 
614     switch (storage.getPatch().scene[scene].polymode.val.i)
615     {
616     case pm_poly:
617     {
618         SurgeVoice *nvoice = getUnusedVoice(scene);
619         if (nvoice)
620         {
621             int mpeMainChannel = getMpeMainChannel(channel, key);
622 
623             voices[scene].push_back(nvoice);
624             new (nvoice) SurgeVoice(
625                 &storage, &storage.getPatch().scene[scene], storage.getPatch().scenedata[scene],
626                 key, velocity, channel, scene, detune, &channelState[channel].keyState[key],
627                 &channelState[mpeMainChannel], &channelState[channel], mpeEnabled, voiceCounter++);
628         }
629         break;
630     }
631     case pm_mono:
632     case pm_mono_fp:
633     case pm_latch:
634     {
635         list<SurgeVoice *>::const_iterator iter;
636         bool glide = false;
637 
638         int primode = storage.getPatch().scene[scene].monoVoicePriorityMode;
639         bool createVoice = true;
640         if (primode == ALWAYS_HIGHEST || primode == ALWAYS_LOWEST)
641         {
642             /*
643              * There is a chance we don't want to make a voice
644              */
645             if (mpeEnabled)
646             {
647                 for (int k = lowkey; k < hikey; ++k)
648                 {
649                     for (int mpeChan = lowMpeChan; mpeChan < highMpeChan; ++mpeChan)
650                     {
651                         if (channelState[mpeChan].keyState[k].keystate)
652                         {
653                             if (primode == ALWAYS_HIGHEST && k > key)
654                                 createVoice = false;
655                             if (primode == ALWAYS_LOWEST && k < key)
656                                 createVoice = false;
657                         }
658                     }
659                 }
660             }
661             else
662             {
663                 for (int k = lowkey; k < hikey; ++k)
664                 {
665                     if (channelState[channel].keyState[k].keystate)
666                     {
667                         if (primode == ALWAYS_HIGHEST && k > key)
668                             createVoice = false;
669                         if (primode == ALWAYS_LOWEST && k < key)
670                             createVoice = false;
671                     }
672                 }
673             }
674         }
675 
676         if (createVoice)
677         {
678             for (iter = voices[scene].begin(); iter != voices[scene].end(); iter++)
679             {
680                 SurgeVoice *v = *iter;
681                 if (v->state.scene_id == scene)
682                 {
683                     if (v->state.gate)
684                     {
685                         glide = true;
686                     }
687                     v->uber_release();
688                 }
689             }
690             SurgeVoice *nvoice = getUnusedVoice(scene);
691             if (nvoice)
692             {
693                 int mpeMainChannel = getMpeMainChannel(channel, key);
694 
695                 voices[scene].push_back(nvoice);
696                 if ((storage.getPatch().scene[scene].polymode.val.i == pm_mono_fp) && !glide)
697                     storage.last_key[scene] = key;
698                 new (nvoice) SurgeVoice(&storage, &storage.getPatch().scene[scene],
699                                         storage.getPatch().scenedata[scene], key, velocity, channel,
700                                         scene, detune, &channelState[channel].keyState[key],
701                                         &channelState[mpeMainChannel], &channelState[channel],
702                                         mpeEnabled, voiceCounter++);
703             }
704         }
705         else
706         {
707             /*
708              * We still need to indicate that this is an ordered voice even though we don't create
709              * it
710              */
711             channelState[channel].keyState[key].voiceOrder = voiceCounter++;
712         }
713     }
714     break;
715     case pm_mono_st:
716     case pm_mono_st_fp:
717     {
718         bool found_one = false;
719         int primode = storage.getPatch().scene[scene].monoVoicePriorityMode;
720         bool createVoice = true;
721         if (primode == ALWAYS_HIGHEST || primode == ALWAYS_LOWEST)
722         {
723             /*
724              * There is a chance we don't want to make a voice
725              */
726             if (mpeEnabled)
727             {
728                 for (int k = lowkey; k < hikey; ++k)
729                 {
730                     for (int mpeChan = lowMpeChan; mpeChan < highMpeChan; ++mpeChan)
731                     {
732                         if (channelState[mpeChan].keyState[k].keystate)
733                         {
734                             if (primode == ALWAYS_HIGHEST && k > key)
735                                 createVoice = false;
736                             if (primode == ALWAYS_LOWEST && k < key)
737                                 createVoice = false;
738                         }
739                     }
740                 }
741             }
742             else
743             {
744                 for (int k = lowkey; k < hikey; ++k)
745                 {
746                     if (channelState[channel].keyState[k].keystate)
747                     {
748                         if (primode == ALWAYS_HIGHEST && k > key)
749                             createVoice = false;
750                         if (primode == ALWAYS_LOWEST && k < key)
751                             createVoice = false;
752                     }
753                 }
754             }
755         }
756 
757         if (createVoice)
758         {
759             list<SurgeVoice *>::const_iterator iter;
760             for (iter = voices[scene].begin(); iter != voices[scene].end(); iter++)
761             {
762                 SurgeVoice *v = *iter;
763                 if ((v->state.scene_id == scene) && (v->state.gate))
764                 {
765                     v->legato(key, velocity, detune);
766                     found_one = true;
767                     if (mpeEnabled)
768                     {
769                         /*
770                         ** This voice was created on a channel but is being legato held to another
771                         *channel
772                         ** so it needs to borrow the channel and channelState. Obviously this can
773                         *only
774                         ** happen in MPE mode.
775                         */
776                         v->state.channel = channel;
777                         v->state.voiceChannelState = &channelState[channel];
778                     }
779                     break;
780                 }
781                 else
782                 {
783                     if (v->state.scene_id == scene)
784                         v->uber_release(); // make this optional for poly legato
785                 }
786             }
787             if (!found_one)
788             {
789                 int mpeMainChannel = getMpeMainChannel(channel, key);
790 
791                 SurgeVoice *nvoice = getUnusedVoice(scene);
792                 if (nvoice)
793                 {
794                     voices[scene].push_back(nvoice);
795                     new (nvoice) SurgeVoice(
796                         &storage, &storage.getPatch().scene[scene],
797                         storage.getPatch().scenedata[scene], key, velocity, channel, scene, detune,
798                         &channelState[channel].keyState[key], &channelState[mpeMainChannel],
799                         &channelState[channel], mpeEnabled, voiceCounter++);
800                 }
801             }
802             else
803             {
804                 /*
805                  * Here we are legato sliding a voice which is fine but it means we
806                  * don't create a new voice. That will screw up the voice counters
807                  * - basically all voices will have the same count - so a concept of
808                  * latest doesn't work. Thus update the channel state making this key
809                  * 'newer' than the prior voice (as is normally done in the SurgeVoice
810                  * constructor call).
811                  */
812                 channelState[channel].keyState[key].voiceOrder = voiceCounter++;
813             }
814         }
815         else
816         {
817             /*
818              * Still need to update the counter if we don't create in hilow mode
819              */
820             channelState[channel].keyState[key].voiceOrder = voiceCounter++;
821         }
822     }
823     break;
824     }
825 
826     updateHighLowKeys(scene);
827 }
828 
releaseScene(int s)829 void SurgeSynthesizer::releaseScene(int s)
830 {
831     list<SurgeVoice *>::const_iterator iter;
832     for (iter = voices[s].begin(); iter != voices[s].end(); iter++)
833     {
834         freeVoice(*iter);
835     }
836     voices[s].clear();
837 }
838 
releaseNote(char channel,char key,char velocity)839 void SurgeSynthesizer::releaseNote(char channel, char key, char velocity)
840 {
841     bool foundVoice[n_scenes];
842     for (int sc = 0; sc < n_scenes; ++sc)
843     {
844         foundVoice[sc] = false;
845         for (auto *v : voices[sc])
846         {
847             foundVoice[sc] = true;
848             if ((v->state.key == key) && (v->state.channel == channel))
849                 v->state.releasevelocity = velocity;
850         }
851     }
852 
853     /*
854      * Update the midi key for scene
855      */
856     auto scmd = (scene_mode)storage.getPatch().scenemode.val.i;
857     switch (scmd)
858     {
859     case sm_single:
860     {
861         auto sc = storage.getPatch().scene_active.val.i;
862         midiKeyPressedForScene[sc][key] = 0;
863         break;
864     }
865     case sm_dual:
866     {
867         for (int i = 0; i < n_scenes; ++i)
868             midiKeyPressedForScene[i][key] = 0;
869         break;
870     }
871     case sm_split:
872     {
873         auto splitkey = storage.getPatch().splitpoint.val.i;
874         if (key < splitkey)
875         {
876             midiKeyPressedForScene[0][key] = 0;
877         }
878         else
879         {
880             midiKeyPressedForScene[1][key] = 0;
881         }
882 
883         break;
884     }
885     case sm_chsplit:
886     {
887         auto splitChan = (int)(storage.getPatch().splitpoint.val.i / 8 + 1);
888         if (channel < splitChan)
889         {
890             midiKeyPressedForScene[0][key] = 0;
891         }
892         else
893         {
894             midiKeyPressedForScene[1][key] = 0;
895         }
896         break;
897     }
898     default:
899         break;
900     }
901 
902     bool noHold = !channelState[channel].hold;
903     if (mpeEnabled)
904         noHold = noHold && !channelState[0].hold;
905 
906     for (int sc = 0; sc < n_scenes; ++sc)
907     {
908         bool sceneNoHold = noHold;
909         auto pm = storage.getPatch().scene[sc].polymode.val.i;
910         if (!sceneNoHold && !mpeEnabled && storage.monoPedalMode == RELEASE_IF_OTHERS_HELD &&
911             (pm == pm_mono || pm == pm_mono_fp || pm == pm_mono_st || pm == pm_mono_st_fp))
912         {
913             /*
914              * OK so we have a key we are about to put in the hold buffer. BUT in the
915              * RELEASE_IF_OTHERS_HELD mode we dont' want to hold it if we have other keys
916              * down. So do we?
917              */
918             for (auto k = 127; k >= 0; k--) // search downwards
919             {
920                 if (k != key && channelState[channel].keyState[k].keystate)
921                 {
922                     sceneNoHold =
923                         true; // This effects a release of current key because another key is down
924                 }
925             }
926         }
927 
928         if (sceneNoHold)
929             releaseNotePostHoldCheck(sc, channel, key, velocity);
930         else
931             holdbuffer[sc].push_back(
932                 std::make_pair(channel, key)); // hold pedal is down, add to bufffer
933     }
934 }
935 
releaseNotePostHoldCheck(int scene,char channel,char key,char velocity)936 void SurgeSynthesizer::releaseNotePostHoldCheck(int scene, char channel, char key, char velocity)
937 {
938     channelState[channel].keyState[key].keystate = 0;
939     list<SurgeVoice *>::const_iterator iter;
940     for (int s = 0; s < n_scenes; s++)
941     {
942         bool do_switch = false;
943         int k = 0;
944 
945         for (iter = voices[scene].begin(); iter != voices[scene].end(); iter++)
946         {
947             SurgeVoice *v = *iter;
948             int lowkey = 0, hikey = 127;
949             if (storage.getPatch().scenemode.val.i == sm_split)
950             {
951                 if (v->state.scene_id == 0)
952                     hikey = storage.getPatch().splitpoint.val.i - 1;
953                 else
954                     lowkey = storage.getPatch().splitpoint.val.i;
955             }
956 
957             int lowMpeChan = 1; // Control chan gets skipped
958             int highMpeChan = 16;
959             if (storage.getPatch().scenemode.val.i == sm_chsplit)
960             {
961                 if (v->state.scene_id == 0)
962                 {
963                     highMpeChan = (int)(storage.getPatch().splitpoint.val.i / 8 + 1);
964                 }
965                 else
966                 {
967                     lowMpeChan = (int)(storage.getPatch().splitpoint.val.i / 8 + 1);
968                 }
969             }
970 
971             switch (storage.getPatch().scene[v->state.scene_id].polymode.val.i)
972             {
973             case pm_poly:
974                 if ((v->state.key == key) && (v->state.channel == channel))
975                     v->release();
976                 break;
977             case pm_mono:
978             case pm_mono_fp:
979             case pm_latch:
980             {
981 
982                 /*
983                 ** In these modes, our job when we release a note is to see if
984                 ** any other note is held.
985                 **
986                 ** In normal MIDI mode, that means scanning the keystate of our
987                 ** channel looking for another note.
988                 **
989                 ** In MPE mode, where each note is per channel, that means
990                 ** scanning all non-main channels rather than ourself for the
991                 ** highest note
992                 *
993                 * But with the introduction of voice modes finding the next one
994                 * is trickier so add these two little lambdas
995                 */
996 
997                 if ((v->state.key == key) && (v->state.channel == channel))
998                 {
999                     int activateVoiceKey = 60, activateVoiceChannel = 0; // these will be overriden
1000                     auto priorityMode =
1001                         storage.getPatch().scene[v->state.scene_id].monoVoicePriorityMode;
1002 
1003                     // v->release();
1004                     if (!mpeEnabled)
1005                     {
1006                         int highest = -1, lowest = 128, latest = -1;
1007                         int64_t lt = 0;
1008                         for (k = hikey; k >= lowkey && !do_switch; k--) // search downwards
1009                         {
1010                             if (channelState[channel].keyState[k].keystate)
1011                             {
1012                                 if (k >= highest)
1013                                     highest = k;
1014                                 if (k <= lowest)
1015                                     lowest = k;
1016                                 if (channelState[channel].keyState[k].voiceOrder >= lt)
1017                                 {
1018                                     latest = k;
1019                                     lt = channelState[channel].keyState[k].voiceOrder;
1020                                 }
1021                             }
1022                         }
1023 
1024                         switch (storage.getPatch().scene[v->state.scene_id].monoVoicePriorityMode)
1025                         {
1026                         case ALWAYS_HIGHEST:
1027                         case NOTE_ON_LATEST_RETRIGGER_HIGHEST:
1028                             k = highest >= 0 ? highest : -1;
1029                             break;
1030                         case ALWAYS_LATEST:
1031                             k = latest >= 0 ? latest : -1;
1032                             break;
1033                         case ALWAYS_LOWEST:
1034                             k = lowest <= 127 ? lowest : -1;
1035                             break;
1036                         }
1037 
1038                         if (k >= 0)
1039                         {
1040                             do_switch = true;
1041                             activateVoiceKey = k;
1042                             activateVoiceChannel = channel;
1043                         }
1044                     }
1045                     else
1046                     {
1047                         int highest = -1, lowest = 128, latest = -1;
1048                         int hichan, lowchan, latechan;
1049                         int64_t lt = 0;
1050 
1051                         for (k = hikey; k >= lowkey && !do_switch; k--)
1052                         {
1053                             for (int mpeChan = lowMpeChan; mpeChan < highMpeChan; ++mpeChan)
1054                             {
1055                                 if (mpeChan != channel &&
1056                                     channelState[mpeChan].keyState[k].keystate)
1057                                 {
1058                                     if (k >= highest)
1059                                     {
1060                                         highest = k;
1061                                         hichan = mpeChan;
1062                                     }
1063                                     if (k <= lowest)
1064                                     {
1065                                         lowest = k;
1066                                         lowchan = mpeChan;
1067                                     }
1068                                     if (channelState[mpeChan].keyState[k].voiceOrder >= lt)
1069                                     {
1070                                         lt = channelState[mpeChan].keyState[k].voiceOrder;
1071                                         latest = k;
1072                                         latechan = mpeChan;
1073                                     }
1074                                 }
1075                             }
1076                         }
1077                         k = -1;
1078                         int kchan;
1079 
1080                         switch (storage.getPatch().scene[v->state.scene_id].monoVoicePriorityMode)
1081                         {
1082                         case ALWAYS_HIGHEST:
1083                         case NOTE_ON_LATEST_RETRIGGER_HIGHEST:
1084                             k = highest >= 0 ? highest : -1;
1085                             kchan = hichan;
1086                             break;
1087                         case ALWAYS_LATEST:
1088                             k = latest >= 0 ? latest : -1;
1089                             kchan = latechan;
1090                             break;
1091                         case ALWAYS_LOWEST:
1092                             k = lowest <= 127 ? lowest : -1;
1093                             kchan = lowchan;
1094                             break;
1095                         }
1096 
1097                         if (k >= 0)
1098                         {
1099                             do_switch = true;
1100                             activateVoiceChannel = kchan;
1101                             activateVoiceKey = k;
1102                         }
1103                     }
1104                     if (!do_switch)
1105                     {
1106                         if (storage.getPatch().scene[v->state.scene_id].polymode.val.i != pm_latch)
1107                             v->release();
1108                     }
1109                     else
1110                     {
1111                         // confirm that no notes are active
1112                         v->uber_release();
1113                         if (getNonUltrareleaseVoices(scene) == 0)
1114                         {
1115                             playVoice(scene, activateVoiceChannel, activateVoiceKey, velocity,
1116                                       channelState[activateVoiceChannel].keyState[k].lastdetune);
1117                         }
1118                     }
1119                 }
1120             }
1121             break;
1122             case pm_mono_st:
1123             case pm_mono_st_fp:
1124             {
1125                 /*
1126                 ** In these modes the note will collide on the main channel
1127                 */
1128                 int stateChannel = getMpeMainChannel(v->state.channel, v->state.key);
1129                 int noteChannel = getMpeMainChannel(channel, key);
1130 
1131                 if ((v->state.key == key) && (stateChannel == noteChannel))
1132                 {
1133                     bool do_release = true;
1134                     /*
1135                     ** Again the note I need to legato to is on my channel in non MPE and
1136                     ** is on another channel in MPE mode
1137                     */
1138                     if (!mpeEnabled)
1139                     {
1140                         int highest = -1, lowest = 128, latest = -1;
1141                         int64_t lt = 0;
1142                         for (k = hikey; k >= lowkey; k--) // search downwards
1143                         {
1144                             if (k != key && channelState[channel].keyState[k].keystate)
1145                             {
1146                                 if (k >= highest)
1147                                     highest = k;
1148                                 if (k <= lowest)
1149                                     lowest = k;
1150                                 if (channelState[channel].keyState[k].voiceOrder >= lt)
1151                                 {
1152                                     latest = k;
1153                                     lt = channelState[channel].keyState[k].voiceOrder;
1154                                 }
1155                             }
1156                         }
1157 
1158                         switch (storage.getPatch().scene[v->state.scene_id].monoVoicePriorityMode)
1159                         {
1160                         case ALWAYS_HIGHEST:
1161                         case NOTE_ON_LATEST_RETRIGGER_HIGHEST:
1162                             k = highest >= 0 ? highest : -1;
1163                             break;
1164                         case ALWAYS_LATEST:
1165                             k = latest >= 0 ? latest : -1;
1166                             break;
1167                         case ALWAYS_LOWEST:
1168                             k = lowest <= 127 ? lowest : -1;
1169                             break;
1170                         }
1171 
1172                         if (k >= 0)
1173                         {
1174                             v->legato(k, velocity, channelState[channel].keyState[k].lastdetune);
1175                             do_release = false;
1176                         }
1177                     }
1178                     else
1179                     {
1180                         int highest = -1, lowest = 128, latest = -1;
1181                         int hichan, lowchan, latechan;
1182                         int64_t lt = 0;
1183 
1184                         for (k = hikey; k >= lowkey && !do_switch; k--)
1185                         {
1186                             for (int mpeChan = lowMpeChan; mpeChan < highMpeChan; ++mpeChan)
1187                             {
1188                                 if (mpeChan != channel &&
1189                                     channelState[mpeChan].keyState[k].keystate)
1190                                 {
1191                                     if (k >= highest)
1192                                     {
1193                                         highest = k;
1194                                         hichan = mpeChan;
1195                                     }
1196                                     if (k <= lowest)
1197                                     {
1198                                         lowest = k;
1199                                         lowchan = mpeChan;
1200                                     }
1201                                     if (channelState[mpeChan].keyState[k].voiceOrder >= lt)
1202                                     {
1203                                         lt = channelState[mpeChan].keyState[k].voiceOrder;
1204                                         latest = k;
1205                                         latechan = mpeChan;
1206                                     }
1207                                 }
1208                             }
1209                         }
1210                         k = -1;
1211                         int kchan;
1212 
1213                         switch (storage.getPatch().scene[v->state.scene_id].monoVoicePriorityMode)
1214                         {
1215                         case ALWAYS_HIGHEST:
1216                         case NOTE_ON_LATEST_RETRIGGER_HIGHEST:
1217                             k = highest >= 0 ? highest : -1;
1218                             kchan = hichan;
1219                             break;
1220                         case ALWAYS_LATEST:
1221                             k = latest >= 0 ? latest : -1;
1222                             kchan = latechan;
1223                             break;
1224                         case ALWAYS_LOWEST:
1225                             k = lowest <= 127 ? lowest : -1;
1226                             kchan = lowchan;
1227                             break;
1228                         }
1229 
1230                         if (k >= 0)
1231                         {
1232                             v->legato(k, velocity, channelState[kchan].keyState[k].lastdetune);
1233                             do_release = false;
1234                             // See the comment above at the other _st legato spot
1235                             v->state.channel = kchan;
1236                             v->state.voiceChannelState = &channelState[kchan];
1237                             // std::cout << _D(v->state.gate) << _D(v->state.key) <<
1238                             // _D(v->state.scene_id ) << std::endl;
1239                         }
1240                     }
1241 
1242                     if (do_release)
1243                         v->release();
1244                 }
1245             }
1246             break;
1247             };
1248         }
1249     }
1250 
1251     updateHighLowKeys(scene);
1252 
1253     // Used to be a scene loop here
1254     {
1255         if (getNonReleasedVoices(scene) == 0)
1256         {
1257             for (int l = 0; l < n_lfos_scene; l++)
1258                 storage.getPatch().scene[scene].modsources[ms_slfo1 + l]->release();
1259         }
1260     }
1261 }
1262 
updateHighLowKeys(int scene)1263 void SurgeSynthesizer::updateHighLowKeys(int scene)
1264 {
1265     static constexpr bool resetToZeroOnLastRelease = false;
1266 
1267     float ktRoot = (float)storage.getPatch().scene[scene].keytrack_root.val.i;
1268     float twelfth = 1.f / 12.f;
1269 
1270     int highest = -1, lowest = 129, latest = -1, latestC = 0;
1271     for (int k = 0; k < 128; ++k)
1272     {
1273         if (midiKeyPressedForScene[scene][k] > 0)
1274         {
1275             highest = std::max(k, highest);
1276             lowest = std::min(k, lowest);
1277         }
1278         if (midiKeyPressedForScene[scene][k] > latestC)
1279         {
1280             latestC = midiKeyPressedForScene[scene][k];
1281             latest = k;
1282         }
1283     }
1284 
1285     if (lowest < 129)
1286         ((ControllerModulationSource *)storage.getPatch().scene[scene].modsources[ms_lowest_key])
1287             ->init((lowest - ktRoot) * twelfth);
1288     else if (resetToZeroOnLastRelease)
1289         ((ControllerModulationSource *)storage.getPatch().scene[scene].modsources[ms_lowest_key])
1290             ->init(0.f);
1291 
1292     if (highest >= 0)
1293         ((ControllerModulationSource *)storage.getPatch().scene[scene].modsources[ms_highest_key])
1294             ->init((highest - ktRoot) * twelfth);
1295     else if (resetToZeroOnLastRelease)
1296         ((ControllerModulationSource *)storage.getPatch().scene[scene].modsources[ms_highest_key])
1297             ->init(0.f);
1298 
1299     if (latest >= 0)
1300         ((ControllerModulationSource *)storage.getPatch().scene[scene].modsources[ms_latest_key])
1301             ->init((latest - ktRoot) * twelfth);
1302     else if (resetToZeroOnLastRelease)
1303         ((ControllerModulationSource *)storage.getPatch().scene[scene].modsources[ms_latest_key])
1304             ->init(0.f);
1305 }
1306 
pitchBend(char channel,int value)1307 void SurgeSynthesizer::pitchBend(char channel, int value)
1308 {
1309     if (mpeEnabled && channel != 0)
1310     {
1311         channelState[channel].pitchBend = value;
1312 
1313         /*
1314         ** TODO: handling of channel 0 and mpeGlobalPitchBendRange was broken with the addition
1315         ** of smoothing. we should probably add that back in if it turns out someone actually uses
1316         *it :)
1317         ** currently channelState[].pitchBendInSemitones is now unused, but it hasn't been removed
1318         *from
1319         ** the code yet for this reason.
1320         ** For now, we ignore channel zero here so it functions like the old code did in practice
1321         *when
1322         ** mpeGlobalPitchBendRange remained at zero.
1323         */
1324     }
1325 
1326     /*
1327     ** So here's the thing. We want global pitch bend modulation to work for other things in MPE
1328     *mode.
1329     ** This code has been here forever. But that means we need to ignore the channel[0] MPE
1330     *pitchbend
1331     ** elsewhere, especially since the range was hardwired to 2 (but is now 0). As far as I know the
1332     ** main MPE devices don't have a global pitch bend anyway so this just screws up regular
1333     *keyboards
1334     ** sending channel 0 pitch bend in MPE mode.
1335     */
1336     if (!mpeEnabled || channel == 0)
1337     {
1338         storage.pitch_bend = value / 8192.f;
1339 
1340         for (int sc = 0; sc < n_scenes; sc++)
1341         {
1342             ((ControllerModulationSource *)storage.getPatch().scene[sc].modsources[ms_pitchbend])
1343                 ->set_target(storage.pitch_bend);
1344         }
1345     }
1346 }
channelAftertouch(char channel,int value)1347 void SurgeSynthesizer::channelAftertouch(char channel, int value)
1348 {
1349     float fval = (float)value / 127.f;
1350 
1351     channelState[channel].pressure = fval;
1352 
1353     if (!mpeEnabled || channel == 0)
1354     {
1355         for (int sc = 0; sc < n_scenes; sc++)
1356         {
1357             ((ControllerModulationSource *)storage.getPatch().scene[sc].modsources[ms_aftertouch])
1358                 ->set_target(fval);
1359         }
1360     }
1361 }
1362 
polyAftertouch(char channel,int key,int value)1363 void SurgeSynthesizer::polyAftertouch(char channel, int key, int value)
1364 {
1365     float fval = (float)value / 127.f;
1366     storage.poly_aftertouch[0][key & 127] = fval;
1367     storage.poly_aftertouch[1][key & 127] = fval;
1368 }
1369 
programChange(char channel,int value)1370 void SurgeSynthesizer::programChange(char channel, int value)
1371 {
1372     PCH = value;
1373     // load_patch((CC0<<7) + PCH);
1374     patchid_queue = (CC0 << 7) + PCH;
1375 }
1376 
updateDisplay()1377 void SurgeSynthesizer::updateDisplay()
1378 {
1379     // This used to (in VST2) call updateDisplay but that did an Audio -> UI thread cross. Just mark
1380     // the flag as true
1381     refresh_editor = true;
1382 }
1383 
sendParameterAutomation(long index,float value)1384 void SurgeSynthesizer::sendParameterAutomation(long index, float value)
1385 {
1386     ID eid;
1387     if (!fromSynthSideId(index, eid))
1388         return;
1389 
1390 #if TARGET_AUDIOUNIT
1391     getParent()->ParameterUpdate(eid.getDawSideIndex());
1392 #elif TARGET_VST3
1393     getParent()->setParameterAutomated(index, value);
1394 #elif TARGET_JUCE_UI
1395     getParent()->surgeParameterUpdated(eid, value);
1396 #elif TARGET_HEADLESS || TARGET_APP
1397         // NO OP
1398 #else
1399     getParent()->setParameterAutomated(eid.getDawSideIndex(), value);
1400 #endif
1401 }
1402 
onRPN(int channel,int lsbRPN,int msbRPN,int lsbValue,int msbValue)1403 void SurgeSynthesizer::onRPN(int channel, int lsbRPN, int msbRPN, int lsbValue, int msbValue)
1404 {
1405     /* OK there are two things we are dealing with here
1406 
1407      1: The MPE specification v1.0 section 2.1.1 says the message format for RPN is
1408 
1409         Bn 64 06
1410         Bn 65 00
1411         Bn 06 mm
1412 
1413      where n = 0 is lower zone, n=F is upper zone, all others are invalid, and mm=0 means no MPE and
1414      mm=1->F is zone.
1415 
1416      So you would think the Roli Seaboard would send, since it is one zone
1417 
1418         B0 64 06 B0 65 00 B0 06 0F
1419 
1420      and be done with it. If it did this code would work.
1421 
1422      But it doesn't. At least with Roli Seaboard Firmware 1.1.7.
1423 
1424      Instead on *each* channel it sends
1425 
1426         Bn 64 04 Bn 64 0 Bn 06 00
1427         Bn 64 03 Bn 64 0 Bn 06 00
1428 
1429      for each channel. Which seems unrelated to the spec. But as a result the original onRPN code
1430      means you get no MPE with a Roli Seaboard.
1431 
1432      Hey one year later an edit: Those aren't coming from ROLI they are coming from Logic PRO and
1433      now that I correct modify and stream MPE state, we should not listen to those messages.
1434      */
1435 
1436     if (lsbRPN == 0 && msbRPN == 0) // PITCH BEND RANGE
1437     {
1438         if (channel == 1)
1439         {
1440             storage.mpePitchBendRange = msbValue;
1441         }
1442         else if (channel == 0)
1443         {
1444             mpeGlobalPitchBendRange = msbValue;
1445         }
1446     }
1447     else if (lsbRPN == 6 && msbRPN == 0) // MPE mode
1448     {
1449         mpeEnabled = msbValue > 0;
1450         mpeVoices = msbValue & 0xF;
1451         if (storage.mpePitchBendRange < 0.0f)
1452             storage.mpePitchBendRange =
1453                 Surge::Storage::getUserDefaultValue(&storage, "mpePitchBendRange", 48);
1454         mpeGlobalPitchBendRange = 0;
1455         return;
1456     }
1457     else if (lsbRPN == 4 && msbRPN == 0 && channel != 0 && channel != 0xF)
1458     {
1459         /*
1460         ** This is code sent by logic in all cases for some reason. In ancient times
1461         ** I thought it came from a roli. But I since changed the MPE state management so
1462         ** with 1.6.5 do this:
1463         */
1464 #if 0
1465        // This is the invalid message which the ROLI sends. Rather than have the Roli not work
1466        mpeEnabled = true;
1467        mpeVoices = msbValue & 0xF;
1468        mpePitchBendRange = Surge::Storage::getUserDefaultValue(&storage, "mpePitchBendRange", 48);
1469        std::cout << __LINE__ << " " << __FILE__ << " MPEE=" << mpeEnabled << " MPEPBR=" << mpePitchBendRange << std::endl;
1470        mpeGlobalPitchBendRange = 0;
1471 #endif
1472         return;
1473     }
1474 }
1475 
onNRPN(int channel,int lsbNRPN,int msbNRPN,int lsbValue,int msbValue)1476 void SurgeSynthesizer::onNRPN(int channel, int lsbNRPN, int msbNRPN, int lsbValue, int msbValue) {}
1477 
int7ToBipolarFloat(int x)1478 float int7ToBipolarFloat(int x)
1479 {
1480     if (x > 64)
1481     {
1482         return (x - 64) * (1.f / 63.f);
1483     }
1484     else if (x < 64)
1485     {
1486         return (x - 64) * (1.f / 64.f);
1487     }
1488 
1489     return 0;
1490 }
1491 
channelController(char channel,int cc,int value)1492 void SurgeSynthesizer::channelController(char channel, int cc, int value)
1493 {
1494     float fval = (float)value * (1.f / 127.f);
1495 
1496     // store all possible NRPN & RPNs in a short array... amounts to 128 KB or thereabouts
1497     switch (cc)
1498     {
1499     case 0:
1500         CC0 = value;
1501         return;
1502     case 1:
1503         for (int sc = 0; sc < n_scenes; sc++)
1504         {
1505             ((ControllerModulationSource *)storage.getPatch().scene[sc].modsources[ms_modwheel])
1506                 ->set_target(fval);
1507         }
1508         break;
1509     case 2:
1510         for (int sc = 0; sc < n_scenes; sc++)
1511         {
1512             ((ControllerModulationSource *)storage.getPatch().scene[sc].modsources[ms_breath])
1513                 ->set_target(fval);
1514         }
1515         break;
1516     case 6:
1517         if (channelState[channel].nrpn_last)
1518         {
1519             channelState[channel].nrpn_v[1] = value;
1520 
1521             onNRPN(channel, channelState[channel].nrpn[0], channelState[channel].nrpn[1],
1522                    channelState[channel].nrpn_v[0], channelState[channel].nrpn_v[1]);
1523         }
1524         else
1525         {
1526             channelState[channel].rpn_v[1] = value;
1527 
1528             onRPN(channel, channelState[channel].rpn[0], channelState[channel].rpn[1],
1529                   channelState[channel].rpn_v[0], channelState[channel].rpn_v[1]);
1530         }
1531         return;
1532     case 10:
1533     {
1534         if (mpeEnabled)
1535         {
1536             channelState[channel].pan = int7ToBipolarFloat(value);
1537             return;
1538         }
1539         break;
1540     }
1541     case 11:
1542         for (int sc = 0; sc < n_scenes; sc++)
1543         {
1544             ((ControllerModulationSource *)storage.getPatch().scene[sc].modsources[ms_expression])
1545                 ->set_target(fval);
1546         }
1547         break;
1548     case 32:
1549         CC32 = value;
1550         return;
1551     case 38:
1552         if (channelState[channel].nrpn_last)
1553             channelState[channel].nrpn_v[0] = value;
1554         else
1555             channelState[channel].rpn_v[0] = value;
1556         break;
1557     case 64:
1558     {
1559         for (int sc = 0; sc < n_scenes; sc++)
1560         {
1561             ((ControllerModulationSource *)storage.getPatch().scene[sc].modsources[ms_sustain])
1562                 ->set_target(fval);
1563         }
1564 
1565         channelState[channel].hold = value > 63; // check hold pedal
1566 
1567         // OK in single mode, only purge scene 0, but in split or dual purge both, and in chsplit
1568         // pick based on channel
1569         switch (storage.getPatch().scenemode.val.i)
1570         {
1571         case sm_single:
1572             purgeHoldbuffer(storage.getPatch().scene_active.val.i);
1573             break;
1574         case sm_split:
1575         case sm_dual:
1576             purgeHoldbuffer(0);
1577             purgeHoldbuffer(1);
1578             break;
1579         case sm_chsplit:
1580             if (mpeEnabled && channel == 0) // a control channel message
1581             {
1582                 purgeHoldbuffer(0);
1583                 purgeHoldbuffer(1);
1584             }
1585             else
1586             {
1587                 if (channel < ((int)(storage.getPatch().splitpoint.val.i / 8) + 1))
1588                     purgeHoldbuffer(0);
1589                 else
1590                     purgeHoldbuffer(1);
1591             }
1592             break;
1593         }
1594 
1595         return;
1596     }
1597     case 74:
1598     {
1599         if (mpeEnabled)
1600         {
1601             channelState[channel].timbre = int7ToBipolarFloat(value);
1602             return;
1603         }
1604         break;
1605     }
1606     case 98: // NRPN LSB
1607         channelState[channel].nrpn[0] = value;
1608         channelState[channel].nrpn_last = true;
1609         return;
1610     case 99: // NRPN MSB
1611         channelState[channel].nrpn[1] = value;
1612         channelState[channel].nrpn_last = true;
1613         return;
1614     case 100: // RPN LSB
1615         channelState[channel].rpn[0] = value;
1616         channelState[channel].nrpn_last = false;
1617         return;
1618     case 101: // RPN MSB
1619         channelState[channel].rpn[1] = value;
1620         channelState[channel].nrpn_last = false;
1621         return;
1622     case 120: // all sound off
1623     case 123: // all notes off
1624         return;
1625     };
1626 
1627     int cc_encoded = cc;
1628 
1629     if ((cc == 6) || (cc == 38)) // handle RPN/NRPNs (untested)
1630     {
1631         int tv, cnum;
1632         if (channelState[channel].nrpn_last)
1633         {
1634             tv = (channelState[channel].nrpn_v[1] << 7) + channelState[channel].nrpn_v[0];
1635             cnum = (channelState[channel].nrpn[1] << 7) + channelState[channel].nrpn[0];
1636             cc_encoded = cnum | (1 << 16);
1637         }
1638         else
1639         {
1640             tv = (channelState[channel].rpn_v[1] << 7) + channelState[channel].rpn_v[0];
1641             cnum = (channelState[channel].rpn[1] << 7) + channelState[channel].rpn[0];
1642             cc_encoded = cnum | (2 << 16);
1643         }
1644 
1645         fval = (float)tv / 16384.0f;
1646         // int cmode = channelState[channel].nrpn_last;
1647     }
1648 
1649     for (int i = 0; i < n_customcontrollers; i++)
1650     {
1651         if (storage.controllers[i] == cc_encoded)
1652         {
1653             ((ControllerModulationSource *)storage.getPatch().scene[0].modsources[ms_ctrl1 + i])
1654                 ->set_target01(fval);
1655         }
1656     }
1657 
1658     if (learn_param >= 0)
1659     {
1660         if (learn_param < n_global_params)
1661         {
1662             storage.getPatch().param_ptr[learn_param]->midictrl = cc_encoded;
1663         }
1664         else
1665         {
1666             int a = learn_param;
1667             if (learn_param >= (n_global_params + n_scene_params))
1668                 a -= n_scene_params;
1669 
1670             storage.getPatch().param_ptr[a]->midictrl = cc_encoded;
1671             storage.getPatch().param_ptr[a + n_scene_params]->midictrl = cc_encoded;
1672         }
1673         learn_param = -1;
1674     }
1675 
1676     if ((learn_custom >= 0) && (learn_custom < n_customcontrollers))
1677     {
1678         storage.controllers[learn_custom] = cc_encoded;
1679         learn_custom = -1;
1680     }
1681 
1682     // if(storage.getPatch().scene_active.val.i == 1)
1683     for (int i = 0; i < n_global_params; i++)
1684     {
1685         if (storage.getPatch().param_ptr[i]->midictrl == cc_encoded)
1686         {
1687             this->setParameterSmoothed(i, fval);
1688             int j = 0;
1689             while (j < 7)
1690             {
1691                 if ((refresh_ctrl_queue[j] > -1) && (refresh_ctrl_queue[j] != i))
1692                     j++;
1693                 else
1694                     break;
1695             }
1696             refresh_ctrl_queue[j] = i;
1697             refresh_ctrl_queue_value[j] = fval;
1698         }
1699     }
1700     int a = n_global_params + storage.getPatch().scene_active.val.i * n_scene_params;
1701     for (int i = a; i < (a + n_scene_params); i++)
1702     {
1703         if (storage.getPatch().param_ptr[i]->midictrl == cc_encoded)
1704         {
1705             this->setParameterSmoothed(i, fval);
1706             int j = 0;
1707             while (j < 7)
1708             {
1709                 if ((refresh_ctrl_queue[j] > -1) && (refresh_ctrl_queue[j] != i))
1710                     j++;
1711                 else
1712                     break;
1713             }
1714             refresh_ctrl_queue[j] = i;
1715             refresh_ctrl_queue_value[j] = fval;
1716         }
1717     }
1718 }
1719 
purgeHoldbuffer(int scene)1720 void SurgeSynthesizer::purgeHoldbuffer(int scene)
1721 {
1722     std::list<std::pair<int, int>> retainBuffer;
1723     for (auto hp : holdbuffer[scene])
1724     {
1725         auto channel = hp.first;
1726         auto key = hp.second;
1727 
1728         if (channel < 0 || key < 0)
1729         {
1730             // std::cout << "Caught tricky double releease condition!" << std::endl;
1731         }
1732         else
1733         {
1734             if (!channelState[0].hold && !channelState[channel].hold)
1735             {
1736                 releaseNotePostHoldCheck(scene, channel, key, 127);
1737             }
1738             else
1739             {
1740                 retainBuffer.push_back(hp);
1741             }
1742         }
1743     }
1744     holdbuffer[scene] = retainBuffer;
1745 }
1746 
allNotesOff()1747 void SurgeSynthesizer::allNotesOff()
1748 {
1749     for (int i = 0; i < 16; i++)
1750     {
1751         channelState[i].hold = false;
1752 
1753         for (int k = 0; k < 128; k++)
1754         {
1755             channelState[i].keyState[k].keystate = 0;
1756             channelState[i].keyState[k].lastdetune = 0;
1757         }
1758     }
1759 
1760     for (int s = 0; s < n_scenes; s++)
1761     {
1762         list<SurgeVoice *>::const_iterator iter;
1763         for (iter = voices[s].begin(); iter != voices[s].end(); iter++)
1764         {
1765             //_aligned_free(*iter);
1766             freeVoice(*iter);
1767         }
1768         voices[s].clear();
1769     }
1770     holdbuffer[0].clear();
1771     holdbuffer[1].clear();
1772     halfbandA.reset();
1773     halfbandB.reset();
1774     halfbandIN.reset();
1775 
1776     hpA.suspend();
1777     hpB.suspend();
1778 
1779     for (int i = 0; i < n_fx_slots; i++)
1780     {
1781         if (fx[i])
1782         {
1783             fx[i]->suspend();
1784         }
1785     }
1786 
1787     memset(mControlInterpolatorUsed, 0, sizeof(bool) * num_controlinterpolators);
1788 }
1789 
setSamplerate(float sr)1790 void SurgeSynthesizer::setSamplerate(float sr)
1791 {
1792     storage.setSamplerate(sr);
1793     sinus.set_rate(1000.0 * dsamplerate_inv);
1794 }
1795 
1796 //-------------------------------------------------------------------------------------------------
1797 
GetFreeControlInterpolatorIndex()1798 int SurgeSynthesizer::GetFreeControlInterpolatorIndex()
1799 {
1800     for (int i = 0; i < num_controlinterpolators; i++)
1801     {
1802         if (!mControlInterpolatorUsed[i])
1803         {
1804             return i;
1805         }
1806     }
1807     assert(0);
1808     return -1;
1809 }
1810 
1811 //-------------------------------------------------------------------------------------------------
1812 
GetControlInterpolatorIndex(int Id)1813 int SurgeSynthesizer::GetControlInterpolatorIndex(int Id)
1814 {
1815     for (int i = 0; i < num_controlinterpolators; i++)
1816     {
1817         if (mControlInterpolatorUsed[i] && mControlInterpolator[i].id == Id)
1818         {
1819             return i;
1820         }
1821     }
1822     return -1;
1823 }
1824 
1825 //-------------------------------------------------------------------------------------------------
1826 
ReleaseControlInterpolator(int Id)1827 void SurgeSynthesizer::ReleaseControlInterpolator(int Id)
1828 {
1829     int Index = GetControlInterpolatorIndex(Id);
1830     if (Index >= 0)
1831     {
1832         assert(Index < num_controlinterpolators);
1833         mControlInterpolatorUsed[Index] = false;
1834     }
1835 }
1836 
1837 //-------------------------------------------------------------------------------------------------
1838 
ControlInterpolator(int Id)1839 ControllerModulationSource *SurgeSynthesizer::ControlInterpolator(int Id)
1840 {
1841     int Index = GetControlInterpolatorIndex(Id);
1842 
1843     if (Index < 0)
1844         return nullptr;
1845 
1846     return &mControlInterpolator[Index];
1847 }
1848 
1849 //-------------------------------------------------------------------------------------------------
1850 
AddControlInterpolator(int Id,bool & AlreadyExisted)1851 ControllerModulationSource *SurgeSynthesizer::AddControlInterpolator(int Id, bool &AlreadyExisted)
1852 {
1853     int Index = GetControlInterpolatorIndex(Id);
1854 
1855     AlreadyExisted = false;
1856 
1857     if (Index >= 0)
1858     {
1859         // Already exists, return it
1860         AlreadyExisted = true;
1861         return &mControlInterpolator[Index];
1862     }
1863 
1864     Index = GetFreeControlInterpolatorIndex();
1865 
1866     if (Index >= 0)
1867     {
1868         // Add new
1869         mControlInterpolator[Index].id = Id;
1870         mControlInterpolatorUsed[Index] = true;
1871 
1872         mControlInterpolator[Index].smoothingMode = storage.smoothingMode; // IMPLEMENT THIS HERE
1873         return &mControlInterpolator[Index];
1874     }
1875 
1876     return nullptr;
1877 }
1878 
1879 //-------------------------------------------------------------------------------------------------
1880 
setParameterSmoothed(long index,float value)1881 void SurgeSynthesizer::setParameterSmoothed(long index, float value)
1882 {
1883     bool AlreadyExisted;
1884     ControllerModulationSource *mc = AddControlInterpolator(index, AlreadyExisted);
1885 
1886     if (mc)
1887     {
1888         if (!AlreadyExisted)
1889         {
1890             float oldval = storage.getPatch().param_ptr[index]->get_value_f01();
1891             mc->init(oldval);
1892             mc->set_target(value);
1893         }
1894         else
1895         {
1896             mc->set_target(value);
1897         }
1898     }
1899 }
1900 
1901 //-------------------------------------------------------------------------------------------------
1902 
setParameter01(long index,float value,bool external,bool force_integer)1903 bool SurgeSynthesizer::setParameter01(long index, float value, bool external, bool force_integer)
1904 {
1905     // does the parameter exist in the interpolator array? If it does, delete it
1906     ReleaseControlInterpolator(index);
1907 
1908     bool need_refresh = false;
1909 
1910     if (index >= metaparam_offset)
1911     {
1912         ((ControllerModulationSource *)storage.getPatch().scene[0].modsources[ms_ctrl1 + index -
1913                                                                               metaparam_offset])
1914             ->set_target01(value, true);
1915         return false;
1916     }
1917 
1918     if (index < storage.getPatch().param_ptr.size())
1919     {
1920         pdata oldval;
1921         oldval.i = storage.getPatch().param_ptr[index]->val.i;
1922 
1923         storage.getPatch().param_ptr[index]->set_value_f01(value, force_integer);
1924         if (storage.getPatch().param_ptr[index]->affect_other_parameters)
1925         {
1926             storage.getPatch().update_controls();
1927             need_refresh = true;
1928         }
1929 
1930         /*if(storage.getPatch().param_ptr[index]->ctrltype == ct_polymode)
1931         {
1932                 if (storage.getPatch().param_ptr[index]->val.i == pm_latch)
1933                 {
1934                         int s = storage.getPatch().param_ptr[index]->scene - 1;
1935                         release_if_latched[s&1] = true;
1936                         release_anyway[s&1] = true;
1937                         // release old notes if previous polymode was latch
1938                 }
1939         }*/
1940 
1941         switch (storage.getPatch().param_ptr[index]->ctrltype)
1942         {
1943         case ct_scenemode:
1944             release_if_latched[0] = true;
1945             release_if_latched[1] = true;
1946             release_anyway[0] = false;
1947             release_anyway[1] = false;
1948             break;
1949         case ct_polymode:
1950             if ((oldval.i == pm_latch) && (storage.getPatch().param_ptr[index]->val.i != pm_latch))
1951             {
1952                 int s = storage.getPatch().param_ptr[index]->scene - 1;
1953                 release_if_latched[s & 1] = true;
1954                 release_anyway[s & 1] = true;
1955                 // release old notes if previous polymode was latch
1956             }
1957             break;
1958         case ct_filtertype:
1959             switch_toggled_queued = true;
1960             {
1961                 // Oh my goodness this is deeply sketchy code to not document! It assumes that
1962                 // subtype is right after type in ID space without documenting it. So now
1963                 // documented!
1964                 auto typep = (storage.getPatch().param_ptr[index]);
1965                 auto subtypep = storage.getPatch().param_ptr[index + 1];
1966 
1967                 /* Used to be an lpmoog -> 3 type thing in here but that moved to the SurgeStorage
1968                  * ctor */
1969                 subtypep->val.i =
1970                     storage.subtypeMemory[typep->scene - 1][typep->ctrlgroup_entry][typep->val.i];
1971             }
1972             refresh_editor = true;
1973             break;
1974         case ct_osctype:
1975         {
1976             int s = storage.getPatch().param_ptr[index]->scene - 1;
1977 
1978             if (storage.getPatch().param_ptr[index]->val.i != oldval.i)
1979             {
1980                 /*
1981                  ** Wish there was a better way to figure out my osc but thsi works
1982                  */
1983                 for (auto oi = 0; s >= 0 && s <= 1 && oi < n_oscs; oi++)
1984                 {
1985                     if (storage.getPatch().scene[s].osc[oi].type.id ==
1986                         storage.getPatch().param_ptr[index]->id)
1987                     {
1988                         storage.getPatch().scene[s].osc[oi].queue_type =
1989                             storage.getPatch().param_ptr[index]->val.i;
1990                     }
1991                 }
1992             }
1993             /*
1994              * Since we are setting a Queue, we don't need to toggle controls
1995              */
1996             switch_toggled_queued = false;
1997             need_refresh = true;
1998             refresh_editor = true;
1999             break;
2000         }
2001         case ct_wstype:
2002         case ct_bool_mute:
2003         case ct_bool_fm:
2004         case ct_fbconfig:
2005             switch_toggled_queued = true;
2006             break;
2007         case ct_filtersubtype:
2008             // See above: We know the filter type for this subtype is at index - 1. Cap max to be
2009             // the fut-subtype
2010             {
2011                 auto subp = storage.getPatch().param_ptr[index];
2012                 auto filterType = storage.getPatch().param_ptr[index - 1]->val.i;
2013                 auto maxIVal = fut_subcount[filterType];
2014                 if (maxIVal == 0)
2015                     subp->val.i = 0;
2016                 else
2017                     subp->val.i = std::min(maxIVal - 1, subp->val.i);
2018                 storage.subtypeMemory[subp->scene - 1][subp->ctrlgroup_entry][filterType] =
2019                     subp->val.i;
2020 
2021                 switch_toggled_queued = true;
2022                 break;
2023             }
2024         case ct_fxtype:
2025         {
2026             // OK so this would work you would think but remember that FXSync is primary not the
2027             // patch so
2028             auto p = storage.getPatch().param_ptr[index];
2029             if (p->val.i != oldval.i)
2030             {
2031                 int cge = p->ctrlgroup_entry;
2032 
2033                 fxsync[cge].type.val.i = p->val.i;
2034                 p->val.i = oldval.i; // so funnily we want to set the value *back* so the loadFX
2035                                      // picks up the change in fxsync
2036                 Effect *t_fx = spawn_effect(fxsync[cge].type.val.i, &storage, &fxsync[cge], 0);
2037                 if (t_fx)
2038                 {
2039                     t_fx->init_ctrltypes();
2040                     t_fx->init_default_values();
2041                     delete t_fx;
2042                 }
2043 
2044                 switch_toggled_queued = true;
2045                 load_fx_needed = true;
2046                 fx_reload[cge] = true;
2047             }
2048             break;
2049         }
2050         case ct_bool_relative_switch:
2051         {
2052             int s = storage.getPatch().param_ptr[index]->scene - 1;
2053             bool down = storage.getPatch().param_ptr[index]->val.b;
2054             float polarity = down ? -1.f : 1.f;
2055 
2056             if (oldval.b == down)
2057                 polarity = 0.f;
2058 
2059             if (s >= 0)
2060             {
2061                 storage.getPatch().scene[s].filterunit[1].cutoff.val.f +=
2062                     polarity * storage.getPatch().scene[s].filterunit[0].cutoff.val.f;
2063                 storage.getPatch().scene[s].filterunit[1].envmod.val.f +=
2064                     polarity * storage.getPatch().scene[s].filterunit[0].envmod.val.f;
2065                 storage.getPatch().scene[s].filterunit[1].keytrack.val.f +=
2066                     polarity * storage.getPatch().scene[s].filterunit[0].keytrack.val.f;
2067             }
2068 
2069             if (down)
2070             {
2071                 storage.getPatch().scene[s].filterunit[1].cutoff.set_type(ct_freq_mod);
2072                 storage.getPatch().scene[s].filterunit[1].cutoff.set_name("Offset");
2073             }
2074             else
2075             {
2076                 storage.getPatch().scene[s].filterunit[1].cutoff.set_type(
2077                     ct_freq_audible_with_tunability);
2078                 storage.getPatch().scene[s].filterunit[1].cutoff.set_name("Cutoff");
2079             }
2080             need_refresh = true;
2081         }
2082         break;
2083         case ct_envmode:
2084             refresh_editor = true;
2085             need_refresh = true; // See github issue #160
2086             break;
2087         case ct_bool_link_switch:
2088             need_refresh = true;
2089             break;
2090         case ct_bool_solo:
2091             // pre-1.7.2 unique (single) solo
2092             /*
2093             if (storage.getPatch().param_ptr[index]->val.b)
2094             {
2095                int s = storage.getPatch().param_ptr[index]->scene - 1;
2096                if (s >= 0)
2097                {
2098                   storage.getPatch().scene[s].solo_o1.val.b = false;
2099                   storage.getPatch().scene[s].solo_o2.val.b = false;
2100                   storage.getPatch().scene[s].solo_o3.val.b = false;
2101                   storage.getPatch().scene[s].solo_ring_12.val.b = false;
2102                   storage.getPatch().scene[s].solo_ring_23.val.b = false;
2103                   storage.getPatch().scene[s].solo_noise.val.b = false;
2104                   storage.getPatch().param_ptr[index]->val.b = true;
2105                }
2106             }
2107             */
2108             switch_toggled_queued = true;
2109             need_refresh = true;
2110             break;
2111         };
2112     }
2113     if (external && !need_refresh)
2114     {
2115         bool got = false;
2116         for (int i = 0; i < 8; i++)
2117         {
2118             if (refresh_parameter_queue[i] < 0 || refresh_parameter_queue[i] == index)
2119             {
2120                 refresh_parameter_queue[i] = index;
2121                 got = true;
2122                 break;
2123             }
2124         }
2125         if (!got)
2126             refresh_overflow = true;
2127     }
2128     return need_refresh;
2129 }
2130 
switch_toggled()2131 void SurgeSynthesizer::switch_toggled()
2132 {
2133     for (int s = 0; s < n_scenes; s++)
2134     {
2135         list<SurgeVoice *>::iterator iter;
2136         for (iter = voices[s].begin(); iter != voices[s].end(); iter++)
2137         {
2138             SurgeVoice *v = *iter;
2139             v->switch_toggled();
2140         }
2141     }
2142 }
2143 
loadFx(bool initp,bool force_reload_all)2144 bool SurgeSynthesizer::loadFx(bool initp, bool force_reload_all)
2145 {
2146     load_fx_needed = false;
2147     for (int s = 0; s < n_fx_slots; s++)
2148     {
2149         bool something_changed = false;
2150         if ((fxsync[s].type.val.i != storage.getPatch().fx[s].type.val.i) || force_reload_all)
2151         {
2152             fx_reload[s] = false;
2153 
2154             fx[s].reset();
2155             /*if (!force_reload_all)*/ storage.getPatch().fx[s].type.val.i = fxsync[s].type.val.i;
2156             // else fxsync[s].type.val.i = storage.getPatch().fx[s].type.val.i;
2157 
2158             for (int j = 0; j < n_fx_params; j++)
2159             {
2160                 storage.getPatch().fx[s].p[j].set_type(ct_none);
2161                 std::string n = "Param ";
2162                 n += std::to_string(j + 1);
2163                 storage.getPatch().fx[s].p[j].set_name(n.c_str());
2164                 storage.getPatch().fx[s].p[j].val.i = 0;
2165                 storage.getPatch().globaldata[storage.getPatch().fx[s].p[j].id].i = 0;
2166             }
2167 
2168             if (/*!force_reload_all && */ storage.getPatch().fx[s].type.val.i)
2169                 memcpy((void *)&storage.getPatch().fx[s].p, (void *)&fxsync[s].p,
2170                        sizeof(Parameter) * n_fx_params);
2171 
2172             // std::cout << "About to call reset with " << _D(initp) << " at " << s << " to " <<
2173             // fxsync[s].type.val.i << std::endl;
2174             std::lock_guard<std::mutex> g(fxSpawnMutex);
2175 
2176             fx[s].reset(spawn_effect(storage.getPatch().fx[s].type.val.i, &storage,
2177                                      &storage.getPatch().fx[s], storage.getPatch().globaldata));
2178             if (fx[s])
2179             {
2180                 fx[s]->init_ctrltypes();
2181                 if (initp)
2182                     fx[s]->init_default_values();
2183                 else
2184                 {
2185                     for (int j = 0; j < n_fx_params; j++)
2186                     {
2187                         auto p = &(storage.getPatch().fx[s].p[j]);
2188                         if (p->ctrltype != ct_none)
2189                         {
2190                             if (p->valtype == vt_float)
2191                             {
2192                                 if (p->val.f < p->val_min.f)
2193                                 {
2194                                     p->val.f = p->val_min.f;
2195                                 }
2196                                 if (p->val.f > p->val_max.f)
2197                                 {
2198                                     p->val.f = p->val_max.f;
2199                                 }
2200                             }
2201                             else if (p->valtype == vt_int)
2202                             {
2203                                 if (p->val.i < p->val_min.i)
2204                                 {
2205                                     p->val.i = p->val_min.i;
2206                                 }
2207                                 if (p->val.i > p->val_max.i)
2208                                 {
2209                                     p->val.i = p->val_max.i;
2210                                 }
2211                             }
2212                         }
2213                     }
2214                 }
2215                 /*for(int j=0; j<n_fx_params; j++)
2216                 {
2217                     storage.getPatch().globaldata[storage.getPatch().fx[s].p[j].id].f =
2218                     storage.getPatch().fx[s].p[j].val.f;
2219                 }*/
2220 
2221                 fx[s]->init();
2222 
2223                 /*
2224                 ** Clear modulation onto FX otherwise it hangs around from old ones, often with
2225                 ** disastrously bad meaning. #2036. But only do this if it is a one FX change
2226                 ** (not a patch load)
2227                 */
2228                 if (!force_reload_all)
2229                 {
2230                     for (int j = 0; j < n_fx_params; j++)
2231                     {
2232                         auto p = &(storage.getPatch().fx[s].p[j]);
2233                         for (int ms = 1; ms < n_modsources; ms++)
2234                         {
2235                             clearModulation(p->id, (modsources)ms, true);
2236                         }
2237                     }
2238                     if (fx_reload_mod[s])
2239                     {
2240                         for (auto &t : fxmodsync[s])
2241                         {
2242                             setModulation(storage.getPatch().fx[s].p[std::get<1>(t)].id,
2243                                           (modsources)std::get<0>(t), std::get<2>(t));
2244                         }
2245                         fxmodsync[s].clear();
2246                         fx_reload_mod[s] = false;
2247                     }
2248                 }
2249             }
2250             else
2251             {
2252                 // We have re-loaded to NULL; so we want to clear modulation that points at us
2253                 // no matter what
2254                 for (int j = 0; j < n_fx_params; j++)
2255                 {
2256                     auto p = &(storage.getPatch().fx[s].p[j]);
2257                     for (int ms = 1; ms < n_modsources; ms++)
2258                     {
2259                         clearModulation(p->id, (modsources)ms, true);
2260                     }
2261                 }
2262             }
2263 
2264             something_changed = true;
2265             refresh_editor = true;
2266         }
2267         else if (fx_reload[s])
2268         {
2269             // This branch will happen when we change a preset for an FX; or when we turn an fx to
2270             // OFF
2271             if (storage.getPatch().fx[s].type.val.i != fxt_off)
2272                 memcpy((void *)&storage.getPatch().fx[s].p, (void *)&fxsync[s].p,
2273                        sizeof(Parameter) * n_fx_params);
2274             if (fx[s])
2275             {
2276                 std::lock_guard<std::mutex> g(fxSpawnMutex);
2277                 fx[s]->suspend();
2278                 fx[s]->init();
2279             }
2280             fx_reload[s] = false;
2281             fx_reload_mod[s] = false;
2282             refresh_editor = true;
2283             something_changed = true;
2284         }
2285 
2286         if (fx[s] && something_changed)
2287         {
2288             fx[s]->updateAfterReload();
2289         }
2290     }
2291 
2292     // if (something_changed) storage.getPatch().update_controls(false);
2293     return true;
2294 }
2295 
loadOscalgos()2296 bool SurgeSynthesizer::loadOscalgos()
2297 {
2298     for (int s = 0; s < n_scenes; s++)
2299     {
2300         for (int i = 0; i < n_oscs; i++)
2301         {
2302             bool resend = false;
2303 
2304             if (storage.getPatch().scene[s].osc[i].queue_type > -1)
2305             {
2306                 // clear assigned modulation if we change osc type, see issue #2224
2307                 if (storage.getPatch().scene[s].osc[i].queue_type !=
2308                     storage.getPatch().scene[s].osc[i].type.val.i)
2309                 {
2310                     clear_osc_modulation(s, i);
2311                 }
2312 
2313                 storage.getPatch().scene[s].osc[i].type.val.i =
2314                     storage.getPatch().scene[s].osc[i].queue_type;
2315                 storage.getPatch().update_controls(false, &storage.getPatch().scene[s].osc[i]);
2316                 storage.getPatch().scene[s].osc[i].queue_type = -1;
2317                 switch_toggled_queued = true;
2318                 refresh_editor = true;
2319                 resend = true;
2320             }
2321 
2322             TiXmlElement *e = (TiXmlElement *)storage.getPatch().scene[s].osc[i].queue_xmldata;
2323             if (e)
2324             {
2325                 resend = true;
2326                 for (int k = 0; k < n_osc_params; k++)
2327                 {
2328                     double d;
2329                     int j;
2330                     char lbl[TXT_SIZE];
2331 
2332                     snprintf(lbl, TXT_SIZE, "p%i", k);
2333 
2334                     if (storage.getPatch().scene[s].osc[i].p[k].valtype == vt_float)
2335                     {
2336                         if (e->QueryDoubleAttribute(lbl, &d) == TIXML_SUCCESS)
2337                         {
2338                             storage.getPatch().scene[s].osc[i].p[k].val.f = (float)d;
2339                         }
2340                     }
2341                     else
2342                     {
2343                         if (e->QueryIntAttribute(lbl, &j) == TIXML_SUCCESS)
2344                         {
2345                             storage.getPatch().scene[s].osc[i].p[k].val.i = j;
2346                         }
2347                     }
2348 
2349                     snprintf(lbl, TXT_SIZE, "p%i_deform_type", k);
2350 
2351                     if (e->QueryIntAttribute(lbl, &j) == TIXML_SUCCESS)
2352                     {
2353                         storage.getPatch().scene[s].osc[i].p[k].deform_type = j;
2354                     }
2355 
2356                     snprintf(lbl, TXT_SIZE, "p%i_extend_range", k);
2357 
2358                     if (e->QueryIntAttribute(lbl, &j) == TIXML_SUCCESS)
2359                     {
2360                         storage.getPatch().scene[s].osc[i].p[k].extend_range = j;
2361                     }
2362                 }
2363 
2364                 int rt;
2365                 if (e->QueryIntAttribute("retrigger", &rt) == TIXML_SUCCESS)
2366                 {
2367                     storage.getPatch().scene[s].osc[i].retrigger.val.b = rt;
2368                 }
2369 
2370                 /*
2371                  * Some oscillator types can change display when you change values
2372                  */
2373                 if (storage.getPatch().scene[s].osc[i].type.val.i == ot_modern)
2374                 {
2375                     refresh_editor = true;
2376                 }
2377                 storage.getPatch().scene[s].osc[i].queue_xmldata = 0;
2378             }
2379             if (resend)
2380             {
2381 #if TARGET_LV2
2382                 auto tp = &(storage.getPatch().scene[s].osc[i].type);
2383                 sendParameterAutomation(tp->id, getParameter01(tp->id));
2384                 for (int k = 0; k < n_osc_params; k++)
2385                 {
2386                     auto pp = &(storage.getPatch().scene[s].osc[i].p[k]);
2387                     sendParameterAutomation(pp->id, getParameter01(pp->id));
2388                 }
2389 #endif
2390             }
2391         }
2392     }
2393     return true;
2394 }
2395 
isValidModulation(long ptag,modsources modsource)2396 bool SurgeSynthesizer::isValidModulation(long ptag, modsources modsource)
2397 {
2398     if (!modsource)
2399         return false;
2400     if (!(ptag < storage.getPatch().param_ptr.size()))
2401         return false;
2402 
2403     Parameter *p = storage.getPatch().param_ptr[ptag];
2404 
2405     if (!p->modulateable)
2406         return false;
2407     if (p->valtype != ((valtypes)vt_float))
2408         return false;
2409     if (!p->per_voice_processing && !canModulateMonophonicTarget(modsource))
2410         return false;
2411 
2412     for (int sc = 0; sc < n_scenes; sc++)
2413     {
2414         if ((modsource == ms_keytrack) && (p == &storage.getPatch().scene[sc].pitch))
2415             return false;
2416     }
2417     if ((p->ctrlgroup == cg_LFO) && (p->ctrlgroup_entry == modsource))
2418         return false;
2419     if ((p->ctrlgroup == cg_LFO) && (p->ctrlgroup_entry >= ms_slfo1) && (!isScenelevel(modsource)))
2420         return false;
2421     if ((p->ctrlgroup == cg_ENV) && !canModulateModulators(modsource))
2422         return false;
2423     return true;
2424 }
2425 
getModRouting(long ptag,modsources modsource)2426 ModulationRouting *SurgeSynthesizer::getModRouting(long ptag, modsources modsource)
2427 {
2428     if (!isValidModulation(ptag, modsource))
2429         return 0;
2430 
2431     int scene = storage.getPatch().param_ptr[ptag]->scene;
2432     vector<ModulationRouting> *modlist = nullptr;
2433 
2434     if (!scene)
2435     {
2436         modlist = &storage.getPatch().modulation_global;
2437     }
2438     else
2439     {
2440         if (isScenelevel(modsource))
2441             modlist = &storage.getPatch().scene[scene - 1].modulation_scene;
2442         else
2443             modlist = &storage.getPatch().scene[scene - 1].modulation_voice;
2444     }
2445 
2446     int id = storage.getPatch().param_ptr[ptag]->param_id_in_scene;
2447     if (!scene)
2448         id = ptag;
2449     int n = modlist->size();
2450 
2451     for (int i = 0; i < n; i++)
2452     {
2453         if ((modlist->at(i).destination_id == id) && (modlist->at(i).source_id == modsource))
2454         {
2455             return &modlist->at(i);
2456         }
2457     }
2458 
2459     return 0;
2460 }
2461 
getModDepth(long ptag,modsources modsource)2462 float SurgeSynthesizer::getModDepth(long ptag, modsources modsource)
2463 {
2464     ModulationRouting *r = getModRouting(ptag, modsource);
2465     float d = 0.f;
2466     if (r)
2467         d = r->depth;
2468     Parameter *p = storage.getPatch().param_ptr.at(ptag);
2469     if (p && p->extend_range)
2470         d = p->get_extended(d);
2471     return d;
2472 }
2473 
isActiveModulation(long ptag,modsources modsource)2474 bool SurgeSynthesizer::isActiveModulation(long ptag, modsources modsource)
2475 {
2476     // if(!isValidModulation(ptag,modsource)) return false;
2477     if (getModRouting(ptag, modsource))
2478         return true;
2479     return false;
2480 }
2481 
isBipolarModulation(modsources tms)2482 bool SurgeSynthesizer::isBipolarModulation(modsources tms)
2483 {
2484     int scene_ms = storage.getPatch().scene_active.val.i;
2485 
2486     // You would think you could just do this nad ask for is_bipolar but remember the LFOs are made
2487     // at voice time so...
2488     if (tms >= ms_lfo1 && tms <= ms_slfo6)
2489     {
2490         bool isup =
2491             storage.getPatch().scene[scene_ms].lfo[tms - ms_lfo1].unipolar.val.i ||
2492             storage.getPatch().scene[scene_ms].lfo[tms - ms_lfo1].shape.val.i == lt_envelope;
2493 
2494         // For now
2495         return !isup;
2496     }
2497     if (tms >= ms_ctrl1 && tms <= ms_ctrl8)
2498     {
2499         // Macros can also be bipolar
2500         auto ms = storage.getPatch().scene[scene_ms].modsources[tms];
2501         if (ms)
2502             return ms->is_bipolar();
2503         else
2504             return false;
2505     }
2506     if (tms == ms_keytrack || tms == ms_lowest_key || tms == ms_highest_key ||
2507         tms == ms_latest_key || tms == ms_pitchbend || tms == ms_random_bipolar ||
2508         tms == ms_alternate_bipolar || tms == ms_timbre)
2509         return true;
2510     else
2511         return false;
2512 }
2513 
isModDestUsed(long ptag)2514 bool SurgeSynthesizer::isModDestUsed(long ptag)
2515 {
2516     int scene_ms = storage.getPatch().scene_active.val.i;
2517     int scene_p = storage.getPatch().param_ptr[ptag]->scene;
2518 
2519     long md_id = storage.getPatch().param_ptr[ptag]->id;
2520     if (scene_p)
2521         md_id = storage.getPatch().param_ptr[ptag]->param_id_in_scene;
2522 
2523     for (int j = 0; j < 3; j++)
2524     {
2525         // if((scene && (j>0))||(!scene && (j==0)))
2526         if ((scene_p && (j > 0)) || (!scene_p && (j == 0)))
2527         {
2528             vector<ModulationRouting> *modlist;
2529 
2530             switch (j)
2531             {
2532             case 0:
2533                 modlist = &storage.getPatch().modulation_global;
2534                 break;
2535             case 1:
2536                 modlist = &storage.getPatch().scene[scene_ms].modulation_scene;
2537                 break;
2538             case 2:
2539                 modlist = &storage.getPatch().scene[scene_ms].modulation_voice;
2540                 break;
2541             }
2542 
2543             int n = modlist->size();
2544             for (int i = 0; i < n; i++)
2545             {
2546                 if (modlist->at(i).destination_id == md_id)
2547                     return true;
2548             }
2549         }
2550     }
2551     return false;
2552 }
2553 
updateUsedState()2554 void SurgeSynthesizer::updateUsedState()
2555 {
2556     // intended for GUI only
2557     for (int i = 0; i < n_modsources; i++)
2558         modsourceused[i] = false;
2559 
2560     int scene = storage.getPatch().scene_active.val.i;
2561 
2562     for (int j = 0; j < 3; j++)
2563     {
2564         vector<ModulationRouting> *modlist;
2565 
2566         switch (j)
2567         {
2568         case 0:
2569             modlist = &storage.getPatch().modulation_global;
2570             break;
2571         case 1:
2572             modlist = &storage.getPatch().scene[scene].modulation_scene;
2573             break;
2574         case 2:
2575             modlist = &storage.getPatch().scene[scene].modulation_voice;
2576             break;
2577         }
2578 
2579         int n = modlist->size();
2580         for (int i = 0; i < n; i++)
2581         {
2582             int id = modlist->at(i).source_id;
2583             assert((id > 0) && (id < n_modsources));
2584             modsourceused[id] = true;
2585         }
2586     }
2587 }
2588 
prepareModsourceDoProcess(int scenemask)2589 void SurgeSynthesizer::prepareModsourceDoProcess(int scenemask)
2590 {
2591     for (int scene = 0; scene < n_scenes; scene++)
2592     {
2593         if ((1 << scene) & scenemask)
2594         {
2595             for (int i = 0; i < n_modsources; i++)
2596             {
2597                 bool setTo = false;
2598                 if (i >= ms_lfo1 && i <= ms_lfo6)
2599                 {
2600                     auto lf = &(storage.getPatch().scene[scene].lfo[i - ms_lfo1]);
2601                     if (lf->shape.val.i == lt_stepseq)
2602                     {
2603                         auto ss = &(storage.getPatch().stepsequences[scene][i - ms_lfo1]);
2604                         setTo = (ss->trigmask != 0);
2605                     }
2606                 }
2607                 storage.getPatch().scene[scene].modsource_doprocess[i] = setTo;
2608             }
2609 
2610             for (int j = 0; j < 3; j++)
2611             {
2612                 vector<ModulationRouting> *modlist;
2613 
2614                 switch (j)
2615                 {
2616                 case 0:
2617                     modlist = &storage.getPatch().modulation_global;
2618                     break;
2619                 case 1:
2620                     modlist = &storage.getPatch().scene[scene].modulation_scene;
2621                     break;
2622                 case 2:
2623                     modlist = &storage.getPatch().scene[scene].modulation_voice;
2624                     break;
2625                 }
2626 
2627                 int n = modlist->size();
2628                 for (int i = 0; i < n; i++)
2629                 {
2630                     int id = modlist->at(i).source_id;
2631                     assert((id > 0) && (id < n_modsources));
2632                     storage.getPatch().scene[scene].modsource_doprocess[id] = true;
2633                 }
2634             }
2635         }
2636     }
2637 }
2638 
isModsourceUsed(modsources modsource)2639 bool SurgeSynthesizer::isModsourceUsed(modsources modsource)
2640 {
2641     updateUsedState();
2642     return modsourceused[modsource];
2643 }
2644 
getModulation(long ptag,modsources modsource)2645 float SurgeSynthesizer::getModulation(long ptag, modsources modsource)
2646 {
2647     if (!isValidModulation(ptag, modsource))
2648         return 0.0f;
2649 
2650     ModulationRouting *r = getModRouting(ptag, modsource);
2651     if (r)
2652         return storage.getPatch().param_ptr[ptag]->get_modulation_f01(r->depth);
2653 
2654     return storage.getPatch().param_ptr[ptag]->get_modulation_f01(0);
2655 }
2656 
clear_osc_modulation(int scene,int entry)2657 void SurgeSynthesizer::clear_osc_modulation(int scene, int entry)
2658 {
2659     storage.modRoutingMutex.lock();
2660     vector<ModulationRouting>::iterator iter;
2661 
2662     int pid = storage.getPatch().scene[scene].osc[entry].p[0].param_id_in_scene;
2663     iter = storage.getPatch().scene[scene].modulation_scene.begin();
2664     while (iter != storage.getPatch().scene[scene].modulation_scene.end())
2665     {
2666         if ((iter->destination_id >= pid) && (iter->destination_id < (pid + n_osc_params)))
2667         {
2668             iter = storage.getPatch().scene[scene].modulation_scene.erase(iter);
2669         }
2670         else
2671             iter++;
2672     }
2673     iter = storage.getPatch().scene[scene].modulation_voice.begin();
2674     while (iter != storage.getPatch().scene[scene].modulation_voice.end())
2675     {
2676         if ((iter->destination_id >= pid) && (iter->destination_id < (pid + n_osc_params)))
2677         {
2678             iter = storage.getPatch().scene[scene].modulation_voice.erase(iter);
2679         }
2680         else
2681             iter++;
2682     }
2683     storage.modRoutingMutex.unlock();
2684 }
2685 
clearModulation(long ptag,modsources modsource,bool clearEvenIfInvalid)2686 void SurgeSynthesizer::clearModulation(long ptag, modsources modsource, bool clearEvenIfInvalid)
2687 {
2688     if (!isValidModulation(ptag, modsource) && !clearEvenIfInvalid)
2689         return;
2690 
2691     int scene = storage.getPatch().param_ptr[ptag]->scene;
2692 
2693     vector<ModulationRouting> *modlist;
2694 
2695     if (!scene)
2696     {
2697         modlist = &storage.getPatch().modulation_global;
2698     }
2699     else
2700     {
2701         if (isScenelevel(modsource))
2702             modlist = &storage.getPatch().scene[scene - 1].modulation_scene;
2703         else
2704             modlist = &storage.getPatch().scene[scene - 1].modulation_voice;
2705     }
2706 
2707     int id = storage.getPatch().param_ptr[ptag]->param_id_in_scene;
2708     if (!scene)
2709         id = ptag;
2710     int n = modlist->size();
2711 
2712     for (int i = 0; i < n; i++)
2713     {
2714         if ((modlist->at(i).destination_id == id) && (modlist->at(i).source_id == modsource))
2715         {
2716             storage.modRoutingMutex.lock();
2717             modlist->erase(modlist->begin() + i);
2718             storage.modRoutingMutex.unlock();
2719             return;
2720         }
2721     }
2722 }
2723 
setModulation(long ptag,modsources modsource,float val)2724 bool SurgeSynthesizer::setModulation(long ptag, modsources modsource, float val)
2725 {
2726     if (!isValidModulation(ptag, modsource))
2727         return false;
2728     float value = storage.getPatch().param_ptr[ptag]->set_modulation_f01(val);
2729     int scene = storage.getPatch().param_ptr[ptag]->scene;
2730 
2731     vector<ModulationRouting> *modlist;
2732 
2733     if (!scene)
2734     {
2735         modlist = &storage.getPatch().modulation_global;
2736     }
2737     else
2738     {
2739         if (isScenelevel(modsource))
2740             modlist = &storage.getPatch().scene[scene - 1].modulation_scene;
2741         else
2742             modlist = &storage.getPatch().scene[scene - 1].modulation_voice;
2743     }
2744 
2745     storage.modRoutingMutex.lock();
2746 
2747     int id = storage.getPatch().param_ptr[ptag]->param_id_in_scene;
2748     if (!scene)
2749         id = ptag;
2750     int n = modlist->size();
2751     int found_id = -1;
2752     for (int i = 0; i < n; i++)
2753     {
2754         if ((modlist->at(i).destination_id == id) && (modlist->at(i).source_id == modsource))
2755         {
2756             found_id = i;
2757             break;
2758         }
2759     }
2760 
2761     if (value == 0)
2762     {
2763         if (found_id >= 0)
2764         {
2765             modlist->erase(modlist->begin() + found_id);
2766         }
2767     }
2768     else
2769     {
2770         if (found_id < 0)
2771         {
2772             ModulationRouting t;
2773             t.depth = value;
2774             t.source_id = modsource;
2775             t.destination_id = id;
2776             modlist->push_back(t);
2777         }
2778         else
2779         {
2780             modlist->at(found_id).depth = value;
2781         }
2782     }
2783     storage.modRoutingMutex.unlock();
2784 
2785     return true;
2786 }
2787 
2788 #if 0
2789 int SurgeSynthesizer::remapExternalApiToInternalId(unsigned int x)
2790 {
2791    if (x < n_customcontrollers)
2792       return metaparam_offset + x;
2793    else if (x >= n_total_params)
2794       return x - n_total_params;
2795    return x;
2796 }
2797 
2798 int SurgeSynthesizer::remapInternalToExternalApiId(unsigned int x)
2799 {
2800    if (x >= metaparam_offset)
2801       return (x - metaparam_offset);
2802    else if (x < n_customcontrollers)
2803       return x + n_total_params;
2804    return x;
2805 }
2806 #endif
2807 
getParameter01(long index)2808 float SurgeSynthesizer::getParameter01(long index)
2809 {
2810     if (index < 0)
2811         return 0.f;
2812     if (index >= metaparam_offset)
2813         return storage.getPatch()
2814             .scene[0]
2815             .modsources[ms_ctrl1 + index - metaparam_offset]
2816             ->get_output01();
2817     if (index < storage.getPatch().param_ptr.size())
2818         return storage.getPatch().param_ptr[index]->get_value_f01();
2819     return 0.f;
2820 }
2821 
getParameterDisplay(long index,char * text)2822 void SurgeSynthesizer::getParameterDisplay(long index, char *text)
2823 {
2824     if ((index >= 0) && (index < storage.getPatch().param_ptr.size()))
2825     {
2826         storage.getPatch().param_ptr[index]->get_display(text);
2827     }
2828     else if (index >= metaparam_offset)
2829     {
2830         snprintf(text, TXT_SIZE, "%.2f %%",
2831                  100.f * storage.getPatch()
2832                              .scene[0]
2833                              .modsources[ms_ctrl1 + index - metaparam_offset]
2834                              ->get_output());
2835     }
2836     else
2837         snprintf(text, TXT_SIZE, "-");
2838 }
2839 
getParameterDisplayAlt(long index,char * text)2840 void SurgeSynthesizer::getParameterDisplayAlt(long index, char *text)
2841 {
2842     if ((index >= 0) && (index < storage.getPatch().param_ptr.size()))
2843     {
2844         storage.getPatch().param_ptr[index]->get_display_alt(text);
2845     }
2846     else
2847     {
2848         text[0] = 0;
2849     }
2850 }
2851 
getParameterDisplay(long index,char * text,float x)2852 void SurgeSynthesizer::getParameterDisplay(long index, char *text, float x)
2853 {
2854     if ((index >= 0) && (index < storage.getPatch().param_ptr.size()))
2855     {
2856         storage.getPatch().param_ptr[index]->get_display(text, true, x);
2857     }
2858     else if (index >= metaparam_offset)
2859     {
2860         snprintf(text, TXT_SIZE, "%.2f %%",
2861                  100.f * storage.getPatch()
2862                              .scene[0]
2863                              .modsources[ms_ctrl1 + index - metaparam_offset]
2864                              ->get_output());
2865     }
2866     else
2867         snprintf(text, TXT_SIZE, "-");
2868 }
2869 
getParameterName(long index,char * text)2870 void SurgeSynthesizer::getParameterName(long index, char *text)
2871 {
2872     if ((index >= 0) && (index < storage.getPatch().param_ptr.size()))
2873     {
2874         int scn = storage.getPatch().param_ptr[index]->scene;
2875         // TODO: FIX SCENE ASSUMPTION
2876         string sn[3] = {"", "A ", "B "};
2877 
2878         snprintf(text, TXT_SIZE, "%s%s", sn[scn].c_str(),
2879                  storage.getPatch().param_ptr[index]->get_full_name());
2880     }
2881     else if (index >= metaparam_offset)
2882     {
2883         int c = index - metaparam_offset;
2884         snprintf(text, TXT_SIZE, "Macro %i: %s", c + 1,
2885                  storage.getPatch().CustomControllerLabel[c]);
2886     }
2887     else
2888         snprintf(text, TXT_SIZE, "-");
2889 }
2890 
getParameterNameW(long index,wchar_t * ptr)2891 void SurgeSynthesizer::getParameterNameW(long index, wchar_t *ptr)
2892 {
2893     if ((index >= 0) && (index < storage.getPatch().param_ptr.size()))
2894     {
2895         int scn = storage.getPatch().param_ptr[index]->scene;
2896         // TODO: FIX SCENE ASSUMPTION
2897         char sn[3][3] = {"", "A ", "B "};
2898         char pname[256];
2899 
2900         snprintf(pname, 255, "%s%s", sn[scn], storage.getPatch().param_ptr[index]->get_full_name());
2901 
2902         // the input is not wide so don't use %S
2903         swprintf(ptr, 128, L"%s", pname);
2904     }
2905     else if (index >= metaparam_offset)
2906     {
2907         int c = index - metaparam_offset;
2908         // For a reason I don't understand, on windows, we need to sprintf then swprinf just the
2909         // short char to make just these names work. :shrug:
2910         char wideHack[256];
2911 
2912         if (c >= num_metaparameters)
2913         {
2914             snprintf(wideHack, 255, "Macro: ERROR");
2915         }
2916         else
2917         {
2918             snprintf(wideHack, 255, "Macro %d: %s", c + 1,
2919                      storage.getPatch().CustomControllerLabel[c]);
2920         }
2921         swprintf(ptr, 128, L"%s", wideHack);
2922     }
2923     else
2924     {
2925         swprintf(ptr, 128, L"-");
2926     }
2927 }
2928 
getParameterShortNameW(long index,wchar_t * ptr)2929 void SurgeSynthesizer::getParameterShortNameW(long index, wchar_t *ptr)
2930 {
2931     if ((index >= 0) && (index < storage.getPatch().param_ptr.size()))
2932     {
2933         int scn = storage.getPatch().param_ptr[index]->scene;
2934         // TODO: FIX SCENE ASSUMPTION
2935         string sn[3] = {"", "A ", "B "};
2936 
2937         swprintf(ptr, 128, L"%s%s", sn[scn].c_str(),
2938                  storage.getPatch().param_ptr[index]->get_name());
2939     }
2940     else if (index >= metaparam_offset)
2941     {
2942         getParameterNameW(index, ptr);
2943     }
2944     else
2945     {
2946         swprintf(ptr, 128, L"-");
2947     }
2948 }
2949 
getParameterUnitW(long index,wchar_t * ptr)2950 void SurgeSynthesizer::getParameterUnitW(long index, wchar_t *ptr)
2951 {
2952     if ((index >= 0) && (index < storage.getPatch().param_ptr.size()))
2953     {
2954         swprintf(ptr, 128, L"%s", storage.getPatch().param_ptr[index]->getUnit());
2955     }
2956     else
2957     {
2958         swprintf(ptr, 128, L"");
2959     }
2960 }
2961 
getParameterStringW(long index,float value,wchar_t * ptr)2962 void SurgeSynthesizer::getParameterStringW(long index, float value, wchar_t *ptr)
2963 {
2964     if ((index >= 0) && (index < storage.getPatch().param_ptr.size()))
2965     {
2966         char text[128];
2967         storage.getPatch().param_ptr[index]->get_display(text, true, value);
2968 
2969         swprintf(ptr, 128, L"%s", text);
2970     }
2971     else if (index >= metaparam_offset)
2972     {
2973         // For a reason I don't understand, on windows, we need to sprintf then swprinf just the
2974         // short char to make just these names work. :shrug:
2975         char wideHack[256];
2976         snprintf(wideHack, 256, "%.2f %%", 100.f * value);
2977         swprintf(ptr, 128, L"%s", wideHack);
2978     }
2979     else
2980     {
2981         swprintf(ptr, 128, L"-");
2982     }
2983 }
2984 
getParameterMeta(long index,parametermeta & pm)2985 void SurgeSynthesizer::getParameterMeta(long index, parametermeta &pm)
2986 {
2987     if ((index >= 0) && (index < storage.getPatch().param_ptr.size()))
2988     {
2989         pm.flags = storage.getPatch().param_ptr[index]->ctrlstyle;
2990         pm.fmin = 0.f; // storage.getPatch().param_ptr[index]->val_min.f;
2991         pm.fmax = 1.f; // storage.getPatch().param_ptr[index]->val_max.f;
2992         pm.fdefault =
2993             storage.getPatch()
2994                 .param_ptr[index]
2995                 ->get_default_value_f01(); // storage.getPatch().param_ptr[index]->val_default.f;
2996         pm.hide = (pm.flags & kHide) != 0;
2997         pm.meta = (pm.flags & kMeta) != 0;
2998         pm.expert = !(pm.flags & kEasy);
2999         pm.clump = 2;
3000         if (storage.getPatch().param_ptr[index]->scene)
3001         {
3002             pm.clump += storage.getPatch().param_ptr[index]->ctrlgroup +
3003                         (storage.getPatch().param_ptr[index]->scene - 1) * 6;
3004             if (storage.getPatch().param_ptr[index]->ctrlgroup == 0)
3005                 pm.clump++;
3006         }
3007     }
3008     else if (index >= metaparam_offset)
3009     {
3010         pm.flags = 0;
3011         pm.fmin = 0.f;
3012         pm.fmax = 1.f;
3013         pm.fdefault = 0.5f;
3014         pm.hide = false;
3015         pm.meta =
3016             false; // ironic as they are metaparameters, but they don't affect any other sliders
3017         pm.expert = false;
3018         pm.clump = 1;
3019     }
3020 }
3021 /*unsigned int sub3_synth::getParameterFlags (long index)
3022 {
3023         if (index<storage.getPatch().param_ptr.size())
3024         {
3025                 return storage.getPatch().param_ptr[index]->ctrlstyle;
3026         }
3027         return 0;
3028 }*/
3029 
getParameter(long index)3030 float SurgeSynthesizer::getParameter(long index)
3031 {
3032     if (index < 0)
3033         return 0.f;
3034     if (index >= metaparam_offset)
3035         return storage.getPatch()
3036             .scene[0]
3037             .modsources[ms_ctrl1 + index - metaparam_offset]
3038             ->get_output();
3039     if (index < storage.getPatch().param_ptr.size())
3040         return storage.getPatch().param_ptr[index]->get_value_f01();
3041     return 0.f;
3042 }
3043 
normalizedToValue(long index,float value)3044 float SurgeSynthesizer::normalizedToValue(long index, float value)
3045 {
3046     if (index < 0)
3047         return 0.f;
3048     if (index >= metaparam_offset)
3049         return value;
3050     if (index < storage.getPatch().param_ptr.size())
3051         return storage.getPatch().param_ptr[index]->normalized_to_value(value);
3052     return 0.f;
3053 }
3054 
valueToNormalized(long index,float value)3055 float SurgeSynthesizer::valueToNormalized(long index, float value)
3056 {
3057     if (index < 0)
3058         return 0.f;
3059     if (index >= metaparam_offset)
3060         return value;
3061     if (index < storage.getPatch().param_ptr.size())
3062         return storage.getPatch().param_ptr[index]->value_to_normalized(value);
3063     return 0.f;
3064 }
3065 
stringToNormalizedValue(const ID & index,std::string s,float & outval)3066 bool SurgeSynthesizer::stringToNormalizedValue(const ID &index, std::string s, float &outval)
3067 {
3068     int id = index.getSynthSideId();
3069     if (id < 0)
3070         return false;
3071     if (id >= metaparam_offset)
3072         return false;
3073     if (id >= storage.getPatch().param_ptr.size())
3074         return false;
3075 
3076     auto p = storage.getPatch().param_ptr[id];
3077     if (p->valtype != vt_float)
3078         return false;
3079 
3080     pdata vt = p->val;
3081     auto res = p->set_value_from_string_onto(s, vt);
3082 
3083     if (res)
3084     {
3085         outval = (vt.f - p->val_min.f) / (p->val_max.f - p->val_min.f);
3086         return true;
3087     }
3088 
3089     return false;
3090 }
3091 
3092 #if MAC || LINUX
loadPatchInBackgroundThread(void * sy)3093 void *loadPatchInBackgroundThread(void *sy)
3094 {
3095 #else
3096 DWORD WINAPI loadPatchInBackgroundThread(LPVOID lpParam)
3097 {
3098     void *sy = lpParam;
3099 #endif
3100 
3101     SurgeSynthesizer *synth = (SurgeSynthesizer *)sy;
3102     std::lock_guard<std::mutex> mg(synth->patchLoadSpawnMutex);
3103     if (synth->patchid_queue >= 0)
3104     {
3105         int patchid = synth->patchid_queue;
3106         synth->patchid_queue = -1;
3107         synth->allNotesOff();
3108         synth->loadPatch(patchid);
3109     }
3110     if (synth->has_patchid_file)
3111     {
3112         auto p(string_to_path(synth->patchid_file));
3113         auto s = path_to_string(p.stem());
3114         synth->has_patchid_file = false;
3115         synth->allNotesOff();
3116 
3117         int ptid = -1, ct = 0;
3118         for (const auto &pti : synth->storage.patch_list)
3119         {
3120             if (path_to_string(pti.path) == synth->patchid_file)
3121             {
3122                 ptid = ct;
3123             }
3124             ct++;
3125         }
3126 
3127         if (ptid >= 0)
3128         {
3129             synth->loadPatch(ptid);
3130         }
3131         else
3132         {
3133             synth->loadPatchByPath(synth->patchid_file, -1, s.c_str());
3134         }
3135     }
3136 #if TARGET_LV2
3137     synth->getParent()->patchChanged();
3138 #endif
3139 
3140     synth->halt_engine = false;
3141 
3142     return 0;
3143 }
3144 
3145 void SurgeSynthesizer::processThreadunsafeOperations()
3146 {
3147     if (!audio_processing_active)
3148     {
3149         // if the audio processing is inactive, patchloading should occur anyway
3150         if (patchid_queue >= 0)
3151         {
3152             loadPatch(patchid_queue);
3153 #if TARGET_LV2
3154             getParent()->patchChanged();
3155 #endif
3156             patchid_queue = -1;
3157         }
3158 
3159         if (load_fx_needed)
3160             loadFx(false, false);
3161 
3162         loadOscalgos();
3163     }
3164 }
3165 
3166 void SurgeSynthesizer::resetStateFromTimeData()
3167 {
3168     storage.songpos = time_data.ppqPos;
3169     if (time_data.tempo > 0)
3170     {
3171         storage.temposyncratio = time_data.tempo / 120.f;
3172         storage.temposyncratio_inv = 1.f / storage.temposyncratio;
3173     }
3174     else
3175     {
3176         storage.temposyncratio = 1.f;
3177         storage.temposyncratio_inv = 1.f;
3178     }
3179 }
3180 void SurgeSynthesizer::processControl()
3181 {
3182     processEnqueuedPatchIfNeeded();
3183 
3184     storage.perform_queued_wtloads();
3185     int sm = storage.getPatch().scenemode.val.i;
3186     // TODO: FIX SCENE ASSUMPTION
3187     bool playA = (sm == sm_split) || (sm == sm_dual) || (sm == sm_chsplit) ||
3188                  (storage.getPatch().scene_active.val.i == 0);
3189     bool playB = (sm == sm_split) || (sm == sm_dual) || (sm == sm_chsplit) ||
3190                  (storage.getPatch().scene_active.val.i == 1);
3191 
3192     storage.songpos = time_data.ppqPos;
3193     storage.temposyncratio = time_data.tempo / 120.f;
3194     storage.temposyncratio_inv = 1.f / storage.temposyncratio;
3195 
3196     // TODO: FIX SCENE ASSUMPTION
3197     if (release_if_latched[0])
3198     {
3199         if (!playA || release_anyway[0])
3200             releaseScene(0);
3201         release_if_latched[0] = false;
3202         release_anyway[0] = false;
3203     }
3204     if (release_if_latched[1])
3205     {
3206         if (!playB || release_anyway[1])
3207             releaseScene(1);
3208         release_if_latched[1] = false;
3209         release_anyway[1] = false;
3210     }
3211 
3212     // TODO: FIX SCENE ASSUMPTION
3213     if (playA && (storage.getPatch().scene[0].polymode.val.i == pm_latch) && voices[0].empty())
3214         playNote(1, 60, 100, 0);
3215     if (playB && (storage.getPatch().scene[1].polymode.val.i == pm_latch) && voices[1].empty())
3216         playNote(2, 60, 100, 0);
3217 
3218     // interpolate MIDI controllers
3219     for (int i = 0; i < num_controlinterpolators; i++)
3220     {
3221         if (mControlInterpolatorUsed[i])
3222         {
3223             ControllerModulationSource *mc = &mControlInterpolator[i];
3224             bool cont = mc->process_block_until_close(0.001f);
3225             int id = mc->id;
3226             storage.getPatch().param_ptr[id]->set_value_f01(mc->output);
3227             if (!cont)
3228             {
3229                 mControlInterpolatorUsed[i] = false;
3230             }
3231         }
3232     }
3233 
3234     storage.getPatch().copy_globaldata(
3235         storage.getPatch()
3236             .globaldata); // Drains a great deal of CPU while in Debug mode.. optimize?
3237 
3238     // TODO: FIX SCENE ASSUMPTION
3239     if (playA)
3240         storage.getPatch().copy_scenedata(storage.getPatch().scenedata[0], 0); // -""-
3241     if (playB)
3242         storage.getPatch().copy_scenedata(storage.getPatch().scenedata[1], 1);
3243 
3244     //	if(sm == sm_morph) storage.getPatch().do_morph();
3245 
3246     prepareModsourceDoProcess((playA ? 1 : 0) | (playB ? 2 : 0));
3247 
3248     for (int s = 0; s < n_scenes; s++)
3249     {
3250         if (((s == 0) && playA) || ((s == 1) && playB))
3251         {
3252             if (storage.getPatch().scene[s].modsource_doprocess[ms_modwheel])
3253                 storage.getPatch().scene[s].modsources[ms_modwheel]->process_block();
3254             if (storage.getPatch().scene[s].modsource_doprocess[ms_breath])
3255                 storage.getPatch().scene[s].modsources[ms_breath]->process_block();
3256             if (storage.getPatch().scene[s].modsource_doprocess[ms_expression])
3257                 storage.getPatch().scene[s].modsources[ms_expression]->process_block();
3258             if (storage.getPatch().scene[s].modsource_doprocess[ms_sustain])
3259                 storage.getPatch().scene[s].modsources[ms_sustain]->process_block();
3260             if (storage.getPatch().scene[s].modsource_doprocess[ms_aftertouch])
3261                 storage.getPatch().scene[s].modsources[ms_aftertouch]->process_block();
3262             if (storage.getPatch().scene[s].modsource_doprocess[ms_lowest_key])
3263                 storage.getPatch().scene[s].modsources[ms_lowest_key]->process_block();
3264             if (storage.getPatch().scene[s].modsource_doprocess[ms_highest_key])
3265                 storage.getPatch().scene[s].modsources[ms_highest_key]->process_block();
3266             if (storage.getPatch().scene[s].modsource_doprocess[ms_latest_key])
3267                 storage.getPatch().scene[s].modsources[ms_latest_key]->process_block();
3268 
3269             if (storage.getPatch().scene[s].modsource_doprocess[ms_random_unipolar])
3270                 storage.getPatch().scene[s].modsources[ms_random_unipolar]->process_block();
3271             if (storage.getPatch().scene[s].modsource_doprocess[ms_random_bipolar])
3272                 storage.getPatch().scene[s].modsources[ms_random_bipolar]->process_block();
3273             if (storage.getPatch().scene[s].modsource_doprocess[ms_alternate_bipolar])
3274                 storage.getPatch().scene[s].modsources[ms_alternate_bipolar]->process_block();
3275             if (storage.getPatch().scene[s].modsource_doprocess[ms_alternate_unipolar])
3276                 storage.getPatch().scene[s].modsources[ms_alternate_unipolar]->process_block();
3277 
3278             storage.getPatch().scene[s].modsources[ms_pitchbend]->process_block();
3279 
3280             for (int i = 0; i < n_customcontrollers; i++)
3281                 storage.getPatch().scene[s].modsources[ms_ctrl1 + i]->process_block();
3282 
3283             // for(int i=0; i<n_lfos_scene; i++)
3284             // storage.getPatch().scene[s].modsources[ms_slfo1+i]->process_block();
3285 
3286             int n = storage.getPatch().scene[s].modulation_scene.size();
3287             for (int i = 0; i < n; i++)
3288             {
3289                 int src_id = storage.getPatch().scene[s].modulation_scene[i].source_id;
3290                 if (storage.getPatch().scene[s].modsources[src_id])
3291                 {
3292                     int dst_id = storage.getPatch().scene[s].modulation_scene[i].destination_id;
3293                     float depth = storage.getPatch().scene[s].modulation_scene[i].depth;
3294                     storage.getPatch().scenedata[s][dst_id].f +=
3295                         depth * storage.getPatch().scene[s].modsources[src_id]->output;
3296                 }
3297             }
3298 
3299             for (int i = 0; i < n_lfos_scene; i++)
3300                 storage.getPatch().scene[s].modsources[ms_slfo1 + i]->process_block();
3301         }
3302     }
3303 
3304     loadOscalgos();
3305 
3306     int n = storage.getPatch().modulation_global.size();
3307     for (int i = 0; i < n; i++)
3308     {
3309         int src_id = storage.getPatch().modulation_global[i].source_id;
3310         int dst_id = storage.getPatch().modulation_global[i].destination_id;
3311         float depth = storage.getPatch().modulation_global[i].depth;
3312         storage.getPatch().globaldata[dst_id].f +=
3313             depth * storage.getPatch().scene[0].modsources[src_id]->output;
3314     }
3315 
3316     if (switch_toggled_queued)
3317     {
3318         switch_toggled();
3319         switch_toggled_queued = false;
3320     }
3321 
3322     if (load_fx_needed)
3323         loadFx(false, false);
3324 
3325     if (fx_suspend_bitmask)
3326     {
3327         for (int i = 0; i < n_fx_slots; i++)
3328         {
3329             if (((1 << i) & fx_suspend_bitmask) && fx[i])
3330                 fx[i]->suspend();
3331         }
3332         fx_suspend_bitmask = 0;
3333     }
3334 
3335     for (int i = 0; i < n_fx_slots; ++i)
3336         if (fx[i])
3337             refresh_editor |= fx[i]->checkHasInvalidatedUI();
3338 
3339     if (storage.oddsound_mts_client)
3340     {
3341         storage.oddsound_mts_on_check = (storage.oddsound_mts_on_check + 1) & (1024 - 1);
3342         if (storage.oddsound_mts_on_check == 0)
3343         {
3344             bool prior = storage.oddsound_mts_active;
3345             storage.oddsound_mts_active = MTS_HasMaster(storage.oddsound_mts_client);
3346             if (prior != storage.oddsound_mts_active)
3347             {
3348                 refresh_editor = true;
3349             }
3350         }
3351     }
3352 }
3353 
3354 void SurgeSynthesizer::process()
3355 {
3356 #if DEBUG_RNG_THREADING
3357     storage.audioThreadID = pthread_self();
3358 #endif
3359 
3360     float mfade = 1.f;
3361 
3362     if (halt_engine)
3363     {
3364         clear_block(output[0], BLOCK_SIZE_QUAD);
3365         clear_block(output[1], BLOCK_SIZE_QUAD);
3366         return;
3367     }
3368     else if (patchid_queue >= 0 || has_patchid_file)
3369     {
3370         masterfade = max(0.f, masterfade - 0.05f);
3371         mfade = masterfade * masterfade;
3372 
3373         if (masterfade < 0.0001f)
3374         {
3375             std::lock_guard<std::mutex> mg(patchLoadSpawnMutex);
3376             // spawn patch-loading thread
3377             allNotesOff();
3378             halt_engine = true;
3379 
3380 #if MAC || LINUX
3381             pthread_t thread;
3382             pthread_attr_t attributes;
3383             int ret;
3384             sched_param params;
3385 
3386             /* initialized with default attributes */
3387             ret = pthread_attr_init(&attributes);
3388 
3389             /* safe to get existing scheduling param */
3390             ret = pthread_attr_getschedparam(&attributes, &params);
3391 
3392             /* set the priority; others are unchanged */
3393             params.sched_priority = sched_get_priority_min(SCHED_OTHER);
3394 
3395             /* setting the new scheduling param */
3396             ret = pthread_attr_setschedparam(&attributes, &params);
3397 
3398             ret = pthread_create(&thread, &attributes, loadPatchInBackgroundThread, this);
3399 #else
3400 
3401             DWORD dwThreadId;
3402             HANDLE hThread = CreateThread(NULL, // default security attributes
3403                                           0,    // use default stack size
3404                                           loadPatchInBackgroundThread, // thread function
3405                                           this,         // argument to thread function
3406                                           0,            // use default creation flags
3407                                           &dwThreadId); // returns the thread identifier
3408             SetThreadPriority(hThread, THREAD_PRIORITY_NORMAL);
3409 #endif
3410 
3411             clear_block(output[0], BLOCK_SIZE_QUAD);
3412             clear_block(output[1], BLOCK_SIZE_QUAD);
3413             return;
3414         }
3415     }
3416 
3417     // process inputs (upsample & halfrate)
3418     if (process_input)
3419     {
3420         hardclip_block8(input[0], BLOCK_SIZE_QUAD);
3421         hardclip_block8(input[1], BLOCK_SIZE_QUAD);
3422         copy_block(input[0], storage.audio_in_nonOS[0], BLOCK_SIZE_QUAD);
3423         copy_block(input[1], storage.audio_in_nonOS[1], BLOCK_SIZE_QUAD);
3424         halfbandIN.process_block_U2(input[0], input[1], storage.audio_in[0], storage.audio_in[1]);
3425     }
3426     else
3427     {
3428         clear_block_antidenormalnoise(storage.audio_in[0], BLOCK_SIZE_OS_QUAD);
3429         clear_block_antidenormalnoise(storage.audio_in[1], BLOCK_SIZE_OS_QUAD);
3430         clear_block_antidenormalnoise(storage.audio_in_nonOS[1], BLOCK_SIZE_QUAD);
3431         clear_block_antidenormalnoise(storage.audio_in_nonOS[1], BLOCK_SIZE_QUAD);
3432     }
3433 
3434     // TODO: FIX SCENE ASSUMPTION
3435     float fxsendout alignas(16)[2][2][BLOCK_SIZE];
3436     bool play_scene[n_scenes];
3437 
3438     {
3439         clear_block_antidenormalnoise(sceneout[0][0], BLOCK_SIZE_OS_QUAD);
3440         clear_block_antidenormalnoise(sceneout[0][1], BLOCK_SIZE_OS_QUAD);
3441         clear_block_antidenormalnoise(sceneout[1][0], BLOCK_SIZE_OS_QUAD);
3442         clear_block_antidenormalnoise(sceneout[1][1], BLOCK_SIZE_OS_QUAD);
3443 
3444         clear_block_antidenormalnoise(fxsendout[0][0], BLOCK_SIZE_QUAD);
3445         clear_block_antidenormalnoise(fxsendout[0][1], BLOCK_SIZE_QUAD);
3446         clear_block_antidenormalnoise(fxsendout[1][0], BLOCK_SIZE_QUAD);
3447         clear_block_antidenormalnoise(fxsendout[1][1], BLOCK_SIZE_QUAD);
3448     }
3449 
3450     storage.modRoutingMutex.lock();
3451     processControl();
3452 
3453     amp.set_target_smoothed(db_to_linear(storage.getPatch().volume.val.f));
3454     amp_mute.set_target(mfade);
3455 
3456     int fx_bypass = storage.getPatch().fx_bypass.val.i;
3457 
3458     if (fx_bypass == fxb_all_fx)
3459     {
3460         if (fx[fxslot_send1])
3461         {
3462             FX1.set_target_smoothed(
3463                 amp_to_linear(storage.getPatch()
3464                                   .globaldata[storage.getPatch().fx[fxslot_send1].return_level.id]
3465                                   .f));
3466             send[0][0].set_target_smoothed(amp_to_linear(
3467                 storage.getPatch()
3468                     .scenedata[0][storage.getPatch().scene[0].send_level[0].param_id_in_scene]
3469                     .f));
3470             send[0][1].set_target_smoothed(amp_to_linear(
3471                 storage.getPatch()
3472                     .scenedata[1][storage.getPatch().scene[1].send_level[0].param_id_in_scene]
3473                     .f));
3474         }
3475         if (fx[fxslot_send2])
3476         {
3477             FX2.set_target_smoothed(
3478                 amp_to_linear(storage.getPatch()
3479                                   .globaldata[storage.getPatch().fx[fxslot_send2].return_level.id]
3480                                   .f));
3481             send[1][0].set_target_smoothed(amp_to_linear(
3482                 storage.getPatch()
3483                     .scenedata[0][storage.getPatch().scene[0].send_level[1].param_id_in_scene]
3484                     .f));
3485             send[1][1].set_target_smoothed(amp_to_linear(
3486                 storage.getPatch()
3487                     .scenedata[1][storage.getPatch().scene[1].send_level[1].param_id_in_scene]
3488                     .f));
3489         }
3490     }
3491 
3492     list<SurgeVoice *>::iterator iter;
3493 
3494     for (int sc = 0; sc < n_scenes; sc++)
3495     {
3496         play_scene[sc] = (!voices[sc].empty());
3497     }
3498 
3499     int FBentry[n_scenes];
3500     int vcount = 0;
3501 
3502     for (int s = 0; s < n_scenes; s++)
3503     {
3504         FBentry[s] = 0;
3505         iter = voices[s].begin();
3506         while (iter != voices[s].end())
3507         {
3508             SurgeVoice *v = *iter;
3509             assert(v);
3510             bool resume = v->process_block(FBQ[s][FBentry[s] >> 2], FBentry[s] & 3);
3511             FBentry[s]++;
3512 
3513             vcount++;
3514 
3515             if (!resume)
3516             {
3517                 //_aligned_free(v);
3518                 freeVoice(v);
3519                 iter = voices[s].erase(iter);
3520             }
3521             else
3522                 iter++;
3523         }
3524 
3525         storage.modRoutingMutex.unlock();
3526 
3527         fbq_global g;
3528         g.FU1ptr = GetQFPtrFilterUnit(storage.getPatch().scene[s].filterunit[0].type.val.i,
3529                                       storage.getPatch().scene[s].filterunit[0].subtype.val.i);
3530         g.FU2ptr = GetQFPtrFilterUnit(storage.getPatch().scene[s].filterunit[1].type.val.i,
3531                                       storage.getPatch().scene[s].filterunit[1].subtype.val.i);
3532         g.WSptr = GetQFPtrWaveshaper(storage.getPatch().scene[s].wsunit.type.val.i);
3533 
3534         FBQFPtr ProcessQuadFB =
3535             GetFBQPointer(storage.getPatch().scene[s].filterblock_configuration.val.i,
3536                           g.FU1ptr != 0, g.WSptr != 0, g.FU2ptr != 0);
3537 
3538         for (int e = 0; e < FBentry[s]; e += 4)
3539         {
3540             int units = FBentry[s] - e;
3541             for (int i = units; i < 4; i++)
3542             {
3543                 FBQ[s][e >> 2].FU[0].active[i] = 0;
3544                 FBQ[s][e >> 2].FU[1].active[i] = 0;
3545                 FBQ[s][e >> 2].FU[2].active[i] = 0;
3546                 FBQ[s][e >> 2].FU[3].active[i] = 0;
3547             }
3548             ProcessQuadFB(FBQ[s][e >> 2], g, sceneout[s][0], sceneout[s][1]);
3549         }
3550 
3551         if (s == 0 && storage.otherscene_clients > 0)
3552         {
3553             // Make available for scene B
3554             copy_block(sceneout[0][0], storage.audio_otherscene[0], BLOCK_SIZE_OS_QUAD);
3555             copy_block(sceneout[0][1], storage.audio_otherscene[1], BLOCK_SIZE_OS_QUAD);
3556         }
3557 
3558         iter = voices[s].begin();
3559         while (iter != voices[s].end())
3560         {
3561             SurgeVoice *v = *iter;
3562             assert(v);
3563             v->GetQFB(); // save filter state in voices after quad processing is done
3564             iter++;
3565         }
3566         storage.modRoutingMutex.lock();
3567     }
3568 
3569     storage.modRoutingMutex.unlock();
3570     polydisplay = vcount;
3571 
3572     // TODO: FIX SCENE ASSUMPTION
3573     if (play_scene[0])
3574     {
3575         switch (storage.sceneHardclipMode[0])
3576         {
3577         case SurgeStorage::HARDCLIP_TO_18DBFS:
3578             hardclip_block8(sceneout[0][0], BLOCK_SIZE_OS_QUAD);
3579             hardclip_block8(sceneout[0][1], BLOCK_SIZE_OS_QUAD);
3580             break;
3581         case SurgeStorage::HARDCLIP_TO_0DBFS:
3582             hardclip_block(sceneout[0][0], BLOCK_SIZE_OS_QUAD);
3583             hardclip_block(sceneout[0][1], BLOCK_SIZE_OS_QUAD);
3584             break;
3585         case SurgeStorage::BYPASS_HARDCLIP:
3586             break;
3587         }
3588 
3589         halfbandA.process_block_D2(sceneout[0][0], sceneout[0][1]);
3590     }
3591 
3592     if (play_scene[1])
3593     {
3594         switch (storage.sceneHardclipMode[1])
3595         {
3596         case SurgeStorage::HARDCLIP_TO_18DBFS:
3597             hardclip_block8(sceneout[1][0], BLOCK_SIZE_OS_QUAD);
3598             hardclip_block8(sceneout[1][1], BLOCK_SIZE_OS_QUAD);
3599             break;
3600         case SurgeStorage::HARDCLIP_TO_0DBFS:
3601             hardclip_block(sceneout[1][0], BLOCK_SIZE_OS_QUAD);
3602             hardclip_block(sceneout[1][1], BLOCK_SIZE_OS_QUAD);
3603             break;
3604         case SurgeStorage::BYPASS_HARDCLIP:
3605             break;
3606         }
3607 
3608         halfbandB.process_block_D2(sceneout[1][0], sceneout[1][1]);
3609     }
3610 
3611     // TODO: FIX SCENE ASSUMPTION
3612     if (storage.getPatch().scene[0].lowcut.deactivated == false)
3613     {
3614         auto freq =
3615             storage.getPatch().scenedata[0][storage.getPatch().scene[0].lowcut.param_id_in_scene].f;
3616 
3617         hpA.coeff_HP(hpA.calc_omega(freq / 12.0), 0.4);    // var 0.707
3618         hpA.process_block(sceneout[0][0], sceneout[0][1]); // TODO: quadify
3619     }
3620 
3621     if (storage.getPatch().scene[1].lowcut.deactivated == false)
3622     {
3623         auto freq =
3624             storage.getPatch().scenedata[1][storage.getPatch().scene[1].lowcut.param_id_in_scene].f;
3625 
3626         hpB.coeff_HP(hpB.calc_omega(freq / 12.0), 0.4);
3627         hpB.process_block(sceneout[1][0], sceneout[1][1]);
3628     }
3629 
3630     for (int cls = 0; cls < n_scenes; ++cls)
3631     {
3632         switch (storage.sceneHardclipMode[cls])
3633         {
3634         case SurgeStorage::HARDCLIP_TO_18DBFS:
3635             hardclip_block8(sceneout[cls][0], BLOCK_SIZE_QUAD);
3636             hardclip_block8(sceneout[cls][1], BLOCK_SIZE_QUAD);
3637             break;
3638         case SurgeStorage::HARDCLIP_TO_0DBFS:
3639             hardclip_block(sceneout[cls][0], BLOCK_SIZE_QUAD);
3640             hardclip_block(sceneout[cls][1], BLOCK_SIZE_QUAD);
3641             break;
3642         default:
3643             break;
3644         }
3645     }
3646 
3647     // TODO: FIX SCENE ASSUMPTION
3648     bool sc_state[n_scenes];
3649 
3650     for (int i = 0; i < n_scenes; i++)
3651     {
3652         sc_state[i] = play_scene[i];
3653     }
3654 
3655     // apply insert effects
3656     if (fx_bypass != fxb_no_fx)
3657     {
3658         if (fx[fxslot_ains1] && !(storage.getPatch().fx_disable.val.i & (1 << 0)))
3659         {
3660             sc_state[0] =
3661                 fx[fxslot_ains1]->process_ringout(sceneout[0][0], sceneout[0][1], sc_state[0]);
3662         }
3663 
3664         if (fx[fxslot_ains2] && !(storage.getPatch().fx_disable.val.i & (1 << 1)))
3665         {
3666             sc_state[0] =
3667                 fx[fxslot_ains2]->process_ringout(sceneout[0][0], sceneout[0][1], sc_state[0]);
3668         }
3669 
3670         if (fx[fxslot_bins1] && !(storage.getPatch().fx_disable.val.i & (1 << 2)))
3671         {
3672             sc_state[1] =
3673                 fx[fxslot_bins1]->process_ringout(sceneout[1][0], sceneout[1][1], sc_state[1]);
3674         }
3675 
3676         if (fx[fxslot_bins2] && !(storage.getPatch().fx_disable.val.i & (1 << 3)))
3677         {
3678             sc_state[1] =
3679                 fx[fxslot_bins2]->process_ringout(sceneout[1][0], sceneout[1][1], sc_state[1]);
3680         }
3681     }
3682 
3683     for (int cls = 0; cls < n_scenes; ++cls)
3684     {
3685         switch (storage.sceneHardclipMode[cls])
3686         {
3687         case SurgeStorage::HARDCLIP_TO_18DBFS:
3688             hardclip_block8(sceneout[cls][0], BLOCK_SIZE_QUAD);
3689             hardclip_block8(sceneout[cls][1], BLOCK_SIZE_QUAD);
3690             break;
3691         case SurgeStorage::HARDCLIP_TO_0DBFS:
3692             hardclip_block(sceneout[cls][0], BLOCK_SIZE_QUAD);
3693             hardclip_block(sceneout[cls][1], BLOCK_SIZE_QUAD);
3694             break;
3695         default:
3696             break;
3697         }
3698     }
3699 
3700     // sum scenes
3701     // TODO: FIX SCENE ASSUMPTION
3702     copy_block(sceneout[0][0], output[0], BLOCK_SIZE_QUAD);
3703     copy_block(sceneout[0][1], output[1], BLOCK_SIZE_QUAD);
3704     accumulate_block(sceneout[1][0], output[0], BLOCK_SIZE_QUAD);
3705     accumulate_block(sceneout[1][1], output[1], BLOCK_SIZE_QUAD);
3706 
3707     bool send1 = false, send2 = false;
3708     // add send effects
3709     // TODO: FIX SCENE ASSUMPTION
3710     if (fx_bypass == fxb_all_fx)
3711     {
3712         if (fx[fxslot_send1] && !(storage.getPatch().fx_disable.val.i & (1 << 4)))
3713         {
3714             send[0][0].MAC_2_blocks_to(sceneout[0][0], sceneout[0][1], fxsendout[0][0],
3715                                        fxsendout[0][1], BLOCK_SIZE_QUAD);
3716             send[0][1].MAC_2_blocks_to(sceneout[1][0], sceneout[1][1], fxsendout[0][0],
3717                                        fxsendout[0][1], BLOCK_SIZE_QUAD);
3718             send1 = fx[fxslot_send1]->process_ringout(fxsendout[0][0], fxsendout[0][1],
3719                                                       sc_state[0] || sc_state[1]);
3720             FX1.MAC_2_blocks_to(fxsendout[0][0], fxsendout[0][1], output[0], output[1],
3721                                 BLOCK_SIZE_QUAD);
3722         }
3723         if (fx[fxslot_send2] && !(storage.getPatch().fx_disable.val.i & (1 << 5)))
3724         {
3725             send[1][0].MAC_2_blocks_to(sceneout[0][0], sceneout[0][1], fxsendout[1][0],
3726                                        fxsendout[1][1], BLOCK_SIZE_QUAD);
3727             send[1][1].MAC_2_blocks_to(sceneout[1][0], sceneout[1][1], fxsendout[1][0],
3728                                        fxsendout[1][1], BLOCK_SIZE_QUAD);
3729             send2 = fx[fxslot_send2]->process_ringout(fxsendout[1][0], fxsendout[1][1],
3730                                                       sc_state[0] || sc_state[1]);
3731             FX2.MAC_2_blocks_to(fxsendout[1][0], fxsendout[1][1], output[0], output[1],
3732                                 BLOCK_SIZE_QUAD);
3733         }
3734     }
3735 
3736     // apply global effects
3737     if ((fx_bypass == fxb_all_fx) || (fx_bypass == fxb_no_sends))
3738     {
3739         bool glob = sc_state[0] || sc_state[1] || send1 || send2;
3740 
3741         if (fx[fxslot_global1] && !(storage.getPatch().fx_disable.val.i & (1 << 6)))
3742         {
3743             glob = fx[fxslot_global1]->process_ringout(output[0], output[1], glob);
3744         }
3745 
3746         if (fx[fxslot_global2] && !(storage.getPatch().fx_disable.val.i & (1 << 7)))
3747         {
3748             glob = fx[fxslot_global2]->process_ringout(output[0], output[1], glob);
3749         }
3750     }
3751 
3752     amp.multiply_2_blocks(output[0], output[1], BLOCK_SIZE_QUAD);
3753     amp_mute.multiply_2_blocks(output[0], output[1], BLOCK_SIZE_QUAD);
3754 
3755     // VU
3756     // falloff
3757     float a = storage.vu_falloff;
3758     vu_peak[0] = min(2.f, a * vu_peak[0]);
3759     vu_peak[1] = min(2.f, a * vu_peak[1]);
3760     vu_peak[0] = max(vu_peak[0], get_absmax(output[0], BLOCK_SIZE_QUAD));
3761     vu_peak[1] = max(vu_peak[1], get_absmax(output[1], BLOCK_SIZE_QUAD));
3762 
3763     switch (storage.hardclipMode)
3764     {
3765     case SurgeStorage::HARDCLIP_TO_18DBFS:
3766         hardclip_block8(output[0], BLOCK_SIZE_QUAD);
3767         hardclip_block8(output[1], BLOCK_SIZE_QUAD);
3768         break;
3769 
3770     case SurgeStorage::HARDCLIP_TO_0DBFS:
3771         hardclip_block(output[0], BLOCK_SIZE_QUAD);
3772         hardclip_block(output[1], BLOCK_SIZE_QUAD);
3773         break;
3774     case SurgeStorage::BYPASS_HARDCLIP:
3775         break;
3776     }
3777 
3778     // since the sceneout is now routable we also need to mute it
3779     for (int sc = 0; sc < n_scenes; ++sc)
3780     {
3781         amp_mute.multiply_2_blocks(sceneout[sc][0], sceneout[sc][1], BLOCK_SIZE_QUAD);
3782     }
3783 }
3784 
3785 PluginLayer *SurgeSynthesizer::getParent()
3786 {
3787     assert(_parent != nullptr);
3788     return _parent;
3789 }
3790 
3791 void SurgeSynthesizer::populateDawExtraState()
3792 {
3793     storage.getPatch().dawExtraState.isPopulated = true;
3794     storage.getPatch().dawExtraState.mpeEnabled = mpeEnabled;
3795     storage.getPatch().dawExtraState.mpePitchBendRange = storage.mpePitchBendRange;
3796 
3797     storage.getPatch().dawExtraState.hasScale = !storage.isStandardScale;
3798     if (!storage.isStandardScale)
3799         storage.getPatch().dawExtraState.scaleContents = storage.currentScale.rawText;
3800     else
3801         storage.getPatch().dawExtraState.scaleContents = "";
3802 
3803     storage.getPatch().dawExtraState.hasMapping = !storage.isStandardMapping;
3804     if (!storage.isStandardMapping)
3805     {
3806         storage.getPatch().dawExtraState.mappingContents = storage.currentMapping.rawText;
3807         storage.getPatch().dawExtraState.mappingName = storage.currentMapping.name;
3808     }
3809     else
3810     {
3811         storage.getPatch().dawExtraState.mappingContents = "";
3812         storage.getPatch().dawExtraState.mappingName = "";
3813     }
3814 
3815     int n = n_global_params + n_scene_params; // only store midictrl's for scene A (scene A -> scene
3816                                               // B will be duplicated on load)
3817     for (int i = 0; i < n; i++)
3818     {
3819         if (storage.getPatch().param_ptr[i]->midictrl >= 0)
3820         {
3821             storage.getPatch().dawExtraState.midictrl_map[i] =
3822                 storage.getPatch().param_ptr[i]->midictrl;
3823         }
3824     }
3825 
3826     for (int i = 0; i < n_customcontrollers; ++i)
3827     {
3828         storage.getPatch().dawExtraState.customcontrol_map[i] = storage.controllers[i];
3829     }
3830 
3831     storage.getPatch().dawExtraState.monoPedalMode = storage.monoPedalMode;
3832     storage.getPatch().dawExtraState.oddsoundRetuneMode = storage.oddsoundRetuneMode;
3833 }
3834 
3835 void SurgeSynthesizer::loadFromDawExtraState()
3836 {
3837     if (!storage.getPatch().dawExtraState.isPopulated)
3838         return;
3839     mpeEnabled = storage.getPatch().dawExtraState.mpeEnabled;
3840     if (storage.getPatch().dawExtraState.mpePitchBendRange > 0)
3841         storage.mpePitchBendRange = storage.getPatch().dawExtraState.mpePitchBendRange;
3842 
3843     storage.monoPedalMode = (MonoPedalMode)storage.getPatch().dawExtraState.monoPedalMode;
3844     storage.oddsoundRetuneMode =
3845         (SurgeStorage::OddsoundRetuneMode)storage.getPatch().dawExtraState.oddsoundRetuneMode;
3846 
3847     if (storage.getPatch().dawExtraState.hasScale)
3848     {
3849         try
3850         {
3851             auto sc = Tunings::parseSCLData(storage.getPatch().dawExtraState.scaleContents);
3852             storage.retuneToScale(sc);
3853         }
3854         catch (Tunings::TuningError &e)
3855         {
3856             Surge::UserInteractions::promptError(e.what(), "Unable to restore tuning!");
3857             storage.retuneTo12TETScale();
3858         }
3859     }
3860     else
3861     {
3862         storage.retuneTo12TETScale();
3863     }
3864 
3865     if (storage.getPatch().dawExtraState.hasMapping)
3866     {
3867         try
3868         {
3869             auto kb = Tunings::parseKBMData(storage.getPatch().dawExtraState.mappingContents);
3870             if (storage.getPatch().dawExtraState.mappingName.size() > 1)
3871             {
3872                 kb.name = storage.getPatch().dawExtraState.mappingName;
3873             }
3874             else
3875             {
3876                 kb.name = storage.guessAtKBMName(kb);
3877             }
3878             storage.remapToKeyboard(kb);
3879         }
3880         catch (Tunings::TuningError &e)
3881         {
3882             Surge::UserInteractions::promptError(e.what(), "Unable to restore mapping!");
3883             storage.remapToConcertCKeyboard();
3884         }
3885     }
3886     else
3887     {
3888         storage.remapToConcertCKeyboard();
3889     }
3890 
3891     int n = n_global_params + n_scene_params; // only store midictrl's for scene A (scene A -> scene
3892                                               // B will be duplicated on load)
3893     for (int i = 0; i < n; i++)
3894     {
3895         if (storage.getPatch().dawExtraState.midictrl_map.find(i) !=
3896             storage.getPatch().dawExtraState.midictrl_map.end())
3897         {
3898             storage.getPatch().param_ptr[i]->midictrl =
3899                 storage.getPatch().dawExtraState.midictrl_map[i];
3900             if (i >= n_global_params)
3901             {
3902                 storage.getPatch().param_ptr[i + n_scene_params]->midictrl =
3903                     storage.getPatch().dawExtraState.midictrl_map[i];
3904             }
3905         }
3906     }
3907 
3908     for (int i = 0; i < n_customcontrollers; ++i)
3909     {
3910         if (storage.getPatch().dawExtraState.customcontrol_map.find(i) !=
3911             storage.getPatch().dawExtraState.customcontrol_map.end())
3912             storage.controllers[i] = storage.getPatch().dawExtraState.customcontrol_map[i];
3913     }
3914 }
3915 
3916 void SurgeSynthesizer::setupActivateExtraOutputs()
3917 {
3918     bool defval = true;
3919     if (hostProgram.find("Fruit") == 0) // FruityLoops default off
3920         defval = false;
3921 
3922     activateExtraOutputs =
3923         Surge::Storage::getUserDefaultValue(&(storage), "activateExtraOutputs", defval ? 1 : 0);
3924 }
3925 
3926 void SurgeSynthesizer::swapMetaControllers(int c1, int c2)
3927 {
3928     char nt[20];
3929     strxcpy(nt, storage.getPatch().CustomControllerLabel[c1], 16);
3930     strxcpy(storage.getPatch().CustomControllerLabel[c1],
3931             storage.getPatch().CustomControllerLabel[c2], 16);
3932     strxcpy(storage.getPatch().CustomControllerLabel[c2], nt, 16);
3933 
3934     storage.modRoutingMutex.lock();
3935 
3936     auto tmp1 = storage.getPatch().scene[0].modsources[ms_ctrl1 + c1];
3937     auto tmp2 = storage.getPatch().scene[0].modsources[ms_ctrl1 + c2];
3938 
3939     for (int sc = 0; sc < n_scenes; ++sc)
3940     {
3941         storage.getPatch().scene[sc].modsources[ms_ctrl1 + c2] = tmp1;
3942         storage.getPatch().scene[sc].modsources[ms_ctrl1 + c1] = tmp2;
3943     }
3944 
3945     // Now swap the routings
3946     for (int sc = 0; sc < n_scenes; ++sc)
3947     {
3948         for (int vt = 0; vt < 3; ++vt)
3949         {
3950             std::vector<ModulationRouting> *mv = nullptr;
3951             if (sc == 0 && vt == 0)
3952             {
3953                 mv = &(storage.getPatch().modulation_global);
3954             }
3955             else if (vt == 1)
3956             {
3957                 mv = &(storage.getPatch().scene[sc].modulation_scene);
3958             }
3959             else if (vt == 2)
3960             {
3961                 mv = &(storage.getPatch().scene[sc].modulation_voice);
3962             }
3963 
3964             if (mv)
3965             {
3966                 int n = mv->size();
3967                 for (int i = 0; i < n; ++i)
3968                 {
3969                     if (mv->at(i).source_id == ms_ctrl1 + c1)
3970                     {
3971                         auto q = mv->at(i);
3972                         q.source_id = ms_ctrl1 + c2;
3973                         mv->at(i) = q;
3974                     }
3975                     else if (mv->at(i).source_id == ms_ctrl1 + c2)
3976                     {
3977                         auto q = mv->at(i);
3978                         q.source_id = ms_ctrl1 + c1;
3979                         mv->at(i) = q;
3980                     }
3981                 }
3982             }
3983         }
3984     }
3985 
3986     storage.modRoutingMutex.unlock();
3987 
3988     refresh_editor = true;
3989 }
3990 
3991 void SurgeSynthesizer::changeModulatorSmoothing(ControllerModulationSource::SmoothingMode m)
3992 {
3993     storage.smoothingMode = m;
3994     for (int sc = 0; sc < n_scenes; ++sc)
3995     {
3996         for (int q = 0; q < n_modsources; ++q)
3997         {
3998             auto cms = dynamic_cast<ControllerModulationSource *>(
3999                 storage.getPatch().scene[sc].modsources[q]);
4000             if (cms)
4001             {
4002                 cms->smoothingMode = m;
4003             }
4004         }
4005     }
4006 }
4007 
4008 void SurgeSynthesizer::reorderFx(int source, int target, FXReorderMode m)
4009 {
4010     if (source < 0 || source >= n_fx_slots || target < 0 || target >= n_fx_slots)
4011         return;
4012 
4013     std::lock_guard<std::recursive_mutex> lockModulation(storage.modRoutingMutex);
4014 
4015     FxStorage so, to;
4016     memcpy((void *)&so, (void *)(&storage.getPatch().fx[source]), sizeof(FxStorage));
4017     memcpy((void *)&to, (void *)(&storage.getPatch().fx[target]), sizeof(FxStorage));
4018 
4019     fxmodsync[source].clear();
4020     fxmodsync[target].clear();
4021 
4022     fxsync[target].type.val.i = so.type.val.i;
4023     Effect *t_fx = spawn_effect(fxsync[target].type.val.i, &storage, &fxsync[target], 0);
4024     if (t_fx)
4025     {
4026         t_fx->init_ctrltypes();
4027         t_fx->init_default_values();
4028         delete t_fx;
4029     }
4030 
4031     if (m == FXReorderMode::MOVE)
4032     {
4033         fxsync[source].type.val.i = 0;
4034     }
4035     else if (m == FXReorderMode::SWAP)
4036     {
4037         fxsync[source].type.val.i = to.type.val.i;
4038         t_fx = spawn_effect(fxsync[source].type.val.i, &storage, &fxsync[source], 0);
4039         if (t_fx)
4040         {
4041             t_fx->init_ctrltypes();
4042             t_fx->init_default_values();
4043             delete t_fx;
4044         }
4045     }
4046     // else leave the source alone
4047 
4048     /*
4049      * OK we can't copy the params - they contain things like id in scene - we need to copy the
4050      * values
4051      */
4052     auto cp = [](Parameter &to, const Parameter &from) {
4053         to.val = from.val;
4054         to.temposync = from.temposync;
4055         to.extend_range = from.extend_range;
4056         to.deactivated = from.deactivated;
4057         to.absolute = from.absolute;
4058     };
4059     for (int i = 0; i < n_fx_params; ++i)
4060     {
4061         if (m == FXReorderMode::SWAP)
4062             cp(fxsync[source].p[i], to.p[i]);
4063         cp(fxsync[target].p[i], so.p[i]);
4064     }
4065 
4066     // Now swap the routings. FX routings are always global
4067     std::vector<ModulationRouting> *mv = nullptr;
4068     mv = &(storage.getPatch().modulation_global);
4069     int n = mv->size();
4070     for (int i = 0; i < n; ++i)
4071     {
4072         if (mv->at(i).destination_id >= fxsync[source].p[0].id &&
4073             mv->at(i).destination_id <= fxsync[source].p[n_fx_params - 1].id)
4074         {
4075             fx_reload_mod[target] = true;
4076             int whichForReal = -1;
4077             for (int q = 0; q < n_fx_params; ++q)
4078             {
4079                 if (mv->at(i).destination_id == fxsync[source].p[q].id)
4080                 {
4081                     whichForReal = q;
4082                 }
4083             }
4084             auto depth =
4085                 getModulation(fxsync[source].p[whichForReal].id, (modsources)mv->at(i).source_id);
4086             fxmodsync[target].push_back(std::make_tuple(mv->at(i).source_id, whichForReal, depth));
4087         }
4088         if (m == FXReorderMode::SWAP)
4089         {
4090             if (mv->at(i).destination_id >= fxsync[target].p[0].id &&
4091                 mv->at(i).destination_id <= fxsync[target].p[n_fx_params - 1].id)
4092             {
4093                 fx_reload_mod[source] = true;
4094                 int whichForReal = -1;
4095                 for (int q = 0; q < n_fx_params; ++q)
4096                 {
4097                     if (mv->at(i).destination_id == fxsync[target].p[q].id)
4098                     {
4099                         whichForReal = q;
4100                     }
4101                 }
4102                 auto depth = getModulation(fxsync[target].p[whichForReal].id,
4103                                            (modsources)mv->at(i).source_id);
4104                 fxmodsync[source].push_back(
4105                     std::make_tuple(mv->at(i).source_id, whichForReal, depth));
4106             }
4107         }
4108     }
4109 
4110     load_fx_needed = true;
4111     fx_reload[source] = true;
4112     fx_reload[target] = true;
4113     refresh_editor = true;
4114 }
4115 
4116 bool SurgeSynthesizer::getParameterIsBoolean(const ID &id)
4117 {
4118     auto index = id.getSynthSideId();
4119 
4120     if ((index >= 0) && (index < storage.getPatch().param_ptr.size()))
4121     {
4122         auto t = storage.getPatch().param_ptr[index]->valtype;
4123         if (t == vt_bool)
4124             return true;
4125     }
4126 
4127     return false;
4128 }
4129