1 /*
2 ** Surge Synthesizer is Free and Open Source Software
3 **
4 ** Surge is made available under the Gnu General Public License, v3.0
5 ** https://www.gnu.org/licenses/gpl-3.0.en.html
6 **
7 ** Copyright 2004-2020 by various individuals as described by the Git transaction log
8 **
9 ** All source at: https://github.com/surge-synthesizer/surge.git
10 **
11 ** Surge was a commercial product from 2004-2018, with Copyright and ownership
12 ** in that period held by Claes Johanson at Vember Audio. Claes made Surge
13 ** open source in September 2018.
14 */
15 
16 #pragma once
17 #include "SurgeStorage.h"
18 #include "SurgeVoice.h"
19 #include "effect/Effect.h"
20 #include "BiquadFilter.h"
21 #include "UserInteractions.h"
22 
23 struct QuadFilterChainState;
24 
25 #include <list>
26 #include <utility>
27 #include <atomic>
28 #include <cstdio>
29 
30 #if TARGET_AUDIOUNIT
31 class aulayer;
32 typedef aulayer PluginLayer;
33 #elif TARGET_VST3
34 class SurgeVst3Processor;
35 typedef SurgeVst3Processor PluginLayer;
36 #elif TARGET_VST2
37 class Vst2PluginInstance;
38 using PluginLayer = Vst2PluginInstance;
39 #elif TARGET_LV2
40 class SurgeLv2Wrapper;
41 using PluginLayer = SurgeLv2Wrapper;
42 #elif TARGET_JUCE
43 class JUCEPluginLayerProxy;
44 using PluginLayer = JUCEPluginLayerProxy;
45 #elif TARGET_JUCE_SYNTH
46 #include <JuceHeader.h>
47 class SurgeSynthProcessor;
48 using PluginLayer = SurgeSynthProcessor;
49 #elif TARGET_HEADLESS
50 class HeadlessPluginLayerProxy;
51 using PluginLayer = HeadlessPluginLayerProxy;
52 #else
53 class PluginLayer;
54 #endif
55 
56 struct timedata
57 {
58     double ppqPos, tempo;
59     int timeSigNumerator = 4, timeSigDenominator = 4;
60 };
61 
62 struct parametermeta
63 {
64     float fmin, fmax, fdefault;
65     unsigned int flags, clump;
66     bool hide, expert, meta;
67 };
68 
69 class alignas(16) SurgeSynthesizer
70 {
71   public:
72     float output alignas(16)[N_OUTPUTS][BLOCK_SIZE];
73     float sceneout alignas(
74         16)[n_scenes][N_OUTPUTS][BLOCK_SIZE_OS]; // this is blocksize_os but has been downsampled by
75                                                  // the end of process into block_size
76 
77     float input alignas(16)[N_INPUTS][BLOCK_SIZE];
78     timedata time_data;
79     bool audio_processing_active;
80 
81     // aligned stuff
82     SurgeStorage storage alignas(16);
83     lipol_ps FX1 alignas(16), // TODO: FIX SCENE ASSUMPTION
84         FX2 alignas(16),      // TODO: FIX SCENE ASSUMPTION
85         amp alignas(16), amp_mute alignas(16), send alignas(16)[2][2];
86 
87     // methods
88   public:
89     SurgeSynthesizer(PluginLayer *parent, std::string suppliedDataPath = "");
90     virtual ~SurgeSynthesizer();
91     void playNote(char channel, char key, char velocity, char detune);
92     void releaseNote(char channel, char key, char velocity);
93     void releaseNotePostHoldCheck(int scene, char channel, char key, char velocity);
94     void pitchBend(char channel, int value);
95     void polyAftertouch(char channel, int key, int value);
96     void channelAftertouch(char channel, int value);
97     void channelController(char channel, int cc, int value);
98     void programChange(char channel, int value);
99     void allNotesOff();
100     void setSamplerate(float sr);
101     void updateHighLowKeys(int scene);
getNumInputs()102     int getNumInputs() { return N_INPUTS; }
getNumOutputs()103     int getNumOutputs() { return N_OUTPUTS; }
getBlockSize()104     int getBlockSize() { return BLOCK_SIZE; }
105     int getMpeMainChannel(int voiceChannel, int key);
106     void process();
107 
108     PluginLayer *getParent();
109 
110     // protected:
111 
112     void onRPN(int channel, int lsbRPN, int msbRPN, int lsbValue, int msbValue);
113     void onNRPN(int channel, int lsbNRPN, int msbNRPN, int lsbValue, int msbValue);
114 
115     void resetStateFromTimeData();
116     void processControl();
117     void processThreadunsafeOperations();
118     bool loadFx(bool initp, bool force_reload_all);
119     bool loadOscalgos();
120     bool load_fx_needed;
121 
122     /*
123      * FX Lifecycle events happen on the audio thread but is read in the openOrRecreateEditor
124      * so if you swpan or init the fx[s] object lock this mutex
125      */
126     std::mutex fxSpawnMutex;
127     std::mutex patchLoadSpawnMutex;
128     enum FXReorderMode
129     {
130         NONE,
131         SWAP,
132         COPY,
133         MOVE
134     };
135     void reorderFx(
136         int source, int target,
137         FXReorderMode m); // This is safe to call from the UI thread since it just edits the sync
138 
139     void playVoice(int scene, char channel, char key, char velocity, char detune);
140     void releaseScene(int s);
141     int calculateChannelMask(int channel, int key);
142     void softkillVoice(int scene);
143     void enforcePolyphonyLimit(int scene, int margin);
144     int getNonUltrareleaseVoices(int scene);
145     int getNonReleasedVoices(int scene);
146 
147     SurgeVoice *getUnusedVoice(int scene);
148     void freeVoice(SurgeVoice *);
149     std::array<std::array<SurgeVoice, MAX_VOICES>, 2> voices_array;
150     unsigned int voices_usedby[2][MAX_VOICES]; // 0 indicates no user, 1 is scene A & 2 is scene B
151                                                // // TODO: FIX SCENE ASSUMPTION!
152     int64_t voiceCounter = 1L;
153 
154   public:
155     /*
156      * For more on this IFDEF see the comment in SurgeSynthesizerIDManagement.cpp
157      */
158 #if TARGET_VST3 || TARGET_HEADLESS
159 #define PLUGIN_ID_AND_INDEX_ARE_DISTINCT 1
160 #endif
161 
162     struct ID
163     {
getDawSideIndexID164         int getDawSideIndex() const { return dawindex; }
getDawSideIdID165         int getDawSideId() const
166         {
167 #if PLUGIN_ID_AND_INDEX_ARE_DISTINCT
168             return dawid;
169 #else
170             return dawindex;
171 #endif
172         }
getSynthSideIdID173         int getSynthSideId() const { return synthid; }
174 
toStringID175         std::string toString() const
176         {
177             std::ostringstream oss;
178             oss << "ID[ dawidx=" << dawindex
179 #if PLUGIN_ID_AND_INDEX_ARE_DISTINCT
180                 << ", dawid=" << dawid
181 #endif
182                 << " synthid=" << synthid << " ]";
183             return oss.str();
184         }
185 
186         bool operator==(const ID &other) const
187         {
188             return dawindex == other.dawindex
189 #if PLUGIN_ID_AND_INDEX_ARE_DISTINCT
190                    && dawid == other.dawid
191 #endif
192                    && synthid == other.synthid;
193         }
194         bool operator!=(const ID &other) const { return !(*this == other); }
195 
196         friend std::ostream &operator<<(std::ostream &os, const ID &id)
197         {
198             os << id.toString();
199             return os;
200         }
201 
202       private:
203         int dawindex = -1,
204 #if PLUGIN_ID_AND_INDEX_ARE_DISTINCT
205             dawid = -1,
206 #endif
207             synthid = -1;
208         friend SurgeSynthesizer;
209     };
210 
211 #if PLUGIN_ID_AND_INDEX_ARE_DISTINCT
212     bool fromDAWSideId(int i, ID &q);
213 #endif
214     bool fromDAWSideIndex(int i, ID &q);
215     bool fromSynthSideId(int i, ID &q);
216     bool fromSynthSideIdWithGuiOffset(int i, int start_paramtags, int start_metacontrol_tag, ID &q);
217 
idForParameter(const Parameter * p)218     const ID idForParameter(const Parameter *p)
219     {
220         // We know this will always work
221         ID i;
222         fromSynthSideId(p->id, i);
223         return i;
224     }
225 
getParameterDisplay(const ID & index,char * text)226     void getParameterDisplay(const ID &index, char *text)
227     {
228         getParameterDisplay(index.getSynthSideId(), text);
229     }
getParameterDisplay(const ID & index,char * text,float x)230     void getParameterDisplay(const ID &index, char *text, float x)
231     {
232         getParameterDisplay(index.getSynthSideId(), text);
233     }
getParameterDisplayAlt(const ID & index,char * text)234     void getParameterDisplayAlt(const ID &index, char *text)
235     {
236         getParameterDisplayAlt(index.getSynthSideId(), text);
237     }
getParameterName(const ID & index,char * text)238     void getParameterName(const ID &index, char *text)
239     {
240         getParameterName(index.getSynthSideId(), text);
241     }
getParameterMeta(const ID & index,parametermeta & pm)242     void getParameterMeta(const ID &index, parametermeta &pm)
243     {
244         getParameterMeta(index.getSynthSideId(), pm);
245     }
getParameterNameW(const ID & index,wchar_t * ptr)246     void getParameterNameW(const ID &index, wchar_t *ptr)
247     {
248         getParameterNameW(index.getSynthSideId(), ptr);
249     }
getParameterShortNameW(const ID & index,wchar_t * ptr)250     void getParameterShortNameW(const ID &index, wchar_t *ptr)
251     {
252         getParameterShortNameW(index.getSynthSideId(), ptr);
253     }
getParameterUnitW(const ID & index,wchar_t * ptr)254     void getParameterUnitW(const ID &index, wchar_t *ptr)
255     {
256         getParameterUnitW(index.getSynthSideId(), ptr);
257     }
getParameterStringW(const ID & index,float value,wchar_t * ptr)258     void getParameterStringW(const ID &index, float value, wchar_t *ptr)
259     {
260         getParameterStringW(index.getSynthSideId(), value, ptr);
261     }
getParameter01(const ID & index)262     float getParameter01(const ID &index) { return getParameter01(index.getSynthSideId()); }
263     bool setParameter01(const ID &index, float value, bool external = false,
264                         bool force_integer = false)
265     {
266         return setParameter01(index.getSynthSideId(), value, external, force_integer);
267     }
268 
269     bool getParameterIsBoolean(const ID &index);
270 
271     bool stringToNormalizedValue(const ID &index, std::string s, float &outval);
272 
normalizedToValue(const ID & index,float val)273     float normalizedToValue(const ID &index, float val)
274     {
275         return normalizedToValue(index.getSynthSideId(), val);
276     }
277 
valueToNormalized(const ID & index,float val)278     float valueToNormalized(const ID &index, float val)
279     {
280         return valueToNormalized(index.getSynthSideId(), val);
281     }
282 
sendParameterAutomation(const ID & index,float val)283     void sendParameterAutomation(const ID &index, float val)
284     {
285         sendParameterAutomation(index.getSynthSideId(), val);
286     }
287 
288   private:
289     bool setParameter01(long index, float value, bool external = false, bool force_integer = false);
290     void sendParameterAutomation(long index, float value);
291     float getParameter01(long index);
292     float getParameter(long index);
293     float normalizedToValue(long parameterIndex, float value);
294     float valueToNormalized(long parameterIndex, float value);
295     void getParameterDisplay(long index, char *text);
296     void getParameterDisplay(long index, char *text, float x);
297     void getParameterDisplayAlt(long index, char *text);
298     void getParameterName(long index, char *text);
299     void getParameterMeta(long index, parametermeta &pm);
300     void getParameterNameW(long index, wchar_t *ptr);
301     void getParameterShortNameW(long index, wchar_t *ptr);
302     void getParameterUnitW(long index, wchar_t *ptr);
303     void getParameterStringW(long index, float value, wchar_t *ptr);
304     //	unsigned int getParameterFlags (long index);
305 
306   public:
307     void updateDisplay();
308     // bool setParameter (long index, float value);
309     //	float getParameter (long index);
310     bool isValidModulation(long ptag, modsources modsource);
311     bool isActiveModulation(long ptag, modsources modsource);
312     bool isBipolarModulation(modsources modsources);
313     bool isModsourceUsed(modsources modsource);
314     bool isModDestUsed(long moddest);
315     ModulationRouting *getModRouting(long ptag, modsources modsource);
316     bool setModulation(long ptag, modsources modsource, float value);
317     float getModulation(long ptag, modsources modsource);
318     float getModDepth(long ptag, modsources modsource);
319     void clearModulation(long ptag, modsources modsource, bool clearEvenIfInvalid = false);
320     void clear_osc_modulation(
321         int scene, int entry); // clear the modulation routings on the algorithm-specific sliders
322   public:
323     std::atomic<bool> rawLoadEnqueued{false}, rawLoadNeedsUIDawExtraState{false};
324     std::mutex rawLoadQueueMutex;
325     void *enqueuedLoadData{nullptr}; // if this is set I need to free it
326     int enqueuedLoadSize{0};
327     void enqueuePatchForLoad(void *data, int size); // safe from any thread
328     void processEnqueuedPatchIfNeeded();            // only safe from audio thread
329 
330     void loadRaw(const void *data, int size, bool preset = false);
331     void loadPatch(int id);
332     bool loadPatchByPath(const char *fxpPath, int categoryId, const char *name);
333     void incrementPatch(bool nextPrev, bool insideCategory = true);
334     void incrementCategory(bool nextPrev);
335     void selectRandomPatch();
336 
337     void swapMetaControllers(int ct1, int ct2);
338 
339     std::string getUserPatchDirectory();
340     std::string getLegacyUserPatchDirectory();
341 
342     void savePatchToPath(fs::path p);
343     void savePatch();
344     void updateUsedState();
345     void prepareModsourceDoProcess(int scenemask);
346     unsigned int saveRaw(void **data);
347     // synth -> editor variables
348     std::atomic<int>
349         polydisplay; // updated in audio thread, read from ui, so have assignments be atomic
350     bool refresh_editor, patch_loaded;
351     int learn_param, learn_custom;
352     int refresh_ctrl_queue[8];
353     int refresh_parameter_queue[8];
354     bool refresh_overflow = false;
355     float refresh_ctrl_queue_value[8];
356     bool process_input;
357     std::atomic<int> patchid_queue;
358     bool has_patchid_file;
359     char patchid_file[FILENAME_MAX];
360 
361     float vu_peak[8];
362 
363     void populateDawExtraState();
364 
365     void loadFromDawExtraState();
366 
367   public:
368     int CC0, CC32, PCH, patchid;
369     float masterfade = 0;
370     HalfRateFilter halfbandA, halfbandB,
371         halfbandIN; // TODO: FIX SCENE ASSUMPTION (for halfbandA/B - use std::array)
372     std::list<SurgeVoice *> voices[n_scenes];
373     std::unique_ptr<Effect> fx[n_fx_slots];
374     std::atomic<bool> halt_engine;
375     MidiChannelState channelState[16];
376     bool mpeEnabled = false;
377     int mpeVoices = 0;
378     int mpeGlobalPitchBendRange = 0;
379 
380     std::array<uint64_t, 128> midiKeyPressedForScene[n_scenes];
381     uint64_t orderedMidiKey = 0;
382 
383     int current_category_id = 0;
384     bool modsourceused[n_modsources];
385     bool midiprogramshavechanged = false;
386 
387     bool switch_toggled_queued, release_if_latched[n_scenes], release_anyway[n_scenes];
388     void setParameterSmoothed(long index, float value);
389     BiquadFilter hpA, hpB; // TODO: FIX SCENE ASSUMPTION (use std::array)
390 
391     bool fx_reload[n_fx_slots];   // if true, reload new effect parameters from fxsync
392     FxStorage fxsync[n_fx_slots]; // used for synchronisation of parameter init
393     bool fx_reload_mod[n_fx_slots];
394     std::array<std::vector<std::tuple<int, int, float>>, n_fx_slots> fxmodsync;
395     int fx_suspend_bitmask;
396 
397     // hold pedal stuff
398 
399     std::list<std::pair<int, int>> holdbuffer[n_scenes];
400     void purgeHoldbuffer(int scene);
401     quadr_osc sinus;
402     int demo_counter = 0;
403 
404     QuadFilterChainState *FBQ[n_scenes];
405 
406     std::string hostProgram = "Unknown Host";
407     bool activateExtraOutputs = true;
408     void setupActivateExtraOutputs();
409 
410     void changeModulatorSmoothing(ControllerModulationSource::SmoothingMode m);
411 
412     // these have to be thread-safe, so keep private
413   private:
414     PluginLayer *_parent = nullptr;
415 
416     void switch_toggled();
417 
418     // midicontrol-interpolators
419     static const int num_controlinterpolators = 128;
420     ControllerModulationSource mControlInterpolator[num_controlinterpolators];
421     bool mControlInterpolatorUsed[num_controlinterpolators];
422 
423     int GetFreeControlInterpolatorIndex();
424     int GetControlInterpolatorIndex(int Idx);
425     void ReleaseControlInterpolator(int Idx);
426     ControllerModulationSource *ControlInterpolator(int Idx);
427     ControllerModulationSource *AddControlInterpolator(int Idx, bool &AlreadyExisted);
428 };
429 
430 namespace std
431 {
432 
433 template <> struct hash<SurgeSynthesizer::ID>
434 {
435     std::size_t operator()(const SurgeSynthesizer::ID &k) const
436     {
437         return std::hash<int>()(k.getSynthSideId());
438     }
439 };
440 
441 } // namespace std