2 * Carla FluidSynth Plugin
3 * Copyright (C) 2011-2020 Filipe Coelho <falktx@falktx.com>
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.
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.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #include "CarlaPluginInternal.hpp"
19 #include "CarlaEngine.hpp"
21 #ifdef HAVE_FLUIDSYNTH
23 #include "CarlaBackendUtils.hpp"
24 #include "CarlaMathUtils.hpp"
26 #include "water/text/StringArray.h"
28 #include <fluidsynth.h>
30 #define FLUID_DEFAULT_POLYPHONY 64
33 using water::StringArray
;
35 CARLA_BACKEND_START_NAMESPACE
37 // -------------------------------------------------------------------------------------------------------------------
40 static const ExternalMidiNote kExternalMidiNoteFallback
= { -1, 0, 0 };
42 // -------------------------------------------------------------------------------------------------------------------
44 class CarlaPluginFluidSynth
: public CarlaPlugin
47 CarlaPluginFluidSynth(CarlaEngine
* const engine
, const uint id
, const bool use16Outs
)
48 : CarlaPlugin(engine
, id
),
49 kUse16Outs(use16Outs
),
53 fAudio16Buffers(nullptr),
56 carla_debug("CarlaPluginFluidSynth::CarlaPluginFluidSynth(%p, %i, %s)", engine
, id
, bool2str(use16Outs
));
58 carla_zeroFloats(fParamBuffers
, FluidSynthParametersMax
);
59 carla_fill
<int32_t>(fCurMidiProgs
, 0, MAX_MIDI_CHANNELS
);
62 fSettings
= new_fluid_settings();
63 CARLA_SAFE_ASSERT_RETURN(fSettings
!= nullptr,);
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);
75 fluid_settings_setint(fSettings
, "synth.threadsafe-api", 0);
77 fluid_settings_setint(fSettings
, "synth.verbose", 1);
81 fSynth
= new_fluid_synth(fSettings
);
82 CARLA_SAFE_ASSERT_RETURN(fSynth
!= nullptr,);
84 initializeFluidDefaultsIfNeeded();
86 #if FLUIDSYNTH_VERSION_MAJOR < 2
87 fluid_synth_set_sample_rate(fSynth
, static_cast<float>(pData
->engine
->getSampleRate()));
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
]);
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
));
106 fluid_synth_set_polyphony(fSynth
, FLUID_DEFAULT_POLYPHONY
);
107 fluid_synth_set_gain(fSynth
, 1.0f
);
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
));
113 ~CarlaPluginFluidSynth() override
115 carla_debug("CarlaPluginFluidSynth::~CarlaPluginFluidSynth()");
117 pData
->singleMutex
.lock();
118 pData
->masterMutex
.lock();
120 if (pData
->client
!= nullptr && pData
->client
->isActive())
121 pData
->client
->deactivate(true);
126 pData
->active
= false;
129 if (fSynth
!= nullptr)
131 delete_fluid_synth(fSynth
);
135 if (fSettings
!= nullptr)
137 delete_fluid_settings(fSettings
);
141 if (fLabel
!= nullptr)
150 // -------------------------------------------------------------------
151 // Information (base)
153 PluginType
getType() const noexcept override
158 PluginCategory
getCategory() const noexcept override
160 return PLUGIN_CATEGORY_SYNTH
;
163 // -------------------------------------------------------------------
164 // Information (count)
166 uint32_t getParameterScalePointCount(const uint32_t parameterId
) const noexcept override
170 case FluidSynthChorusType
:
172 case FluidSynthInterpolation
:
179 // -------------------------------------------------------------------
180 // Information (current data)
184 // -------------------------------------------------------------------
185 // Information (per-plugin data)
187 uint
getOptionsAvailable() const noexcept override
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
;
204 float getParameterValue(const uint32_t parameterId
) const noexcept override
206 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, 0.0f
);
208 return fParamBuffers
[parameterId
];
211 float getParameterScalePointValue(const uint32_t parameterId
, const uint32_t scalePointId
) const noexcept override
215 case FluidSynthChorusType
:
216 switch (scalePointId
)
219 return FLUID_CHORUS_MOD_SINE
;
221 return FLUID_CHORUS_MOD_TRIANGLE
;
223 return sFluidDefaults
[FluidSynthChorusType
];
225 case FluidSynthInterpolation
:
226 switch (scalePointId
)
229 return FLUID_INTERP_NONE
;
231 return FLUID_INTERP_LINEAR
;
233 return FLUID_INTERP_4THORDER
;
235 return FLUID_INTERP_7THORDER
;
237 return sFluidDefaults
[FluidSynthInterpolation
];
244 bool getLabel(char* const strBuf
) const noexcept override
246 if (fLabel
!= nullptr)
248 std::strncpy(strBuf
, fLabel
, STR_MAX
);
252 return CarlaPlugin::getLabel(strBuf
);
255 bool getMaker(char* const strBuf
) const noexcept override
257 std::strncpy(strBuf
, "FluidSynth SF2 engine", STR_MAX
);
261 bool getCopyright(char* const strBuf
) const noexcept override
263 std::strncpy(strBuf
, "GNU GPL v2+", STR_MAX
);
267 bool getRealName(char* const strBuf
) const noexcept override
269 return getLabel(strBuf
);
272 bool getParameterName(const uint32_t parameterId
, char* const strBuf
) const noexcept override
274 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, false);
278 case FluidSynthReverbOnOff
:
279 std::strncpy(strBuf
, "Reverb On/Off", STR_MAX
);
281 case FluidSynthReverbRoomSize
:
282 std::strncpy(strBuf
, "Reverb Room Size", STR_MAX
);
284 case FluidSynthReverbDamp
:
285 std::strncpy(strBuf
, "Reverb Damp", STR_MAX
);
287 case FluidSynthReverbLevel
:
288 std::strncpy(strBuf
, "Reverb Level", STR_MAX
);
290 case FluidSynthReverbWidth
:
291 std::strncpy(strBuf
, "Reverb Width", STR_MAX
);
293 case FluidSynthChorusOnOff
:
294 std::strncpy(strBuf
, "Chorus On/Off", STR_MAX
);
296 case FluidSynthChorusNr
:
297 std::strncpy(strBuf
, "Chorus Voice Count", STR_MAX
);
299 case FluidSynthChorusLevel
:
300 std::strncpy(strBuf
, "Chorus Level", STR_MAX
);
302 case FluidSynthChorusSpeedHz
:
303 std::strncpy(strBuf
, "Chorus Speed", STR_MAX
);
305 case FluidSynthChorusDepthMs
:
306 std::strncpy(strBuf
, "Chorus Depth", STR_MAX
);
308 case FluidSynthChorusType
:
309 std::strncpy(strBuf
, "Chorus Type", STR_MAX
);
311 case FluidSynthPolyphony
:
312 std::strncpy(strBuf
, "Polyphony", STR_MAX
);
314 case FluidSynthInterpolation
:
315 std::strncpy(strBuf
, "Interpolation", STR_MAX
);
317 case FluidSynthVoiceCount
:
318 std::strncpy(strBuf
, "Voice Count", STR_MAX
);
322 return CarlaPlugin::getParameterName(parameterId
, strBuf
);
325 bool getParameterUnit(const uint32_t parameterId
, char* const strBuf
) const noexcept override
327 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, false);
331 case FluidSynthChorusSpeedHz
:
332 std::strncpy(strBuf
, "Hz", STR_MAX
);
334 case FluidSynthChorusDepthMs
:
335 std::strncpy(strBuf
, "ms", STR_MAX
);
339 return CarlaPlugin::getParameterUnit(parameterId
, strBuf
);
342 bool getParameterScalePointLabel(const uint32_t parameterId
, const uint32_t scalePointId
, char* const strBuf
) const noexcept override
344 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, false);
345 CARLA_SAFE_ASSERT_RETURN(scalePointId
< getParameterScalePointCount(parameterId
), false);
349 case FluidSynthChorusType
:
350 switch (scalePointId
)
353 std::strncpy(strBuf
, "Sine wave", STR_MAX
);
356 std::strncpy(strBuf
, "Triangle wave", STR_MAX
);
360 case FluidSynthInterpolation
:
361 switch (scalePointId
)
364 std::strncpy(strBuf
, "None", STR_MAX
);
367 std::strncpy(strBuf
, "Straight-line", STR_MAX
);
370 std::strncpy(strBuf
, "Fourth-order", STR_MAX
);
373 std::strncpy(strBuf
, "Seventh-order", STR_MAX
);
379 return CarlaPlugin::getParameterScalePointLabel(parameterId
, scalePointId
, strBuf
);
382 // -------------------------------------------------------------------
385 void prepareForSave(bool) override
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]);
394 CarlaPlugin::setCustomData(CUSTOM_DATA_TYPE_STRING
, "midiPrograms", strBuf
, false);
397 // -------------------------------------------------------------------
398 // Set data (internal stuff)
400 void setCtrlChannel(const int8_t channel
, const bool sendOsc
, const bool sendCallback
) noexcept override
402 if (channel
>= 0 && channel
< MAX_MIDI_CHANNELS
)
403 pData
->midiprog
.current
= fCurMidiProgs
[channel
];
405 CarlaPlugin::setCtrlChannel(channel
, sendOsc
, sendCallback
);
408 // -------------------------------------------------------------------
409 // Set data (plugin-specific stuff)
411 void setParameterValue(const uint32_t parameterId
, const float value
, const bool sendGui
, const bool sendOsc
, const bool sendCallback
) noexcept override
413 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
,);
414 CARLA_SAFE_ASSERT_RETURN(sendGui
|| sendOsc
|| sendCallback
,);
419 const ScopedSingleProcessLocker
spl(this, (sendGui
|| sendOsc
|| sendCallback
));
420 fixedValue
= setParameterValueInFluidSynth(parameterId
, value
);
424 CarlaPlugin::setParameterValue(parameterId
, fixedValue
, sendGui
, sendOsc
, sendCallback
);
427 void setParameterValueRT(const uint32_t parameterId
, const float value
, const uint32_t frameOffset
, const bool sendCallbackLater
) noexcept override
429 const float fixedValue
= setParameterValueInFluidSynth(parameterId
, value
);
431 CarlaPlugin::setParameterValueRT(parameterId
, fixedValue
, frameOffset
, sendCallbackLater
);
434 float setParameterValueInFluidSynth(const uint32_t parameterId
, const float value
) noexcept
436 CARLA_SAFE_ASSERT_RETURN(parameterId
< pData
->param
.count
, value
);
438 const float fixedValue(pData
->param
.getFixedValue(parameterId
, value
));
439 fParamBuffers
[parameterId
] = fixedValue
;
443 case FluidSynthReverbOnOff
:
445 fluid_synth_set_reverb_on(fSynth
, (fixedValue
> 0.5f
) ? 1 : 0);
446 } CARLA_SAFE_EXCEPTION("fluid_synth_set_reverb_on")
449 case FluidSynthReverbRoomSize
:
450 case FluidSynthReverbDamp
:
451 case FluidSynthReverbLevel
:
452 case FluidSynthReverbWidth
:
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")
462 case FluidSynthChorusOnOff
:
464 fluid_synth_set_chorus_on(fSynth
, (value
> 0.5f
) ? 1 : 0);
465 } CARLA_SAFE_EXCEPTION("fluid_synth_set_chorus_on")
468 case FluidSynthChorusNr
:
469 case FluidSynthChorusLevel
:
470 case FluidSynthChorusSpeedHz
:
471 case FluidSynthChorusDepthMs
:
472 case FluidSynthChorusType
:
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")
483 case FluidSynthPolyphony
:
485 fluid_synth_set_polyphony(fSynth
, static_cast<int>(value
+ 0.5f
));
486 } CARLA_SAFE_EXCEPTION("fluid_synth_set_polyphony")
489 case FluidSynthInterpolation
:
490 for (int i
=0; i
< MAX_MIDI_CHANNELS
; ++i
)
493 fluid_synth_set_interp_method(fSynth
, i
, static_cast<int>(value
+ 0.5f
));
494 } CARLA_SAFE_EXCEPTION_BREAK("fluid_synth_set_interp_method")
505 void setCustomData(const char* const type
, const char* const key
, const char* const value
, const bool sendGui
) override
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
));
513 if (std::strcmp(type
, CUSTOM_DATA_TYPE_PROPERTY
) == 0)
514 return CarlaPlugin::setCustomData(type
, key
, value
, sendGui
);
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
));
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
));
522 StringArray
midiProgramList(StringArray::fromTokens(value
, ":", ""));
524 if (midiProgramList
.size() == MAX_MIDI_CHANNELS
)
527 for (String
*it
=midiProgramList
.begin(), *end
=midiProgramList
.end(); it
!= end
; ++it
)
529 const int index(it
->getIntValue());
531 if (index
>= 0 && index
< static_cast<int>(pData
->midiprog
.count
))
533 const uint32_t bank
= pData
->midiprog
.data
[index
].bank
;
534 const uint32_t program
= pData
->midiprog
.data
[index
].program
;
536 #if FLUIDSYNTH_VERSION_MAJOR >= 2
537 fluid_synth_program_select(fSynth
,
538 static_cast<int>(channel
),
540 static_cast<int>(bank
),
541 static_cast<int>(program
));
543 fluid_synth_program_select(fSynth
, channel
, fSynthId
, bank
, program
);
545 fCurMidiProgs
[channel
] = index
;
547 if (pData
->ctrlChannel
== static_cast<int32_t>(channel
))
549 pData
->midiprog
.current
= index
;
550 pData
->engine
->callback(true, true,
551 ENGINE_CALLBACK_MIDI_PROGRAM_CHANGED
,
554 0, 0, 0.0f
, nullptr);
560 CARLA_SAFE_ASSERT(channel
== MAX_MIDI_CHANNELS
);
563 CarlaPlugin::setCustomData(type
, key
, value
, sendGui
);
566 void setMidiProgram(const int32_t index
, const bool sendGui
, const bool sendOsc
, const bool sendCallback
, const bool doingInit
) noexcept override
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
,);
572 if (index
>= 0 && pData
->ctrlChannel
>= 0 && pData
->ctrlChannel
< MAX_MIDI_CHANNELS
)
574 const uint32_t bank
= pData
->midiprog
.data
[index
].bank
;
575 const uint32_t program
= pData
->midiprog
.data
[index
].program
;
577 const ScopedSingleProcessLocker
spl(this, (sendGui
|| sendOsc
|| sendCallback
));
580 #if FLUIDSYNTH_VERSION_MAJOR >= 2
581 fluid_synth_program_select(fSynth
, pData
->ctrlChannel
, fSynthId
,
582 static_cast<int>(bank
), static_cast<int>(program
));
584 fluid_synth_program_select(fSynth
, pData
->ctrlChannel
, fSynthId
, bank
, program
);
586 } CARLA_SAFE_EXCEPTION("fluid_synth_program_select")
588 fCurMidiProgs
[pData
->ctrlChannel
] = index
;
591 CarlaPlugin::setMidiProgram(index
, sendGui
, sendOsc
, sendCallback
, doingInit
);
594 // FIXME: this is never used
595 void setMidiProgramRT(const uint32_t uindex
, const bool sendCallbackLater
) noexcept override
597 CARLA_SAFE_ASSERT_RETURN(fSynth
!= nullptr,);
598 CARLA_SAFE_ASSERT_RETURN(uindex
< pData
->midiprog
.count
,);
600 if (pData
->ctrlChannel
>= 0 && pData
->ctrlChannel
< MAX_MIDI_CHANNELS
)
602 const uint32_t bank
= pData
->midiprog
.data
[uindex
].bank
;
603 const uint32_t program
= pData
->midiprog
.data
[uindex
].program
;
606 #if FLUIDSYNTH_VERSION_MAJOR >= 2
607 fluid_synth_program_select(fSynth
, pData
->ctrlChannel
, fSynthId
,
608 static_cast<int>(bank
), static_cast<int>(program
));
610 fluid_synth_program_select(fSynth
, pData
->ctrlChannel
, fSynthId
, bank
, program
);
612 } CARLA_SAFE_EXCEPTION("fluid_synth_program_select")
614 fCurMidiProgs
[pData
->ctrlChannel
] = static_cast<int32_t>(uindex
);
617 CarlaPlugin::setMidiProgramRT(uindex
, sendCallbackLater
);
620 // -------------------------------------------------------------------
625 // -------------------------------------------------------------------
628 void reload() override
630 CARLA_SAFE_ASSERT_RETURN(pData
->engine
!= nullptr,);
631 CARLA_SAFE_ASSERT_RETURN(fSynth
!= nullptr,);
632 carla_debug("CarlaPluginFluidSynth::reload() - start");
634 const EngineProcessMode
processMode(pData
->engine
->getProccessMode());
636 // Safely disable plugin for reload
637 const ScopedDisabler
sd(this);
644 uint32_t aOuts
, params
;
645 aOuts
= kUse16Outs
? 32 : 2;
646 params
= FluidSynthParametersMax
;
648 pData
->audioOut
.createNew(aOuts
);
649 pData
->param
.createNew(params
, false);
651 const uint
portNameSize(pData
->engine
->getMaxPortNameSize());
652 CarlaString portName
;
654 // ---------------------------------------
659 for (uint32_t i
=0; i
< 32; ++i
)
663 if (processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
665 portName
= pData
->name
;
674 portName
+= CarlaString((i
+2)/2);
681 portName
.truncate(portNameSize
);
683 pData
->audioOut
.ports
[i
].port
= (CarlaEngineAudioPort
*)pData
->client
->addPort(kEnginePortTypeAudio
, portName
, false, i
);
684 pData
->audioOut
.ports
[i
].rindex
= i
;
687 fAudio16Buffers
= new float*[aOuts
];
689 for (uint32_t i
=0; i
< aOuts
; ++i
)
690 fAudio16Buffers
[i
] = nullptr;
697 if (processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
699 portName
= pData
->name
;
703 portName
+= "out-left";
704 portName
.truncate(portNameSize
);
706 pData
->audioOut
.ports
[0].port
= (CarlaEngineAudioPort
*)pData
->client
->addPort(kEnginePortTypeAudio
, portName
, false, 0);
707 pData
->audioOut
.ports
[0].rindex
= 0;
712 if (processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
714 portName
= pData
->name
;
718 portName
+= "out-right";
719 portName
.truncate(portNameSize
);
721 pData
->audioOut
.ports
[1].port
= (CarlaEngineAudioPort
*)pData
->client
->addPort(kEnginePortTypeAudio
, portName
, false, 1);
722 pData
->audioOut
.ports
[1].rindex
= 1;
725 // ---------------------------------------
731 if (processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
733 portName
= pData
->name
;
737 portName
+= "events-in";
738 portName
.truncate(portNameSize
);
740 pData
->event
.portIn
= (CarlaEngineEventPort
*)pData
->client
->addPort(kEnginePortTypeEvent
, portName
, true, 0);
743 // ---------------------------------------
749 if (processMode
== ENGINE_PROCESS_MODE_SINGLE_CLIENT
)
751 portName
= pData
->name
;
755 portName
+= "events-out";
756 portName
.truncate(portNameSize
);
758 pData
->event
.portOut
= (CarlaEngineEventPort
*)pData
->client
->addPort(kEnginePortTypeEvent
, portName
, false, 0);
761 // ---------------------------------------
767 // ----------------------
768 j
= FluidSynthReverbOnOff
;
769 pData
->param
.data
[j
].type
= PARAMETER_INPUT
;
770 pData
->param
.data
[j
].hints
= PARAMETER_IS_ENABLED
/*| PARAMETER_IS_AUTOMATABLE*/ | 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
;
780 // ----------------------
781 j
= FluidSynthReverbRoomSize
;
782 pData
->param
.data
[j
].type
= PARAMETER_INPUT
;
783 pData
->param
.data
[j
].hints
= PARAMETER_IS_ENABLED
/*| PARAMETER_IS_AUTOMATABLE*/;
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
;
793 // ----------------------
794 j
= FluidSynthReverbDamp
;
795 pData
->param
.data
[j
].type
= PARAMETER_INPUT
;
796 pData
->param
.data
[j
].hints
= PARAMETER_IS_ENABLED
/*| PARAMETER_IS_AUTOMATABLE*/;
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
;
806 // ----------------------
807 j
= FluidSynthReverbLevel
;
808 pData
->param
.data
[j
].type
= PARAMETER_INPUT
;
809 pData
->param
.data
[j
].hints
= PARAMETER_IS_ENABLED
/*| PARAMETER_IS_AUTOMATABLE*/;
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
;
820 // ----------------------
821 j
= FluidSynthReverbWidth
;
822 pData
->param
.data
[j
].type
= PARAMETER_INPUT
;
823 pData
->param
.data
[j
].hints
= PARAMETER_IS_ENABLED
/*| PARAMETER_IS_AUTOMATABLE*/;
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
;
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
;
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
;
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
;
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
;
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
;
895 pData
->param
.ranges
[j
].max
= float(2048.0 * 1000.0 / pData
->engine
->getSampleRate()); // FIXME?
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
;
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
;
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
;
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
;
941 // ----------------------
942 j
= FluidSynthVoiceCount
;
943 pData
->param
.data
[j
].type
= PARAMETER_OUTPUT
;
944 pData
->param
.data
[j
].hints
= PARAMETER_IS_ENABLED
| PARAMETER_IS_AUTOMATABLE
| 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
;
954 for (j
=0; j
<FluidSynthParametersMax
; ++j
)
955 fParamBuffers
[j
] = pData
->param
.ranges
[j
].def
;
958 // ---------------------------------------
962 pData
->hints
|= PLUGIN_IS_SYNTH
;
963 pData
->hints
|= PLUGIN_CAN_VOLUME
;
964 pData
->hints
|= PLUGIN_USES_MULTI_PROGS
;
967 pData
->hints
|= PLUGIN_CAN_BALANCE
;
969 // extra plugin hints
970 pData
->extraHints
= 0x0;
971 pData
->extraHints
|= PLUGIN_EXTRA_HINT_HAS_MIDI_IN
;
973 bufferSizeChanged(pData
->engine
->getBufferSize());
974 reloadPrograms(true);
979 carla_debug("CarlaPluginFluidSynth::reload() - end");
982 void reloadPrograms(const bool doInit
) override
984 carla_debug("CarlaPluginFluidSynth::reloadPrograms(%s)", bool2str(doInit
));
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;
991 // Delete old programs
992 pData
->midiprog
.clear();
994 // Query new programs
997 if (fluid_sfont_t
* const f_sfont
= fluid_synth_get_sfont_by_id(fSynth
, fSynthId
))
999 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1000 fluid_preset_t
* f_preset
;
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
);)
1007 // sound kits must always have at least 1 midi-program
1008 CARLA_SAFE_ASSERT_RETURN(count
> 0,);
1010 pData
->midiprog
.createNew(count
);
1015 fluid_sfont_iteration_start(f_sfont
);
1017 for (; (f_preset
= fluid_sfont_iteration_next(f_sfont
));)
1019 CARLA_SAFE_ASSERT_BREAK(i
< count
);
1021 tmp
= fluid_preset_get_banknum(f_preset
);
1022 pData
->midiprog
.data
[i
].bank
= (tmp
>= 0) ? static_cast<uint32_t>(tmp
) : 0;
1024 tmp
= fluid_preset_get_num(f_preset
);
1025 pData
->midiprog
.data
[i
].program
= (tmp
>= 0) ? static_cast<uint32_t>(tmp
) : 0;
1027 pData
->midiprog
.data
[i
].name
= carla_strdup(fluid_preset_get_name(f_preset
));
1029 fluid_preset_t f_preset
;
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
);)
1036 // sound kits must always have at least 1 midi-program
1037 CARLA_SAFE_ASSERT_RETURN(count
> 0,);
1039 pData
->midiprog
.createNew(count
);
1044 f_sfont
->iteration_start(f_sfont
);
1046 for (; f_sfont
->iteration_next(f_sfont
, &f_preset
);)
1048 CARLA_SAFE_ASSERT_BREAK(i
< count
);
1050 tmp
= f_preset
.get_banknum(&f_preset
);
1051 pData
->midiprog
.data
[i
].bank
= (tmp
>= 0) ? static_cast<uint32_t>(tmp
) : 0;
1053 tmp
= f_preset
.get_num(&f_preset
);
1054 pData
->midiprog
.data
[i
].program
= (tmp
>= 0) ? static_cast<uint32_t>(tmp
) : 0;
1056 pData
->midiprog
.data
[i
].name
= carla_strdup(f_preset
.get_name(&f_preset
));
1059 if (pData
->midiprog
.data
[i
].bank
== 128 && ! hasDrums
)
1063 drumProg
= pData
->midiprog
.data
[i
].program
;
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__
);
1078 fluid_synth_program_reset(fSynth
);
1080 // select first program, or 128 for ch10
1081 for (int i
=0; i
< MAX_MIDI_CHANNELS
&& i
!= 9; ++i
)
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
));
1089 fluid_synth_program_select(fSynth
, i
, fSynthId
,
1090 pData
->midiprog
.data
[0].bank
, pData
->midiprog
.data
[0].program
);
1092 fCurMidiProgs
[i
] = 0;
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
));
1101 fluid_synth_program_select(fSynth
, 9, fSynthId
, 128, drumProg
);
1103 fCurMidiProgs
[9] = static_cast<int32_t>(drumIndex
);
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
));
1113 fluid_synth_program_select(fSynth
, 9, fSynthId
,
1114 pData
->midiprog
.data
[0].bank
, pData
->midiprog
.data
[0].program
);
1116 fCurMidiProgs
[9] = 0;
1119 pData
->midiprog
.current
= 0;
1123 pData
->engine
->callback(true, true, ENGINE_CALLBACK_RELOAD_PROGRAMS
, pData
->id
, 0, 0, 0, 0.0f
, nullptr);
1127 // -------------------------------------------------------------------
1128 // Plugin processing
1130 void process(const float* const* const, float** const audioOut
,
1131 const float* const*, float**, const uint32_t frames
) override
1133 // --------------------------------------------------------------------------------------------------------
1136 if (! pData
->active
)
1138 // disable any output sound
1139 for (uint32_t i
=0; i
< pData
->audioOut
.count
; ++i
)
1140 carla_zeroFloats(audioOut
[i
], frames
);
1144 // --------------------------------------------------------------------------------------------------------
1145 // Check if needs reset
1147 if (pData
->needsReset
)
1149 if (pData
->options
& PLUGIN_OPTION_SEND_ALL_SOUND_OFF
)
1151 for (int i
=0; i
< MAX_MIDI_CHANNELS
; ++i
)
1153 fluid_synth_all_notes_off(fSynth
, i
);
1154 fluid_synth_all_sounds_off(fSynth
, i
);
1157 else if (pData
->ctrlChannel
>= 0 && pData
->ctrlChannel
< MAX_MIDI_CHANNELS
)
1159 for (int i
=0; i
< MAX_MIDI_NOTE
; ++i
)
1160 fluid_synth_noteoff(fSynth
, pData
->ctrlChannel
, i
);
1163 pData
->needsReset
= false;
1166 // --------------------------------------------------------------------------------------------------------
1167 // Event Input and Processing
1170 // ----------------------------------------------------------------------------------------------------
1171 // MIDI Input (External)
1173 if (pData
->extNotes
.mutex
.tryLock())
1175 for (RtLinkedList
<ExternalMidiNote
>::Itenerator it
= pData
->extNotes
.data
.begin2(); it
.valid(); it
.next())
1177 const ExternalMidiNote
& note(it
.getValue(kExternalMidiNoteFallback
));
1178 CARLA_SAFE_ASSERT_CONTINUE(note
.channel
>= 0 && note
.channel
< MAX_MIDI_CHANNELS
);
1181 fluid_synth_noteon(fSynth
, note
.channel
, note
.note
, note
.velo
);
1183 fluid_synth_noteoff(fSynth
,note
.channel
, note
.note
);
1186 pData
->extNotes
.data
.clear();
1187 pData
->extNotes
.mutex
.unlock();
1189 } // End of MIDI Input (External)
1191 // ----------------------------------------------------------------------------------------------------
1192 // Event Input (System)
1194 #ifndef BUILD_BRIDGE
1195 bool allNotesOffSent
= false;
1197 uint32_t timeOffset
= 0;
1199 uint32_t nextBankIds
[MAX_MIDI_CHANNELS
] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0 };
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
;
1204 for (uint32_t i
=0, numEvents
=pData
->event
.portIn
->getEventCount(); i
< numEvents
; ++i
)
1206 const EngineEvent
& event(pData
->event
.portIn
->getEvent(i
));
1208 uint32_t eventTime
= event
.time
;
1209 CARLA_SAFE_ASSERT_UINT2_CONTINUE(eventTime
< frames
, eventTime
, frames
);
1211 if (eventTime
< timeOffset
)
1213 carla_stderr2("Timing error, eventTime:%u < timeOffset:%u for '%s'",
1214 eventTime
, timeOffset
, pData
->name
);
1215 eventTime
= timeOffset
;
1217 else if (eventTime
> timeOffset
)
1219 if (processSingle(audioOut
, eventTime
- timeOffset
, timeOffset
))
1221 timeOffset
= eventTime
;
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
;
1231 case kEngineEventTypeNull
:
1234 case kEngineEventTypeControl
:
1236 const EngineControlEvent
& ctrlEvent
= event
.ctrl
;
1238 switch (ctrlEvent
.type
)
1240 case kEngineControlEventTypeNull
:
1243 case kEngineControlEventTypeParameter
:
1247 #ifndef BUILD_BRIDGE_ALTERNATIVE_ARCH
1248 // Control backend stuff
1249 if (event
.channel
== pData
->ctrlChannel
)
1251 if (MIDI_IS_CONTROL_BREATH_CONTROLLER(ctrlEvent
.param
) && (pData
->hints
& PLUGIN_CAN_DRYWET
) != 0)
1253 value
= ctrlEvent
.normalizedValue
;
1254 setDryWetRT(value
, true);
1257 if (MIDI_IS_CONTROL_CHANNEL_VOLUME(ctrlEvent
.param
) && (pData
->hints
& PLUGIN_CAN_VOLUME
) != 0)
1259 value
= ctrlEvent
.normalizedValue
*127.0f
/100.0f
;
1260 setVolumeRT(value
, true);
1263 if (MIDI_IS_CONTROL_BALANCE(ctrlEvent
.param
) && (pData
->hints
& PLUGIN_CAN_BALANCE
) != 0)
1266 value
= ctrlEvent
.normalizedValue
/0.5f
- 1.0f
;
1271 right
= (value
*2.0f
)+1.0f
;
1273 else if (value
> 0.0f
)
1275 left
= (value
*2.0f
)-1.0f
;
1284 setBalanceLeftRT(left
, true);
1285 setBalanceRightRT(right
, true);
1289 // Control plugin parameters
1290 for (uint32_t k
=0; k
< pData
->param
.count
; ++k
)
1292 if (pData
->param
.data
[k
].midiChannel
!= event
.channel
)
1294 if (pData
->param
.data
[k
].mappedControlIndex
!= ctrlEvent
.param
)
1296 if (pData
->param
.data
[k
].hints
!= PARAMETER_INPUT
)
1298 if ((pData
->param
.data
[k
].hints
& PARAMETER_IS_AUTOMATABLE
) == 0)
1301 value
= pData
->param
.getFinalUnnormalizedValue(k
, ctrlEvent
.normalizedValue
);
1302 setParameterValueRT(k
, value
, event
.time
, true);
1305 if ((pData
->options
& PLUGIN_OPTION_SEND_CONTROL_CHANGES
) != 0 && ctrlEvent
.param
< MAX_MIDI_VALUE
)
1307 fluid_synth_cc(fSynth
, event
.channel
, ctrlEvent
.param
, int(ctrlEvent
.normalizedValue
*127.0f
+ 0.5f
));
1312 case kEngineControlEventTypeMidiBank
:
1313 if (event
.channel
< MAX_MIDI_CHANNELS
&& (pData
->options
& PLUGIN_OPTION_MAP_PROGRAM_CHANGES
) != 0)
1314 nextBankIds
[event
.channel
] = ctrlEvent
.param
;
1317 case kEngineControlEventTypeMidiProgram
:
1318 if (event
.channel
< MAX_MIDI_CHANNELS
&& (pData
->options
& PLUGIN_OPTION_MAP_PROGRAM_CHANGES
) != 0)
1320 const uint32_t bankId(nextBankIds
[event
.channel
]);
1321 const uint32_t progId(ctrlEvent
.param
);
1323 // TODO int32_t midiprog.find(bank, prog)
1324 for (uint32_t k
=0; k
< pData
->midiprog
.count
; ++k
)
1326 if (pData
->midiprog
.data
[k
].bank
== bankId
&& pData
->midiprog
.data
[k
].program
== progId
)
1328 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1329 fluid_synth_program_select(fSynth
, event
.channel
, fSynthId
,
1330 static_cast<int>(bankId
), static_cast<int>(progId
));
1332 fluid_synth_program_select(fSynth
, event
.channel
, fSynthId
, bankId
, progId
);
1334 fCurMidiProgs
[event
.channel
] = static_cast<int32_t>(k
);
1336 if (event
.channel
== pData
->ctrlChannel
)
1338 pData
->postponeMidiProgramChangeRtEvent(true, k
);
1347 case kEngineControlEventTypeAllSoundOff
:
1348 if (pData
->options
& PLUGIN_OPTION_SEND_ALL_SOUND_OFF
)
1349 fluid_synth_all_sounds_off(fSynth
, event
.channel
);
1352 case kEngineControlEventTypeAllNotesOff
:
1353 if (pData
->options
& PLUGIN_OPTION_SEND_ALL_SOUND_OFF
)
1355 #ifndef BUILD_BRIDGE
1356 if (event
.channel
== pData
->ctrlChannel
&& ! allNotesOffSent
)
1358 allNotesOffSent
= true;
1359 postponeRtAllNotesOff();
1363 fluid_synth_all_notes_off(fSynth
, event
.channel
);
1371 case kEngineEventTypeMidi
: {
1372 const EngineMidiEvent
& midiEvent(event
.midi
);
1374 if (midiEvent
.size
> EngineMidiEvent::kDataSize
)
1377 uint8_t status
= uint8_t(MIDI_GET_STATUS_FROM_DATA(midiEvent
.data
));
1380 if (status
== MIDI_STATUS_NOTE_ON
&& midiEvent
.data
[2] == 0)
1381 status
= MIDI_STATUS_NOTE_OFF
;
1385 case MIDI_STATUS_NOTE_OFF
:
1386 if ((pData
->options
& PLUGIN_OPTION_SKIP_SENDING_NOTES
) == 0x0)
1388 const uint8_t note
= midiEvent
.data
[1];
1390 fluid_synth_noteoff(fSynth
, event
.channel
, note
);
1392 pData
->postponeNoteOffRtEvent(true, event
.channel
, note
);
1396 case MIDI_STATUS_NOTE_ON
:
1397 if ((pData
->options
& PLUGIN_OPTION_SKIP_SENDING_NOTES
) == 0x0)
1399 const uint8_t note
= midiEvent
.data
[1];
1400 const uint8_t velo
= midiEvent
.data
[2];
1402 fluid_synth_noteon(fSynth
, event
.channel
, note
, velo
);
1404 pData
->postponeNoteOnRtEvent(true, event
.channel
, note
, velo
);
1408 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1409 case MIDI_STATUS_POLYPHONIC_AFTERTOUCH
:
1410 if (pData
->options
& PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH
)
1412 const uint8_t note
= midiEvent
.data
[1];
1413 const uint8_t pressure
= midiEvent
.data
[2];
1415 fluid_synth_key_pressure(fSynth
, event
.channel
, note
, pressure
);
1420 case MIDI_STATUS_CONTROL_CHANGE
:
1421 if (pData
->options
& PLUGIN_OPTION_SEND_CONTROL_CHANGES
)
1423 const uint8_t control
= midiEvent
.data
[1];
1424 const uint8_t value
= midiEvent
.data
[2];
1426 fluid_synth_cc(fSynth
, event
.channel
, control
, value
);
1430 case MIDI_STATUS_CHANNEL_PRESSURE
:
1431 if (pData
->options
& PLUGIN_OPTION_SEND_CHANNEL_PRESSURE
)
1433 const uint8_t pressure
= midiEvent
.data
[1];
1435 fluid_synth_channel_pressure(fSynth
, event
.channel
, pressure
);;
1439 case MIDI_STATUS_PITCH_WHEEL_CONTROL
:
1440 if (pData
->options
& PLUGIN_OPTION_SEND_PITCHBEND
)
1442 const uint8_t lsb
= midiEvent
.data
[1];
1443 const uint8_t msb
= midiEvent
.data
[2];
1444 const int value
= ((msb
<< 7) | lsb
);
1446 fluid_synth_pitch_bend(fSynth
, event
.channel
, value
);
1453 } // switch (status)
1455 } // switch (event.type)
1458 pData
->postRtEvents
.trySplice();
1460 if (frames
> timeOffset
)
1461 processSingle(audioOut
, frames
- timeOffset
, timeOffset
);
1463 } // End of Event Input and Processing
1465 #ifndef BUILD_BRIDGE
1466 // --------------------------------------------------------------------------------------------------------
1470 uint32_t k
= FluidSynthVoiceCount
;
1471 fParamBuffers
[k
] = float(fluid_synth_get_active_voice_count(fSynth
));
1472 pData
->param
.ranges
[k
].fixValue(fParamBuffers
[k
]);
1474 if (pData
->param
.data
[k
].mappedControlIndex
> 0)
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
),
1485 } // End of Control Output
1489 bool processSingle(float** const outBuffer
, const uint32_t frames
, const uint32_t timeOffset
)
1491 CARLA_SAFE_ASSERT_RETURN(outBuffer
!= nullptr, false);
1492 CARLA_SAFE_ASSERT_RETURN(frames
> 0, false);
1494 // --------------------------------------------------------------------------------------------------------
1495 // Try lock, silence otherwise
1497 #ifndef STOAT_TEST_BUILD
1498 if (pData
->engine
->isOffline())
1500 pData
->singleMutex
.lock();
1504 if (! pData
->singleMutex
.tryLock())
1506 for (uint32_t i
=0; i
< pData
->audioOut
.count
; ++i
)
1508 for (uint32_t k
=0; k
< frames
; ++k
)
1509 outBuffer
[i
][k
+timeOffset
] = 0.0f
;
1515 // --------------------------------------------------------------------------------------------------------
1516 // Fill plugin buffers and Run plugin
1520 for (uint32_t i
=0; i
< pData
->audioOut
.count
; ++i
)
1521 carla_zeroFloats(fAudio16Buffers
[i
], frames
);
1523 // FIXME use '32' or '16' instead of outs
1524 fluid_synth_process(fSynth
, static_cast<int>(frames
),
1526 static_cast<int>(pData
->audioOut
.count
), fAudio16Buffers
);
1530 fluid_synth_write_float(fSynth
, static_cast<int>(frames
),
1531 outBuffer
[0] + timeOffset
, 0, 1,
1532 outBuffer
[1] + timeOffset
, 0, 1);
1535 #ifndef BUILD_BRIDGE
1536 // --------------------------------------------------------------------------------------------------------
1537 // Post-processing (volume and balance)
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
));
1544 float* const oldBufLeft
= pData
->postProc
.extraBuffer
;
1546 for (uint32_t i
=0; i
< pData
->audioOut
.count
; ++i
)
1552 carla_copyFloats(oldBufLeft
, outBuffer
[i
]+timeOffset
, frames
);
1554 float balRangeL
= (pData
->postProc
.balanceLeft
+ 1.0f
)/2.0f
;
1555 float balRangeR
= (pData
->postProc
.balanceRight
+ 1.0f
)/2.0f
;
1557 for (uint32_t k
=0; k
< frames
; ++k
)
1562 outBuffer
[i
][k
+timeOffset
] = oldBufLeft
[k
] * (1.0f
- balRangeL
);
1563 outBuffer
[i
][k
+timeOffset
] += outBuffer
[i
+1][k
+timeOffset
] * (1.0f
- balRangeR
);
1568 outBuffer
[i
][k
+timeOffset
] = outBuffer
[i
][k
+timeOffset
] * balRangeR
;
1569 outBuffer
[i
][k
+timeOffset
] += oldBufLeft
[k
] * balRangeL
;
1577 for (uint32_t k
=0; k
< frames
; ++k
)
1578 outBuffer
[i
][k
+timeOffset
] = fAudio16Buffers
[i
][k
] * pData
->postProc
.volume
;
1582 for (uint32_t k
=0; k
< frames
; ++k
)
1583 outBuffer
[i
][k
+timeOffset
] *= pData
->postProc
.volume
;
1587 } // End of Post-processing
1591 for (uint32_t i
=0; i
< pData
->audioOut
.count
; ++i
)
1593 for (uint32_t k
=0; k
< frames
; ++k
)
1594 outBuffer
[i
][k
+timeOffset
] = fAudio16Buffers
[i
][k
];
1599 // --------------------------------------------------------------------------------------------------------
1601 pData
->singleMutex
.unlock();
1605 void bufferSizeChanged(const uint32_t newBufferSize
) override
1609 for (uint32_t i
=0; i
< pData
->audioOut
.count
; ++i
)
1611 if (fAudio16Buffers
[i
] != nullptr)
1612 delete[] fAudio16Buffers
[i
];
1613 fAudio16Buffers
[i
] = new float[newBufferSize
];
1617 CarlaPlugin::bufferSizeChanged(newBufferSize
);
1620 void sampleRateChanged(const double newSampleRate
) override
1622 CARLA_SAFE_ASSERT_RETURN(fSettings
!= nullptr,);
1623 fluid_settings_setnum(fSettings
, "synth.sample-rate", newSampleRate
);
1625 #if FLUIDSYNTH_VERSION_MAJOR < 2
1626 CARLA_SAFE_ASSERT_RETURN(fSynth
!= nullptr,);
1627 fluid_synth_set_sample_rate(fSynth
, static_cast<float>(newSampleRate
));
1631 // -------------------------------------------------------------------
1634 void clearBuffers() noexcept override
1636 carla_debug("CarlaPluginFluidSynth::clearBuffers() - start");
1638 if (fAudio16Buffers
!= nullptr)
1640 for (uint32_t i
=0; i
< pData
->audioOut
.count
; ++i
)
1642 if (fAudio16Buffers
[i
] != nullptr)
1644 delete[] fAudio16Buffers
[i
];
1645 fAudio16Buffers
[i
] = nullptr;
1649 delete[] fAudio16Buffers
;
1650 fAudio16Buffers
= nullptr;
1653 CarlaPlugin::clearBuffers();
1655 carla_debug("CarlaPluginFluidSynth::clearBuffers() - end");
1658 // -------------------------------------------------------------------
1660 const void* getExtraStuff() const noexcept override
1662 static const char xtrue
[] = "true";
1663 static const char xfalse
[] = "false";
1664 return kUse16Outs
? xtrue
: xfalse
;
1667 // -------------------------------------------------------------------
1669 bool init(const CarlaPluginPtr plugin
,
1670 const char* const filename
, const char* const name
, const char* const label
, const uint options
)
1672 CARLA_SAFE_ASSERT_RETURN(pData
->engine
!= nullptr, false);
1674 // ---------------------------------------------------------------
1677 if (pData
->client
!= nullptr)
1679 pData
->engine
->setLastError("Plugin client is already registered");
1683 if (fSynth
== nullptr)
1685 pData
->engine
->setLastError("null synth");
1689 if (filename
== nullptr || filename
[0] == '\0')
1691 pData
->engine
->setLastError("null filename");
1695 if (label
== nullptr || label
[0] == '\0')
1697 pData
->engine
->setLastError("null label");
1701 // ---------------------------------------------------------------
1704 const int synthId
= fluid_synth_sfload(fSynth
, filename
, 0);
1708 pData
->engine
->setLastError("Failed to load SoundFont file");
1712 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1715 fSynthId
= static_cast<uint
>(synthId
);
1719 // ---------------------------------------------------------------
1722 CarlaString
label2(label
);
1724 if (kUse16Outs
&& ! label2
.endsWith(" (16 outs)"))
1725 label2
+= " (16 outs)";
1727 fLabel
= label2
.dup();
1728 pData
->filename
= carla_strdup(filename
);
1730 if (name
!= nullptr && name
[0] != '\0')
1731 pData
->name
= pData
->engine
->getUniquePluginName(name
);
1733 pData
->name
= pData
->engine
->getUniquePluginName(label
);
1735 // ---------------------------------------------------------------
1738 pData
->client
= pData
->engine
->addClient(plugin
);
1740 if (pData
->client
== nullptr || ! pData
->client
->isOk())
1742 pData
->engine
->setLastError("Failed to register plugin client");
1746 // ---------------------------------------------------------------
1749 pData
->options
= 0x0;
1751 if (isPluginOptionEnabled(options
, PLUGIN_OPTION_SEND_CONTROL_CHANGES
))
1752 pData
->options
|= PLUGIN_OPTION_SEND_CONTROL_CHANGES
;
1753 if (isPluginOptionEnabled(options
, PLUGIN_OPTION_SEND_CHANNEL_PRESSURE
))
1754 pData
->options
|= PLUGIN_OPTION_SEND_CHANNEL_PRESSURE
;
1755 if (isPluginOptionEnabled(options
, PLUGIN_OPTION_SEND_PITCHBEND
))
1756 pData
->options
|= PLUGIN_OPTION_SEND_PITCHBEND
;
1757 if (isPluginOptionEnabled(options
, PLUGIN_OPTION_SEND_ALL_SOUND_OFF
))
1758 pData
->options
|= PLUGIN_OPTION_SEND_ALL_SOUND_OFF
;
1759 if (isPluginOptionEnabled(options
, PLUGIN_OPTION_MAP_PROGRAM_CHANGES
))
1760 pData
->options
|= PLUGIN_OPTION_MAP_PROGRAM_CHANGES
;
1761 if (isPluginOptionInverseEnabled(options
, PLUGIN_OPTION_SKIP_SENDING_NOTES
))
1762 pData
->options
|= PLUGIN_OPTION_SKIP_SENDING_NOTES
;
1763 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1764 if (isPluginOptionEnabled(options
, PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH
))
1765 pData
->options
|= PLUGIN_OPTION_SEND_NOTE_AFTERTOUCH
;
1772 void initializeFluidDefaultsIfNeeded()
1774 if (sFluidDefaultsStored
)
1777 sFluidDefaultsStored
= true;
1780 sFluidDefaults
[FluidSynthReverbOnOff
] = 1.0f
;
1781 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1785 fluid_settings_getnum_default(fSettings
, "synth.reverb.room-size", &reverbVal
);
1786 sFluidDefaults
[FluidSynthReverbRoomSize
] = static_cast<float>(reverbVal
);
1789 fluid_settings_getnum_default(fSettings
, "synth.reverb.damp", &reverbVal
);
1790 sFluidDefaults
[FluidSynthReverbDamp
] = static_cast<float>(reverbVal
);
1793 fluid_settings_getnum_default(fSettings
, "synth.reverb.level", &reverbVal
);
1794 sFluidDefaults
[FluidSynthReverbLevel
] = static_cast<float>(reverbVal
);
1797 fluid_settings_getnum_default(fSettings
, "synth.reverb.width", &reverbVal
);
1798 sFluidDefaults
[FluidSynthReverbWidth
] = static_cast<float>(reverbVal
);
1800 sFluidDefaults
[FluidSynthReverbRoomSize
] = FLUID_REVERB_DEFAULT_ROOMSIZE
;
1801 sFluidDefaults
[FluidSynthReverbDamp
] = FLUID_REVERB_DEFAULT_DAMP
;
1802 sFluidDefaults
[FluidSynthReverbLevel
] = FLUID_REVERB_DEFAULT_LEVEL
;
1803 sFluidDefaults
[FluidSynthReverbWidth
] = FLUID_REVERB_DEFAULT_WIDTH
;
1807 sFluidDefaults
[FluidSynthChorusOnOff
] = 1.0f
;
1808 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1812 fluid_settings_getnum_default(fSettings
, "synth.chorus.nr", &chorusVal
);
1813 sFluidDefaults
[FluidSynthChorusNr
] = static_cast<float>(chorusVal
);
1816 fluid_settings_getnum_default(fSettings
, "synth.chorus.level", &chorusVal
);
1817 sFluidDefaults
[FluidSynthChorusLevel
] = static_cast<float>(chorusVal
);
1820 fluid_settings_getnum_default(fSettings
, "synth.chorus.speed", &chorusVal
);
1821 sFluidDefaults
[FluidSynthChorusSpeedHz
] = static_cast<float>(chorusVal
);
1824 fluid_settings_getnum_default(fSettings
, "synth.chorus.depth", &chorusVal
);
1825 sFluidDefaults
[FluidSynthChorusDepthMs
] = static_cast<float>(chorusVal
);
1827 // There is no settings for chorus default type
1828 sFluidDefaults
[FluidSynthChorusType
] = static_cast<float>(fluid_synth_get_chorus_type(fSynth
));
1830 sFluidDefaults
[FluidSynthChorusNr
] = FLUID_CHORUS_DEFAULT_N
;
1831 sFluidDefaults
[FluidSynthChorusLevel
] = FLUID_CHORUS_DEFAULT_LEVEL
;
1832 sFluidDefaults
[FluidSynthChorusSpeedHz
] = FLUID_CHORUS_DEFAULT_SPEED
;
1833 sFluidDefaults
[FluidSynthChorusDepthMs
] = FLUID_CHORUS_DEFAULT_DEPTH
;
1834 sFluidDefaults
[FluidSynthChorusType
] = FLUID_CHORUS_DEFAULT_TYPE
;
1838 sFluidDefaults
[FluidSynthInterpolation
] = FLUID_INTERP_DEFAULT
;
1839 sFluidDefaults
[FluidSynthPolyphony
] = FLUID_DEFAULT_POLYPHONY
;
1842 enum FluidSynthParameters
{
1843 FluidSynthReverbOnOff
= 0,
1844 FluidSynthReverbRoomSize
= 1,
1845 FluidSynthReverbDamp
= 2,
1846 FluidSynthReverbLevel
= 3,
1847 FluidSynthReverbWidth
= 4,
1848 FluidSynthChorusOnOff
= 5,
1849 FluidSynthChorusNr
= 6,
1850 FluidSynthChorusLevel
= 7,
1851 FluidSynthChorusSpeedHz
= 8,
1852 FluidSynthChorusDepthMs
= 9,
1853 FluidSynthChorusType
= 10,
1854 FluidSynthPolyphony
= 11,
1855 FluidSynthInterpolation
= 12,
1856 FluidSynthVoiceCount
= 13,
1857 FluidSynthParametersMax
= 14
1860 const bool kUse16Outs
;
1862 fluid_settings_t
* fSettings
;
1863 fluid_synth_t
* fSynth
;
1864 #if FLUIDSYNTH_VERSION_MAJOR >= 2
1870 float** fAudio16Buffers
;
1871 float fParamBuffers
[FluidSynthParametersMax
];
1873 static bool sFluidDefaultsStored
;
1874 static float sFluidDefaults
[FluidSynthParametersMax
];
1876 int32_t fCurMidiProgs
[MAX_MIDI_CHANNELS
];
1880 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaPluginFluidSynth
)
1883 bool CarlaPluginFluidSynth::sFluidDefaultsStored
= false;
1884 float CarlaPluginFluidSynth::sFluidDefaults
[FluidSynthParametersMax
] = {
1885 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
,
1888 CARLA_BACKEND_END_NAMESPACE
1890 #endif // HAVE_FLUIDSYNTH
1892 CARLA_BACKEND_START_NAMESPACE
1894 // -------------------------------------------------------------------------------------------------------------------
1896 CarlaPluginPtr
CarlaPlugin::newFluidSynth(const Initializer
& init
, PluginType ptype
, bool use16Outs
)
1898 carla_debug("CarlaPlugin::newFluidSynth({%p, \"%s\", \"%s\", \"%s\", " P_INT64
"}, %s)",
1899 init
.engine
, init
.filename
, init
.name
, init
.label
, init
.uniqueId
, bool2str(use16Outs
));
1901 #ifdef HAVE_FLUIDSYNTH
1902 if (init
.engine
->getProccessMode() == ENGINE_PROCESS_MODE_CONTINUOUS_RACK
)
1905 if (ptype
== PLUGIN_SF2
&& ! fluid_is_soundfont(init
.filename
))
1907 init
.engine
->setLastError("Requested file is not a valid SoundFont");
1910 #ifndef HAVE_FLUIDSYNTH_INSTPATCH
1911 if (ptype
== PLUGIN_DLS
)
1913 init
.engine
->setLastError("DLS file support not available");
1916 if (ptype
== PLUGIN_GIG
)
1918 init
.engine
->setLastError("GIG file support not available");
1923 std::shared_ptr
<CarlaPluginFluidSynth
> plugin(new CarlaPluginFluidSynth(init
.engine
, init
.id
, use16Outs
));
1925 if (! plugin
->init(plugin
, init
.filename
, init
.name
, init
.label
, init
.options
))
1930 init
.engine
->setLastError("fluidsynth support not available");
1939 // -------------------------------------------------------------------------------------------------------------------
1941 CARLA_BACKEND_END_NAMESPACE