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.

1360 lines
45KB

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