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, ¶ms);
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, ¶ms);
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