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