Audio plugin host https://kx.studio/carla
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.

1020 lines
27KB

  1. /*
  2. * Carla Native Plugins
  3. * Copyright (C) 2012-2014 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or
  6. * modify it under the terms of the GNU General Public License as
  7. * published by the Free Software Foundation; either version 2 of
  8. * the License, or any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU General Public License for more details.
  14. *
  15. * For a full copy of the GNU General Public License see the doc/GPL.txt file.
  16. */
  17. #include "CarlaNative.hpp"
  18. #include "CarlaMIDI.h"
  19. #include "CarlaThread.hpp"
  20. #include "LinkedList.hpp"
  21. #include "CarlaMathUtils.hpp"
  22. #include "DSP/FFTwrapper.h"
  23. #include "Misc/Master.h"
  24. #include "Misc/Part.h"
  25. #include "Misc/Util.h"
  26. #ifdef HAVE_ZYN_UI_DEPS
  27. # define WANT_ZYNADDSUBFX_UI
  28. #endif
  29. #ifdef WANT_ZYNADDSUBFX_UI
  30. # ifdef override
  31. # define override_hack
  32. # undef override
  33. # endif
  34. # include "UI/common.H"
  35. # include "UI/MasterUI.h"
  36. # include <FL/Fl_Shared_Image.H>
  37. # include <FL/Fl_Tiled_Image.H>
  38. # include <FL/Fl_Theme.H>
  39. # ifdef override_hack
  40. # define override
  41. # undef override_hack
  42. # endif
  43. #endif
  44. #include <ctime>
  45. #include <set>
  46. #include <string>
  47. #include "juce_audio_basics.h"
  48. using juce::FloatVectorOperations;
  49. #ifdef WANT_ZYNADDSUBFX_UI
  50. static Fl_Tiled_Image* gModuleBackdrop = nullptr;
  51. static CarlaString gPixmapPath;
  52. extern CarlaString gUiPixmapPath;
  53. void set_module_parameters(Fl_Widget* o)
  54. {
  55. CARLA_SAFE_ASSERT_RETURN(gModuleBackdrop != nullptr,);
  56. o->box(FL_DOWN_FRAME);
  57. o->align(o->align() | FL_ALIGN_IMAGE_BACKDROP);
  58. o->color(FL_BLACK);
  59. o->labeltype(FL_SHADOW_LABEL);
  60. o->image(gModuleBackdrop);
  61. }
  62. #endif
  63. // -----------------------------------------------------------------------
  64. class ZynAddSubFxPrograms
  65. {
  66. public:
  67. ZynAddSubFxPrograms() noexcept
  68. : fInitiated(false),
  69. #ifdef CARLA_PROPER_CPP11_SUPPORT
  70. fRetProgram({0, 0, nullptr}),
  71. #endif
  72. fPrograms() {}
  73. ~ZynAddSubFxPrograms() noexcept
  74. {
  75. if (! fInitiated)
  76. return;
  77. for (LinkedList<const ProgramInfo*>::Itenerator it = fPrograms.begin(); it.valid(); it.next())
  78. {
  79. const ProgramInfo* const& pInfo(it.getValue(nullptr));
  80. delete pInfo;
  81. }
  82. fPrograms.clear();
  83. }
  84. void initIfNeeded()
  85. {
  86. if (fInitiated)
  87. return;
  88. fInitiated = true;
  89. Master& master(Master::getInstance());
  90. pthread_mutex_lock(&master.mutex);
  91. fPrograms.append(new ProgramInfo(0, 0, "default"));
  92. // refresh banks
  93. master.bank.rescanforbanks();
  94. for (uint32_t i=0, size=static_cast<uint32_t>(master.bank.banks.size()); i<size; ++i)
  95. {
  96. if (master.bank.banks[i].dir.empty())
  97. continue;
  98. master.bank.loadbank(master.bank.banks[i].dir);
  99. for (uint instrument = 0; instrument < BANK_SIZE; ++instrument)
  100. {
  101. const std::string insName(master.bank.getname(instrument));
  102. if (insName.empty() || insName[0] == '\0' || insName[0] == ' ')
  103. continue;
  104. fPrograms.append(new ProgramInfo(i+1, instrument, insName.c_str()));
  105. }
  106. }
  107. pthread_mutex_unlock(&master.mutex);
  108. }
  109. void load(Master* const master, const uint8_t channel, const uint32_t bank, const uint32_t program)
  110. {
  111. if (bank == 0)
  112. {
  113. pthread_mutex_lock(&master->mutex);
  114. master->partonoff(channel, 1);
  115. master->part[channel]->defaults();
  116. master->part[channel]->applyparameters(false);
  117. pthread_mutex_unlock(&master->mutex);
  118. return;
  119. }
  120. const std::string& bankdir(master->bank.banks[bank-1].dir);
  121. if (! bankdir.empty())
  122. {
  123. pthread_mutex_lock(&master->mutex);
  124. master->partonoff(channel, 1);
  125. master->bank.loadbank(bankdir);
  126. master->bank.loadfromslot(program, master->part[channel]);
  127. master->part[channel]->applyparameters(false);
  128. pthread_mutex_unlock(&master->mutex);
  129. }
  130. }
  131. uint32_t count() const noexcept
  132. {
  133. return static_cast<uint32_t>(fPrograms.count());
  134. }
  135. const NativeMidiProgram* getInfo(const uint32_t index) const noexcept
  136. {
  137. if (index >= fPrograms.count())
  138. return nullptr;
  139. const ProgramInfo* const pInfo(fPrograms.getAt(index, nullptr));
  140. CARLA_SAFE_ASSERT_RETURN(pInfo != nullptr, nullptr);
  141. fRetProgram.bank = pInfo->bank;
  142. fRetProgram.program = pInfo->prog;
  143. fRetProgram.name = pInfo->name;
  144. return &fRetProgram;
  145. }
  146. private:
  147. struct ProgramInfo {
  148. uint32_t bank;
  149. uint32_t prog;
  150. const char* name;
  151. ProgramInfo(uint32_t b, uint32_t p, const char* n) noexcept
  152. : bank(b),
  153. prog(p),
  154. name(carla_strdup_safe(n)) {}
  155. ~ProgramInfo() noexcept
  156. {
  157. if (name != nullptr)
  158. {
  159. delete[] name;
  160. name = nullptr;
  161. }
  162. }
  163. #ifdef CARLA_PROPER_CPP11_SUPPORT
  164. ProgramInfo() = delete;
  165. ProgramInfo(ProgramInfo&) = delete;
  166. ProgramInfo(const ProgramInfo&) = delete;
  167. ProgramInfo& operator=(ProgramInfo&);
  168. ProgramInfo& operator=(const ProgramInfo&);
  169. #endif
  170. };
  171. bool fInitiated;
  172. mutable NativeMidiProgram fRetProgram;
  173. LinkedList<const ProgramInfo*> fPrograms;
  174. CARLA_PREVENT_HEAP_ALLOCATION
  175. CARLA_DECLARE_NON_COPY_CLASS(ZynAddSubFxPrograms)
  176. };
  177. static ZynAddSubFxPrograms sPrograms;
  178. // -----------------------------------------------------------------------
  179. class ZynAddSubFxInstanceCount
  180. {
  181. public:
  182. ZynAddSubFxInstanceCount()
  183. : fCount(0) {}
  184. ~ZynAddSubFxInstanceCount()
  185. {
  186. CARLA_ASSERT(fCount == 0);
  187. }
  188. void addOne(const NativeHostDescriptor* const host)
  189. {
  190. if (fCount++ != 0)
  191. return;
  192. CARLA_SAFE_ASSERT(synth == nullptr);
  193. CARLA_SAFE_ASSERT(denormalkillbuf == nullptr);
  194. reinit(host);
  195. #ifdef WANT_ZYNADDSUBFX_UI
  196. if (gPixmapPath.isEmpty())
  197. {
  198. gPixmapPath = host->resourceDir;
  199. gPixmapPath += "/zynaddsubfx/";
  200. gUiPixmapPath = gPixmapPath;
  201. }
  202. #endif
  203. }
  204. void removeOne()
  205. {
  206. if (--fCount != 0)
  207. return;
  208. CARLA_SAFE_ASSERT(synth != nullptr);
  209. CARLA_SAFE_ASSERT(denormalkillbuf != nullptr);
  210. Master::deleteInstance();
  211. delete[] denormalkillbuf;
  212. denormalkillbuf = nullptr;
  213. delete synth;
  214. synth = nullptr;
  215. }
  216. void reinit(const NativeHostDescriptor* const host)
  217. {
  218. Master::deleteInstance();
  219. if (denormalkillbuf != nullptr)
  220. {
  221. delete[] denormalkillbuf;
  222. denormalkillbuf = nullptr;
  223. }
  224. if (synth != nullptr)
  225. {
  226. delete synth;
  227. synth = nullptr;
  228. }
  229. synth = new SYNTH_T();
  230. synth->buffersize = static_cast<int>(host->get_buffer_size(host->handle));
  231. synth->samplerate = static_cast<uint>(host->get_sample_rate(host->handle));
  232. if (synth->buffersize > 32)
  233. synth->buffersize = 32;
  234. synth->alias();
  235. config.init();
  236. config.cfg.SoundBufferSize = synth->buffersize;
  237. config.cfg.SampleRate = static_cast<int>(synth->samplerate);
  238. config.cfg.GzipCompression = 0;
  239. sprng(static_cast<prng_t>(std::time(nullptr)));
  240. denormalkillbuf = new float[synth->buffersize];
  241. for (int i=0; i < synth->buffersize; ++i)
  242. denormalkillbuf[i] = (RND - 0.5f) * 1e-16f;
  243. Master::getInstance();
  244. }
  245. void maybeReinit(const NativeHostDescriptor* const host)
  246. {
  247. if (static_cast< int>(host->get_buffer_size(host->handle)) == synth->buffersize &&
  248. static_cast<uint>(host->get_sample_rate(host->handle)) == synth->samplerate)
  249. return;
  250. reinit(host);
  251. }
  252. private:
  253. int fCount;
  254. CARLA_PREVENT_HEAP_ALLOCATION
  255. CARLA_DECLARE_NON_COPY_CLASS(ZynAddSubFxInstanceCount)
  256. };
  257. static ZynAddSubFxInstanceCount sInstanceCount;
  258. // -----------------------------------------------------------------------
  259. class ZynAddSubFxThread : public CarlaThread
  260. {
  261. public:
  262. ZynAddSubFxThread(Master* const master, const NativeHostDescriptor* const host)
  263. : CarlaThread("ZynAddSubFxThread"),
  264. fMaster(master),
  265. kHost(host),
  266. #ifdef WANT_ZYNADDSUBFX_UI
  267. fUi(nullptr),
  268. fUiClosed(0),
  269. fNextUiAction(-1),
  270. #endif
  271. fChangeProgram(false),
  272. fNextChannel(0),
  273. fNextBank(0),
  274. fNextProgram(0) {}
  275. ~ZynAddSubFxThread()
  276. {
  277. #ifdef WANT_ZYNADDSUBFX_UI
  278. // must be closed by now
  279. CARLA_SAFE_ASSERT(fUi == nullptr);
  280. #endif
  281. }
  282. void loadProgramLater(const uint8_t channel, const uint32_t bank, const uint32_t program)
  283. {
  284. fNextChannel = channel;
  285. fNextBank = bank;
  286. fNextProgram = program;
  287. fChangeProgram = true;
  288. }
  289. void stopLoadProgramLater()
  290. {
  291. fChangeProgram = false;
  292. fNextChannel = 0;
  293. fNextBank = 0;
  294. fNextProgram = 0;
  295. }
  296. void setMaster(Master* const master)
  297. {
  298. fMaster = master;
  299. }
  300. #ifdef WANT_ZYNADDSUBFX_UI
  301. void uiHide()
  302. {
  303. fNextUiAction = 0;
  304. }
  305. void uiShow()
  306. {
  307. fNextUiAction = 1;
  308. }
  309. void uiRepaint()
  310. {
  311. if (fUi != nullptr)
  312. fNextUiAction = 2;
  313. }
  314. void uiChangeName(const char* const name)
  315. {
  316. if (fUi != nullptr)
  317. {
  318. Fl::lock();
  319. fUi->masterwindow->label(name);
  320. Fl::unlock();
  321. }
  322. }
  323. #endif
  324. protected:
  325. void run() override
  326. {
  327. while (! shouldThreadExit())
  328. {
  329. #ifdef WANT_ZYNADDSUBFX_UI
  330. Fl::lock();
  331. if (fNextUiAction == 2) // repaint
  332. {
  333. CARLA_ASSERT(fUi != nullptr);
  334. if (fUi != nullptr)
  335. fUi->refresh_master_ui();
  336. }
  337. else if (fNextUiAction == 1) // init/show
  338. {
  339. static bool initialized = false;
  340. if (! initialized)
  341. {
  342. initialized = true;
  343. fl_register_images();
  344. Fl_Dial::default_style(Fl_Dial::PIXMAP_DIAL);
  345. if (Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "knob.png"))
  346. Fl_Dial::default_image(img);
  347. if (Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "window_backdrop.png"))
  348. Fl::scheme_bg(new Fl_Tiled_Image(img));
  349. if(Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "module_backdrop.png"))
  350. gModuleBackdrop = new Fl_Tiled_Image(img);
  351. Fl::background(50, 50, 50);
  352. Fl::background2(70, 70, 70);
  353. Fl::foreground(255, 255, 255);
  354. Fl_Theme::set("Cairo");
  355. }
  356. if (fUi == nullptr)
  357. {
  358. fUiClosed = 0;
  359. fUi = new MasterUI(fMaster, &fUiClosed);
  360. fUi->masterwindow->label(kHost->uiName);
  361. fUi->showUI();
  362. }
  363. else
  364. fUi->showUI();
  365. }
  366. else if (fNextUiAction == 0) // close
  367. {
  368. CARLA_ASSERT(fUi != nullptr);
  369. if (fUi != nullptr)
  370. {
  371. delete fUi;
  372. fUi = nullptr;
  373. }
  374. }
  375. fNextUiAction = -1;
  376. if (fUiClosed != 0)
  377. {
  378. fUiClosed = 0;
  379. fNextUiAction = 0;
  380. kHost->ui_closed(kHost->handle);
  381. }
  382. Fl::check();
  383. Fl::unlock();
  384. #endif
  385. if (fChangeProgram)
  386. {
  387. fChangeProgram = false;
  388. sPrograms.load(fMaster, fNextChannel, fNextBank, fNextProgram);
  389. fNextChannel = 0;
  390. fNextBank = 0;
  391. fNextProgram = 0;
  392. #ifdef WANT_ZYNADDSUBFX_UI
  393. if (fUi != nullptr)
  394. {
  395. Fl::lock();
  396. fUi->refresh_master_ui();
  397. Fl::unlock();
  398. }
  399. #endif
  400. carla_msleep(15);
  401. }
  402. else
  403. {
  404. carla_msleep(30);
  405. }
  406. }
  407. #ifdef WANT_ZYNADDSUBFX_UI
  408. if (fUi != nullptr)
  409. {
  410. Fl::lock();
  411. delete fUi;
  412. fUi = nullptr;
  413. Fl::check();
  414. Fl::unlock();
  415. }
  416. #endif
  417. }
  418. private:
  419. Master* fMaster;
  420. const NativeHostDescriptor* const kHost;
  421. #ifdef WANT_ZYNADDSUBFX_UI
  422. MasterUI* fUi;
  423. int fUiClosed;
  424. volatile int fNextUiAction;
  425. #endif
  426. volatile bool fChangeProgram;
  427. volatile uint8_t fNextChannel;
  428. volatile uint32_t fNextBank;
  429. volatile uint32_t fNextProgram;
  430. CARLA_PREVENT_VIRTUAL_HEAP_ALLOCATION
  431. CARLA_DECLARE_NON_COPY_CLASS(ZynAddSubFxThread)
  432. };
  433. // -----------------------------------------------------------------------
  434. class ZynAddSubFxPlugin : public NativePluginClass
  435. {
  436. public:
  437. enum Parameters {
  438. kParamFilterCutoff = 0, // Filter Frequency
  439. kParamFilterQ, // Filter Resonance
  440. kParamBandwidth, // Bandwidth
  441. kParamModAmp, // FM Gain
  442. kParamResCenter, // Resonance center frequency
  443. kParamResBandwidth, // Resonance bandwidth
  444. kParamCount
  445. };
  446. ZynAddSubFxPlugin(const NativeHostDescriptor* const host)
  447. : NativePluginClass(host),
  448. fMaster(nullptr),
  449. fSampleRate(static_cast<uint>(getSampleRate())),
  450. fIsActive(false),
  451. fThread(nullptr, host),
  452. leakDetector_ZynAddSubFxPlugin()
  453. {
  454. // init parameters to default
  455. fParameters[kParamFilterCutoff] = 64.0f;
  456. fParameters[kParamFilterQ] = 64.0f;
  457. fParameters[kParamBandwidth] = 64.0f;
  458. fParameters[kParamModAmp] = 127.0f;
  459. fParameters[kParamResCenter] = 64.0f;
  460. fParameters[kParamResBandwidth] = 64.0f;
  461. _initMaster();
  462. sPrograms.initIfNeeded();
  463. }
  464. ~ZynAddSubFxPlugin() override
  465. {
  466. _deleteMaster();
  467. }
  468. protected:
  469. // -------------------------------------------------------------------
  470. // Plugin parameter calls
  471. uint32_t getParameterCount() const final
  472. {
  473. return kParamCount;
  474. }
  475. const NativeParameter* getParameterInfo(const uint32_t index) const override
  476. {
  477. CARLA_SAFE_ASSERT_RETURN(index < kParamCount, nullptr);
  478. static NativeParameter param;
  479. int hints = NATIVE_PARAMETER_IS_ENABLED|NATIVE_PARAMETER_IS_INTEGER|NATIVE_PARAMETER_IS_AUTOMABLE;
  480. param.name = nullptr;
  481. param.unit = nullptr;
  482. param.ranges.def = 64.0f;
  483. param.ranges.min = 0.0f;
  484. param.ranges.max = 127.0f;
  485. param.ranges.step = 1.0f;
  486. param.ranges.stepSmall = 1.0f;
  487. param.ranges.stepLarge = 20.0f;
  488. param.scalePointCount = 0;
  489. param.scalePoints = nullptr;
  490. switch (index)
  491. {
  492. case kParamFilterCutoff:
  493. param.name = "Filter Cutoff";
  494. break;
  495. case kParamFilterQ:
  496. param.name = "Filter Q";
  497. break;
  498. case kParamBandwidth:
  499. param.name = "Bandwidth";
  500. break;
  501. case kParamModAmp:
  502. param.name = "FM Gain";
  503. param.ranges.def = 127.0f;
  504. break;
  505. case kParamResCenter:
  506. param.name = "Res Center Freq";
  507. break;
  508. case kParamResBandwidth:
  509. param.name = "Res Bandwidth";
  510. break;
  511. }
  512. param.hints = static_cast<NativeParameterHints>(hints);
  513. return &param;
  514. }
  515. float getParameterValue(const uint32_t index) const final
  516. {
  517. CARLA_SAFE_ASSERT_RETURN(index < kParamCount, 0.0f);
  518. return fParameters[index];
  519. }
  520. // -------------------------------------------------------------------
  521. // Plugin midi-program calls
  522. uint32_t getMidiProgramCount() const override
  523. {
  524. return sPrograms.count();
  525. }
  526. const NativeMidiProgram* getMidiProgramInfo(const uint32_t index) const override
  527. {
  528. return sPrograms.getInfo(index);
  529. }
  530. // -------------------------------------------------------------------
  531. // Plugin state calls
  532. void setParameterValue(const uint32_t index, const float value) final
  533. {
  534. CARLA_SAFE_ASSERT_RETURN(index < kParamCount,);
  535. const uint zynIndex(getZynParameterFromIndex(index));
  536. CARLA_SAFE_ASSERT_RETURN(zynIndex != C_NULL,);
  537. fParameters[index] = value;
  538. for (int npart=0; npart<NUM_MIDI_PARTS; ++npart)
  539. {
  540. if (fMaster->part[npart] != nullptr && fMaster->part[npart]->Penabled != 0)
  541. fMaster->part[npart]->SetController(zynIndex, static_cast<int>(value));
  542. }
  543. }
  544. void setMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program) override
  545. {
  546. if (bank >= fMaster->bank.banks.size())
  547. return;
  548. if (program >= BANK_SIZE)
  549. return;
  550. if (isOffline() || ! fIsActive)
  551. {
  552. sPrograms.load(fMaster, channel, bank, program);
  553. #ifdef WANT_ZYNADDSUBFX_UI
  554. fThread.uiRepaint();
  555. #endif
  556. return;
  557. }
  558. fThread.loadProgramLater(channel, bank, program);
  559. }
  560. void setCustomData(const char* const key, const char* const value) override
  561. {
  562. CARLA_SAFE_ASSERT_RETURN(key != nullptr,);
  563. CARLA_SAFE_ASSERT_RETURN(value != nullptr,);
  564. pthread_mutex_lock(&fMaster->mutex);
  565. /**/ if (std::strcmp(key, "CarlaAlternateFile1") == 0) // xmz
  566. {
  567. fMaster->defaults();
  568. fMaster->loadXML(value);
  569. }
  570. else if (std::strcmp(key, "CarlaAlternateFile2") == 0) // xiz
  571. {
  572. fMaster->part[0]->defaultsinstrument();
  573. fMaster->part[0]->loadXMLinstrument(value);
  574. }
  575. pthread_mutex_unlock(&fMaster->mutex);
  576. fMaster->applyparameters();
  577. }
  578. // -------------------------------------------------------------------
  579. // Plugin process calls
  580. void activate() override
  581. {
  582. fIsActive = true;
  583. }
  584. void deactivate() override
  585. {
  586. fIsActive = false;
  587. }
  588. void process(float**, float** const outBuffer, const uint32_t frames, const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override
  589. {
  590. if (pthread_mutex_trylock(&fMaster->mutex) != 0)
  591. {
  592. FloatVectorOperations::clear(outBuffer[0], static_cast<int>(frames));
  593. FloatVectorOperations::clear(outBuffer[1], static_cast<int>(frames));
  594. return;
  595. }
  596. for (uint32_t i=0; i < midiEventCount; ++i)
  597. {
  598. const NativeMidiEvent* const midiEvent(&midiEvents[i]);
  599. const uint8_t status = MIDI_GET_STATUS_FROM_DATA(midiEvent->data);
  600. const char channel = MIDI_GET_CHANNEL_FROM_DATA(midiEvent->data);
  601. if (MIDI_IS_STATUS_NOTE_OFF(status))
  602. {
  603. const char note = static_cast<char>(midiEvent->data[1]);
  604. fMaster->noteOff(channel, note);
  605. }
  606. else if (MIDI_IS_STATUS_NOTE_ON(status))
  607. {
  608. const char note = static_cast<char>(midiEvent->data[1]);
  609. const char velo = static_cast<char>(midiEvent->data[2]);
  610. fMaster->noteOn(channel, note, velo);
  611. }
  612. else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status))
  613. {
  614. const char note = static_cast<char>(midiEvent->data[1]);
  615. const char pressure = static_cast<char>(midiEvent->data[2]);
  616. fMaster->polyphonicAftertouch(channel, note, pressure);
  617. }
  618. else if (MIDI_IS_STATUS_CONTROL_CHANGE(status))
  619. {
  620. // skip controls which we map to parameters
  621. if (getZynParameterFromIndex(midiEvent->data[1]) == C_NULL)
  622. continue;
  623. const int control = midiEvent->data[1];
  624. const int value = midiEvent->data[2];
  625. fMaster->setController(channel, control, value);
  626. }
  627. else if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status))
  628. {
  629. const uint8_t lsb = midiEvent->data[1];
  630. const uint8_t msb = midiEvent->data[2];
  631. const int value = ((msb << 7) | lsb) - 8192;
  632. fMaster->setController(channel, C_pitchwheel, value);
  633. }
  634. }
  635. fMaster->GetAudioOutSamples(frames, fSampleRate, outBuffer[0], outBuffer[1]);
  636. pthread_mutex_unlock(&fMaster->mutex);
  637. }
  638. #ifdef WANT_ZYNADDSUBFX_UI
  639. // -------------------------------------------------------------------
  640. // Plugin UI calls
  641. void uiShow(const bool show) override
  642. {
  643. if (show)
  644. fThread.uiShow();
  645. else
  646. fThread.uiHide();
  647. }
  648. #endif
  649. // -------------------------------------------------------------------
  650. // Plugin state calls
  651. char* getState() const override
  652. {
  653. config.save();
  654. char* data = nullptr;
  655. fMaster->getalldata(&data);
  656. return data;
  657. }
  658. void setState(const char* const data) override
  659. {
  660. fThread.stopLoadProgramLater();
  661. fMaster->putalldata(const_cast<char*>(data), 0);
  662. fMaster->applyparameters(true);
  663. }
  664. // -------------------------------------------------------------------
  665. // Plugin dispatcher
  666. void bufferSizeChanged(const uint32_t) final
  667. {
  668. char* const state(getState());
  669. _deleteMaster();
  670. sInstanceCount.maybeReinit(getHostHandle());
  671. _initMaster();
  672. if (state != nullptr)
  673. {
  674. fMaster->putalldata(state, 0);
  675. fMaster->applyparameters(true);
  676. std::free(state);
  677. }
  678. }
  679. void sampleRateChanged(const double sampleRate) final
  680. {
  681. fSampleRate = static_cast<uint>(sampleRate);
  682. char* const state(getState());
  683. _deleteMaster();
  684. sInstanceCount.maybeReinit(getHostHandle());
  685. _initMaster();
  686. if (state != nullptr)
  687. {
  688. fMaster->putalldata(state, 0);
  689. fMaster->applyparameters(true);
  690. std::free(state);
  691. }
  692. }
  693. #ifdef WANT_ZYNADDSUBFX_UI
  694. void uiNameChanged(const char* const uiName) override
  695. {
  696. fThread.uiChangeName(uiName);
  697. }
  698. #endif
  699. // -------------------------------------------------------------------
  700. private:
  701. Master* fMaster;
  702. uint fSampleRate;
  703. bool fIsActive;
  704. float fParameters[kParamCount];
  705. ZynAddSubFxThread fThread;
  706. /*
  707. static Parameters getParameterFromZynIndex(const MidiControllers index)
  708. {
  709. switch (index)
  710. {
  711. case C_filtercutoff:
  712. return kParamFilterCutoff;
  713. case C_filterq:
  714. return kParamFilterQ;
  715. case C_bandwidth:
  716. return kParamBandwidth;
  717. case C_fmamp:
  718. return kParamModAmp;
  719. case C_resonance_center:
  720. return kParamResCenter;
  721. case C_resonance_bandwidth:
  722. return kParamResBandwidth;
  723. default:
  724. return kParamCount;
  725. }
  726. }
  727. */
  728. static uint getZynParameterFromIndex(const uint index)
  729. {
  730. switch (index)
  731. {
  732. case kParamFilterCutoff:
  733. return C_filtercutoff;
  734. case kParamFilterQ:
  735. return C_filterq;
  736. case kParamBandwidth:
  737. return C_bandwidth;
  738. case kParamModAmp:
  739. return C_fmamp;
  740. case kParamResCenter:
  741. return C_resonance_center;
  742. case kParamResBandwidth:
  743. return C_resonance_bandwidth;
  744. case kParamCount:
  745. return C_NULL;
  746. }
  747. return C_NULL;
  748. }
  749. // -------------------------------------------------------------------
  750. void _initMaster()
  751. {
  752. fMaster = new Master();
  753. fThread.setMaster(fMaster);
  754. fThread.startThread();
  755. for (int i=0; i<NUM_MIDI_PARTS; ++i)
  756. {
  757. fMaster->partonoff(i, 1);
  758. for (int npart=0; npart<NUM_MIDI_PARTS; ++npart)
  759. {
  760. fMaster->part[npart]->SetController(C_filtercutoff, static_cast<int>(fParameters[kParamFilterCutoff]));
  761. fMaster->part[npart]->SetController(C_filterq, static_cast<int>(fParameters[kParamFilterQ]));
  762. fMaster->part[npart]->SetController(C_bandwidth, static_cast<int>(fParameters[kParamBandwidth]));
  763. fMaster->part[npart]->SetController(C_fmamp, static_cast<int>(fParameters[kParamModAmp]));
  764. fMaster->part[npart]->SetController(C_resonance_center, static_cast<int>(fParameters[kParamResCenter]));
  765. fMaster->part[npart]->SetController(C_resonance_bandwidth, static_cast<int>(fParameters[kParamResBandwidth]));
  766. }
  767. }
  768. }
  769. void _deleteMaster()
  770. {
  771. //ensure that everything has stopped
  772. pthread_mutex_lock(&fMaster->mutex);
  773. pthread_mutex_unlock(&fMaster->mutex);
  774. fThread.stopThread(-1);
  775. delete fMaster;
  776. fMaster = nullptr;
  777. }
  778. // -------------------------------------------------------------------
  779. public:
  780. static NativePluginHandle _instantiate(const NativeHostDescriptor* host)
  781. {
  782. sInstanceCount.addOne(host);
  783. return new ZynAddSubFxPlugin(host);
  784. }
  785. static void _cleanup(NativePluginHandle handle)
  786. {
  787. delete (ZynAddSubFxPlugin*)handle;
  788. sInstanceCount.removeOne();
  789. }
  790. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ZynAddSubFxPlugin)
  791. };
  792. // -----------------------------------------------------------------------
  793. static const NativePluginDescriptor zynaddsubfxDesc = {
  794. /* category */ NATIVE_PLUGIN_CATEGORY_SYNTH,
  795. /* hints */ static_cast<NativePluginHints>(NATIVE_PLUGIN_IS_SYNTH
  796. #ifdef WANT_ZYNADDSUBFX_UI
  797. |NATIVE_PLUGIN_HAS_UI
  798. #endif
  799. |NATIVE_PLUGIN_USES_MULTI_PROGS
  800. |NATIVE_PLUGIN_USES_STATE),
  801. /* supports */ static_cast<NativePluginSupports>(NATIVE_PLUGIN_SUPPORTS_CONTROL_CHANGES
  802. |NATIVE_PLUGIN_SUPPORTS_NOTE_AFTERTOUCH
  803. |NATIVE_PLUGIN_SUPPORTS_PITCHBEND
  804. |NATIVE_PLUGIN_SUPPORTS_ALL_SOUND_OFF),
  805. /* audioIns */ 0,
  806. /* audioOuts */ 2,
  807. /* midiIns */ 1,
  808. /* midiOuts */ 0,
  809. /* paramIns */ ZynAddSubFxPlugin::kParamCount,
  810. /* paramOuts */ 0,
  811. /* name */ "ZynAddSubFX",
  812. /* label */ "zynaddsubfx",
  813. /* maker */ "falkTX, Mark McCurry, Nasca Octavian Paul",
  814. /* copyright */ "GNU GPL v2+",
  815. PluginDescriptorFILL(ZynAddSubFxPlugin)
  816. };
  817. // -----------------------------------------------------------------------
  818. CARLA_EXPORT
  819. void carla_register_native_plugin_zynaddsubfx_synth();
  820. CARLA_EXPORT
  821. void carla_register_native_plugin_zynaddsubfx_synth()
  822. {
  823. carla_register_native_plugin(&zynaddsubfxDesc);
  824. }
  825. // -----------------------------------------------------------------------