1 /*
2  * Carla FluidSynth Plugin
3  * Copyright (C) 2011-2020 Filipe Coelho <falktx@falktx.com>
4  *
5  * This program is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU General Public License as
7  * published by the Free Software Foundation; either version 2 of
8  * the License, or any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * For a full copy of the GNU General Public License see the doc/GPL.txt file.
16  */
17 
18 #include "CarlaPluginInternal.hpp"
19 #include "CarlaEngine.hpp"
20 
21 #ifdef HAVE_FLUIDSYNTH
22 
23 #include "CarlaBackendUtils.hpp"
24 #include "CarlaMathUtils.hpp"
25 
26 #include "water/text/StringArray.h"
27 
28 #include <fluidsynth.h>
29 
30 #define FLUID_DEFAULT_POLYPHONY 64
31 
32 using water::String;
33 using water::StringArray;
34 
35 CARLA_BACKEND_START_NAMESPACE
36 
37 // -------------------------------------------------------------------------------------------------------------------
38 // Fallback data
39 
40 static const ExternalMidiNote kExternalMidiNoteFallback = { -1, 0, 0 };
41 
42 // -------------------------------------------------------------------------------------------------------------------
43 
44 class CarlaPluginFluidSynth : public CarlaPlugin
45 {
46 public:
CarlaPluginFluidSynth(CarlaEngine * const engine,const uint id,const bool use16Outs)47     CarlaPluginFluidSynth(CarlaEngine* const engine, const uint id, const bool use16Outs)
48         : CarlaPlugin(engine, id),
49           kUse16Outs(use16Outs),
50           fSettings(nullptr),
51           fSynth(nullptr),
52           fSynthId(0),
53           fAudio16Buffers(nullptr),
54           fLabel(nullptr)
55     {
56         carla_debug("CarlaPluginFluidSynth::CarlaPluginFluidSynth(%p, %i, %s)", engine, id,  bool2str(use16Outs));
57 
58         carla_zeroFloats(fParamBuffers, FluidSynthParametersMax);
59         carla_fill<int32_t>(fCurMidiProgs, 0, MAX_MIDI_CHANNELS);
60 
61         // create settings
62         fSettings = new_fluid_settings();
63         CARLA_SAFE_ASSERT_RETURN(fSettings != nullptr,);
64 
65         // define settings
66         fluid_settings_setint(fSettings, "synth.audio-channels", use16Outs ? 16 : 1);
67         fluid_settings_setint(fSettings, "synth.audio-groups", use16Outs ? 16 : 1);
68         fluid_settings_setnum(fSettings, "synth.sample-rate", pData->engine->getSampleRate());
69         //fluid_settings_setnum(fSettings, "synth.cpu-cores", 2);
70         fluid_settings_setint(fSettings, "synth.ladspa.active", 0);
71         fluid_settings_setint(fSettings, "synth.lock-memory", 1);
72 #if FLUIDSYNTH_VERSION_MAJOR < 2
73         fluid_settings_setint(fSettings, "synth.parallel-render", 1);
74 #endif
75         fluid_settings_setint(fSettings, "synth.threadsafe-api", 0);
76 #ifdef DEBUG
77         fluid_settings_setint(fSettings, "synth.verbose", 1);
78 #endif
79 
80         // create synth
81         fSynth = new_fluid_synth(fSettings);
82         CARLA_SAFE_ASSERT_RETURN(fSynth != nullptr,);
83 
84         initializeFluidDefaultsIfNeeded();
85 
86 #if FLUIDSYNTH_VERSION_MAJOR < 2
87         fluid_synth_set_sample_rate(fSynth, static_cast<float>(pData->engine->getSampleRate()));
88 #endif
89 
90         // set default values
91         fluid_synth_set_reverb_on(fSynth, 1);
92         fluid_synth_set_reverb(fSynth,
93                                sFluidDefaults[FluidSynthReverbRoomSize],
94                                sFluidDefaults[FluidSynthReverbDamp],
95                                sFluidDefaults[FluidSynthReverbWidth],
96                                sFluidDefaults[FluidSynthReverbLevel]);
97 
98         fluid_synth_set_chorus_on(fSynth, 1);
99         fluid_synth_set_chorus(fSynth,
100                                static_cast<int>(sFluidDefaults[FluidSynthChorusNr] + 0.5f),
101                                sFluidDefaults[FluidSynthChorusLevel],
102                                sFluidDefaults[FluidSynthChorusSpeedHz],
103                                sFluidDefaults[FluidSynthChorusDepthMs],
104                                static_cast<int>(sFluidDefaults[FluidSynthChorusType] + 0.5f));
105 
106         fluid_synth_set_polyphony(fSynth, FLUID_DEFAULT_POLYPHONY);
107         fluid_synth_set_gain(fSynth, 1.0f);
108 
109         for (int i=0; i < MAX_MIDI_CHANNELS; ++i)
110             fluid_synth_set_interp_method(fSynth, i, static_cast<int>(sFluidDefaults[FluidSynthInterpolation] + 0.5f));
111     }
112 
~CarlaPluginFluidSynth()113     ~CarlaPluginFluidSynth() override
114     {
115         carla_debug("CarlaPluginFluidSynth::~CarlaPluginFluidSynth()");
116 
117         pData->singleMutex.lock();
118         pData->masterMutex.lock();
119 
120         if (pData->client != nullptr && pData->client->isActive())
121             pData->client->deactivate(true);
122 
123         if (pData->active)
124         {
125             deactivate();
126             pData->active = false;
127         }
128 
129         if (fSynth != nullptr)
130         {
131             delete_fluid_synth(fSynth);
132             fSynth = nullptr;
133         }
134 
135         if (fSettings != nullptr)
136         {
137             delete_fluid_settings(fSettings);
138             fSettings = nullptr;
139         }
140 
141         if (fLabel != nullptr)
142         {
143             delete[] fLabel;
144             fLabel = nullptr;
145         }
146 
147         clearBuffers();
148     }
149 
150     // -------------------------------------------------------------------
151     // Information (base)
152 
getType() const153     PluginType getType() const noexcept override
154     {
155         return PLUGIN_SF2;
156     }
157 
getCategory() const158     PluginCategory getCategory() const noexcept override
159     {
160         return PLUGIN_CATEGORY_SYNTH;
161     }
162 
163     // -------------------------------------------------------------------
164     // Information (count)
165 
getParameterScalePointCount(const uint32_t parameterId) const166     uint32_t getParameterScalePointCount(const uint32_t parameterId) const noexcept override
167     {
168         switch (parameterId)
169         {
170         case FluidSynthChorusType:
171             return 2;
172         case FluidSynthInterpolation:
173             return 4;
174         default:
175             return 0;
176         }
177     }
178 
179     // -------------------------------------------------------------------
180     // Information (current data)
181 
182     // nothing
183 
184     // -------------------------------------------------------------------
185     // Information (per-plugin data)
186 
getOptionsAvailable() const187     uint getOptionsAvailable() const noexcept override
188     {
189         uint options = 0x0;
190 
191         options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
192         options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
193         options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
194         options |= PLUGIN_OPTION_SEND_PITCHBEND;
195         options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
196         options |= PLUGIN_OPTION_SKIP_SENDING_NOTES;
197 #if FLUIDSYNTH_VERSION_MAJOR >= 2
198         options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
199 #endif
200 
201         return options;
202     }
203 
getParameterValue(const uint32_t parameterId) const204     float getParameterValue(const uint32_t parameterId) const noexcept override
205     {
206         CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, 0.0f);
207 
208         return fParamBuffers[parameterId];
209     }
210 
getParameterScalePointValue(const uint32_t parameterId,const uint32_t scalePointId) const211     float getParameterScalePointValue(const uint32_t parameterId, const uint32_t scalePointId) const noexcept override
212     {
213         switch (parameterId)
214         {
215         case FluidSynthChorusType:
216             switch (scalePointId)
217             {
218             case 0:
219                 return FLUID_CHORUS_MOD_SINE;
220             case 1:
221                 return FLUID_CHORUS_MOD_TRIANGLE;
222             default:
223                 return sFluidDefaults[FluidSynthChorusType];
224             }
225         case FluidSynthInterpolation:
226             switch (scalePointId)
227             {
228             case 0:
229                 return FLUID_INTERP_NONE;
230             case 1:
231                 return FLUID_INTERP_LINEAR;
232             case 2:
233                 return FLUID_INTERP_4THORDER;
234             case 3:
235                 return FLUID_INTERP_7THORDER;
236             default:
237                 return sFluidDefaults[FluidSynthInterpolation];
238             }
239         default:
240             return 0.0f;
241         }
242     }
243 
getLabel(char * const strBuf) const244     bool getLabel(char* const strBuf) const noexcept override
245     {
246         if (fLabel != nullptr)
247         {
248             std::strncpy(strBuf, fLabel, STR_MAX);
249             return true;
250         }
251 
252         return CarlaPlugin::getLabel(strBuf);
253     }
254 
getMaker(char * const strBuf) const255     bool getMaker(char* const strBuf) const noexcept override
256     {
257         std::strncpy(strBuf, "FluidSynth SF2 engine", STR_MAX);
258         return true;
259     }
260 
getCopyright(char * const strBuf) const261     bool getCopyright(char* const strBuf) const noexcept override
262     {
263         std::strncpy(strBuf, "GNU GPL v2+", STR_MAX);
264         return true;
265     }
266 
getRealName(char * const strBuf) const267     bool getRealName(char* const strBuf) const noexcept override
268     {
269         return getLabel(strBuf);
270     }
271 
getParameterName(const uint32_t parameterId,char * const strBuf) const272     bool getParameterName(const uint32_t parameterId, char* const strBuf) const noexcept override
273     {
274         CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
275 
276         switch (parameterId)
277         {
278         case FluidSynthReverbOnOff:
279             std::strncpy(strBuf, "Reverb On/Off", STR_MAX);
280             return true;
281         case FluidSynthReverbRoomSize:
282             std::strncpy(strBuf, "Reverb Room Size", STR_MAX);
283             return true;
284         case FluidSynthReverbDamp:
285             std::strncpy(strBuf, "Reverb Damp", STR_MAX);
286             return true;
287         case FluidSynthReverbLevel:
288             std::strncpy(strBuf, "Reverb Level", STR_MAX);
289             return true;
290         case FluidSynthReverbWidth:
291             std::strncpy(strBuf, "Reverb Width", STR_MAX);
292             return true;
293         case FluidSynthChorusOnOff:
294             std::strncpy(strBuf, "Chorus On/Off", STR_MAX);
295             return true;
296         case FluidSynthChorusNr:
297             std::strncpy(strBuf, "Chorus Voice Count", STR_MAX);
298             return true;
299         case FluidSynthChorusLevel:
300             std::strncpy(strBuf, "Chorus Level", STR_MAX);
301             return true;
302         case FluidSynthChorusSpeedHz:
303             std::strncpy(strBuf, "Chorus Speed", STR_MAX);
304             return true;
305         case FluidSynthChorusDepthMs:
306             std::strncpy(strBuf, "Chorus Depth", STR_MAX);
307             return true;
308         case FluidSynthChorusType:
309             std::strncpy(strBuf, "Chorus Type", STR_MAX);
310             return true;
311         case FluidSynthPolyphony:
312             std::strncpy(strBuf, "Polyphony", STR_MAX);
313             return true;
314         case FluidSynthInterpolation:
315             std::strncpy(strBuf, "Interpolation", STR_MAX);
316             return true;
317         case FluidSynthVoiceCount:
318             std::strncpy(strBuf, "Voice Count", STR_MAX);
319             return true;
320         }
321 
322         return CarlaPlugin::getParameterName(parameterId, strBuf);
323     }
324 
getParameterUnit(const uint32_t parameterId,char * const strBuf) const325     bool getParameterUnit(const uint32_t parameterId, char* const strBuf) const noexcept override
326     {
327         CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
328 
329         switch (parameterId)
330         {
331         case FluidSynthChorusSpeedHz:
332             std::strncpy(strBuf, "Hz", STR_MAX);
333             return true;
334         case FluidSynthChorusDepthMs:
335             std::strncpy(strBuf, "ms", STR_MAX);
336             return true;
337         }
338 
339         return CarlaPlugin::getParameterUnit(parameterId, strBuf);
340     }
341 
getParameterScalePointLabel(const uint32_t parameterId,const uint32_t scalePointId,char * const strBuf) const342     bool getParameterScalePointLabel(const uint32_t parameterId, const uint32_t scalePointId, char* const strBuf) const noexcept override
343     {
344         CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, false);
345         CARLA_SAFE_ASSERT_RETURN(scalePointId < getParameterScalePointCount(parameterId), false);
346 
347         switch (parameterId)
348         {
349         case FluidSynthChorusType:
350             switch (scalePointId)
351             {
352             case 0:
353                 std::strncpy(strBuf, "Sine wave", STR_MAX);
354                 return true;
355             case 1:
356                 std::strncpy(strBuf, "Triangle wave", STR_MAX);
357                 return true;
358             }
359             break;
360         case FluidSynthInterpolation:
361             switch (scalePointId)
362             {
363             case 0:
364                 std::strncpy(strBuf, "None", STR_MAX);
365                 return true;
366             case 1:
367                 std::strncpy(strBuf, "Straight-line", STR_MAX);
368                 return true;
369             case 2:
370                 std::strncpy(strBuf, "Fourth-order", STR_MAX);
371                 return true;
372             case 3:
373                 std::strncpy(strBuf, "Seventh-order", STR_MAX);
374                 return true;
375             }
376             break;
377         }
378 
379         return CarlaPlugin::getParameterScalePointLabel(parameterId, scalePointId, strBuf);
380     }
381 
382     // -------------------------------------------------------------------
383     // Set data (state)
384 
prepareForSave(bool)385     void prepareForSave(bool) override
386     {
387         char strBuf[STR_MAX+1];
388         std::snprintf(strBuf, STR_MAX, "%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i:%i",
389                       fCurMidiProgs[0],  fCurMidiProgs[1],  fCurMidiProgs[2],  fCurMidiProgs[3],
390                       fCurMidiProgs[4],  fCurMidiProgs[5],  fCurMidiProgs[6],  fCurMidiProgs[7],
391                       fCurMidiProgs[8],  fCurMidiProgs[9],  fCurMidiProgs[10], fCurMidiProgs[11],
392                       fCurMidiProgs[12], fCurMidiProgs[13], fCurMidiProgs[14], fCurMidiProgs[15]);
393 
394         CarlaPlugin::setCustomData(CUSTOM_DATA_TYPE_STRING, "midiPrograms", strBuf, false);
395     }
396 
397     // -------------------------------------------------------------------
398     // Set data (internal stuff)
399 
setCtrlChannel(const int8_t channel,const bool sendOsc,const bool sendCallback)400     void setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) noexcept override
401     {
402         if (channel >= 0 && channel < MAX_MIDI_CHANNELS)
403             pData->midiprog.current = fCurMidiProgs[channel];
404 
405         CarlaPlugin::setCtrlChannel(channel, sendOsc, sendCallback);
406     }
407 
408     // -------------------------------------------------------------------
409     // Set data (plugin-specific stuff)
410 
setParameterValue(const uint32_t parameterId,const float value,const bool sendGui,const bool sendOsc,const bool sendCallback)411     void setParameterValue(const uint32_t parameterId, const float value, const bool sendGui, const bool sendOsc, const bool sendCallback) noexcept override
412     {
413         CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count,);
414         CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback,);
415 
416         float fixedValue;
417 
418         {
419             const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback));
420             fixedValue = setParameterValueInFluidSynth(parameterId, value);
421 
422         }
423 
424         CarlaPlugin::setParameterValue(parameterId, fixedValue, sendGui, sendOsc, sendCallback);
425     }
426 
setParameterValueRT(const uint32_t parameterId,const float value,const bool sendCallbackLater)427     void setParameterValueRT(const uint32_t parameterId, const float value, const bool sendCallbackLater) noexcept override
428     {
429         const float fixedValue = setParameterValueInFluidSynth(parameterId, value);
430 
431         CarlaPlugin::setParameterValueRT(parameterId, fixedValue, sendCallbackLater);
432     }
433 
setParameterValueInFluidSynth(const uint32_t parameterId,const float value)434     float setParameterValueInFluidSynth(const uint32_t parameterId, const float value) noexcept
435     {
436         CARLA_SAFE_ASSERT_RETURN(parameterId < pData->param.count, value);
437 
438         const float fixedValue(pData->param.getFixedValue(parameterId, value));
439         fParamBuffers[parameterId] = fixedValue;
440 
441         switch (parameterId)
442         {
443         case FluidSynthReverbOnOff:
444             try {
445                 fluid_synth_set_reverb_on(fSynth, (fixedValue > 0.5f) ? 1 : 0);
446             } CARLA_SAFE_EXCEPTION("fluid_synth_set_reverb_on")
447             break;
448 
449         case FluidSynthReverbRoomSize:
450         case FluidSynthReverbDamp:
451         case FluidSynthReverbLevel:
452         case FluidSynthReverbWidth:
453             try {
454                 fluid_synth_set_reverb(fSynth,
455                                        fParamBuffers[FluidSynthReverbRoomSize],
456                                        fParamBuffers[FluidSynthReverbDamp],
457                                        fParamBuffers[FluidSynthReverbWidth],
458                                        fParamBuffers[FluidSynthReverbLevel]);
459             } CARLA_SAFE_EXCEPTION("fluid_synth_set_reverb")
460             break;
461 
462         case FluidSynthChorusOnOff:
463             try {
464                 fluid_synth_set_chorus_on(fSynth, (value > 0.5f) ? 1 : 0);
465             } CARLA_SAFE_EXCEPTION("fluid_synth_set_chorus_on")
466             break;
467 
468         case FluidSynthChorusNr:
469         case FluidSynthChorusLevel:
470         case FluidSynthChorusSpeedHz:
471         case FluidSynthChorusDepthMs:
472         case FluidSynthChorusType:
473             try {
474                 fluid_synth_set_chorus(fSynth,
475                                        static_cast<int>(fParamBuffers[FluidSynthChorusNr] + 0.5f),
476                                        fParamBuffers[FluidSynthChorusLevel],
477                                        fParamBuffers[FluidSynthChorusSpeedHz],
478                                        fParamBuffers[FluidSynthChorusDepthMs],
479                                        static_cast<int>(fParamBuffers[FluidSynthChorusType] + 0.5f));
480             } CARLA_SAFE_EXCEPTION("fluid_synth_set_chorus")
481             break;
482 
483         case FluidSynthPolyphony:
484             try {
485                 fluid_synth_set_polyphony(fSynth, static_cast<int>(value + 0.5f));
486             } CARLA_SAFE_EXCEPTION("fluid_synth_set_polyphony")
487             break;
488 
489         case FluidSynthInterpolation:
490             for (int i=0; i < MAX_MIDI_CHANNELS; ++i)
491             {
492                 try {
493                     fluid_synth_set_interp_method(fSynth, i, static_cast<int>(value + 0.5f));
494                 } CARLA_SAFE_EXCEPTION_BREAK("fluid_synth_set_interp_method")
495             }
496             break;
497 
498         default:
499             break;
500         }
501 
502         return fixedValue;
503     }
504 
setCustomData(const char * const type,const char * const key,const char * const value,const bool sendGui)505     void setCustomData(const char* const type, const char* const key, const char* const value, const bool sendGui) override
506     {
507         CARLA_SAFE_ASSERT_RETURN(fSynth != nullptr,);
508         CARLA_SAFE_ASSERT_RETURN(type != nullptr && type[0] != '\0',);
509         CARLA_SAFE_ASSERT_RETURN(key != nullptr && key[0] != '\0',);
510         CARLA_SAFE_ASSERT_RETURN(value != nullptr && value[0] != '\0',);
511         carla_debug("CarlaPluginFluidSynth::setCustomData(%s, \"%s\", \"%s\", %s)", type, key, value, bool2str(sendGui));
512 
513         if (std::strcmp(type, CUSTOM_DATA_TYPE_PROPERTY) == 0)
514             return CarlaPlugin::setCustomData(type, key, value, sendGui);
515 
516         if (std::strcmp(type, CUSTOM_DATA_TYPE_STRING) != 0)
517             return carla_stderr2("CarlaPluginFluidSynth::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui));
518 
519         if (std::strcmp(key, "midiPrograms") != 0)
520             return carla_stderr2("CarlaPluginFluidSynth::setCustomData(\"%s\", \"%s\", \"%s\", %s) - type is not string", type, key, value, bool2str(sendGui));
521 
522         StringArray midiProgramList(StringArray::fromTokens(value, ":", ""));
523 
524         if (midiProgramList.size() == MAX_MIDI_CHANNELS)
525         {
526             uint8_t channel = 0;
527             for (String *it=midiProgramList.begin(), *end=midiProgramList.end(); it != end; ++it)
528             {
529                 const int index(it->getIntValue());
530 
531                 if (index >= 0 && index < static_cast<int>(pData->midiprog.count))
532                 {
533                     const uint32_t bank    = pData->midiprog.data[index].bank;
534                     const uint32_t program = pData->midiprog.data[index].program;
535 
536 #if FLUIDSYNTH_VERSION_MAJOR >= 2
537                     fluid_synth_program_select(fSynth,
538                                                static_cast<int>(channel),
539                                                fSynthId,
540                                                static_cast<int>(bank),
541                                                static_cast<int>(program));
542 #else
543                     fluid_synth_program_select(fSynth, channel, fSynthId, bank, program);
544 #endif
545                     fCurMidiProgs[channel] = index;
546 
547                     if (pData->ctrlChannel == static_cast<int32_t>(channel))
548                     {
549                         pData->midiprog.current = index;
550                         pData->engine->callback(true, true,
551                                                 ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED,
552                                                 pData->id,
553                                                 index,
554                                                 0, 0, 0.0f, nullptr);
555                     }
556                 }
557 
558                 ++channel;
559             }
560             CARLA_SAFE_ASSERT(channel == MAX_MIDI_CHANNELS);
561         }
562 
563         CarlaPlugin::setCustomData(type, key, value, sendGui);
564     }
565 
setMidiProgram(const int32_t index,const bool sendGui,const bool sendOsc,const bool sendCallback,const bool doingInit)566     void setMidiProgram(const int32_t index, const bool sendGui, const bool sendOsc, const bool sendCallback, const bool doingInit) noexcept override
567     {
568         CARLA_SAFE_ASSERT_RETURN(fSynth != nullptr,);
569         CARLA_SAFE_ASSERT_RETURN(index >= -1 && index < static_cast<int32_t>(pData->midiprog.count),);
570         CARLA_SAFE_ASSERT_RETURN(sendGui || sendOsc || sendCallback || doingInit,);
571 
572         if (index >= 0 && pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS)
573         {
574             const uint32_t bank    = pData->midiprog.data[index].bank;
575             const uint32_t program = pData->midiprog.data[index].program;
576 
577             const ScopedSingleProcessLocker spl(this, (sendGui || sendOsc || sendCallback));
578 
579             try {
580 #if FLUIDSYNTH_VERSION_MAJOR >= 2
581                 fluid_synth_program_select(fSynth, pData->ctrlChannel, fSynthId,
582                                            static_cast<int>(bank), static_cast<int>(program));
583 #else
584                 fluid_synth_program_select(fSynth, pData->ctrlChannel, fSynthId, bank, program);
585 #endif
586             } CARLA_SAFE_EXCEPTION("fluid_synth_program_select")
587 
588             fCurMidiProgs[pData->ctrlChannel] = index;
589         }
590 
591         CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, doingInit);
592     }
593 
594     // FIXME: this is never used
setMidiProgramRT(const uint32_t uindex,const bool sendCallbackLater)595     void setMidiProgramRT(const uint32_t uindex, const bool sendCallbackLater) noexcept override
596     {
597         CARLA_SAFE_ASSERT_RETURN(fSynth != nullptr,);
598         CARLA_SAFE_ASSERT_RETURN(uindex < pData->midiprog.count,);
599 
600         if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS)
601         {
602             const uint32_t bank    = pData->midiprog.data[uindex].bank;
603             const uint32_t program = pData->midiprog.data[uindex].program;
604 
605             try {
606 #if FLUIDSYNTH_VERSION_MAJOR >= 2
607                 fluid_synth_program_select(fSynth, pData->ctrlChannel, fSynthId,
608                                            static_cast<int>(bank), static_cast<int>(program));
609 #else
610                 fluid_synth_program_select(fSynth, pData->ctrlChannel, fSynthId, bank, program);
611 #endif
612             } CARLA_SAFE_EXCEPTION("fluid_synth_program_select")
613 
614             fCurMidiProgs[pData->ctrlChannel] = static_cast<int32_t>(uindex);
615         }
616 
617         CarlaPlugin::setMidiProgramRT(uindex, sendCallbackLater);
618     }
619 
620     // -------------------------------------------------------------------
621     // Set ui stuff
622 
623     // nothing
624 
625     // -------------------------------------------------------------------
626     // Plugin state
627 
reload()628     void reload() override
629     {
630         CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr,);
631         CARLA_SAFE_ASSERT_RETURN(fSynth != nullptr,);
632         carla_debug("CarlaPluginFluidSynth::reload() - start");
633 
634         const EngineProcessMode processMode(pData->engine->getProccessMode());
635 
636         // Safely disable plugin for reload
637         const ScopedDisabler sd(this);
638 
639         if (pData->active)
640             deactivate();
641 
642         clearBuffers();
643 
644         uint32_t aOuts, params;
645         aOuts  = kUse16Outs ? 32 : 2;
646         params = FluidSynthParametersMax;
647 
648         pData->audioOut.createNew(aOuts);
649         pData->param.createNew(params, false);
650 
651         const uint portNameSize(pData->engine->getMaxPortNameSize());
652         CarlaString portName;
653 
654         // ---------------------------------------
655         // Audio Outputs
656 
657         if (kUse16Outs)
658         {
659             for (uint32_t i=0; i < 32; ++i)
660             {
661                 portName.clear();
662 
663                 if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
664                 {
665                     portName  = pData->name;
666                     portName += ":";
667                 }
668 
669                 portName += "out-";
670 
671                 if ((i+2)/2 < 9)
672                     portName += "0";
673 
674                 portName += CarlaString((i+2)/2);
675 
676                 if (i % 2 == 0)
677                     portName += "L";
678                 else
679                     portName += "R";
680 
681                 portName.truncate(portNameSize);
682 
683                 pData->audioOut.ports[i].port   = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, i);
684                 pData->audioOut.ports[i].rindex = i;
685             }
686 
687             fAudio16Buffers = new float*[aOuts];
688 
689             for (uint32_t i=0; i < aOuts; ++i)
690                 fAudio16Buffers[i] = nullptr;
691         }
692         else
693         {
694             // out-left
695             portName.clear();
696 
697             if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
698             {
699                 portName  = pData->name;
700                 portName += ":";
701             }
702 
703             portName += "out-left";
704             portName.truncate(portNameSize);
705 
706             pData->audioOut.ports[0].port   = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, 0);
707             pData->audioOut.ports[0].rindex = 0;
708 
709             // out-right
710             portName.clear();
711 
712             if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
713             {
714                 portName  = pData->name;
715                 portName += ":";
716             }
717 
718             portName += "out-right";
719             portName.truncate(portNameSize);
720 
721             pData->audioOut.ports[1].port   = (CarlaEngineAudioPort*)pData->client->addPort(kEnginePortTypeAudio, portName, false, 1);
722             pData->audioOut.ports[1].rindex = 1;
723         }
724 
725         // ---------------------------------------
726         // Event Input
727 
728         {
729             portName.clear();
730 
731             if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
732             {
733                 portName  = pData->name;
734                 portName += ":";
735             }
736 
737             portName += "events-in";
738             portName.truncate(portNameSize);
739 
740             pData->event.portIn = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, true, 0);
741         }
742 
743         // ---------------------------------------
744         // Event Output
745 
746         {
747             portName.clear();
748 
749             if (processMode == ENGINE_PROCESS_MODE_SINGLE_CLIENT)
750             {
751                 portName  = pData->name;
752                 portName += ":";
753             }
754 
755             portName += "events-out";
756             portName.truncate(portNameSize);
757 
758             pData->event.portOut = (CarlaEngineEventPort*)pData->client->addPort(kEnginePortTypeEvent, portName, false, 0);
759         }
760 
761         // ---------------------------------------
762         // Parameters
763 
764         {
765             int j;
766 
767             // ----------------------
768             j = FluidSynthReverbOnOff;
769             pData->param.data[j].type   = PARAMETER_INPUT;
770             pData->param.data[j].hints  = PARAMETER_IS_ENABLED /*| PARAMETER_IS_AUTOMABLE*/ | PARAMETER_IS_BOOLEAN;
771             pData->param.data[j].index  = j;
772             pData->param.data[j].rindex = j;
773             pData->param.ranges[j].min = 0.0f;
774             pData->param.ranges[j].max = 1.0f;
775             pData->param.ranges[j].def = sFluidDefaults[j];
776             pData->param.ranges[j].step = 1.0f;
777             pData->param.ranges[j].stepSmall = 1.0f;
778             pData->param.ranges[j].stepLarge = 1.0f;
779 
780             // ----------------------
781             j = FluidSynthReverbRoomSize;
782             pData->param.data[j].type   = PARAMETER_INPUT;
783             pData->param.data[j].hints  = PARAMETER_IS_ENABLED /*| PARAMETER_IS_AUTOMABLE*/;
784             pData->param.data[j].index  = j;
785             pData->param.data[j].rindex = j;
786             pData->param.ranges[j].min = 0.0f;
787             pData->param.ranges[j].max = 1.0f;
788             pData->param.ranges[j].def = sFluidDefaults[j];
789             pData->param.ranges[j].step = 0.01f;
790             pData->param.ranges[j].stepSmall = 0.0001f;
791             pData->param.ranges[j].stepLarge = 0.1f;
792 
793             // ----------------------
794             j = FluidSynthReverbDamp;
795             pData->param.data[j].type   = PARAMETER_INPUT;
796             pData->param.data[j].hints  = PARAMETER_IS_ENABLED /*| PARAMETER_IS_AUTOMABLE*/;
797             pData->param.data[j].index  = j;
798             pData->param.data[j].rindex = j;
799             pData->param.ranges[j].min = 0.0f;
800             pData->param.ranges[j].max = 1.0f;
801             pData->param.ranges[j].def = sFluidDefaults[j];
802             pData->param.ranges[j].step = 0.01f;
803             pData->param.ranges[j].stepSmall = 0.0001f;
804             pData->param.ranges[j].stepLarge = 0.1f;
805 
806             // ----------------------
807             j = FluidSynthReverbLevel;
808             pData->param.data[j].type   = PARAMETER_INPUT;
809             pData->param.data[j].hints  = PARAMETER_IS_ENABLED /*| PARAMETER_IS_AUTOMABLE*/;
810             pData->param.data[j].index  = j;
811             pData->param.data[j].rindex = j;
812             pData->param.data[j].mappedControlIndex = MIDI_CONTROL_REVERB_SEND_LEVEL;
813             pData->param.ranges[j].min = 0.0f;
814             pData->param.ranges[j].max = 1.0f;
815             pData->param.ranges[j].def = sFluidDefaults[j];
816             pData->param.ranges[j].step = 0.01f;
817             pData->param.ranges[j].stepSmall = 0.0001f;
818             pData->param.ranges[j].stepLarge = 0.1f;
819 
820             // ----------------------
821             j = FluidSynthReverbWidth;
822             pData->param.data[j].type   = PARAMETER_INPUT;
823             pData->param.data[j].hints  = PARAMETER_IS_ENABLED /*| PARAMETER_IS_AUTOMABLE*/;
824             pData->param.data[j].index  = j;
825             pData->param.data[j].rindex = j;
826             pData->param.ranges[j].min = 0.0f;
827             pData->param.ranges[j].max = 10.0f; // should be 100, but that sounds too much
828             pData->param.ranges[j].def = sFluidDefaults[j];
829             pData->param.ranges[j].step = 0.01f;
830             pData->param.ranges[j].stepSmall = 0.0001f;
831             pData->param.ranges[j].stepLarge = 0.1f;
832 
833             // ----------------------
834             j = FluidSynthChorusOnOff;
835             pData->param.data[j].type   = PARAMETER_INPUT;
836             pData->param.data[j].hints  = PARAMETER_IS_ENABLED | PARAMETER_IS_BOOLEAN;
837             pData->param.data[j].index  = j;
838             pData->param.data[j].rindex = j;
839             pData->param.ranges[j].min = 0.0f;
840             pData->param.ranges[j].max = 1.0f;
841             pData->param.ranges[j].def = sFluidDefaults[j];
842             pData->param.ranges[j].step = 1.0f;
843             pData->param.ranges[j].stepSmall = 1.0f;
844             pData->param.ranges[j].stepLarge = 1.0f;
845 
846             // ----------------------
847             j = FluidSynthChorusNr;
848             pData->param.data[j].type   = PARAMETER_INPUT;
849             pData->param.data[j].hints  = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER;
850             pData->param.data[j].index  = j;
851             pData->param.data[j].rindex = j;
852             pData->param.ranges[j].min = 0.0f;
853             pData->param.ranges[j].max = 99.0f;
854             pData->param.ranges[j].def = sFluidDefaults[j];
855             pData->param.ranges[j].step = 1.0f;
856             pData->param.ranges[j].stepSmall = 1.0f;
857             pData->param.ranges[j].stepLarge = 10.0f;
858 
859             // ----------------------
860             j = FluidSynthChorusLevel;
861             pData->param.data[j].type   = PARAMETER_INPUT;
862             pData->param.data[j].hints  = PARAMETER_IS_ENABLED;
863             pData->param.data[j].index  = j;
864             pData->param.data[j].rindex = j;
865             pData->param.ranges[j].min = 0.0f;
866             pData->param.ranges[j].max = 10.0f;
867             pData->param.ranges[j].def = sFluidDefaults[j];
868             pData->param.ranges[j].step = 0.01f;
869             pData->param.ranges[j].stepSmall = 0.0001f;
870             pData->param.ranges[j].stepLarge = 0.1f;
871 
872             // ----------------------
873             j = FluidSynthChorusSpeedHz;
874             pData->param.data[j].type   = PARAMETER_INPUT;
875             pData->param.data[j].hints  = PARAMETER_IS_ENABLED;
876             pData->param.data[j].index  = j;
877             pData->param.data[j].rindex = j;
878             pData->param.ranges[j].min = 0.29f;
879             pData->param.ranges[j].max = 5.0f;
880             pData->param.ranges[j].def = sFluidDefaults[j];
881             pData->param.ranges[j].step = 0.01f;
882             pData->param.ranges[j].stepSmall = 0.0001f;
883             pData->param.ranges[j].stepLarge = 0.1f;
884 
885             // ----------------------
886             j = FluidSynthChorusDepthMs;
887             pData->param.data[j].type   = PARAMETER_INPUT;
888             pData->param.data[j].hints  = PARAMETER_IS_ENABLED;
889             pData->param.data[j].index  = j;
890             pData->param.data[j].rindex = j;
891             pData->param.ranges[j].min = 0.0f;
892 #if FLUIDSYNTH_VERSION_MAJOR >= 2
893             pData->param.ranges[j].max = 256.0f;
894 #else
895             pData->param.ranges[j].max = float(2048.0 * 1000.0 / pData->engine->getSampleRate()); // FIXME?
896 #endif
897             pData->param.ranges[j].def = sFluidDefaults[j];
898             pData->param.ranges[j].step = 0.01f;
899             pData->param.ranges[j].stepSmall = 0.0001f;
900             pData->param.ranges[j].stepLarge = 0.1f;
901 
902             // ----------------------
903             j = FluidSynthChorusType;
904             pData->param.data[j].type   = PARAMETER_INPUT;
905             pData->param.data[j].hints  = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER | PARAMETER_USES_SCALEPOINTS;
906             pData->param.data[j].index  = j;
907             pData->param.data[j].rindex = j;
908             pData->param.ranges[j].min = FLUID_CHORUS_MOD_SINE;
909             pData->param.ranges[j].max = FLUID_CHORUS_MOD_TRIANGLE;
910             pData->param.ranges[j].def = sFluidDefaults[j];
911             pData->param.ranges[j].step = 1.0f;
912             pData->param.ranges[j].stepSmall = 1.0f;
913             pData->param.ranges[j].stepLarge = 1.0f;
914 
915             // ----------------------
916             j = FluidSynthPolyphony;
917             pData->param.data[j].type   = PARAMETER_INPUT;
918             pData->param.data[j].hints  = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER;
919             pData->param.data[j].index  = j;
920             pData->param.data[j].rindex = j;
921             pData->param.ranges[j].min = 1.0f;
922             pData->param.ranges[j].max = 512.0f; // max theoric is 65535
923             pData->param.ranges[j].def = sFluidDefaults[j];
924             pData->param.ranges[j].step = 1.0f;
925             pData->param.ranges[j].stepSmall = 1.0f;
926             pData->param.ranges[j].stepLarge = 10.0f;
927 
928             // ----------------------
929             j = FluidSynthInterpolation;
930             pData->param.data[j].type   = PARAMETER_INPUT;
931             pData->param.data[j].hints  = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER | PARAMETER_USES_SCALEPOINTS;
932             pData->param.data[j].index  = j;
933             pData->param.data[j].rindex = j;
934             pData->param.ranges[j].min = FLUID_INTERP_NONE;
935             pData->param.ranges[j].max = FLUID_INTERP_HIGHEST;
936             pData->param.ranges[j].def = sFluidDefaults[j];
937             pData->param.ranges[j].step = 1.0f;
938             pData->param.ranges[j].stepSmall = 1.0f;
939             pData->param.ranges[j].stepLarge = 1.0f;
940 
941             // ----------------------
942             j = FluidSynthVoiceCount;
943             pData->param.data[j].type   = PARAMETER_OUTPUT;
944             pData->param.data[j].hints  = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE | PARAMETER_IS_INTEGER;
945             pData->param.data[j].index  = j;
946             pData->param.data[j].rindex = j;
947             pData->param.ranges[j].min = 0.0f;
948             pData->param.ranges[j].max = 65535.0f;
949             pData->param.ranges[j].def = 0.0f;
950             pData->param.ranges[j].step = 1.0f;
951             pData->param.ranges[j].stepSmall = 1.0f;
952             pData->param.ranges[j].stepLarge = 1.0f;
953 
954             for (j=0; j<FluidSynthParametersMax; ++j)
955                 fParamBuffers[j] = pData->param.ranges[j].def;
956         }
957 
958         // ---------------------------------------
959 
960         // plugin hints
961         pData->hints  = 0x0;
962         pData->hints |= PLUGIN_IS_SYNTH;
963         pData->hints |= PLUGIN_CAN_VOLUME;
964         pData->hints |= PLUGIN_USES_MULTI_PROGS;
965 
966         if (! kUse16Outs)
967             pData->hints |= PLUGIN_CAN_BALANCE;
968 
969         // extra plugin hints
970         pData->extraHints  = 0x0;
971         pData->extraHints |= PLUGIN_EXTRA_HINT_HAS_MIDI_IN;
972 
973         bufferSizeChanged(pData->engine->getBufferSize());
974         reloadPrograms(true);
975 
976         if (pData->active)
977             activate();
978 
979         carla_debug("CarlaPluginFluidSynth::reload() - end");
980     }
981 
reloadPrograms(const bool doInit)982     void reloadPrograms(const bool doInit) override
983     {
984         carla_debug("CarlaPluginFluidSynth::reloadPrograms(%s)", bool2str(doInit));
985 
986         // save drum info in case we have one program for it
987         bool hasDrums = false;
988         uint32_t drumIndex, drumProg;
989         drumIndex = drumProg = 0;
990 
991         // Delete old programs
992         pData->midiprog.clear();
993 
994         // Query new programs
995         uint32_t count = 0;
996 
997         if (fluid_sfont_t* const f_sfont = fluid_synth_get_sfont_by_id(fSynth, fSynthId))
998         {
999 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1000             fluid_preset_t* f_preset;
1001 
1002             // initial check to know how many midi-programs we have
1003             fluid_sfont_iteration_start(f_sfont);
1004             for (; fluid_sfont_iteration_next(f_sfont);)
1005                 ++count;
1006 
1007             // sound kits must always have at least 1 midi-program
1008             CARLA_SAFE_ASSERT_RETURN(count > 0,);
1009 
1010             pData->midiprog.createNew(count);
1011 
1012             // Update data
1013             int tmp;
1014             uint32_t i = 0;
1015             fluid_sfont_iteration_start(f_sfont);
1016 
1017             for (; (f_preset = fluid_sfont_iteration_next(f_sfont));)
1018             {
1019                 CARLA_SAFE_ASSERT_BREAK(i < count);
1020 
1021                 tmp = fluid_preset_get_banknum(f_preset);
1022                 pData->midiprog.data[i].bank = (tmp >= 0) ? static_cast<uint32_t>(tmp) : 0;
1023 
1024                 tmp = fluid_preset_get_num(f_preset);
1025                 pData->midiprog.data[i].program = (tmp >= 0) ? static_cast<uint32_t>(tmp) : 0;
1026 
1027                 pData->midiprog.data[i].name = carla_strdup(fluid_preset_get_name(f_preset));
1028 #else
1029             fluid_preset_t f_preset;
1030 
1031             // initial check to know how many midi-programs we have
1032             f_sfont->iteration_start(f_sfont);
1033             for (; f_sfont->iteration_next(f_sfont, &f_preset);)
1034                 ++count;
1035 
1036             // sound kits must always have at least 1 midi-program
1037             CARLA_SAFE_ASSERT_RETURN(count > 0,);
1038 
1039             pData->midiprog.createNew(count);
1040 
1041             // Update data
1042             int tmp;
1043             uint32_t i = 0;
1044             f_sfont->iteration_start(f_sfont);
1045 
1046             for (; f_sfont->iteration_next(f_sfont, &f_preset);)
1047             {
1048                 CARLA_SAFE_ASSERT_BREAK(i < count);
1049 
1050                 tmp = f_preset.get_banknum(&f_preset);
1051                 pData->midiprog.data[i].bank = (tmp >= 0) ? static_cast<uint32_t>(tmp) : 0;
1052 
1053                 tmp = f_preset.get_num(&f_preset);
1054                 pData->midiprog.data[i].program = (tmp >= 0) ? static_cast<uint32_t>(tmp) : 0;
1055 
1056                 pData->midiprog.data[i].name = carla_strdup(f_preset.get_name(&f_preset));
1057 #endif
1058 
1059                 if (pData->midiprog.data[i].bank == 128 && ! hasDrums)
1060                 {
1061                     hasDrums  = true;
1062                     drumIndex = i;
1063                     drumProg  = pData->midiprog.data[i].program;
1064                 }
1065 
1066                 ++i;
1067             }
1068         }
1069         else
1070         {
1071             // failing means 0 midi-programs, it shouldn't happen!
1072             carla_safe_assert("fluid_sfont_t* const f_sfont = fluid_synth_get_sfont_by_id(fSynth, fSynthId)", __FILE__, __LINE__);
1073             return;
1074         }
1075 
1076         if (doInit)
1077         {
1078             fluid_synth_program_reset(fSynth);
1079 
1080             // select first program, or 128 for ch10
1081             for (int i=0; i < MAX_MIDI_CHANNELS && i != 9; ++i)
1082             {
1083                 fluid_synth_set_channel_type(fSynth, i, CHANNEL_TYPE_MELODIC);
1084 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1085                 fluid_synth_program_select(fSynth, i, fSynthId,
1086                                            static_cast<int>(pData->midiprog.data[0].bank),
1087                                            static_cast<int>(pData->midiprog.data[0].program));
1088 #else
1089                 fluid_synth_program_select(fSynth, i, fSynthId,
1090                                            pData->midiprog.data[0].bank, pData->midiprog.data[0].program);
1091 #endif
1092                 fCurMidiProgs[i] = 0;
1093             }
1094 
1095             if (hasDrums)
1096             {
1097                 fluid_synth_set_channel_type(fSynth, 9, CHANNEL_TYPE_DRUM);
1098 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1099                 fluid_synth_program_select(fSynth, 9, fSynthId, 128, static_cast<int>(drumProg));
1100 #else
1101                 fluid_synth_program_select(fSynth, 9, fSynthId, 128, drumProg);
1102 #endif
1103                 fCurMidiProgs[9] = static_cast<int32_t>(drumIndex);
1104             }
1105             else
1106             {
1107                 fluid_synth_set_channel_type(fSynth, 9, CHANNEL_TYPE_MELODIC);
1108 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1109                 fluid_synth_program_select(fSynth, 9, fSynthId,
1110                                            static_cast<int>(pData->midiprog.data[0].bank),
1111                                            static_cast<int>(pData->midiprog.data[0].program));
1112 #else
1113                 fluid_synth_program_select(fSynth, 9, fSynthId,
1114                                            pData->midiprog.data[0].bank, pData->midiprog.data[0].program);
1115 #endif
1116                 fCurMidiProgs[9] = 0;
1117             }
1118 
1119             pData->midiprog.current = 0;
1120         }
1121         else
1122         {
1123             pData->engine->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS, pData->id, 0, 0, 0, 0.0f, nullptr);
1124         }
1125     }
1126 
1127     // -------------------------------------------------------------------
1128     // Plugin processing
1129 
1130     void process(const float* const* const, float** const audioOut,
1131                  const float* const*, float**, const uint32_t frames) override
1132     {
1133         // --------------------------------------------------------------------------------------------------------
1134         // Check if active
1135 
1136         if (! pData->active)
1137         {
1138             // disable any output sound
1139             for (uint32_t i=0; i < pData->audioOut.count; ++i)
1140                 carla_zeroFloats(audioOut[i], frames);
1141             return;
1142         }
1143 
1144         // --------------------------------------------------------------------------------------------------------
1145         // Check if needs reset
1146 
1147         if (pData->needsReset)
1148         {
1149             if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
1150             {
1151                 for (int i=0; i < MAX_MIDI_CHANNELS; ++i)
1152                 {
1153                     fluid_synth_all_notes_off(fSynth, i);
1154                     fluid_synth_all_sounds_off(fSynth, i);
1155                 }
1156             }
1157             else if (pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS)
1158             {
1159                 for (int i=0; i < MAX_MIDI_NOTE; ++i)
1160                     fluid_synth_noteoff(fSynth, pData->ctrlChannel, i);
1161             }
1162 
1163             pData->needsReset = false;
1164         }
1165 
1166         // --------------------------------------------------------------------------------------------------------
1167         // Event Input and Processing
1168 
1169         {
1170             // ----------------------------------------------------------------------------------------------------
1171             // MIDI Input (External)
1172 
1173             if (pData->extNotes.mutex.tryLock())
1174             {
1175                 for (RtLinkedList<ExternalMidiNote>::Itenerator it = pData->extNotes.data.begin2(); it.valid(); it.next())
1176                 {
1177                     const ExternalMidiNote& note(it.getValue(kExternalMidiNoteFallback));
1178                     CARLA_SAFE_ASSERT_CONTINUE(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS);
1179 
1180                     if (note.velo > 0)
1181                         fluid_synth_noteon(fSynth, note.channel, note.note, note.velo);
1182                     else
1183                         fluid_synth_noteoff(fSynth,note.channel, note.note);
1184                 }
1185 
1186                 pData->extNotes.data.clear();
1187                 pData->extNotes.mutex.unlock();
1188 
1189             } // End of MIDI Input (External)
1190 
1191             // ----------------------------------------------------------------------------------------------------
1192             // Event Input (System)
1193 
1194 #ifndef BUILD_BRIDGE
1195             bool allNotesOffSent = false;
1196 #endif
1197             uint32_t timeOffset = 0;
1198 
1199             uint32_t nextBankIds[MAX_MIDI_CHANNELS] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0 };
1200 
1201             if (pData->midiprog.current >= 0 && pData->midiprog.count > 0 && pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS)
1202                 nextBankIds[pData->ctrlChannel] = pData->midiprog.data[pData->midiprog.current].bank;
1203 
1204             for (uint32_t i=0, numEvents=pData->event.portIn->getEventCount(); i < numEvents; ++i)
1205             {
1206                 const EngineEvent& event(pData->event.portIn->getEvent(i));
1207 
1208                 uint32_t eventTime = event.time;
1209                 CARLA_SAFE_ASSERT_UINT2_CONTINUE(eventTime < frames, eventTime, frames);
1210 
1211                 if (eventTime < timeOffset)
1212                 {
1213                     carla_stderr2("Timing error, eventTime:%u < timeOffset:%u for '%s'",
1214                                   eventTime, timeOffset, pData->name);
1215                     eventTime = timeOffset;
1216                 }
1217                 else if (eventTime > timeOffset)
1218                 {
1219                     if (processSingle(audioOut, eventTime - timeOffset, timeOffset))
1220                     {
1221                         timeOffset = eventTime;
1222 
1223                         if (pData->midiprog.current >= 0 && pData->midiprog.count > 0 && pData->ctrlChannel >= 0 && pData->ctrlChannel < MAX_MIDI_CHANNELS)
1224                             nextBankIds[pData->ctrlChannel] = pData->midiprog.data[pData->midiprog.current].bank;
1225                     }
1226                 }
1227 
1228                 // Control change
1229                 switch (event.type)
1230                 {
1231                 case kEngineEventTypeNull:
1232                     break;
1233 
1234                 case kEngineEventTypeControl:
1235                 {
1236                     const EngineControlEvent& ctrlEvent = event.ctrl;
1237 
1238                     switch (ctrlEvent.type)
1239                     {
1240                     case kEngineControlEventTypeNull:
1241                         break;
1242 
1243                     case kEngineControlEventTypeParameter:
1244                     {
1245                         float value;
1246 
1247 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1248                         // Control backend stuff
1249                         if (event.channel == pData->ctrlChannel)
1250                         {
1251                             if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_DRYWET) != 0)
1252                             {
1253                                 value = ctrlEvent.normalizedValue;
1254                                 setDryWetRT(value, true);
1255                             }
1256 
1257                             if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_VOLUME) != 0)
1258                             {
1259                                 value = ctrlEvent.normalizedValue*127.0f/100.0f;
1260                                 setVolumeRT(value, true);
1261                             }
1262 
1263                             if (MIDI_IS_CONTROL_BALANCE(ctrlEvent.param) && (pData->hints & PLUGIN_CAN_BALANCE) != 0)
1264                             {
1265                                 float left, right;
1266                                 value = ctrlEvent.normalizedValue/0.5f - 1.0f;
1267 
1268                                 if (value < 0.0f)
1269                                 {
1270                                     left  = -1.0f;
1271                                     right = (value*2.0f)+1.0f;
1272                                 }
1273                                 else if (value > 0.0f)
1274                                 {
1275                                     left  = (value*2.0f)-1.0f;
1276                                     right = 1.0f;
1277                                 }
1278                                 else
1279                                 {
1280                                     left  = -1.0f;
1281                                     right = 1.0f;
1282                                 }
1283 
1284                                 setBalanceLeftRT(left, true);
1285                                 setBalanceRightRT(right, true);
1286                             }
1287                         }
1288 #endif
1289                         // Control plugin parameters
1290                         for (uint32_t k=0; k < pData->param.count; ++k)
1291                         {
1292                             if (pData->param.data[k].midiChannel != event.channel)
1293                                 continue;
1294                             if (pData->param.data[k].mappedControlIndex != ctrlEvent.param)
1295                                 continue;
1296                             if (pData->param.data[k].hints != PARAMETER_INPUT)
1297                                 continue;
1298                             if ((pData->param.data[k].hints & PARAMETER_IS_AUTOMABLE) == 0)
1299                                 continue;
1300 
1301                             value = pData->param.getFinalUnnormalizedValue(k, ctrlEvent.normalizedValue);
1302                             setParameterValueRT(k, value, true);
1303                         }
1304 
1305                         if ((pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES) != 0 && ctrlEvent.param < MAX_MIDI_VALUE)
1306                         {
1307                             fluid_synth_cc(fSynth, event.channel, ctrlEvent.param, int(ctrlEvent.normalizedValue*127.0f));
1308                         }
1309                         break;
1310                     }
1311 
1312                     case kEngineControlEventTypeMidiBank:
1313                         if (event.channel < MAX_MIDI_CHANNELS && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
1314                             nextBankIds[event.channel] = ctrlEvent.param;
1315                         break;
1316 
1317                     case kEngineControlEventTypeMidiProgram:
1318                         if (event.channel < MAX_MIDI_CHANNELS && (pData->options & PLUGIN_OPTION_MAP_PROGRAM_CHANGES) != 0)
1319                         {
1320                             const uint32_t bankId(nextBankIds[event.channel]);
1321                             const uint32_t progId(ctrlEvent.param);
1322 
1323                             // TODO int32_t midiprog.find(bank, prog)
1324                             for (uint32_t k=0; k < pData->midiprog.count; ++k)
1325                             {
1326                                 if (pData->midiprog.data[k].bank == bankId && pData->midiprog.data[k].program == progId)
1327                                 {
1328 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1329                                     fluid_synth_program_select(fSynth, event.channel, fSynthId,
1330                                                                static_cast<int>(bankId), static_cast<int>(progId));
1331 #else
1332                                     fluid_synth_program_select(fSynth, event.channel, fSynthId, bankId, progId);
1333 #endif
1334                                     fCurMidiProgs[event.channel] = static_cast<int32_t>(k);
1335 
1336                                     if (event.channel == pData->ctrlChannel)
1337                                     {
1338                                         pData->postponeMidiProgramChangeRtEvent(true, k);
1339                                     }
1340 
1341                                     break;
1342                                 }
1343                             }
1344                         }
1345                         break;
1346 
1347                     case kEngineControlEventTypeAllSoundOff:
1348                         if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
1349                             fluid_synth_all_sounds_off(fSynth, event.channel);
1350                         break;
1351 
1352                     case kEngineControlEventTypeAllNotesOff:
1353                         if (pData->options & PLUGIN_OPTION_SEND_ALL_SOUND_OFF)
1354                         {
1355 #ifndef BUILD_BRIDGE
1356                             if (event.channel == pData->ctrlChannel && ! allNotesOffSent)
1357                             {
1358                                 allNotesOffSent = true;
1359                                 postponeRtAllNotesOff();
1360                             }
1361 #endif
1362 
1363                             fluid_synth_all_notes_off(fSynth, event.channel);
1364                         }
1365                         break;
1366                     }
1367 
1368                     break;
1369                 }
1370 
1371                 case kEngineEventTypeMidi: {
1372                     const EngineMidiEvent& midiEvent(event.midi);
1373 
1374                     if (midiEvent.size > EngineMidiEvent::kDataSize)
1375                         continue;
1376 
1377                     uint8_t status = uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent.data));
1378 
1379                     // Fix bad note-off
1380                     if (status == MIDI_STATUS_NOTE_ON && midiEvent.data[2] == 0)
1381                         status = MIDI_STATUS_NOTE_OFF;
1382 
1383                     switch (status)
1384                     {
1385                     case MIDI_STATUS_NOTE_OFF:
1386                         if ((pData->options & PLUGIN_OPTION_SKIP_SENDING_NOTES) == 0x0)
1387                         {
1388                             const uint8_t note = midiEvent.data[1];
1389 
1390                             fluid_synth_noteoff(fSynth, event.channel, note);
1391 
1392                             pData->postponeNoteOffRtEvent(true, event.channel, note);
1393                         }
1394                         break;
1395 
1396                     case MIDI_STATUS_NOTE_ON:
1397                         if ((pData->options & PLUGIN_OPTION_SKIP_SENDING_NOTES) == 0x0)
1398                         {
1399                             const uint8_t note = midiEvent.data[1];
1400                             const uint8_t velo = midiEvent.data[2];
1401 
1402                             fluid_synth_noteon(fSynth, event.channel, note, velo);
1403 
1404                             pData->postponeNoteOnRtEvent(true, event.channel, note, velo);
1405                         }
1406                         break;
1407 
1408 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1409                     case MIDI_STATUS_POLYPHONIC_AFTERTOUCH:
1410                         if (pData->options & PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH)
1411                         {
1412                             const uint8_t note     = midiEvent.data[1];
1413                             const uint8_t pressure = midiEvent.data[2];
1414 
1415                             fluid_synth_key_pressure(fSynth, event.channel, note, pressure);
1416                         }
1417                         break;
1418 #endif
1419 
1420                     case MIDI_STATUS_CONTROL_CHANGE:
1421                         if (pData->options & PLUGIN_OPTION_SEND_CONTROL_CHANGES)
1422                         {
1423                             const uint8_t control = midiEvent.data[1];
1424                             const uint8_t value   = midiEvent.data[2];
1425 
1426                             fluid_synth_cc(fSynth, event.channel, control, value);
1427                         }
1428                         break;
1429 
1430                     case MIDI_STATUS_CHANNEL_PRESSURE:
1431                         if (pData->options & PLUGIN_OPTION_SEND_CHANNEL_PRESSURE)
1432                         {
1433                             const uint8_t pressure = midiEvent.data[1];
1434 
1435                             fluid_synth_channel_pressure(fSynth, event.channel, pressure);;
1436                         }
1437                         break;
1438 
1439                     case MIDI_STATUS_PITCH_WHEEL_CONTROL:
1440                         if (pData->options & PLUGIN_OPTION_SEND_PITCHBEND)
1441                         {
1442                             const uint8_t lsb = midiEvent.data[1];
1443                             const uint8_t msb = midiEvent.data[2];
1444                             const int   value = ((msb << 7) | lsb);
1445 
1446                             fluid_synth_pitch_bend(fSynth, event.channel, value);
1447                         }
1448                         break;
1449 
1450                     default:
1451                         continue;
1452                         break;
1453                     } // switch (status)
1454                 } break;
1455                 } // switch (event.type)
1456             }
1457 
1458             pData->postRtEvents.trySplice();
1459 
1460             if (frames > timeOffset)
1461                 processSingle(audioOut, frames - timeOffset, timeOffset);
1462 
1463         } // End of Event Input and Processing
1464 
1465 #ifndef BUILD_BRIDGE
1466         // --------------------------------------------------------------------------------------------------------
1467         // Control Output
1468 
1469         {
1470             uint32_t k = FluidSynthVoiceCount;
1471             fParamBuffers[k] = float(fluid_synth_get_active_voice_count(fSynth));
1472             pData->param.ranges[k].fixValue(fParamBuffers[k]);
1473 
1474             if (pData->param.data[k].mappedControlIndex > 0)
1475             {
1476                 float value(pData->param.ranges[k].getNormalizedValue(fParamBuffers[k]));
1477                 pData->event.portOut->writeControlEvent(0,
1478                                                         pData->param.data[k].midiChannel,
1479                                                         kEngineControlEventTypeParameter,
1480                                                         static_cast<uint16_t>(pData->param.data[k].mappedControlIndex),
1481                                                         -1,
1482                                                         value);
1483             }
1484 
1485         } // End of Control Output
1486 #endif
1487     }
1488 
1489     bool processSingle(float** const outBuffer, const uint32_t frames, const uint32_t timeOffset)
1490     {
1491         CARLA_SAFE_ASSERT_RETURN(outBuffer != nullptr, false);
1492         CARLA_SAFE_ASSERT_RETURN(frames > 0, false);
1493 
1494         // --------------------------------------------------------------------------------------------------------
1495         // Try lock, silence otherwise
1496 
1497 #ifndef STOAT_TEST_BUILD
1498         if (pData->engine->isOffline())
1499         {
1500             pData->singleMutex.lock();
1501         }
1502         else
1503 #endif
1504         if (! pData->singleMutex.tryLock())
1505         {
1506             for (uint32_t i=0; i < pData->audioOut.count; ++i)
1507             {
1508                 for (uint32_t k=0; k < frames; ++k)
1509                     outBuffer[i][k+timeOffset] = 0.0f;
1510             }
1511 
1512             return false;
1513         }
1514 
1515         // --------------------------------------------------------------------------------------------------------
1516         // Fill plugin buffers and Run plugin
1517 
1518         if (kUse16Outs)
1519         {
1520             for (uint32_t i=0; i < pData->audioOut.count; ++i)
1521                 carla_zeroFloats(fAudio16Buffers[i], frames);
1522 
1523             // FIXME use '32' or '16' instead of outs
1524             fluid_synth_process(fSynth, static_cast<int>(frames),
1525                                 0, nullptr,
1526                                 static_cast<int>(pData->audioOut.count), fAudio16Buffers);
1527         }
1528         else
1529         {
1530             fluid_synth_write_float(fSynth, static_cast<int>(frames),
1531                                     outBuffer[0] + timeOffset, 0, 1,
1532                                     outBuffer[1] + timeOffset, 0, 1);
1533         }
1534 
1535 #ifndef BUILD_BRIDGE
1536         // --------------------------------------------------------------------------------------------------------
1537         // Post-processing (volume and balance)
1538 
1539         {
1540             // note - balance not possible with kUse16Outs, so we can safely skip fAudioOutBuffers
1541             const bool doVolume  = (pData->hints & PLUGIN_CAN_VOLUME) != 0 && carla_isNotEqual(pData->postProc.volume, 1.0f);
1542             const bool doBalance = (pData->hints & PLUGIN_CAN_BALANCE) != 0 && ! (carla_isEqual(pData->postProc.balanceLeft, -1.0f) && carla_isEqual(pData->postProc.balanceRight, 1.0f));
1543 
1544             float oldBufLeft[doBalance ? frames : 1];
1545 
1546             for (uint32_t i=0; i < pData->audioOut.count; ++i)
1547             {
1548                 // Balance
1549                 if (doBalance)
1550                 {
1551                     if (i % 2 == 0)
1552                         carla_copyFloats(oldBufLeft, outBuffer[i]+timeOffset, frames);
1553 
1554                     float balRangeL = (pData->postProc.balanceLeft  + 1.0f)/2.0f;
1555                     float balRangeR = (pData->postProc.balanceRight + 1.0f)/2.0f;
1556 
1557                     for (uint32_t k=0; k < frames; ++k)
1558                     {
1559                         if (i % 2 == 0)
1560                         {
1561                             // left
1562                             outBuffer[i][k+timeOffset]  = oldBufLeft[k]                * (1.0f - balRangeL);
1563                             outBuffer[i][k+timeOffset] += outBuffer[i+1][k+timeOffset] * (1.0f - balRangeR);
1564                         }
1565                         else
1566                         {
1567                             // right
1568                             outBuffer[i][k+timeOffset]  = outBuffer[i][k+timeOffset] * balRangeR;
1569                             outBuffer[i][k+timeOffset] += oldBufLeft[k]              * balRangeL;
1570                         }
1571                     }
1572                 }
1573 
1574                 // Volume
1575                 if (kUse16Outs)
1576                 {
1577                     for (uint32_t k=0; k < frames; ++k)
1578                         outBuffer[i][k+timeOffset] = fAudio16Buffers[i][k] * pData->postProc.volume;
1579                 }
1580                 else if (doVolume)
1581                 {
1582                     for (uint32_t k=0; k < frames; ++k)
1583                         outBuffer[i][k+timeOffset] *= pData->postProc.volume;
1584                 }
1585             }
1586 
1587         } // End of Post-processing
1588 #else
1589         if (kUse16Outs)
1590         {
1591             for (uint32_t i=0; i < pData->audioOut.count; ++i)
1592             {
1593                 for (uint32_t k=0; k < frames; ++k)
1594                     outBuffer[i][k+timeOffset] = fAudio16Buffers[i][k];
1595             }
1596         }
1597 #endif
1598 
1599         // --------------------------------------------------------------------------------------------------------
1600 
1601         pData->singleMutex.unlock();
1602         return true;
1603     }
1604 
1605     void bufferSizeChanged(const uint32_t newBufferSize) override
1606     {
1607         if (! kUse16Outs)
1608             return;
1609 
1610         for (uint32_t i=0; i < pData->audioOut.count; ++i)
1611         {
1612             if (fAudio16Buffers[i] != nullptr)
1613                 delete[] fAudio16Buffers[i];
1614             fAudio16Buffers[i] = new float[newBufferSize];
1615         }
1616     }
1617 
1618     void sampleRateChanged(const double newSampleRate) override
1619     {
1620         CARLA_SAFE_ASSERT_RETURN(fSettings != nullptr,);
1621         fluid_settings_setnum(fSettings, "synth.sample-rate", newSampleRate);
1622 
1623 #if FLUIDSYNTH_VERSION_MAJOR < 2
1624         CARLA_SAFE_ASSERT_RETURN(fSynth != nullptr,);
1625         fluid_synth_set_sample_rate(fSynth, static_cast<float>(newSampleRate));
1626 #endif
1627     }
1628 
1629     // -------------------------------------------------------------------
1630     // Plugin buffers
1631 
1632     void clearBuffers() noexcept override
1633     {
1634         carla_debug("CarlaPluginFluidSynth::clearBuffers() - start");
1635 
1636         if (fAudio16Buffers != nullptr)
1637         {
1638             for (uint32_t i=0; i < pData->audioOut.count; ++i)
1639             {
1640                 if (fAudio16Buffers[i] != nullptr)
1641                 {
1642                     delete[] fAudio16Buffers[i];
1643                     fAudio16Buffers[i] = nullptr;
1644                 }
1645             }
1646 
1647             delete[] fAudio16Buffers;
1648             fAudio16Buffers = nullptr;
1649         }
1650 
1651         CarlaPlugin::clearBuffers();
1652 
1653         carla_debug("CarlaPluginFluidSynth::clearBuffers() - end");
1654     }
1655 
1656     // -------------------------------------------------------------------
1657 
1658     const void* getExtraStuff() const noexcept override
1659     {
1660         static const char xtrue[]  = "true";
1661         static const char xfalse[] = "false";
1662         return kUse16Outs ? xtrue : xfalse;
1663     }
1664 
1665     // -------------------------------------------------------------------
1666 
1667     bool init(const CarlaPluginPtr plugin,
1668               const char* const filename, const char* const name, const char* const label, const uint options)
1669     {
1670         CARLA_SAFE_ASSERT_RETURN(pData->engine != nullptr, false);
1671 
1672         // ---------------------------------------------------------------
1673         // first checks
1674 
1675         if (pData->client != nullptr)
1676         {
1677             pData->engine->setLastError("Plugin client is already registered");
1678             return false;
1679         }
1680 
1681         if (fSynth == nullptr)
1682         {
1683             pData->engine->setLastError("null synth");
1684             return false;
1685         }
1686 
1687         if (filename == nullptr || filename[0] == '\0')
1688         {
1689             pData->engine->setLastError("null filename");
1690             return false;
1691         }
1692 
1693         if (label == nullptr || label[0] == '\0')
1694         {
1695             pData->engine->setLastError("null label");
1696             return false;
1697         }
1698 
1699         // ---------------------------------------------------------------
1700         // open soundfont
1701 
1702         const int synthId = fluid_synth_sfload(fSynth, filename, 0);
1703 
1704         if (synthId < 0)
1705         {
1706             pData->engine->setLastError("Failed to load SoundFont file");
1707             return false;
1708         }
1709 
1710 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1711         fSynthId = synthId;
1712 #else
1713         fSynthId = static_cast<uint>(synthId);
1714 #endif
1715 
1716 
1717         // ---------------------------------------------------------------
1718         // get info
1719 
1720         CarlaString label2(label);
1721 
1722         if (kUse16Outs && ! label2.endsWith(" (16 outs)"))
1723             label2 += " (16 outs)";
1724 
1725         fLabel          = label2.dup();
1726         pData->filename = carla_strdup(filename);
1727 
1728         if (name != nullptr && name[0] != '\0')
1729             pData->name = pData->engine->getUniquePluginName(name);
1730         else
1731             pData->name = pData->engine->getUniquePluginName(label);
1732 
1733         // ---------------------------------------------------------------
1734         // register client
1735 
1736         pData->client = pData->engine->addClient(plugin);
1737 
1738         if (pData->client == nullptr || ! pData->client->isOk())
1739         {
1740             pData->engine->setLastError("Failed to register plugin client");
1741             return false;
1742         }
1743 
1744         // ---------------------------------------------------------------
1745         // set options
1746 
1747         pData->options = 0x0;
1748 
1749         if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CONTROL_CHANGES))
1750             pData->options |= PLUGIN_OPTION_SEND_CONTROL_CHANGES;
1751         if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE))
1752             pData->options |= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE;
1753         if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_PITCHBEND))
1754             pData->options |= PLUGIN_OPTION_SEND_PITCHBEND;
1755         if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_ALL_SOUND_OFF))
1756             pData->options |= PLUGIN_OPTION_SEND_ALL_SOUND_OFF;
1757         if (isPluginOptionEnabled(options, PLUGIN_OPTION_MAP_PROGRAM_CHANGES))
1758             pData->options |= PLUGIN_OPTION_MAP_PROGRAM_CHANGES;
1759         if (isPluginOptionInverseEnabled(options, PLUGIN_OPTION_SKIP_SENDING_NOTES))
1760             pData->options |= PLUGIN_OPTION_SKIP_SENDING_NOTES;
1761 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1762         if (isPluginOptionEnabled(options, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH))
1763             pData->options |= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH;
1764 #endif
1765 
1766         return true;
1767     }
1768 
1769 private:
1770     void initializeFluidDefaultsIfNeeded()
1771     {
1772         if (sFluidDefaultsStored)
1773             return;
1774 
1775         sFluidDefaultsStored = true;
1776 
1777         // reverb defaults
1778         sFluidDefaults[FluidSynthReverbOnOff] = 1.0f;
1779 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1780         double reverbVal;
1781 
1782         reverbVal = 0.2;
1783         fluid_settings_getnum_default(fSettings, "synth.reverb.room-size", &reverbVal);
1784         sFluidDefaults[FluidSynthReverbRoomSize] = static_cast<float>(reverbVal);
1785 
1786         reverbVal = 0.0;
1787         fluid_settings_getnum_default(fSettings, "synth.reverb.damp", &reverbVal);
1788         sFluidDefaults[FluidSynthReverbDamp] = static_cast<float>(reverbVal);
1789 
1790         reverbVal = 0.9;
1791         fluid_settings_getnum_default(fSettings, "synth.reverb.level", &reverbVal);
1792         sFluidDefaults[FluidSynthReverbLevel] = static_cast<float>(reverbVal);
1793 
1794         reverbVal = 0.5;
1795         fluid_settings_getnum_default(fSettings, "synth.reverb.width", &reverbVal);
1796         sFluidDefaults[FluidSynthReverbWidth] = static_cast<float>(reverbVal);
1797 #else
1798         sFluidDefaults[FluidSynthReverbRoomSize] = FLUID_REVERB_DEFAULT_ROOMSIZE;
1799         sFluidDefaults[FluidSynthReverbDamp] = FLUID_REVERB_DEFAULT_DAMP;
1800         sFluidDefaults[FluidSynthReverbLevel] = FLUID_REVERB_DEFAULT_LEVEL;
1801         sFluidDefaults[FluidSynthReverbWidth] = FLUID_REVERB_DEFAULT_WIDTH;
1802 #endif
1803 
1804         // chorus defaults
1805         sFluidDefaults[FluidSynthChorusOnOff] = 1.0f;
1806 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1807         double chorusVal;
1808 
1809         chorusVal = 3.0;
1810         fluid_settings_getnum_default(fSettings, "synth.chorus.nr", &chorusVal);
1811         sFluidDefaults[FluidSynthChorusNr] = static_cast<float>(chorusVal);
1812 
1813         chorusVal = 2.0;
1814         fluid_settings_getnum_default(fSettings, "synth.chorus.level", &chorusVal);
1815         sFluidDefaults[FluidSynthChorusLevel] = static_cast<float>(chorusVal);
1816 
1817         chorusVal = 0.3;
1818         fluid_settings_getnum_default(fSettings, "synth.chorus.speed", &chorusVal);
1819         sFluidDefaults[FluidSynthChorusSpeedHz] = static_cast<float>(chorusVal);
1820 
1821         chorusVal = 8.0;
1822         fluid_settings_getnum_default(fSettings, "synth.chorus.depth", &chorusVal);
1823         sFluidDefaults[FluidSynthChorusDepthMs] = static_cast<float>(chorusVal);
1824 
1825         // There is no settings for chorus default type
1826         sFluidDefaults[FluidSynthChorusType] = static_cast<float>(fluid_synth_get_chorus_type(fSynth));
1827 #else
1828         sFluidDefaults[FluidSynthChorusNr] = FLUID_CHORUS_DEFAULT_N;
1829         sFluidDefaults[FluidSynthChorusLevel] = FLUID_CHORUS_DEFAULT_LEVEL;
1830         sFluidDefaults[FluidSynthChorusSpeedHz] = FLUID_CHORUS_DEFAULT_SPEED;
1831         sFluidDefaults[FluidSynthChorusDepthMs] = FLUID_CHORUS_DEFAULT_DEPTH;
1832         sFluidDefaults[FluidSynthChorusType] = FLUID_CHORUS_DEFAULT_TYPE;
1833 #endif
1834 
1835         // misc. defaults
1836         sFluidDefaults[FluidSynthInterpolation] = FLUID_INTERP_DEFAULT;
1837         sFluidDefaults[FluidSynthPolyphony] = FLUID_DEFAULT_POLYPHONY;
1838     }
1839 
1840     enum FluidSynthParameters {
1841         FluidSynthReverbOnOff    = 0,
1842         FluidSynthReverbRoomSize = 1,
1843         FluidSynthReverbDamp     = 2,
1844         FluidSynthReverbLevel    = 3,
1845         FluidSynthReverbWidth    = 4,
1846         FluidSynthChorusOnOff    = 5,
1847         FluidSynthChorusNr       = 6,
1848         FluidSynthChorusLevel    = 7,
1849         FluidSynthChorusSpeedHz  = 8,
1850         FluidSynthChorusDepthMs  = 9,
1851         FluidSynthChorusType     = 10,
1852         FluidSynthPolyphony      = 11,
1853         FluidSynthInterpolation  = 12,
1854         FluidSynthVoiceCount     = 13,
1855         FluidSynthParametersMax  = 14
1856     };
1857 
1858     const bool kUse16Outs;
1859 
1860     fluid_settings_t* fSettings;
1861     fluid_synth_t*    fSynth;
1862 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1863     int fSynthId;
1864 #else
1865     uint fSynthId;
1866 #endif
1867 
1868     float** fAudio16Buffers;
1869     float   fParamBuffers[FluidSynthParametersMax];
1870 
1871     static bool sFluidDefaultsStored;
1872     static float sFluidDefaults[FluidSynthParametersMax];
1873 
1874     int32_t fCurMidiProgs[MAX_MIDI_CHANNELS];
1875 
1876     const char* fLabel;
1877 
1878     CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginFluidSynth)
1879 };
1880 
1881 bool CarlaPluginFluidSynth::sFluidDefaultsStored = false;
1882 float CarlaPluginFluidSynth::sFluidDefaults[FluidSynthParametersMax] = {
1883     0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f,
1884 };
1885 
1886 CARLA_BACKEND_END_NAMESPACE
1887 
1888 #endif // HAVE_FLUIDSYNTH
1889 
1890 CARLA_BACKEND_START_NAMESPACE
1891 
1892 // -------------------------------------------------------------------------------------------------------------------
1893 
newFluidSynth(const Initializer & init,PluginType ptype,bool use16Outs)1894 CarlaPluginPtr CarlaPlugin::newFluidSynth(const Initializer& init, PluginType ptype, bool use16Outs)
1895 {
1896     carla_debug("CarlaPlugin::newFluidSynth({%p, \"%s\", \"%s\", \"%s\", " P_INT64 "}, %s)",
1897                 init.engine, init.filename, init.name, init.label, init.uniqueId, bool2str(use16Outs));
1898 
1899 #ifdef HAVE_FLUIDSYNTH
1900     if (init.engine->getProccessMode() == ENGINE_PROCESS_MODE_CONTINUOUS_RACK)
1901         use16Outs = false;
1902 
1903     if (ptype == PLUGIN_SF2 && ! fluid_is_soundfont(init.filename))
1904     {
1905         init.engine->setLastError("Requested file is not a valid SoundFont");
1906         return nullptr;
1907     }
1908 #ifndef HAVE_FLUIDSYNTH_INSTPATCH
1909     if (ptype == PLUGIN_DLS)
1910     {
1911         init.engine->setLastError("DLS file support not available");
1912         return nullptr;
1913     }
1914     if (ptype == PLUGIN_GIG)
1915     {
1916         init.engine->setLastError("GIG file support not available");
1917         return nullptr;
1918     }
1919 #endif
1920 
1921     std::shared_ptr<CarlaPluginFluidSynth> plugin(new CarlaPluginFluidSynth(init.engine, init.id,  use16Outs));
1922 
1923     if (! plugin->init(plugin, init.filename, init.name, init.label, init.options))
1924         return nullptr;
1925 
1926     return plugin;
1927 #else
1928     init.engine->setLastError("fluidsynth support not available");
1929     return nullptr;
1930 
1931     // unused
1932     (void)ptype;
1933     (void)use16Outs;
1934 #endif
1935 }
1936 
1937 // -------------------------------------------------------------------------------------------------------------------
1938 
1939 CARLA_BACKEND_END_NAMESPACE
1940