Collection of tools useful for audio production
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1325 lines
44KB

  1. /*
  2. * Carla Backend
  3. * Copyright (C) 2011-2012 Filipe Coelho <falktx@gmail.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * 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 COPYING file
  16. */
  17. #ifdef BUILD_BRIDGE
  18. #error Should not use fluidsynth for bridges!
  19. #endif
  20. #include "carla_plugin.h"
  21. #ifdef WANT_FLUIDSYNTH
  22. #include "carla_fluidsynth.h"
  23. #else
  24. #warning fluidsynth not available (no SF2 support)
  25. #endif
  26. CARLA_BACKEND_START_NAMESPACE
  27. #ifdef WANT_FLUIDSYNTH
  28. /*!
  29. * @defgroup CarlaBackendFluidSynthPlugin Carla Backend FluidSynth Plugin
  30. *
  31. * The Carla Backend FluidSynth Plugin.\n
  32. * http://www.fluidsynth.org/
  33. * @{
  34. */
  35. class FluidSynthPlugin : public CarlaPlugin
  36. {
  37. public:
  38. FluidSynthPlugin(CarlaEngine* const engine, unsigned short id) : CarlaPlugin(engine, id)
  39. {
  40. qDebug("FluidSynthPlugin::FluidSynthPlugin()");
  41. m_type = PLUGIN_SF2;
  42. m_label = nullptr;
  43. // create settings
  44. f_settings = new_fluid_settings();
  45. // define settings
  46. fluid_settings_setnum(f_settings, "synth.sample-rate", x_engine->getSampleRate());
  47. fluid_settings_setint(f_settings, "synth.threadsafe-api ", 0);
  48. // create synth
  49. f_synth = new_fluid_synth(f_settings);
  50. #ifdef FLUIDSYNTH_VERSION_NEW_API
  51. fluid_synth_set_sample_rate(f_synth, x_engine->getSampleRate());
  52. #endif
  53. // set default values
  54. fluid_synth_set_reverb_on(f_synth, 0);
  55. fluid_synth_set_reverb(f_synth, FLUID_REVERB_DEFAULT_ROOMSIZE, FLUID_REVERB_DEFAULT_DAMP, FLUID_REVERB_DEFAULT_WIDTH, FLUID_REVERB_DEFAULT_LEVEL);
  56. fluid_synth_set_chorus_on(f_synth, 0);
  57. fluid_synth_set_chorus(f_synth, FLUID_CHORUS_DEFAULT_N, FLUID_CHORUS_DEFAULT_LEVEL, FLUID_CHORUS_DEFAULT_SPEED, FLUID_CHORUS_DEFAULT_DEPTH, FLUID_CHORUS_DEFAULT_TYPE);
  58. fluid_synth_set_polyphony(f_synth, 64);
  59. for (int i=0; i < 16; i++)
  60. fluid_synth_set_interp_method(f_synth, i, FLUID_INTERP_DEFAULT);
  61. }
  62. ~FluidSynthPlugin()
  63. {
  64. qDebug("FluidSynthPlugin::~FluidSynthPlugin()");
  65. if (m_label)
  66. free((void*)m_label);
  67. delete_fluid_synth(f_synth);
  68. delete_fluid_settings(f_settings);
  69. }
  70. // -------------------------------------------------------------------
  71. // Information (base)
  72. PluginCategory category()
  73. {
  74. return PLUGIN_CATEGORY_SYNTH;
  75. }
  76. // -------------------------------------------------------------------
  77. // Information (count)
  78. uint32_t parameterScalePointCount(uint32_t parameterId)
  79. {
  80. Q_ASSERT(parameterId < param.count);
  81. switch (parameterId)
  82. {
  83. case FluidSynthChorusType:
  84. return 2;
  85. case FluidSynthInterpolation:
  86. return 4;
  87. default:
  88. return 0;
  89. }
  90. }
  91. // -------------------------------------------------------------------
  92. // Information (per-plugin data)
  93. double getParameterValue(uint32_t parameterId)
  94. {
  95. Q_ASSERT(parameterId < param.count);
  96. return param_buffers[parameterId];
  97. }
  98. double getParameterScalePointValue(uint32_t parameterId, uint32_t scalePointId)
  99. {
  100. Q_ASSERT(parameterId < param.count);
  101. Q_ASSERT(scalePointId < parameterScalePointCount(parameterId));
  102. switch (parameterId)
  103. {
  104. case FluidSynthChorusType:
  105. switch (scalePointId)
  106. {
  107. case 0:
  108. return FLUID_CHORUS_MOD_SINE;
  109. case 1:
  110. return FLUID_CHORUS_MOD_TRIANGLE;
  111. default:
  112. return FLUID_CHORUS_DEFAULT_TYPE;
  113. }
  114. case FluidSynthInterpolation:
  115. switch (scalePointId)
  116. {
  117. case 0:
  118. return FLUID_INTERP_NONE;
  119. case 1:
  120. return FLUID_INTERP_LINEAR;
  121. case 2:
  122. return FLUID_INTERP_4THORDER;
  123. case 3:
  124. return FLUID_INTERP_7THORDER;
  125. default:
  126. return FLUID_INTERP_DEFAULT;
  127. }
  128. default:
  129. return 0.0;
  130. }
  131. }
  132. void getLabel(char* const strBuf)
  133. {
  134. strncpy(strBuf, m_label, STR_MAX);
  135. }
  136. void getMaker(char* const strBuf)
  137. {
  138. strncpy(strBuf, "FluidSynth SF2 engine", STR_MAX);
  139. }
  140. void getCopyright(char* const strBuf)
  141. {
  142. strncpy(strBuf, "GNU GPL v2+", STR_MAX);
  143. }
  144. void getRealName(char* const strBuf)
  145. {
  146. getLabel(strBuf);
  147. }
  148. void getParameterName(uint32_t parameterId, char* const strBuf)
  149. {
  150. Q_ASSERT(parameterId < param.count);
  151. switch (parameterId)
  152. {
  153. case FluidSynthReverbOnOff:
  154. strncpy(strBuf, "Reverb On/Off", STR_MAX);
  155. break;
  156. case FluidSynthReverbRoomSize:
  157. strncpy(strBuf, "Reverb Room Size", STR_MAX);
  158. break;
  159. case FluidSynthReverbDamp:
  160. strncpy(strBuf, "Reverb Damp", STR_MAX);
  161. break;
  162. case FluidSynthReverbLevel:
  163. strncpy(strBuf, "Reverb Level", STR_MAX);
  164. break;
  165. case FluidSynthReverbWidth:
  166. strncpy(strBuf, "Reverb Width", STR_MAX);
  167. break;
  168. case FluidSynthChorusOnOff:
  169. strncpy(strBuf, "Chorus On/Off", STR_MAX);
  170. break;
  171. case FluidSynthChorusNr:
  172. strncpy(strBuf, "Chorus Voice Count", STR_MAX);
  173. break;
  174. case FluidSynthChorusLevel:
  175. strncpy(strBuf, "Chorus Level", STR_MAX);
  176. break;
  177. case FluidSynthChorusSpeedHz:
  178. strncpy(strBuf, "Chorus Speed", STR_MAX);
  179. break;
  180. case FluidSynthChorusDepthMs:
  181. strncpy(strBuf, "Chorus Depth", STR_MAX);
  182. break;
  183. case FluidSynthChorusType:
  184. strncpy(strBuf, "Chorus Type", STR_MAX);
  185. break;
  186. case FluidSynthPolyphony:
  187. strncpy(strBuf, "Polyphony", STR_MAX);
  188. break;
  189. case FluidSynthInterpolation:
  190. strncpy(strBuf, "Interpolation", STR_MAX);
  191. break;
  192. case FluidSynthVoiceCount:
  193. strncpy(strBuf, "Voice Count", STR_MAX);
  194. break;
  195. default:
  196. *strBuf = 0;
  197. break;
  198. }
  199. }
  200. void getParameterUnit(uint32_t parameterId, char* const strBuf)
  201. {
  202. Q_ASSERT(parameterId < param.count);
  203. switch (parameterId)
  204. {
  205. case FluidSynthChorusSpeedHz:
  206. strncpy(strBuf, "Hz", STR_MAX);
  207. break;
  208. case FluidSynthChorusDepthMs:
  209. strncpy(strBuf, "ms", STR_MAX);
  210. break;
  211. default:
  212. *strBuf = 0;
  213. break;
  214. }
  215. }
  216. void getParameterScalePointLabel(uint32_t parameterId, uint32_t scalePointId, char* const strBuf)
  217. {
  218. Q_ASSERT(parameterId < param.count);
  219. Q_ASSERT(scalePointId < parameterScalePointCount(parameterId));
  220. switch (parameterId)
  221. {
  222. case FluidSynthChorusType:
  223. switch (scalePointId)
  224. {
  225. case 0:
  226. strncpy(strBuf, "Sine wave", STR_MAX);
  227. return;
  228. case 1:
  229. strncpy(strBuf, "Triangle wave", STR_MAX);
  230. return;
  231. }
  232. case FluidSynthInterpolation:
  233. switch (scalePointId)
  234. {
  235. case 0:
  236. strncpy(strBuf, "None", STR_MAX);
  237. return;
  238. case 1:
  239. strncpy(strBuf, "Straight-line", STR_MAX);
  240. return;
  241. case 2:
  242. strncpy(strBuf, "Fourth-order", STR_MAX);
  243. return;
  244. case 3:
  245. strncpy(strBuf, "Seventh-order", STR_MAX);
  246. return;
  247. }
  248. }
  249. *strBuf = 0;
  250. }
  251. // -------------------------------------------------------------------
  252. // Set data (plugin-specific stuff)
  253. void setParameterValue(uint32_t parameterId, double value, bool sendGui, bool sendOsc, bool sendCallback)
  254. {
  255. Q_ASSERT(parameterId < param.count);
  256. param_buffers[parameterId] = fixParameterValue(value, param.ranges[parameterId]);
  257. switch (parameterId)
  258. {
  259. case FluidSynthReverbOnOff:
  260. value = value > 0.5 ? 1 : 0;
  261. fluid_synth_set_reverb_on(f_synth, value);
  262. break;
  263. case FluidSynthReverbRoomSize:
  264. case FluidSynthReverbDamp:
  265. case FluidSynthReverbLevel:
  266. case FluidSynthReverbWidth:
  267. fluid_synth_set_reverb(f_synth, param_buffers[FluidSynthReverbRoomSize], param_buffers[FluidSynthReverbDamp], param_buffers[FluidSynthReverbWidth], param_buffers[FluidSynthReverbLevel]);
  268. break;
  269. case FluidSynthChorusOnOff:
  270. {
  271. const ScopedDisabler m(this, ! x_engine->isOffline());
  272. value = value > 0.5 ? 1 : 0;
  273. fluid_synth_set_chorus_on(f_synth, value);
  274. break;
  275. }
  276. case FluidSynthChorusNr:
  277. case FluidSynthChorusLevel:
  278. case FluidSynthChorusSpeedHz:
  279. case FluidSynthChorusDepthMs:
  280. case FluidSynthChorusType:
  281. {
  282. const ScopedDisabler m(this, ! x_engine->isOffline());
  283. fluid_synth_set_chorus(f_synth, rint(param_buffers[FluidSynthChorusNr]), param_buffers[FluidSynthChorusLevel], param_buffers[FluidSynthChorusSpeedHz], param_buffers[FluidSynthChorusDepthMs], rint(param_buffers[FluidSynthChorusType]));
  284. break;
  285. }
  286. case FluidSynthPolyphony:
  287. {
  288. const ScopedDisabler m(this, ! x_engine->isOffline());
  289. fluid_synth_set_polyphony(f_synth, rint(value));
  290. break;
  291. }
  292. case FluidSynthInterpolation:
  293. {
  294. const ScopedDisabler m(this, ! x_engine->isOffline());
  295. for (int i=0; i < 16; i++)
  296. fluid_synth_set_interp_method(f_synth, i, rint(value));
  297. break;
  298. }
  299. default:
  300. break;
  301. }
  302. CarlaPlugin::setParameterValue(parameterId, value, sendGui, sendOsc, sendCallback);
  303. }
  304. void setMidiProgram(int32_t index, bool sendGui, bool sendOsc, bool sendCallback, bool block)
  305. {
  306. Q_ASSERT(index < (int32_t)midiprog.count);
  307. if (m_ctrlInChannel < 0 || m_ctrlInChannel > 15)
  308. return;
  309. if (index >= 0)
  310. {
  311. if (x_engine->isOffline())
  312. {
  313. const CarlaEngine::ScopedLocker m(x_engine, block);
  314. fluid_synth_program_select(f_synth, m_ctrlInChannel, f_id, midiprog.data[index].bank, midiprog.data[index].program);
  315. }
  316. else
  317. {
  318. const ScopedDisabler m(this, block);
  319. fluid_synth_program_select(f_synth, m_ctrlInChannel, f_id, midiprog.data[index].bank, midiprog.data[index].program);
  320. }
  321. }
  322. CarlaPlugin::setMidiProgram(index, sendGui, sendOsc, sendCallback, block);
  323. }
  324. // -------------------------------------------------------------------
  325. // Plugin state
  326. void reload()
  327. {
  328. qDebug("FluidSynthPlugin::reload() - start");
  329. Q_ASSERT(f_synth);
  330. // Safely disable plugin for reload
  331. const ScopedDisabler m(this);
  332. if (x_client->isActive())
  333. x_client->deactivate();
  334. // Remove client ports
  335. removeClientPorts();
  336. // Delete old data
  337. deleteBuffers();
  338. uint32_t aOuts, params, j;
  339. aOuts = 2;
  340. params = FluidSynthParametersMax;
  341. aOut.ports = new CarlaEngineAudioPort*[aOuts];
  342. aOut.rindexes = new uint32_t[aOuts];
  343. param.data = new ParameterData[params];
  344. param.ranges = new ParameterRanges[params];
  345. //const int portNameSize = CarlaEngine::maxPortNameSize() - 1;
  346. char portName[STR_MAX];
  347. // ---------------------------------------
  348. // Audio Outputs
  349. #ifndef BUILD_BRIDGE
  350. if (carlaOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS)
  351. {
  352. strcpy(portName, m_name);
  353. strcat(portName, ":out-left");
  354. }
  355. else
  356. #endif
  357. strcpy(portName, "out-left");
  358. aOut.ports[0] = (CarlaEngineAudioPort*)x_client->addPort(CarlaEnginePortTypeAudio, portName, false);
  359. aOut.rindexes[0] = 0;
  360. #ifndef BUILD_BRIDGE
  361. if (carlaOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS)
  362. {
  363. strcpy(portName, m_name);
  364. strcat(portName, ":out-right");
  365. }
  366. else
  367. #endif
  368. strcpy(portName, "out-right");
  369. aOut.ports[1] = (CarlaEngineAudioPort*)x_client->addPort(CarlaEnginePortTypeAudio, portName, false);
  370. aOut.rindexes[1] = 1;
  371. // ---------------------------------------
  372. // MIDI Input
  373. #ifndef BUILD_BRIDGE
  374. if (carlaOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS)
  375. {
  376. strcpy(portName, m_name);
  377. strcat(portName, ":midi-in");
  378. }
  379. else
  380. #endif
  381. strcpy(portName, "midi-in");
  382. midi.portMin = (CarlaEngineMidiPort*)x_client->addPort(CarlaEnginePortTypeMIDI, portName, true);
  383. // ---------------------------------------
  384. // Parameters
  385. #ifndef BUILD_BRIDGE
  386. if (carlaOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS)
  387. {
  388. strcpy(portName, m_name);
  389. strcat(portName, ":control-in");
  390. }
  391. else
  392. #endif
  393. strcpy(portName, "control-in");
  394. param.portCin = (CarlaEngineControlPort*)x_client->addPort(CarlaEnginePortTypeControl, portName, true);
  395. #ifndef BUILD_BRIDGE
  396. if (carlaOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS)
  397. {
  398. strcpy(portName, m_name);
  399. strcat(portName, ":control-out");
  400. }
  401. else
  402. #endif
  403. strcpy(portName, "control-out");
  404. param.portCout = (CarlaEngineControlPort*)x_client->addPort(CarlaEnginePortTypeControl, portName, false);
  405. // ----------------------
  406. j = FluidSynthReverbOnOff;
  407. param.data[j].index = j;
  408. param.data[j].rindex = j;
  409. param.data[j].type = PARAMETER_INPUT;
  410. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN;
  411. param.data[j].midiChannel = 0;
  412. param.data[j].midiCC = -1;
  413. param.ranges[j].min = 0.0;
  414. param.ranges[j].max = 1.0;
  415. param.ranges[j].def = 0.0;
  416. param.ranges[j].step = 1.0;
  417. param.ranges[j].stepSmall = 1.0;
  418. param.ranges[j].stepLarge = 1.0;
  419. param_buffers[j] = param.ranges[j].def;
  420. // ----------------------
  421. j = FluidSynthReverbRoomSize;
  422. param.data[j].index = j;
  423. param.data[j].rindex = j;
  424. param.data[j].type = PARAMETER_INPUT;
  425. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE;
  426. param.data[j].midiChannel = 0;
  427. param.data[j].midiCC = -1;
  428. param.ranges[j].min = 0.0;
  429. param.ranges[j].max = 1.2;
  430. param.ranges[j].def = FLUID_REVERB_DEFAULT_ROOMSIZE;
  431. param.ranges[j].step = 0.01;
  432. param.ranges[j].stepSmall = 0.0001;
  433. param.ranges[j].stepLarge = 0.1;
  434. param_buffers[j] = param.ranges[j].def;
  435. // ----------------------
  436. j = FluidSynthReverbDamp;
  437. param.data[j].index = j;
  438. param.data[j].rindex = j;
  439. param.data[j].type = PARAMETER_INPUT;
  440. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE;
  441. param.data[j].midiChannel = 0;
  442. param.data[j].midiCC = -1;
  443. param.ranges[j].min = 0.0;
  444. param.ranges[j].max = 1.0;
  445. param.ranges[j].def = FLUID_REVERB_DEFAULT_DAMP;
  446. param.ranges[j].step = 0.01;
  447. param.ranges[j].stepSmall = 0.0001;
  448. param.ranges[j].stepLarge = 0.1;
  449. param_buffers[j] = param.ranges[j].def;
  450. // ----------------------
  451. j = FluidSynthReverbLevel;
  452. param.data[j].index = j;
  453. param.data[j].rindex = j;
  454. param.data[j].type = PARAMETER_INPUT;
  455. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE;
  456. param.data[j].midiChannel = 0;
  457. param.data[j].midiCC = MIDI_CONTROL_REVERB_SEND_LEVEL;
  458. param.ranges[j].min = 0.0;
  459. param.ranges[j].max = 1.0;
  460. param.ranges[j].def = FLUID_REVERB_DEFAULT_LEVEL;
  461. param.ranges[j].step = 0.01;
  462. param.ranges[j].stepSmall = 0.0001;
  463. param.ranges[j].stepLarge = 0.1;
  464. param_buffers[j] = param.ranges[j].def;
  465. // ----------------------
  466. j = FluidSynthReverbWidth;
  467. param.data[j].index = j;
  468. param.data[j].rindex = j;
  469. param.data[j].type = PARAMETER_INPUT;
  470. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE;
  471. param.data[j].midiChannel = 0;
  472. param.data[j].midiCC = -1;
  473. param.ranges[j].min = 0.0;
  474. param.ranges[j].max = 10.0; // should be 100, but that sounds too much
  475. param.ranges[j].def = FLUID_REVERB_DEFAULT_WIDTH;
  476. param.ranges[j].step = 0.01;
  477. param.ranges[j].stepSmall = 0.0001;
  478. param.ranges[j].stepLarge = 0.1;
  479. param_buffers[j] = param.ranges[j].def;
  480. // ----------------------
  481. j = FluidSynthChorusOnOff;
  482. param.data[j].index = j;
  483. param.data[j].rindex = j;
  484. param.data[j].type = PARAMETER_INPUT;
  485. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_BOOLEAN;
  486. param.data[j].midiChannel = 0;
  487. param.data[j].midiCC = -1;
  488. param.ranges[j].min = 0.0;
  489. param.ranges[j].max = 1.0;
  490. param.ranges[j].def = 0.0;
  491. param.ranges[j].step = 1.0;
  492. param.ranges[j].stepSmall = 1.0;
  493. param.ranges[j].stepLarge = 1.0;
  494. param_buffers[j] = param.ranges[j].def;
  495. // ----------------------
  496. j = FluidSynthChorusNr;
  497. param.data[j].index = j;
  498. param.data[j].rindex = j;
  499. param.data[j].type = PARAMETER_INPUT;
  500. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER;
  501. param.data[j].midiChannel = 0;
  502. param.data[j].midiCC = -1;
  503. param.ranges[j].min = 0.0;
  504. param.ranges[j].max = 99.0;
  505. param.ranges[j].def = FLUID_CHORUS_DEFAULT_N;
  506. param.ranges[j].step = 1.0;
  507. param.ranges[j].stepSmall = 1.0;
  508. param.ranges[j].stepLarge = 10.0;
  509. param_buffers[j] = param.ranges[j].def;
  510. // ----------------------
  511. j = FluidSynthChorusLevel;
  512. param.data[j].index = j;
  513. param.data[j].rindex = j;
  514. param.data[j].type = PARAMETER_INPUT;
  515. param.data[j].hints = PARAMETER_IS_ENABLED;
  516. param.data[j].midiChannel = 0;
  517. param.data[j].midiCC = 0; //MIDI_CONTROL_CHORUS_SEND_LEVEL;
  518. param.ranges[j].min = 0.0;
  519. param.ranges[j].max = 10.0;
  520. param.ranges[j].def = FLUID_CHORUS_DEFAULT_LEVEL;
  521. param.ranges[j].step = 0.01;
  522. param.ranges[j].stepSmall = 0.0001;
  523. param.ranges[j].stepLarge = 0.1;
  524. param_buffers[j] = param.ranges[j].def;
  525. // ----------------------
  526. j = FluidSynthChorusSpeedHz;
  527. param.data[j].index = j;
  528. param.data[j].rindex = j;
  529. param.data[j].type = PARAMETER_INPUT;
  530. param.data[j].hints = PARAMETER_IS_ENABLED;
  531. param.data[j].midiChannel = 0;
  532. param.data[j].midiCC = -1;
  533. param.ranges[j].min = 0.29;
  534. param.ranges[j].max = 5.0;
  535. param.ranges[j].def = FLUID_CHORUS_DEFAULT_SPEED;
  536. param.ranges[j].step = 0.01;
  537. param.ranges[j].stepSmall = 0.0001;
  538. param.ranges[j].stepLarge = 0.1;
  539. param_buffers[j] = param.ranges[j].def;
  540. // ----------------------
  541. j = FluidSynthChorusDepthMs;
  542. param.data[j].index = j;
  543. param.data[j].rindex = j;
  544. param.data[j].type = PARAMETER_INPUT;
  545. param.data[j].hints = PARAMETER_IS_ENABLED;
  546. param.data[j].midiChannel = 0;
  547. param.data[j].midiCC = -1;
  548. param.ranges[j].min = 0.0;
  549. param.ranges[j].max = 2048000.0 / x_engine->getSampleRate();
  550. param.ranges[j].def = FLUID_CHORUS_DEFAULT_DEPTH;
  551. param.ranges[j].step = 0.01;
  552. param.ranges[j].stepSmall = 0.0001;
  553. param.ranges[j].stepLarge = 0.1;
  554. param_buffers[j] = param.ranges[j].def;
  555. // ----------------------
  556. j = FluidSynthChorusType;
  557. param.data[j].index = j;
  558. param.data[j].rindex = j;
  559. param.data[j].type = PARAMETER_INPUT;
  560. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER | PARAMETER_USES_SCALEPOINTS;
  561. param.data[j].midiChannel = 0;
  562. param.data[j].midiCC = -1;
  563. param.ranges[j].min = FLUID_CHORUS_MOD_SINE;
  564. param.ranges[j].max = FLUID_CHORUS_MOD_TRIANGLE;
  565. param.ranges[j].def = FLUID_CHORUS_DEFAULT_TYPE;
  566. param.ranges[j].step = 1;
  567. param.ranges[j].stepSmall = 1;
  568. param.ranges[j].stepLarge = 1;
  569. param_buffers[j] = param.ranges[j].def;
  570. // ----------------------
  571. j = FluidSynthPolyphony;
  572. param.data[j].index = j;
  573. param.data[j].rindex = j;
  574. param.data[j].type = PARAMETER_INPUT;
  575. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER;
  576. param.data[j].midiChannel = 0;
  577. param.data[j].midiCC = -1;
  578. param.ranges[j].min = 1;
  579. param.ranges[j].max = 512; // max theoric is 65535
  580. param.ranges[j].def = fluid_synth_get_polyphony(f_synth);
  581. param.ranges[j].step = 1;
  582. param.ranges[j].stepSmall = 1;
  583. param.ranges[j].stepLarge = 10;
  584. param_buffers[j] = param.ranges[j].def;
  585. // ----------------------
  586. j = FluidSynthInterpolation;
  587. param.data[j].index = j;
  588. param.data[j].rindex = j;
  589. param.data[j].type = PARAMETER_INPUT;
  590. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER | PARAMETER_USES_SCALEPOINTS;
  591. param.data[j].midiChannel = 0;
  592. param.data[j].midiCC = -1;
  593. param.ranges[j].min = FLUID_INTERP_NONE;
  594. param.ranges[j].max = FLUID_INTERP_HIGHEST;
  595. param.ranges[j].def = FLUID_INTERP_DEFAULT;
  596. param.ranges[j].step = 1;
  597. param.ranges[j].stepSmall = 1;
  598. param.ranges[j].stepLarge = 1;
  599. param_buffers[j] = param.ranges[j].def;
  600. // ----------------------
  601. j = FluidSynthVoiceCount;
  602. param.data[j].index = j;
  603. param.data[j].rindex = j;
  604. param.data[j].type = PARAMETER_OUTPUT;
  605. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE | PARAMETER_IS_INTEGER;
  606. param.data[j].midiChannel = 0;
  607. param.data[j].midiCC = -1;
  608. param.ranges[j].min = 0;
  609. param.ranges[j].max = 65535;
  610. param.ranges[j].def = 0;
  611. param.ranges[j].step = 1;
  612. param.ranges[j].stepSmall = 1;
  613. param.ranges[j].stepLarge = 1;
  614. param_buffers[j] = param.ranges[j].def;
  615. // ---------------------------------------
  616. aOut.count = aOuts;
  617. param.count = params;
  618. // plugin checks
  619. m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE);
  620. m_hints |= PLUGIN_IS_SYNTH;
  621. m_hints |= PLUGIN_CAN_VOLUME;
  622. m_hints |= PLUGIN_CAN_BALANCE;
  623. reloadPrograms(true);
  624. x_client->activate();
  625. qDebug("FluidSynthPlugin::reload() - end");
  626. }
  627. void reloadPrograms(bool init)
  628. {
  629. qDebug("FluidSynthPlugin::reloadPrograms(%s)", bool2str(init));
  630. // Delete old programs
  631. if (midiprog.count > 0)
  632. {
  633. for (uint32_t i=0; i < midiprog.count; i++)
  634. free((void*)midiprog.data[i].name);
  635. delete[] midiprog.data;
  636. }
  637. midiprog.count = 0;
  638. midiprog.data = nullptr;
  639. // Query new programs
  640. fluid_sfont_t* f_sfont;
  641. fluid_preset_t f_preset;
  642. f_sfont = fluid_synth_get_sfont_by_id(f_synth, f_id);
  643. // initial check to know how much midi-programs we have
  644. f_sfont->iteration_start(f_sfont);
  645. while (f_sfont->iteration_next(f_sfont, &f_preset))
  646. midiprog.count += 1;
  647. if (midiprog.count > 0)
  648. midiprog.data = new midi_program_t [midiprog.count];
  649. // Update data
  650. uint32_t i = 0;
  651. f_sfont->iteration_start(f_sfont);
  652. while (f_sfont->iteration_next(f_sfont, &f_preset))
  653. {
  654. Q_ASSERT(i < midiprog.count);
  655. midiprog.data[i].bank = f_preset.get_banknum(&f_preset);
  656. midiprog.data[i].program = f_preset.get_num(&f_preset);
  657. midiprog.data[i].name = strdup(f_preset.get_name(&f_preset));
  658. i++;
  659. }
  660. //f_sfont->free(f_sfont);
  661. #ifndef BUILD_BRIDGE
  662. // Update OSC Names
  663. if (x_engine->isOscControllerRegisted())
  664. {
  665. x_engine->osc_send_control_set_midi_program_count(m_id, midiprog.count);
  666. for (i=0; i < midiprog.count; i++)
  667. x_engine->osc_send_control_set_midi_program_data(m_id, i, midiprog.data[i].bank, midiprog.data[i].program, midiprog.data[i].name);
  668. }
  669. #endif
  670. // FIXME
  671. x_engine->callback(CALLBACK_RELOAD_PROGRAMS, m_id, 0, 0, 0.0);
  672. if (init)
  673. {
  674. fluid_synth_program_reset(f_synth);
  675. if (midiprog.count > 0)
  676. {
  677. for (i=0; i < 16 && i != 9; i++)
  678. {
  679. fluid_synth_program_select(f_synth, i, f_id, midiprog.data[0].bank, midiprog.data[0].program);
  680. #ifdef FLUIDSYNTH_VERSION_NEW_API
  681. fluid_synth_set_channel_type(f_synth, i, CHANNEL_TYPE_MELODIC);
  682. #endif
  683. }
  684. fluid_synth_program_select(f_synth, 9, f_id, 128, 0);
  685. #ifdef FLUIDSYNTH_VERSION_NEW_API
  686. fluid_synth_set_channel_type(f_synth, 9, CHANNEL_TYPE_DRUM);
  687. #endif
  688. setMidiProgram(0, false, false, false, true);
  689. }
  690. }
  691. }
  692. // -------------------------------------------------------------------
  693. // Plugin processing
  694. void process(float** const, float** const outBuffer, const uint32_t frames, const uint32_t framesOffset)
  695. {
  696. uint32_t i, k;
  697. uint32_t midiEventCount = 0;
  698. double aouts_peak_tmp[2] = { 0.0 };
  699. CARLA_PROCESS_CONTINUE_CHECK;
  700. // --------------------------------------------------------------------------------------------------------
  701. // Parameters Input [Automation]
  702. if (m_active && m_activeBefore)
  703. {
  704. bool allNotesOffSent = false;
  705. const CarlaEngineControlEvent* cinEvent;
  706. uint32_t time, nEvents = param.portCin->getEventCount();
  707. unsigned char nextBankIds[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0 };
  708. if (midiprog.current >= 0 && midiprog.count > 0 && m_ctrlInChannel >= 0 && m_ctrlInChannel < 16)
  709. nextBankIds[m_ctrlInChannel] = midiprog.data[midiprog.current].bank;
  710. for (i=0; i < nEvents; i++)
  711. {
  712. cinEvent = param.portCin->getEvent(i);
  713. if (! cinEvent)
  714. continue;
  715. time = cinEvent->time - framesOffset;
  716. if (time >= frames)
  717. continue;
  718. // Control change
  719. switch (cinEvent->type)
  720. {
  721. case CarlaEngineEventNull:
  722. break;
  723. case CarlaEngineEventControlChange:
  724. {
  725. double value;
  726. // Control backend stuff
  727. if (cinEvent->channel == m_ctrlInChannel)
  728. {
  729. if (MIDI_IS_CONTROL_BREATH_CONTROLLER(cinEvent->controller) && (m_hints & PLUGIN_CAN_DRYWET) > 0)
  730. {
  731. value = cinEvent->value;
  732. setDryWet(value, false, false);
  733. postponeEvent(PluginPostEventParameterChange, PARAMETER_DRYWET, 0, value);
  734. continue;
  735. }
  736. if (MIDI_IS_CONTROL_CHANNEL_VOLUME(cinEvent->controller) && (m_hints & PLUGIN_CAN_VOLUME) > 0)
  737. {
  738. value = cinEvent->value*127/100;
  739. setVolume(value, false, false);
  740. postponeEvent(PluginPostEventParameterChange, PARAMETER_VOLUME, 0, value);
  741. continue;
  742. }
  743. if (MIDI_IS_CONTROL_BALANCE(cinEvent->controller) && (m_hints & PLUGIN_CAN_BALANCE) > 0)
  744. {
  745. double left, right;
  746. value = cinEvent->value/0.5 - 1.0;
  747. if (value < 0)
  748. {
  749. left = -1.0;
  750. right = (value*2)+1.0;
  751. }
  752. else if (value > 0)
  753. {
  754. left = (value*2)-1.0;
  755. right = 1.0;
  756. }
  757. else
  758. {
  759. left = -1.0;
  760. right = 1.0;
  761. }
  762. setBalanceLeft(left, false, false);
  763. setBalanceRight(right, false, false);
  764. postponeEvent(PluginPostEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left);
  765. postponeEvent(PluginPostEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right);
  766. continue;
  767. }
  768. }
  769. // Control plugin parameters
  770. for (k=0; k < param.count; k++)
  771. {
  772. if (param.data[k].midiChannel != cinEvent->channel)
  773. continue;
  774. if (param.data[k].midiCC != cinEvent->controller)
  775. continue;
  776. if (param.data[k].type != PARAMETER_INPUT)
  777. continue;
  778. if (param.data[k].hints & PARAMETER_IS_AUTOMABLE)
  779. {
  780. if (param.data[k].hints & PARAMETER_IS_BOOLEAN)
  781. {
  782. value = cinEvent->value < 0.5 ? param.ranges[k].min : param.ranges[k].max;
  783. }
  784. else
  785. {
  786. value = cinEvent->value * (param.ranges[k].max - param.ranges[k].min) + param.ranges[k].min;
  787. if (param.data[k].hints & PARAMETER_IS_INTEGER)
  788. value = rint(value);
  789. }
  790. setParameterValue(k, value, false, false, false);
  791. postponeEvent(PluginPostEventParameterChange, k, 0, value);
  792. }
  793. }
  794. break;
  795. }
  796. case CarlaEngineEventMidiBankChange:
  797. if (cinEvent->channel < 16)
  798. nextBankIds[cinEvent->channel] = rint(cinEvent->value);
  799. break;
  800. case CarlaEngineEventMidiProgramChange:
  801. if (cinEvent->channel < 16)
  802. {
  803. uint32_t bankId = nextBankIds[cinEvent->channel];
  804. uint32_t progId = rint(cinEvent->value);
  805. for (k=0; k < midiprog.count; k++)
  806. {
  807. if (midiprog.data[k].bank == bankId && midiprog.data[k].program == progId)
  808. {
  809. if (cinEvent->channel == m_ctrlInChannel)
  810. {
  811. setMidiProgram(k, false, false, false, false);
  812. postponeEvent(PluginPostEventMidiProgramChange, k, 0, 0.0);
  813. }
  814. else
  815. fluid_synth_program_select(f_synth, cinEvent->channel, f_id, bankId, progId);
  816. break;
  817. }
  818. }
  819. }
  820. break;
  821. case CarlaEngineEventAllSoundOff:
  822. if (cinEvent->channel == m_ctrlInChannel)
  823. {
  824. if (! allNotesOffSent)
  825. sendMidiAllNotesOff();
  826. allNotesOffSent = true;
  827. #ifdef FLUIDSYNTH_VERSION_NEW_API
  828. fluid_synth_all_notes_off(f_synth, m_ctrlInChannel);
  829. fluid_synth_all_sounds_off(f_synth, m_ctrlInChannel);
  830. }
  831. else if (cinEvent->channel < 16)
  832. {
  833. fluid_synth_all_notes_off(f_synth, cinEvent->channel);
  834. fluid_synth_all_sounds_off(f_synth, cinEvent->channel);
  835. #endif
  836. }
  837. break;
  838. case CarlaEngineEventAllNotesOff:
  839. if (cinEvent->channel == m_ctrlInChannel)
  840. {
  841. if (! allNotesOffSent)
  842. sendMidiAllNotesOff();
  843. allNotesOffSent = true;
  844. #ifdef FLUIDSYNTH_VERSION_NEW_API
  845. fluid_synth_all_notes_off(f_synth, m_ctrlInChannel);
  846. }
  847. else if (cinEvent->channel < 16)
  848. {
  849. fluid_synth_all_notes_off(f_synth, cinEvent->channel);
  850. #endif
  851. }
  852. break;
  853. }
  854. }
  855. } // End of Parameters Input
  856. CARLA_PROCESS_CONTINUE_CHECK;
  857. // --------------------------------------------------------------------------------------------------------
  858. // MIDI Input (External)
  859. if (m_ctrlInChannel >= 0 && m_ctrlInChannel < 16 && m_active && m_activeBefore)
  860. {
  861. engineMidiLock();
  862. for (i=0; i < MAX_MIDI_EVENTS && midiEventCount < MAX_MIDI_EVENTS; i++)
  863. {
  864. if (extMidiNotes[i].channel < 0)
  865. break;
  866. if (extMidiNotes[i].velo)
  867. fluid_synth_noteon(f_synth, m_ctrlInChannel, extMidiNotes[i].note, extMidiNotes[i].velo);
  868. else
  869. fluid_synth_noteoff(f_synth, m_ctrlInChannel, extMidiNotes[i].note);
  870. extMidiNotes[i].channel = -1;
  871. midiEventCount += 1;
  872. }
  873. engineMidiUnlock();
  874. } // End of MIDI Input (External)
  875. CARLA_PROCESS_CONTINUE_CHECK;
  876. // --------------------------------------------------------------------------------------------------------
  877. // MIDI Input (System)
  878. if (m_active && m_activeBefore)
  879. {
  880. const CarlaEngineMidiEvent* minEvent;
  881. uint32_t time, nEvents = midi.portMin->getEventCount();
  882. for (i=0; i < nEvents && midiEventCount < MAX_MIDI_EVENTS; i++)
  883. {
  884. minEvent = midi.portMin->getEvent(i);
  885. if (! minEvent)
  886. continue;
  887. time = minEvent->time - framesOffset;
  888. if (time >= frames)
  889. continue;
  890. uint8_t status = minEvent->data[0];
  891. uint8_t channel = status & 0x0F;
  892. // Fix bad note-off
  893. if (MIDI_IS_STATUS_NOTE_ON(status) && minEvent->data[2] == 0)
  894. status -= 0x10;
  895. if (MIDI_IS_STATUS_NOTE_OFF(status))
  896. {
  897. uint8_t note = minEvent->data[1];
  898. fluid_synth_noteoff(f_synth, channel, note);
  899. postponeEvent(PluginPostEventNoteOff, channel, note, 0.0);
  900. }
  901. else if (MIDI_IS_STATUS_NOTE_ON(status))
  902. {
  903. uint8_t note = minEvent->data[1];
  904. uint8_t velo = minEvent->data[2];
  905. fluid_synth_noteon(f_synth, channel, note, velo);
  906. postponeEvent(PluginPostEventNoteOn, channel, note, velo);
  907. }
  908. else if (MIDI_IS_STATUS_AFTERTOUCH(status))
  909. {
  910. uint8_t pressure = minEvent->data[1];
  911. fluid_synth_channel_pressure(f_synth, channel, pressure);
  912. }
  913. else if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status))
  914. {
  915. uint8_t lsb = minEvent->data[1];
  916. uint8_t msb = minEvent->data[2];
  917. fluid_synth_pitch_bend(f_synth, channel, (msb << 7) | lsb);
  918. }
  919. else
  920. continue;
  921. midiEventCount += 1;
  922. }
  923. } // End of MIDI Input (System)
  924. CARLA_PROCESS_CONTINUE_CHECK;
  925. // --------------------------------------------------------------------------------------------------------
  926. // Plugin processing
  927. if (m_active)
  928. {
  929. if (! m_activeBefore)
  930. {
  931. if (m_ctrlInChannel >= 0 && m_ctrlInChannel < 16)
  932. {
  933. fluid_synth_cc(f_synth, m_ctrlInChannel, MIDI_CONTROL_ALL_SOUND_OFF, 0);
  934. fluid_synth_cc(f_synth, m_ctrlInChannel, MIDI_CONTROL_ALL_NOTES_OFF, 0);
  935. }
  936. #ifdef FLUIDSYNTH_VERSION_NEW_API
  937. for (i=0; i < 16; i++)
  938. {
  939. fluid_synth_all_notes_off(f_synth, i);
  940. fluid_synth_all_sounds_off(f_synth, i);
  941. }
  942. #endif
  943. }
  944. fluid_synth_process(f_synth, frames, 0, nullptr, 2, outBuffer);
  945. }
  946. CARLA_PROCESS_CONTINUE_CHECK;
  947. // --------------------------------------------------------------------------------------------------------
  948. // Post-processing (balance and volume)
  949. if (m_active)
  950. {
  951. bool do_balance = (x_balanceLeft != -1.0 || x_balanceRight != 1.0);
  952. double bal_rangeL, bal_rangeR;
  953. float oldBufLeft[do_balance ? frames : 0];
  954. for (i=0; i < aOut.count; i++)
  955. {
  956. // Balance
  957. if (do_balance)
  958. {
  959. if (i%2 == 0)
  960. memcpy(&oldBufLeft, outBuffer[i], sizeof(float)*frames);
  961. bal_rangeL = (x_balanceLeft+1.0)/2;
  962. bal_rangeR = (x_balanceRight+1.0)/2;
  963. for (k=0; k < frames; k++)
  964. {
  965. if (i%2 == 0)
  966. {
  967. // left output
  968. outBuffer[i][k] = oldBufLeft[k]*(1.0-bal_rangeL);
  969. outBuffer[i][k] += outBuffer[i+1][k]*(1.0-bal_rangeR);
  970. }
  971. else
  972. {
  973. // right
  974. outBuffer[i][k] = outBuffer[i][k]*bal_rangeR;
  975. outBuffer[i][k] += oldBufLeft[k]*bal_rangeL;
  976. }
  977. }
  978. }
  979. // Volume, using fluidsynth internals
  980. fluid_synth_set_gain(f_synth, x_volume);
  981. // Output VU
  982. for (k=0; i < 2 && k < frames; k++)
  983. {
  984. if (abs(outBuffer[i][k]) > aouts_peak_tmp[i])
  985. aouts_peak_tmp[i] = abs(outBuffer[i][k]);
  986. }
  987. }
  988. }
  989. else
  990. {
  991. // disable any output sound if not active
  992. for (i=0; i < aOut.count; i++)
  993. memset(outBuffer[i], 0.0f, sizeof(float)*frames);
  994. aouts_peak_tmp[0] = 0.0;
  995. aouts_peak_tmp[1] = 0.0;
  996. } // End of Post-processing
  997. CARLA_PROCESS_CONTINUE_CHECK;
  998. // --------------------------------------------------------------------------------------------------------
  999. // Control Output
  1000. if (m_active)
  1001. {
  1002. k = FluidSynthVoiceCount;
  1003. param_buffers[k] = fluid_synth_get_active_voice_count(f_synth);
  1004. fixParameterValue(param_buffers[k], param.ranges[k]);
  1005. if (param.data[k].midiCC > 0)
  1006. {
  1007. double value = (param_buffers[k] - param.ranges[k].min) / (param.ranges[k].max - param.ranges[k].min);
  1008. param.portCout->writeEvent(CarlaEngineEventControlChange, framesOffset, param.data[k].midiChannel, param.data[k].midiCC, value);
  1009. }
  1010. } // End of Control Output
  1011. CARLA_PROCESS_CONTINUE_CHECK;
  1012. // --------------------------------------------------------------------------------------------------------
  1013. // Peak Values
  1014. x_engine->setOutputPeak(m_id, 0, aouts_peak_tmp[0]);
  1015. x_engine->setOutputPeak(m_id, 1, aouts_peak_tmp[1]);
  1016. m_activeBefore = m_active;
  1017. }
  1018. // -------------------------------------------------------------------
  1019. bool init(const char* const filename, const char* const name, const char* const label)
  1020. {
  1021. // ---------------------------------------------------------------
  1022. // open soundfont
  1023. f_id = fluid_synth_sfload(f_synth, filename, 0);
  1024. if (f_id < 0)
  1025. {
  1026. setLastError("Failed to load SoundFont file");
  1027. return false;
  1028. }
  1029. // ---------------------------------------------------------------
  1030. // get info
  1031. m_filename = strdup(filename);
  1032. m_label = strdup(label);
  1033. if (name)
  1034. m_name = x_engine->getUniqueName(name);
  1035. else
  1036. m_name = x_engine->getUniqueName(label);
  1037. // ---------------------------------------------------------------
  1038. // register client
  1039. x_client = x_engine->addClient(this);
  1040. if (! x_client->isOk())
  1041. {
  1042. setLastError("Failed to register plugin client");
  1043. return false;
  1044. }
  1045. return true;
  1046. }
  1047. private:
  1048. enum FluidSynthInputParameters {
  1049. FluidSynthReverbOnOff = 0,
  1050. FluidSynthReverbRoomSize = 1,
  1051. FluidSynthReverbDamp = 2,
  1052. FluidSynthReverbLevel = 3,
  1053. FluidSynthReverbWidth = 4,
  1054. FluidSynthChorusOnOff = 5,
  1055. FluidSynthChorusNr = 6,
  1056. FluidSynthChorusLevel = 7,
  1057. FluidSynthChorusSpeedHz = 8,
  1058. FluidSynthChorusDepthMs = 9,
  1059. FluidSynthChorusType = 10,
  1060. FluidSynthPolyphony = 11,
  1061. FluidSynthInterpolation = 12,
  1062. FluidSynthVoiceCount = 13,
  1063. FluidSynthParametersMax = 14
  1064. };
  1065. fluid_settings_t* f_settings;
  1066. fluid_synth_t* f_synth;
  1067. int f_id;
  1068. double param_buffers[FluidSynthParametersMax];
  1069. const char* m_label;
  1070. };
  1071. #endif // WANT_FLUIDSYNTH
  1072. CarlaPlugin* CarlaPlugin::newSF2(const initializer& init)
  1073. {
  1074. qDebug("CarlaPlugin::newSF2(%p, \"%s\", \"%s\", \"%s\")", init.engine, init.filename, init.name, init.label);
  1075. #ifdef WANT_FLUIDSYNTH
  1076. short id = init.engine->getNewPluginId();
  1077. if (id < 0 || id > CarlaEngine::maxPluginNumber())
  1078. {
  1079. setLastError("Maximum number of plugins reached");
  1080. return nullptr;
  1081. }
  1082. if (! fluid_is_soundfont(init.filename))
  1083. {
  1084. setLastError("Requested file is not a valid SoundFont");
  1085. return nullptr;
  1086. }
  1087. FluidSynthPlugin* const plugin = new FluidSynthPlugin(init.engine, id);
  1088. if (! plugin->init(init.filename, init.name, init.label))
  1089. {
  1090. delete plugin;
  1091. return nullptr;
  1092. }
  1093. plugin->reload();
  1094. plugin->registerToOsc();
  1095. return plugin;
  1096. #else
  1097. setLastError("fluidsynth support not available");
  1098. return nullptr;
  1099. #endif
  1100. }
  1101. /**@}*/
  1102. CARLA_BACKEND_END_NAMESPACE