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.

1322 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. // Safely disable plugin for reload
  330. const ScopedDisabler m(this);
  331. if (x_client->isActive())
  332. x_client->deactivate();
  333. // Remove client ports
  334. removeClientPorts();
  335. // Delete old data
  336. deleteBuffers();
  337. uint32_t aOuts, params, j;
  338. aOuts = 2;
  339. params = FluidSynthParametersMax;
  340. aOut.ports = new CarlaEngineAudioPort*[aOuts];
  341. aOut.rindexes = new uint32_t[aOuts];
  342. param.data = new ParameterData[params];
  343. param.ranges = new ParameterRanges[params];
  344. //const int portNameSize = CarlaEngine::maxPortNameSize() - 1;
  345. char portName[STR_MAX];
  346. // ---------------------------------------
  347. // Audio Outputs
  348. #ifndef BUILD_BRIDGE
  349. if (carlaOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS)
  350. {
  351. strcpy(portName, m_name);
  352. strcat(portName, ":out-left");
  353. }
  354. else
  355. #endif
  356. strcpy(portName, "out-left");
  357. aOut.ports[0] = (CarlaEngineAudioPort*)x_client->addPort(CarlaEnginePortTypeAudio, portName, false);
  358. aOut.rindexes[0] = 0;
  359. #ifndef BUILD_BRIDGE
  360. if (carlaOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS)
  361. {
  362. strcpy(portName, m_name);
  363. strcat(portName, ":out-right");
  364. }
  365. else
  366. #endif
  367. strcpy(portName, "out-right");
  368. aOut.ports[1] = (CarlaEngineAudioPort*)x_client->addPort(CarlaEnginePortTypeAudio, portName, false);
  369. aOut.rindexes[1] = 1;
  370. // ---------------------------------------
  371. // MIDI Input
  372. #ifndef BUILD_BRIDGE
  373. if (carlaOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS)
  374. {
  375. strcpy(portName, m_name);
  376. strcat(portName, ":midi-in");
  377. }
  378. else
  379. #endif
  380. strcpy(portName, "midi-in");
  381. midi.portMin = (CarlaEngineMidiPort*)x_client->addPort(CarlaEnginePortTypeMIDI, portName, true);
  382. // ---------------------------------------
  383. // Parameters
  384. #ifndef BUILD_BRIDGE
  385. if (carlaOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS)
  386. {
  387. strcpy(portName, m_name);
  388. strcat(portName, ":control-in");
  389. }
  390. else
  391. #endif
  392. strcpy(portName, "control-in");
  393. param.portCin = (CarlaEngineControlPort*)x_client->addPort(CarlaEnginePortTypeControl, portName, true);
  394. #ifndef BUILD_BRIDGE
  395. if (carlaOptions.processMode != PROCESS_MODE_MULTIPLE_CLIENTS)
  396. {
  397. strcpy(portName, m_name);
  398. strcat(portName, ":control-out");
  399. }
  400. else
  401. #endif
  402. strcpy(portName, "control-out");
  403. param.portCout = (CarlaEngineControlPort*)x_client->addPort(CarlaEnginePortTypeControl, portName, false);
  404. // ----------------------
  405. j = FluidSynthReverbOnOff;
  406. param.data[j].index = j;
  407. param.data[j].rindex = j;
  408. param.data[j].type = PARAMETER_INPUT;
  409. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE | PARAMETER_IS_BOOLEAN;
  410. param.data[j].midiChannel = 0;
  411. param.data[j].midiCC = -1;
  412. param.ranges[j].min = 0.0;
  413. param.ranges[j].max = 1.0;
  414. param.ranges[j].def = 0.0;
  415. param.ranges[j].step = 1.0;
  416. param.ranges[j].stepSmall = 1.0;
  417. param.ranges[j].stepLarge = 1.0;
  418. param_buffers[j] = param.ranges[j].def;
  419. // ----------------------
  420. j = FluidSynthReverbRoomSize;
  421. param.data[j].index = j;
  422. param.data[j].rindex = j;
  423. param.data[j].type = PARAMETER_INPUT;
  424. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE;
  425. param.data[j].midiChannel = 0;
  426. param.data[j].midiCC = -1;
  427. param.ranges[j].min = 0.0;
  428. param.ranges[j].max = 1.2;
  429. param.ranges[j].def = FLUID_REVERB_DEFAULT_ROOMSIZE;
  430. param.ranges[j].step = 0.01;
  431. param.ranges[j].stepSmall = 0.0001;
  432. param.ranges[j].stepLarge = 0.1;
  433. param_buffers[j] = param.ranges[j].def;
  434. // ----------------------
  435. j = FluidSynthReverbDamp;
  436. param.data[j].index = j;
  437. param.data[j].rindex = j;
  438. param.data[j].type = PARAMETER_INPUT;
  439. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE;
  440. param.data[j].midiChannel = 0;
  441. param.data[j].midiCC = -1;
  442. param.ranges[j].min = 0.0;
  443. param.ranges[j].max = 1.0;
  444. param.ranges[j].def = FLUID_REVERB_DEFAULT_DAMP;
  445. param.ranges[j].step = 0.01;
  446. param.ranges[j].stepSmall = 0.0001;
  447. param.ranges[j].stepLarge = 0.1;
  448. param_buffers[j] = param.ranges[j].def;
  449. // ----------------------
  450. j = FluidSynthReverbLevel;
  451. param.data[j].index = j;
  452. param.data[j].rindex = j;
  453. param.data[j].type = PARAMETER_INPUT;
  454. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE;
  455. param.data[j].midiChannel = 0;
  456. param.data[j].midiCC = MIDI_CONTROL_REVERB_SEND_LEVEL;
  457. param.ranges[j].min = 0.0;
  458. param.ranges[j].max = 1.0;
  459. param.ranges[j].def = FLUID_REVERB_DEFAULT_LEVEL;
  460. param.ranges[j].step = 0.01;
  461. param.ranges[j].stepSmall = 0.0001;
  462. param.ranges[j].stepLarge = 0.1;
  463. param_buffers[j] = param.ranges[j].def;
  464. // ----------------------
  465. j = FluidSynthReverbWidth;
  466. param.data[j].index = j;
  467. param.data[j].rindex = j;
  468. param.data[j].type = PARAMETER_INPUT;
  469. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE;
  470. param.data[j].midiChannel = 0;
  471. param.data[j].midiCC = -1;
  472. param.ranges[j].min = 0.0;
  473. param.ranges[j].max = 10.0; // should be 100, but that sounds too much
  474. param.ranges[j].def = FLUID_REVERB_DEFAULT_WIDTH;
  475. param.ranges[j].step = 0.01;
  476. param.ranges[j].stepSmall = 0.0001;
  477. param.ranges[j].stepLarge = 0.1;
  478. param_buffers[j] = param.ranges[j].def;
  479. // ----------------------
  480. j = FluidSynthChorusOnOff;
  481. param.data[j].index = j;
  482. param.data[j].rindex = j;
  483. param.data[j].type = PARAMETER_INPUT;
  484. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_BOOLEAN;
  485. param.data[j].midiChannel = 0;
  486. param.data[j].midiCC = -1;
  487. param.ranges[j].min = 0.0;
  488. param.ranges[j].max = 1.0;
  489. param.ranges[j].def = 0.0;
  490. param.ranges[j].step = 1.0;
  491. param.ranges[j].stepSmall = 1.0;
  492. param.ranges[j].stepLarge = 1.0;
  493. param_buffers[j] = param.ranges[j].def;
  494. // ----------------------
  495. j = FluidSynthChorusNr;
  496. param.data[j].index = j;
  497. param.data[j].rindex = j;
  498. param.data[j].type = PARAMETER_INPUT;
  499. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER;
  500. param.data[j].midiChannel = 0;
  501. param.data[j].midiCC = -1;
  502. param.ranges[j].min = 0.0;
  503. param.ranges[j].max = 99.0;
  504. param.ranges[j].def = FLUID_CHORUS_DEFAULT_N;
  505. param.ranges[j].step = 1.0;
  506. param.ranges[j].stepSmall = 1.0;
  507. param.ranges[j].stepLarge = 10.0;
  508. param_buffers[j] = param.ranges[j].def;
  509. // ----------------------
  510. j = FluidSynthChorusLevel;
  511. param.data[j].index = j;
  512. param.data[j].rindex = j;
  513. param.data[j].type = PARAMETER_INPUT;
  514. param.data[j].hints = PARAMETER_IS_ENABLED;
  515. param.data[j].midiChannel = 0;
  516. param.data[j].midiCC = 0; //MIDI_CONTROL_CHORUS_SEND_LEVEL;
  517. param.ranges[j].min = 0.0;
  518. param.ranges[j].max = 10.0;
  519. param.ranges[j].def = FLUID_CHORUS_DEFAULT_LEVEL;
  520. param.ranges[j].step = 0.01;
  521. param.ranges[j].stepSmall = 0.0001;
  522. param.ranges[j].stepLarge = 0.1;
  523. param_buffers[j] = param.ranges[j].def;
  524. // ----------------------
  525. j = FluidSynthChorusSpeedHz;
  526. param.data[j].index = j;
  527. param.data[j].rindex = j;
  528. param.data[j].type = PARAMETER_INPUT;
  529. param.data[j].hints = PARAMETER_IS_ENABLED;
  530. param.data[j].midiChannel = 0;
  531. param.data[j].midiCC = -1;
  532. param.ranges[j].min = 0.29;
  533. param.ranges[j].max = 5.0;
  534. param.ranges[j].def = FLUID_CHORUS_DEFAULT_SPEED;
  535. param.ranges[j].step = 0.01;
  536. param.ranges[j].stepSmall = 0.0001;
  537. param.ranges[j].stepLarge = 0.1;
  538. param_buffers[j] = param.ranges[j].def;
  539. // ----------------------
  540. j = FluidSynthChorusDepthMs;
  541. param.data[j].index = j;
  542. param.data[j].rindex = j;
  543. param.data[j].type = PARAMETER_INPUT;
  544. param.data[j].hints = PARAMETER_IS_ENABLED;
  545. param.data[j].midiChannel = 0;
  546. param.data[j].midiCC = -1;
  547. param.ranges[j].min = 0.0;
  548. param.ranges[j].max = 2048000.0 / x_engine->getSampleRate();
  549. param.ranges[j].def = FLUID_CHORUS_DEFAULT_DEPTH;
  550. param.ranges[j].step = 0.01;
  551. param.ranges[j].stepSmall = 0.0001;
  552. param.ranges[j].stepLarge = 0.1;
  553. param_buffers[j] = param.ranges[j].def;
  554. // ----------------------
  555. j = FluidSynthChorusType;
  556. param.data[j].index = j;
  557. param.data[j].rindex = j;
  558. param.data[j].type = PARAMETER_INPUT;
  559. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER | PARAMETER_USES_SCALEPOINTS;
  560. param.data[j].midiChannel = 0;
  561. param.data[j].midiCC = -1;
  562. param.ranges[j].min = FLUID_CHORUS_MOD_SINE;
  563. param.ranges[j].max = FLUID_CHORUS_MOD_TRIANGLE;
  564. param.ranges[j].def = FLUID_CHORUS_DEFAULT_TYPE;
  565. param.ranges[j].step = 1;
  566. param.ranges[j].stepSmall = 1;
  567. param.ranges[j].stepLarge = 1;
  568. param_buffers[j] = param.ranges[j].def;
  569. // ----------------------
  570. j = FluidSynthPolyphony;
  571. param.data[j].index = j;
  572. param.data[j].rindex = j;
  573. param.data[j].type = PARAMETER_INPUT;
  574. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER;
  575. param.data[j].midiChannel = 0;
  576. param.data[j].midiCC = -1;
  577. param.ranges[j].min = 1;
  578. param.ranges[j].max = 512; // max theoric is 65535
  579. param.ranges[j].def = fluid_synth_get_polyphony(f_synth);
  580. param.ranges[j].step = 1;
  581. param.ranges[j].stepSmall = 1;
  582. param.ranges[j].stepLarge = 10;
  583. param_buffers[j] = param.ranges[j].def;
  584. // ----------------------
  585. j = FluidSynthInterpolation;
  586. param.data[j].index = j;
  587. param.data[j].rindex = j;
  588. param.data[j].type = PARAMETER_INPUT;
  589. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER | PARAMETER_USES_SCALEPOINTS;
  590. param.data[j].midiChannel = 0;
  591. param.data[j].midiCC = -1;
  592. param.ranges[j].min = FLUID_INTERP_NONE;
  593. param.ranges[j].max = FLUID_INTERP_HIGHEST;
  594. param.ranges[j].def = FLUID_INTERP_DEFAULT;
  595. param.ranges[j].step = 1;
  596. param.ranges[j].stepSmall = 1;
  597. param.ranges[j].stepLarge = 1;
  598. param_buffers[j] = param.ranges[j].def;
  599. // ----------------------
  600. j = FluidSynthVoiceCount;
  601. param.data[j].index = j;
  602. param.data[j].rindex = j;
  603. param.data[j].type = PARAMETER_OUTPUT;
  604. param.data[j].hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE | PARAMETER_IS_INTEGER;
  605. param.data[j].midiChannel = 0;
  606. param.data[j].midiCC = -1;
  607. param.ranges[j].min = 0;
  608. param.ranges[j].max = 65535;
  609. param.ranges[j].def = 0;
  610. param.ranges[j].step = 1;
  611. param.ranges[j].stepSmall = 1;
  612. param.ranges[j].stepLarge = 1;
  613. param_buffers[j] = param.ranges[j].def;
  614. // ---------------------------------------
  615. aOut.count = aOuts;
  616. param.count = params;
  617. // plugin checks
  618. m_hints &= ~(PLUGIN_IS_SYNTH | PLUGIN_USES_CHUNKS | PLUGIN_CAN_DRYWET | PLUGIN_CAN_VOLUME | PLUGIN_CAN_BALANCE);
  619. m_hints |= PLUGIN_IS_SYNTH;
  620. m_hints |= PLUGIN_CAN_VOLUME;
  621. m_hints |= PLUGIN_CAN_BALANCE;
  622. reloadPrograms(true);
  623. x_client->activate();
  624. qDebug("FluidSynthPlugin::reload() - end");
  625. }
  626. void reloadPrograms(bool init)
  627. {
  628. qDebug("FluidSynthPlugin::reloadPrograms(%s)", bool2str(init));
  629. // Delete old programs
  630. if (midiprog.count > 0)
  631. {
  632. for (uint32_t i=0; i < midiprog.count; i++)
  633. free((void*)midiprog.data[i].name);
  634. delete[] midiprog.data;
  635. }
  636. midiprog.count = 0;
  637. midiprog.data = nullptr;
  638. // Query new programs
  639. fluid_sfont_t* f_sfont;
  640. fluid_preset_t f_preset;
  641. f_sfont = fluid_synth_get_sfont_by_id(f_synth, f_id);
  642. // initial check to know how much midi-programs we have
  643. f_sfont->iteration_start(f_sfont);
  644. while (f_sfont->iteration_next(f_sfont, &f_preset))
  645. midiprog.count += 1;
  646. if (midiprog.count > 0)
  647. midiprog.data = new midi_program_t [midiprog.count];
  648. // Update data
  649. uint32_t i = 0;
  650. f_sfont->iteration_start(f_sfont);
  651. while (f_sfont->iteration_next(f_sfont, &f_preset))
  652. {
  653. Q_ASSERT(i < midiprog.count);
  654. midiprog.data[i].bank = f_preset.get_banknum(&f_preset);
  655. midiprog.data[i].program = f_preset.get_num(&f_preset);
  656. midiprog.data[i].name = strdup(f_preset.get_name(&f_preset));
  657. i++;
  658. }
  659. //f_sfont->free(f_sfont);
  660. #ifndef BUILD_BRIDGE
  661. // Update OSC Names
  662. //osc_global_send_set_midi_program_count(m_id, midiprog.count);
  663. //for (i=0; i < midiprog.count; i++)
  664. // osc_global_send_set_midi_program_data(m_id, i, midiprog.data[i].bank, midiprog.data[i].program, midiprog.data[i].name);
  665. x_engine->callback(CALLBACK_RELOAD_PROGRAMS, m_id, 0, 0, 0.0);
  666. #endif
  667. if (init)
  668. {
  669. fluid_synth_program_reset(f_synth);
  670. if (midiprog.count > 0)
  671. {
  672. for (i=0; i < 16 && i != 9; i++)
  673. {
  674. fluid_synth_program_select(f_synth, i, f_id, midiprog.data[0].bank, midiprog.data[0].program);
  675. #ifdef FLUIDSYNTH_VERSION_NEW_API
  676. fluid_synth_set_channel_type(f_synth, i, CHANNEL_TYPE_MELODIC);
  677. #endif
  678. }
  679. fluid_synth_program_select(f_synth, 9, f_id, 128, 0);
  680. #ifdef FLUIDSYNTH_VERSION_NEW_API
  681. fluid_synth_set_channel_type(f_synth, 9, CHANNEL_TYPE_DRUM);
  682. #endif
  683. setMidiProgram(0, false, false, false, true);
  684. }
  685. }
  686. }
  687. // -------------------------------------------------------------------
  688. // Plugin processing
  689. void process(float**, float** outBuffer, uint32_t frames, uint32_t framesOffset)
  690. {
  691. uint32_t i, k;
  692. uint32_t midiEventCount = 0;
  693. double aouts_peak_tmp[2] = { 0.0 };
  694. CARLA_PROCESS_CONTINUE_CHECK;
  695. // --------------------------------------------------------------------------------------------------------
  696. // Parameters Input [Automation]
  697. if (m_active && m_activeBefore)
  698. {
  699. bool allNotesOffSent = false;
  700. const CarlaEngineControlEvent* cinEvent;
  701. uint32_t time, nEvents = param.portCin->getEventCount();
  702. unsigned char nextBankIds[16] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 128, 0, 0, 0, 0, 0, 0 };
  703. if (midiprog.current >= 0 && midiprog.count > 0 && m_ctrlInChannel >= 0 && m_ctrlInChannel < 16)
  704. nextBankIds[m_ctrlInChannel] = midiprog.data[midiprog.current].bank;
  705. for (i=0; i < nEvents; i++)
  706. {
  707. cinEvent = param.portCin->getEvent(i);
  708. if (! cinEvent)
  709. continue;
  710. time = cinEvent->time - framesOffset;
  711. if (time >= frames)
  712. continue;
  713. // Control change
  714. switch (cinEvent->type)
  715. {
  716. case CarlaEngineEventNull:
  717. break;
  718. case CarlaEngineEventControlChange:
  719. {
  720. double value;
  721. // Control backend stuff
  722. if (cinEvent->channel == m_ctrlInChannel)
  723. {
  724. if (MIDI_IS_CONTROL_BREATH_CONTROLLER(cinEvent->controller) && (m_hints & PLUGIN_CAN_DRYWET) > 0)
  725. {
  726. value = cinEvent->value;
  727. setDryWet(value, false, false);
  728. postponeEvent(PluginPostEventParameterChange, PARAMETER_DRYWET, 0, value);
  729. continue;
  730. }
  731. if (MIDI_IS_CONTROL_CHANNEL_VOLUME(cinEvent->controller) && (m_hints & PLUGIN_CAN_VOLUME) > 0)
  732. {
  733. value = cinEvent->value*127/100;
  734. setVolume(value, false, false);
  735. postponeEvent(PluginPostEventParameterChange, PARAMETER_VOLUME, 0, value);
  736. continue;
  737. }
  738. if (MIDI_IS_CONTROL_BALANCE(cinEvent->controller) && (m_hints & PLUGIN_CAN_BALANCE) > 0)
  739. {
  740. double left, right;
  741. value = cinEvent->value/0.5 - 1.0;
  742. if (value < 0)
  743. {
  744. left = -1.0;
  745. right = (value*2)+1.0;
  746. }
  747. else if (value > 0)
  748. {
  749. left = (value*2)-1.0;
  750. right = 1.0;
  751. }
  752. else
  753. {
  754. left = -1.0;
  755. right = 1.0;
  756. }
  757. setBalanceLeft(left, false, false);
  758. setBalanceRight(right, false, false);
  759. postponeEvent(PluginPostEventParameterChange, PARAMETER_BALANCE_LEFT, 0, left);
  760. postponeEvent(PluginPostEventParameterChange, PARAMETER_BALANCE_RIGHT, 0, right);
  761. continue;
  762. }
  763. }
  764. // Control plugin parameters
  765. for (k=0; k < param.count; k++)
  766. {
  767. if (param.data[k].midiChannel != cinEvent->channel)
  768. continue;
  769. if (param.data[k].midiCC != cinEvent->controller)
  770. continue;
  771. if (param.data[k].type != PARAMETER_INPUT)
  772. continue;
  773. if (param.data[k].hints & PARAMETER_IS_AUTOMABLE)
  774. {
  775. if (param.data[k].hints & PARAMETER_IS_BOOLEAN)
  776. {
  777. value = cinEvent->value < 0.5 ? param.ranges[k].min : param.ranges[k].max;
  778. }
  779. else
  780. {
  781. value = cinEvent->value * (param.ranges[k].max - param.ranges[k].min) + param.ranges[k].min;
  782. if (param.data[k].hints & PARAMETER_IS_INTEGER)
  783. value = rint(value);
  784. }
  785. setParameterValue(k, value, false, false, false);
  786. postponeEvent(PluginPostEventParameterChange, k, 0, value);
  787. }
  788. }
  789. break;
  790. }
  791. case CarlaEngineEventMidiBankChange:
  792. if (cinEvent->channel < 16)
  793. nextBankIds[cinEvent->channel] = rint(cinEvent->value);
  794. break;
  795. case CarlaEngineEventMidiProgramChange:
  796. if (cinEvent->channel < 16)
  797. {
  798. uint32_t bankId = nextBankIds[cinEvent->channel];
  799. uint32_t progId = rint(cinEvent->value);
  800. for (k=0; k < midiprog.count; k++)
  801. {
  802. if (midiprog.data[k].bank == bankId && midiprog.data[k].program == progId)
  803. {
  804. if (cinEvent->channel == m_ctrlInChannel)
  805. {
  806. setMidiProgram(k, false, false, false, false);
  807. postponeEvent(PluginPostEventMidiProgramChange, k, 0, 0.0);
  808. }
  809. else
  810. fluid_synth_program_select(f_synth, cinEvent->channel, f_id, bankId, progId);
  811. break;
  812. }
  813. }
  814. }
  815. break;
  816. case CarlaEngineEventAllSoundOff:
  817. if (cinEvent->channel == m_ctrlInChannel)
  818. {
  819. if (! allNotesOffSent)
  820. sendMidiAllNotesOff();
  821. allNotesOffSent = true;
  822. #ifdef FLUIDSYNTH_VERSION_NEW_API
  823. fluid_synth_all_notes_off(f_synth, m_ctrlInChannel);
  824. fluid_synth_all_sounds_off(f_synth, m_ctrlInChannel);
  825. }
  826. else if (cinEvent->channel < 16)
  827. {
  828. fluid_synth_all_notes_off(f_synth, cinEvent->channel);
  829. fluid_synth_all_sounds_off(f_synth, cinEvent->channel);
  830. #endif
  831. }
  832. break;
  833. case CarlaEngineEventAllNotesOff:
  834. if (cinEvent->channel == m_ctrlInChannel)
  835. {
  836. if (! allNotesOffSent)
  837. sendMidiAllNotesOff();
  838. allNotesOffSent = true;
  839. #ifdef FLUIDSYNTH_VERSION_NEW_API
  840. fluid_synth_all_notes_off(f_synth, m_ctrlInChannel);
  841. }
  842. else if (cinEvent->channel < 16)
  843. {
  844. fluid_synth_all_notes_off(f_synth, cinEvent->channel);
  845. #endif
  846. }
  847. break;
  848. }
  849. }
  850. } // End of Parameters Input
  851. CARLA_PROCESS_CONTINUE_CHECK;
  852. // --------------------------------------------------------------------------------------------------------
  853. // MIDI Input (External)
  854. if (m_ctrlInChannel >= 0 && m_ctrlInChannel < 16 && m_active && m_activeBefore)
  855. {
  856. engineMidiLock();
  857. for (i=0; i < MAX_MIDI_EVENTS && midiEventCount < MAX_MIDI_EVENTS; i++)
  858. {
  859. if (extMidiNotes[i].channel < 0)
  860. break;
  861. if (extMidiNotes[i].velo)
  862. fluid_synth_noteon(f_synth, m_ctrlInChannel, extMidiNotes[i].note, extMidiNotes[i].velo);
  863. else
  864. fluid_synth_noteoff(f_synth, m_ctrlInChannel, extMidiNotes[i].note);
  865. extMidiNotes[i].channel = -1;
  866. midiEventCount += 1;
  867. }
  868. engineMidiUnlock();
  869. } // End of MIDI Input (External)
  870. CARLA_PROCESS_CONTINUE_CHECK;
  871. // --------------------------------------------------------------------------------------------------------
  872. // MIDI Input (System)
  873. if (m_active && m_activeBefore)
  874. {
  875. const CarlaEngineMidiEvent* minEvent;
  876. uint32_t time, nEvents = midi.portMin->getEventCount();
  877. for (i=0; i < nEvents && midiEventCount < MAX_MIDI_EVENTS; i++)
  878. {
  879. minEvent = midi.portMin->getEvent(i);
  880. if (! minEvent)
  881. continue;
  882. time = minEvent->time - framesOffset;
  883. if (time >= frames)
  884. continue;
  885. uint8_t status = minEvent->data[0];
  886. uint8_t channel = status & 0x0F;
  887. // Fix bad note-off
  888. if (MIDI_IS_STATUS_NOTE_ON(status) && minEvent->data[2] == 0)
  889. status -= 0x10;
  890. if (MIDI_IS_STATUS_NOTE_OFF(status))
  891. {
  892. uint8_t note = minEvent->data[1];
  893. fluid_synth_noteoff(f_synth, channel, note);
  894. if (channel == m_ctrlInChannel)
  895. postponeEvent(PluginPostEventNoteOff, channel, note, 0.0);
  896. }
  897. else if (MIDI_IS_STATUS_NOTE_ON(status))
  898. {
  899. uint8_t note = minEvent->data[1];
  900. uint8_t velo = minEvent->data[2];
  901. fluid_synth_noteon(f_synth, channel, note, velo);
  902. if (channel == m_ctrlInChannel)
  903. postponeEvent(PluginPostEventNoteOn, channel, note, velo);
  904. }
  905. else if (MIDI_IS_STATUS_AFTERTOUCH(status))
  906. {
  907. uint8_t pressure = minEvent->data[1];
  908. fluid_synth_channel_pressure(f_synth, channel, pressure);
  909. }
  910. else if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status))
  911. {
  912. uint8_t lsb = minEvent->data[1];
  913. uint8_t msb = minEvent->data[2];
  914. fluid_synth_pitch_bend(f_synth, channel, (msb << 7) | lsb);
  915. }
  916. else
  917. continue;
  918. midiEventCount += 1;
  919. }
  920. } // End of MIDI Input (System)
  921. CARLA_PROCESS_CONTINUE_CHECK;
  922. // --------------------------------------------------------------------------------------------------------
  923. // Plugin processing
  924. if (m_active)
  925. {
  926. if (! m_activeBefore)
  927. {
  928. if (m_ctrlInChannel >= 0 && m_ctrlInChannel < 16)
  929. {
  930. fluid_synth_cc(f_synth, m_ctrlInChannel, MIDI_CONTROL_ALL_SOUND_OFF, 0);
  931. fluid_synth_cc(f_synth, m_ctrlInChannel, MIDI_CONTROL_ALL_NOTES_OFF, 0);
  932. }
  933. #ifdef FLUIDSYNTH_VERSION_NEW_API
  934. for (i=0; i < 16; i++)
  935. {
  936. fluid_synth_all_notes_off(f_synth, i);
  937. fluid_synth_all_sounds_off(f_synth, i);
  938. }
  939. #endif
  940. }
  941. fluid_synth_process(f_synth, frames, 0, nullptr, 2, outBuffer);
  942. }
  943. CARLA_PROCESS_CONTINUE_CHECK;
  944. // --------------------------------------------------------------------------------------------------------
  945. // Post-processing (balance and volume)
  946. if (m_active)
  947. {
  948. bool do_balance = (x_balanceLeft != -1.0 || x_balanceRight != 1.0);
  949. double bal_rangeL, bal_rangeR;
  950. float oldBufLeft[do_balance ? frames : 0];
  951. for (i=0; i < aOut.count; i++)
  952. {
  953. // Balance
  954. if (do_balance)
  955. {
  956. if (i%2 == 0)
  957. memcpy(&oldBufLeft, outBuffer[i], sizeof(float)*frames);
  958. bal_rangeL = (x_balanceLeft+1.0)/2;
  959. bal_rangeR = (x_balanceRight+1.0)/2;
  960. for (k=0; k < frames; k++)
  961. {
  962. if (i%2 == 0)
  963. {
  964. // left output
  965. outBuffer[i][k] = oldBufLeft[k]*(1.0-bal_rangeL);
  966. outBuffer[i][k] += outBuffer[i+1][k]*(1.0-bal_rangeR);
  967. }
  968. else
  969. {
  970. // right
  971. outBuffer[i][k] = outBuffer[i][k]*bal_rangeR;
  972. outBuffer[i][k] += oldBufLeft[k]*bal_rangeL;
  973. }
  974. }
  975. }
  976. // Volume, using fluidsynth internals
  977. fluid_synth_set_gain(f_synth, x_volume);
  978. // Output VU
  979. for (k=0; i < 2 && k < frames; k++)
  980. {
  981. if (abs(outBuffer[i][k]) > aouts_peak_tmp[i])
  982. aouts_peak_tmp[i] = abs(outBuffer[i][k]);
  983. }
  984. }
  985. }
  986. else
  987. {
  988. // disable any output sound if not active
  989. for (i=0; i < aOut.count; i++)
  990. memset(outBuffer[i], 0.0f, sizeof(float)*frames);
  991. aouts_peak_tmp[0] = 0.0;
  992. aouts_peak_tmp[1] = 0.0;
  993. } // End of Post-processing
  994. CARLA_PROCESS_CONTINUE_CHECK;
  995. // --------------------------------------------------------------------------------------------------------
  996. // Control Output
  997. if (m_active)
  998. {
  999. k = FluidSynthVoiceCount;
  1000. param_buffers[k] = fluid_synth_get_active_voice_count(f_synth);
  1001. fixParameterValue(param_buffers[k], param.ranges[k]);
  1002. if (param.data[k].midiCC > 0)
  1003. {
  1004. double value = (param_buffers[k] - param.ranges[k].min) / (param.ranges[k].max - param.ranges[k].min);
  1005. param.portCout->writeEvent(CarlaEngineEventControlChange, framesOffset, param.data[k].midiChannel, param.data[k].midiCC, value);
  1006. }
  1007. } // End of Control Output
  1008. CARLA_PROCESS_CONTINUE_CHECK;
  1009. // --------------------------------------------------------------------------------------------------------
  1010. // Peak Values
  1011. x_engine->setOutputPeak(m_id, 0, aouts_peak_tmp[0]);
  1012. x_engine->setOutputPeak(m_id, 1, aouts_peak_tmp[1]);
  1013. m_activeBefore = m_active;
  1014. }
  1015. // -------------------------------------------------------------------
  1016. bool init(const char* const filename, const char* const name, const char* const label)
  1017. {
  1018. // ---------------------------------------------------------------
  1019. // open soundfont
  1020. f_id = fluid_synth_sfload(f_synth, filename, 0);
  1021. if (f_id < 0)
  1022. {
  1023. setLastError("Failed to load SoundFont file");
  1024. return false;
  1025. }
  1026. // ---------------------------------------------------------------
  1027. // get info
  1028. m_filename = strdup(filename);
  1029. m_label = strdup(label);
  1030. if (name)
  1031. m_name = x_engine->getUniqueName(name);
  1032. else
  1033. m_name = x_engine->getUniqueName(label);
  1034. // ---------------------------------------------------------------
  1035. // register client
  1036. x_client = x_engine->addClient(this);
  1037. if (! x_client->isOk())
  1038. {
  1039. setLastError("Failed to register plugin client");
  1040. return false;
  1041. }
  1042. return true;
  1043. }
  1044. private:
  1045. enum FluidSynthInputParameters {
  1046. FluidSynthReverbOnOff = 0,
  1047. FluidSynthReverbRoomSize = 1,
  1048. FluidSynthReverbDamp = 2,
  1049. FluidSynthReverbLevel = 3,
  1050. FluidSynthReverbWidth = 4,
  1051. FluidSynthChorusOnOff = 5,
  1052. FluidSynthChorusNr = 6,
  1053. FluidSynthChorusLevel = 7,
  1054. FluidSynthChorusSpeedHz = 8,
  1055. FluidSynthChorusDepthMs = 9,
  1056. FluidSynthChorusType = 10,
  1057. FluidSynthPolyphony = 11,
  1058. FluidSynthInterpolation = 12,
  1059. FluidSynthVoiceCount = 13,
  1060. FluidSynthParametersMax = 14
  1061. };
  1062. fluid_settings_t* f_settings;
  1063. fluid_synth_t* f_synth;
  1064. int f_id;
  1065. double param_buffers[FluidSynthParametersMax];
  1066. const char* m_label;
  1067. };
  1068. #endif // WANT_FLUIDSYNTH
  1069. CarlaPlugin* CarlaPlugin::newSF2(const initializer& init)
  1070. {
  1071. qDebug("CarlaPlugin::newSF2(%p, \"%s\", \"%s\", \"%s\")", init.engine, init.filename, init.name, init.label);
  1072. #ifdef WANT_FLUIDSYNTH
  1073. short id = init.engine->getNewPluginId();
  1074. if (id < 0 || id > MAX_PLUGINS)
  1075. {
  1076. setLastError("Maximum number of plugins reached");
  1077. return nullptr;
  1078. }
  1079. if (! fluid_is_soundfont(init.filename))
  1080. {
  1081. setLastError("Requested file is not a valid SoundFont");
  1082. return nullptr;
  1083. }
  1084. FluidSynthPlugin* const plugin = new FluidSynthPlugin(init.engine, id);
  1085. if (! plugin->init(init.filename, init.name, init.label))
  1086. {
  1087. delete plugin;
  1088. return nullptr;
  1089. }
  1090. plugin->reload();
  1091. plugin->registerToOsc();
  1092. return plugin;
  1093. #else
  1094. setLastError("fluidsynth support not available");
  1095. return nullptr;
  1096. #endif
  1097. }
  1098. /**@}*/
  1099. CARLA_BACKEND_END_NAMESPACE