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.

1805 lines
49KB

  1. /*
  2. * Carla Native Plugins
  3. * Copyright (C) 2012-2013 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 GPL.txt file
  16. */
  17. // for UINT32_MAX
  18. #define __STDC_LIMIT_MACROS
  19. #include <cstdint>
  20. #include "CarlaNative.hpp"
  21. #include "CarlaMIDI.h"
  22. #include "CarlaString.hpp"
  23. #include "RtList.hpp"
  24. #include <QtCore/QThread>
  25. #include "zynaddsubfx/Misc/Master.h"
  26. #include "zynaddsubfx/Misc/Part.h"
  27. #include "zynaddsubfx/Misc/Util.h"
  28. #include "zynaddsubfx/Effects/Alienwah.h"
  29. #include "zynaddsubfx/Effects/Chorus.h"
  30. #include "zynaddsubfx/Effects/Distorsion.h"
  31. #include "zynaddsubfx/Effects/DynamicFilter.h"
  32. #include "zynaddsubfx/Effects/Echo.h"
  33. #include "zynaddsubfx/Effects/EQ.h"
  34. #include "zynaddsubfx/Effects/Phaser.h"
  35. #include "zynaddsubfx/Effects/Reverb.h"
  36. #ifdef WANT_ZYNADDSUBFX_UI
  37. # ifdef override
  38. # define override_hack
  39. # undef override
  40. # endif
  41. # include "zynaddsubfx/UI/common.H"
  42. # include "zynaddsubfx/UI/MasterUI.h"
  43. # include <FL/Fl_Shared_Image.H>
  44. # include <FL/Fl_Tiled_Image.H>
  45. # include <FL/Fl_Theme.H>
  46. # ifdef override_hack
  47. # define override
  48. # undef override_hack
  49. # endif
  50. #endif
  51. #include <ctime>
  52. #include <set>
  53. #include <string>
  54. // Dummy variables and functions for linking purposes
  55. const char* instance_name = nullptr;
  56. class WavFile;
  57. namespace Nio {
  58. bool start(void){return 1;}
  59. void stop(void){}
  60. bool setSource(std::string){return true;}
  61. bool setSink(std::string){return true;}
  62. std::set<std::string> getSources(void){return std::set<std::string>();}
  63. std::set<std::string> getSinks(void){return std::set<std::string>();}
  64. std::string getSource(void){return "";}
  65. std::string getSink(void){return "";}
  66. void waveNew(WavFile*){}
  67. void waveStart(void){}
  68. void waveStop(void){}
  69. void waveEnd(void){}
  70. }
  71. SYNTH_T* synth = nullptr;
  72. #ifdef WANT_ZYNADDSUBFX_UI
  73. #define PIXMAP_PATH "/resources/zynaddsubfx/"
  74. static Fl_Tiled_Image* gModuleBackdrop = nullptr;
  75. static CarlaString gPixmapPath;
  76. extern CarlaString gUiPixmapPath;
  77. void set_module_parameters(Fl_Widget* o)
  78. {
  79. CARLA_ASSERT(gModuleBackdrop != nullptr);
  80. o->box(FL_DOWN_FRAME);
  81. o->align(o->align() | FL_ALIGN_IMAGE_BACKDROP);
  82. o->color(FL_BLACK);
  83. o->labeltype(FL_SHADOW_LABEL);
  84. if (gModuleBackdrop != nullptr)
  85. o->image(gModuleBackdrop);
  86. }
  87. #endif
  88. // -----------------------------------------------------------------------
  89. class ZynAddSubFxPrograms
  90. {
  91. public:
  92. ZynAddSubFxPrograms()
  93. : fInitiated(false)
  94. {
  95. }
  96. ~ZynAddSubFxPrograms()
  97. {
  98. if (! fInitiated)
  99. return;
  100. for (auto it = fPrograms.begin(); it.valid(); it.next())
  101. {
  102. const ProgramInfo*& pInfo(*it);
  103. delete pInfo;
  104. }
  105. fPrograms.clear();
  106. }
  107. void init()
  108. {
  109. if (fInitiated)
  110. return;
  111. fInitiated = true;
  112. fPrograms.append(new ProgramInfo(0, 0, "default"));
  113. Master& master(Master::getInstance());
  114. pthread_mutex_lock(&master.mutex);
  115. // refresh banks
  116. master.bank.rescanforbanks();
  117. for (uint32_t i=0, size = master.bank.banks.size(); i < size; ++i)
  118. {
  119. if (master.bank.banks[i].dir.empty())
  120. continue;
  121. master.bank.loadbank(master.bank.banks[i].dir);
  122. for (unsigned int instrument = 0; instrument < BANK_SIZE; ++instrument)
  123. {
  124. const std::string insName(master.bank.getname(instrument));
  125. if (insName.empty() || insName[0] == '\0' || insName[0] == ' ')
  126. continue;
  127. fPrograms.append(new ProgramInfo(i+1, instrument, insName.c_str()));
  128. }
  129. }
  130. pthread_mutex_unlock(&master.mutex);
  131. }
  132. void load(Master* const master, const uint8_t channel, const uint32_t bank, const uint32_t program)
  133. {
  134. if (bank == 0)
  135. {
  136. pthread_mutex_lock(&master->mutex);
  137. master->partonoff(channel, 1);
  138. master->part[channel]->defaults();
  139. master->part[channel]->applyparameters(false);
  140. pthread_mutex_unlock(&master->mutex);
  141. return;
  142. }
  143. const std::string& bankdir(master->bank.banks[bank-1].dir);
  144. if (! bankdir.empty())
  145. {
  146. pthread_mutex_lock(&master->mutex);
  147. master->partonoff(channel, 1);
  148. master->bank.loadbank(bankdir);
  149. master->bank.loadfromslot(program, master->part[channel]);
  150. master->part[channel]->applyparameters(false);
  151. pthread_mutex_unlock(&master->mutex);
  152. }
  153. }
  154. uint32_t count()
  155. {
  156. return fPrograms.count();
  157. }
  158. const MidiProgram* getInfo(const uint32_t index)
  159. {
  160. if (index >= fPrograms.count())
  161. return nullptr;
  162. const ProgramInfo*& pInfo(fPrograms.getAt(index));
  163. fRetProgram.bank = pInfo->bank;
  164. fRetProgram.program = pInfo->prog;
  165. fRetProgram.name = pInfo->name;
  166. return &fRetProgram;
  167. }
  168. private:
  169. struct ProgramInfo {
  170. uint32_t bank;
  171. uint32_t prog;
  172. const char* name;
  173. ProgramInfo(uint32_t bank_, uint32_t prog_, const char* name_)
  174. : bank(bank_),
  175. prog(prog_),
  176. name(carla_strdup(name_)) {}
  177. ~ProgramInfo()
  178. {
  179. if (name != nullptr)
  180. {
  181. delete[] name;
  182. name = nullptr;
  183. }
  184. }
  185. #ifdef CARLA_PROPER_CPP11_SUPPORT
  186. ProgramInfo() = delete;
  187. ProgramInfo(ProgramInfo&) = delete;
  188. ProgramInfo(const ProgramInfo&) = delete;
  189. #endif
  190. };
  191. bool fInitiated;
  192. MidiProgram fRetProgram;
  193. NonRtList<const ProgramInfo*> fPrograms;
  194. CARLA_DECLARE_NON_COPYABLE(ZynAddSubFxPrograms)
  195. };
  196. static ZynAddSubFxPrograms sPrograms;
  197. // -----------------------------------------------------------------------
  198. class ZynAddSubFxInstanceCount
  199. {
  200. public:
  201. ZynAddSubFxInstanceCount()
  202. : fCount(0)
  203. {
  204. }
  205. ~ZynAddSubFxInstanceCount()
  206. {
  207. CARLA_ASSERT(fCount == 0);
  208. }
  209. void addOne(const HostDescriptor* const host)
  210. {
  211. if (fCount++ == 0)
  212. {
  213. CARLA_ASSERT(synth == nullptr);
  214. CARLA_ASSERT(denormalkillbuf == nullptr);
  215. reinit(host);
  216. #ifdef WANT_ZYNADDSUBFX_UI
  217. if (gPixmapPath.isEmpty())
  218. {
  219. gPixmapPath = host->resource_dir;
  220. gPixmapPath += PIXMAP_PATH;
  221. gUiPixmapPath = gPixmapPath;
  222. }
  223. #endif
  224. }
  225. }
  226. void removeOne()
  227. {
  228. if (--fCount == 0)
  229. {
  230. CARLA_ASSERT(synth != nullptr);
  231. CARLA_ASSERT(denormalkillbuf != nullptr);
  232. Master::deleteInstance();
  233. delete[] denormalkillbuf;
  234. denormalkillbuf = nullptr;
  235. delete synth;
  236. synth = nullptr;
  237. }
  238. }
  239. void reinit(const HostDescriptor* const host)
  240. {
  241. Master::deleteInstance();
  242. if (denormalkillbuf != nullptr)
  243. {
  244. delete[] denormalkillbuf;
  245. denormalkillbuf = nullptr;
  246. }
  247. if (synth != nullptr)
  248. {
  249. delete synth;
  250. synth = nullptr;
  251. }
  252. synth = new SYNTH_T();
  253. synth->buffersize = host->get_buffer_size(host->handle);
  254. synth->samplerate = host->get_sample_rate(host->handle);
  255. synth->alias();
  256. config.init();
  257. config.cfg.SoundBufferSize = synth->buffersize;
  258. config.cfg.SampleRate = synth->samplerate;
  259. config.cfg.GzipCompression = 0;
  260. sprng(std::time(nullptr));
  261. denormalkillbuf = new float[synth->buffersize];
  262. for (int i=0; i < synth->buffersize; ++i)
  263. denormalkillbuf[i] = (RND - 0.5f) * 1e-16;
  264. Master::getInstance();
  265. }
  266. void maybeReinit(const HostDescriptor* const host)
  267. {
  268. if (host->get_buffer_size(host->handle) == static_cast<uint32_t>(synth->buffersize) &&
  269. host->get_sample_rate(host->handle) == static_cast<double>(synth->samplerate))
  270. return;
  271. reinit(host);
  272. }
  273. private:
  274. int fCount;
  275. CARLA_DECLARE_NON_COPYABLE(ZynAddSubFxInstanceCount)
  276. };
  277. static ZynAddSubFxInstanceCount sInstanceCount;
  278. // -----------------------------------------------------------------------
  279. class ZynAddSubFxThread : public QThread
  280. {
  281. public:
  282. ZynAddSubFxThread(Master* const master, const HostDescriptor* const host)
  283. : fMaster(master),
  284. kHost(host),
  285. #ifdef WANT_ZYNADDSUBFX_UI
  286. fUi(nullptr),
  287. fUiClosed(0),
  288. fNextUiAction(-1),
  289. #endif
  290. fQuit(false),
  291. fChangeProgram(false),
  292. fNextChannel(0),
  293. fNextBank(0),
  294. fNextProgram(0)
  295. {
  296. }
  297. ~ZynAddSubFxThread()
  298. {
  299. // must be closed by now
  300. #ifdef WANT_ZYNADDSUBFX_UI
  301. CARLA_ASSERT(fUi == nullptr);
  302. #endif
  303. CARLA_ASSERT(fQuit);
  304. }
  305. void loadProgramLater(const uint8_t channel, const uint32_t bank, const uint32_t program)
  306. {
  307. fNextChannel = channel;
  308. fNextBank = bank;
  309. fNextProgram = program;
  310. fChangeProgram = true;
  311. }
  312. void stopLoadProgramLater()
  313. {
  314. fChangeProgram = false;
  315. fNextChannel = 0;
  316. fNextBank = 0;
  317. fNextProgram = 0;
  318. }
  319. void setMaster(Master* const master)
  320. {
  321. fMaster = master;
  322. }
  323. void stop()
  324. {
  325. fQuit = true;
  326. quit();
  327. }
  328. #ifdef WANT_ZYNADDSUBFX_UI
  329. void uiHide()
  330. {
  331. fNextUiAction = 0;
  332. }
  333. void uiShow()
  334. {
  335. fNextUiAction = 1;
  336. }
  337. void uiRepaint()
  338. {
  339. if (fUi != nullptr)
  340. fNextUiAction = 2;
  341. }
  342. #endif
  343. protected:
  344. void run() override
  345. {
  346. while (! fQuit)
  347. {
  348. #ifdef WANT_ZYNADDSUBFX_UI
  349. Fl::lock();
  350. if (fNextUiAction == 2) // repaint
  351. {
  352. CARLA_ASSERT(fUi != nullptr);
  353. if (fUi != nullptr)
  354. fUi->refresh_master_ui();
  355. }
  356. else if (fNextUiAction == 1) // init/show
  357. {
  358. static bool initialized = false;
  359. if (! initialized)
  360. {
  361. initialized = true;
  362. fl_register_images();
  363. Fl_Dial::default_style(Fl_Dial::PIXMAP_DIAL);
  364. if (Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "knob.png"))
  365. Fl_Dial::default_image(img);
  366. if (Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "window_backdrop.png"))
  367. Fl::scheme_bg(new Fl_Tiled_Image(img));
  368. if(Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "module_backdrop.png"))
  369. gModuleBackdrop = new Fl_Tiled_Image(img);
  370. Fl::background(50, 50, 50);
  371. Fl::background2(70, 70, 70);
  372. Fl::foreground(255, 255, 255);
  373. Fl_Theme::set("Cairo");
  374. }
  375. CARLA_ASSERT(fUi == nullptr);
  376. if (fUi == nullptr)
  377. {
  378. fUiClosed = 0;
  379. fUi = new MasterUI(fMaster, &fUiClosed);
  380. fUi->showUI();
  381. }
  382. }
  383. else if (fNextUiAction == 0) // close
  384. {
  385. CARLA_ASSERT(fUi != nullptr);
  386. if (fUi != nullptr)
  387. {
  388. delete fUi;
  389. fUi = nullptr;
  390. }
  391. }
  392. fNextUiAction = -1;
  393. if (fUiClosed != 0)
  394. {
  395. fUiClosed = 0;
  396. fNextUiAction = 0;
  397. kHost->ui_closed(kHost->handle);
  398. }
  399. Fl::check();
  400. Fl::unlock();
  401. #endif
  402. if (fChangeProgram)
  403. {
  404. fChangeProgram = false;
  405. sPrograms.load(fMaster, fNextChannel, fNextBank, fNextProgram);
  406. fNextChannel = 0;
  407. fNextBank = 0;
  408. fNextProgram = 0;
  409. #ifdef WANT_ZYNADDSUBFX_UI
  410. if (fUi != nullptr)
  411. {
  412. Fl::lock();
  413. fUi->refresh_master_ui();
  414. Fl::unlock();
  415. }
  416. #endif
  417. carla_msleep(15);
  418. }
  419. else
  420. {
  421. carla_msleep(30);
  422. }
  423. }
  424. #ifdef WANT_ZYNADDSUBFX_UI
  425. if (fQuit && fUi != nullptr)
  426. {
  427. Fl::lock();
  428. delete fUi;
  429. fUi = nullptr;
  430. Fl::check();
  431. Fl::unlock();
  432. }
  433. #endif
  434. }
  435. private:
  436. Master* fMaster;
  437. const HostDescriptor* const kHost;
  438. #ifdef WANT_ZYNADDSUBFX_UI
  439. MasterUI* fUi;
  440. int fUiClosed;
  441. int fNextUiAction;
  442. #endif
  443. bool fQuit;
  444. bool fChangeProgram;
  445. uint8_t fNextChannel;
  446. uint32_t fNextBank;
  447. uint32_t fNextProgram;
  448. };
  449. // -----------------------------------------------------------------------
  450. #define ZynPluginDescriptorClassEND(ClassName) \
  451. public: \
  452. static PluginHandle _instantiate(const PluginDescriptor*, HostDescriptor* host) \
  453. { \
  454. sInstanceCount.addOne(host); \
  455. return new ClassName(host); \
  456. } \
  457. static void _cleanup(PluginHandle handle) \
  458. { \
  459. delete (ClassName*)handle; \
  460. sInstanceCount.removeOne(); \
  461. }
  462. // -----------------------------------------------------------------------
  463. class FxAbstractPlugin : public PluginDescriptorClass
  464. {
  465. protected:
  466. FxAbstractPlugin(const HostDescriptor* const host, const uint32_t paramCount, const uint32_t programCount)
  467. : PluginDescriptorClass(host),
  468. fEffect(nullptr),
  469. efxoutl(new float[synth->buffersize]),
  470. efxoutr(new float[synth->buffersize]),
  471. fWetOnly(false),
  472. kParamCount(paramCount-2), // volume and pan handled by host
  473. kProgramCount(programCount)
  474. {
  475. hostDispatcher(HOST_OPCODE_SET_DRYWET, 0, 0, nullptr, 0.5f);
  476. }
  477. ~FxAbstractPlugin() override
  478. {
  479. CARLA_ASSERT(fEffect != nullptr);
  480. if (efxoutl != nullptr)
  481. {
  482. delete[] efxoutl;
  483. efxoutl = nullptr;
  484. }
  485. if (efxoutr != nullptr)
  486. {
  487. delete[] efxoutr;
  488. efxoutr = nullptr;
  489. }
  490. if (fEffect != nullptr)
  491. {
  492. delete fEffect;
  493. fEffect = nullptr;
  494. }
  495. }
  496. // -------------------------------------------------------------------
  497. // Plugin parameter calls
  498. uint32_t getParameterCount() final
  499. {
  500. return kParamCount;
  501. }
  502. float getParameterValue(const uint32_t index) final
  503. {
  504. return fEffect->getpar(index+2);
  505. }
  506. // -------------------------------------------------------------------
  507. // Plugin midi-program calls
  508. uint32_t getMidiProgramCount() final
  509. {
  510. return kProgramCount;
  511. }
  512. // -------------------------------------------------------------------
  513. // Plugin state calls
  514. void setParameterValue(const uint32_t index, const float value) final
  515. {
  516. fEffect->changepar(index+2, value);
  517. }
  518. void setMidiProgram(const uint8_t, const uint32_t, const uint32_t program) final
  519. {
  520. fEffect->setpreset(program);
  521. const float volume(float(fEffect->getpar(0))/127.0f);
  522. hostDispatcher(HOST_OPCODE_SET_VOLUME, 0, 0, nullptr, volume);
  523. const unsigned char pan(fEffect->getpar(1));
  524. const float panning(float(pan)/63.5f-1.0f);
  525. hostDispatcher(HOST_OPCODE_SET_PANNING, 0, 0, nullptr, (pan == 64) ? 0.0f : panning);
  526. }
  527. // -------------------------------------------------------------------
  528. // Plugin process calls
  529. void activate() final
  530. {
  531. fEffect->cleanup();
  532. }
  533. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const uint32_t, const MidiEvent* const) final
  534. {
  535. CARLA_ASSERT(synth->buffersize == static_cast<int>(frames));
  536. fEffect->out(Stereo<float*>(inBuffer[0], inBuffer[1]));
  537. if (fWetOnly)
  538. {
  539. carla_copyFloat(outBuffer[0], efxoutl, frames);
  540. carla_copyFloat(outBuffer[1], efxoutr, frames);
  541. }
  542. else
  543. {
  544. for (uint32_t i=0; i<frames; ++i)
  545. {
  546. outBuffer[0][i] = inBuffer[0][i]/2.0f + efxoutl[i]/2.0f;
  547. outBuffer[1][i] = inBuffer[1][i]/2.0f + efxoutr[i]/2.0f;
  548. }
  549. }
  550. }
  551. // -------------------------------------------------------------------
  552. // Plugin dispatcher
  553. intptr_t pluginDispatcher(const PluginDispatcherOpcode opcode, const int32_t, const intptr_t, void* const, const float) final
  554. {
  555. switch (opcode)
  556. {
  557. case PLUGIN_OPCODE_BUFFER_SIZE_CHANGED:
  558. {
  559. const uint32_t bufferSize(getBufferSize());
  560. delete[] efxoutl;
  561. delete[] efxoutr;
  562. efxoutl = new float[bufferSize];
  563. efxoutr = new float[bufferSize];
  564. *((float**)&fEffect->efxoutl) = efxoutl;
  565. *((float**)&fEffect->efxoutr) = efxoutr;
  566. // no break
  567. }
  568. case PLUGIN_OPCODE_SAMPLE_RATE_CHANGED:
  569. sInstanceCount.maybeReinit(hostHandle());
  570. break;
  571. default:
  572. break;
  573. }
  574. return 0;
  575. }
  576. Effect* fEffect;
  577. float* efxoutl;
  578. float* efxoutr;
  579. bool fWetOnly;
  580. const uint32_t kParamCount;
  581. const uint32_t kProgramCount;
  582. };
  583. // -----------------------------------------------------------------------
  584. class FxAlienWahPlugin : public FxAbstractPlugin
  585. {
  586. public:
  587. FxAlienWahPlugin(const HostDescriptor* const host)
  588. : FxAbstractPlugin(host, 11, 4)
  589. {
  590. fEffect = new Alienwah(false, efxoutl, efxoutr);
  591. }
  592. protected:
  593. // -------------------------------------------------------------------
  594. // Plugin parameter calls
  595. const Parameter* getParameterInfo(const uint32_t index) override
  596. {
  597. if (index >= kParamCount)
  598. return nullptr;
  599. static Parameter param;
  600. static ParameterScalePoint scalePoints[2];
  601. int hints = PARAMETER_IS_ENABLED|PARAMETER_IS_INTEGER;
  602. param.name = nullptr;
  603. param.unit = nullptr;
  604. param.ranges.def = 1.0f;
  605. param.ranges.min = 0.0f;
  606. param.ranges.max = 127.0f;
  607. param.ranges.step = 1.0f;
  608. param.ranges.stepSmall = 1.0f;
  609. param.ranges.stepLarge = 20.0f;
  610. param.scalePointCount = 0;
  611. param.scalePoints = nullptr;
  612. switch (index)
  613. {
  614. case 0:
  615. hints |= PARAMETER_IS_AUTOMABLE;
  616. param.name = "LFO Frequency";
  617. param.ranges.def = 70.0f;
  618. break;
  619. case 1:
  620. hints |= PARAMETER_IS_AUTOMABLE;
  621. param.name = "LFO Randomness";
  622. param.ranges.def = 0.0f;
  623. break;
  624. case 2:
  625. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN|PARAMETER_USES_SCALEPOINTS;
  626. param.name = "LFO Type";
  627. param.ranges.def = 0.0f;
  628. param.ranges.max = 1.0f;
  629. param.scalePointCount = 2;
  630. param.scalePoints = scalePoints;
  631. scalePoints[0].label = "Sine";
  632. scalePoints[1].label = "Triangle";
  633. scalePoints[0].value = 0.0f;
  634. scalePoints[1].value = 1.0f;
  635. break;
  636. case 3:
  637. hints |= PARAMETER_IS_AUTOMABLE;
  638. param.name = "LFO Stereo";
  639. param.ranges.def = 62.0f;
  640. break;
  641. case 4:
  642. hints |= PARAMETER_IS_AUTOMABLE;
  643. param.name = "Depth";
  644. param.ranges.def = 60.0f;
  645. break;
  646. case 5:
  647. hints |= PARAMETER_IS_AUTOMABLE;
  648. param.name = "Feedback";
  649. param.ranges.def = 105.0f;
  650. break;
  651. case 6:
  652. param.name = "Delay";
  653. param.ranges.def = 25.0f;
  654. param.ranges.max = 100.0f;
  655. break;
  656. case 7:
  657. hints |= PARAMETER_IS_AUTOMABLE;
  658. param.name = "L/R Cross";
  659. param.ranges.def = 0.0f;
  660. break;
  661. case 8:
  662. hints |= PARAMETER_IS_AUTOMABLE;
  663. param.name = "Phase";
  664. param.ranges.def = 64.0f;
  665. break;
  666. }
  667. param.hints = static_cast<ParameterHints>(hints);
  668. return &param;
  669. }
  670. // -------------------------------------------------------------------
  671. // Plugin midi-program calls
  672. const MidiProgram* getMidiProgramInfo(const uint32_t index) override
  673. {
  674. if (index >= kProgramCount)
  675. return nullptr;
  676. static MidiProgram midiProg;
  677. midiProg.bank = 0;
  678. midiProg.program = index;
  679. switch (index)
  680. {
  681. case 0:
  682. midiProg.name = "AlienWah1";
  683. break;
  684. case 1:
  685. midiProg.name = "AlienWah2";
  686. break;
  687. case 2:
  688. midiProg.name = "AlienWah3";
  689. break;
  690. case 3:
  691. midiProg.name = "AlienWah4";
  692. break;
  693. default:
  694. midiProg.name = nullptr;
  695. break;
  696. }
  697. return &midiProg;
  698. }
  699. ZynPluginDescriptorClassEND(FxAlienWahPlugin)
  700. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxAlienWahPlugin)
  701. };
  702. // -----------------------------------------------------------------------
  703. class FxChorusPlugin : public FxAbstractPlugin
  704. {
  705. public:
  706. FxChorusPlugin(const HostDescriptor* const host)
  707. : FxAbstractPlugin(host, 12, 10)
  708. {
  709. fEffect = new Chorus(false, efxoutl, efxoutr);
  710. }
  711. protected:
  712. // -------------------------------------------------------------------
  713. // Plugin parameter calls
  714. const Parameter* getParameterInfo(const uint32_t index) override
  715. {
  716. if (index >= kParamCount)
  717. return nullptr;
  718. static Parameter param;
  719. static ParameterScalePoint scalePoints[2];
  720. int hints = PARAMETER_IS_ENABLED|PARAMETER_IS_INTEGER;
  721. param.name = nullptr;
  722. param.unit = nullptr;
  723. param.ranges.def = 1.0f;
  724. param.ranges.min = 0.0f;
  725. param.ranges.max = 127.0f;
  726. param.ranges.step = 1.0f;
  727. param.ranges.stepSmall = 1.0f;
  728. param.ranges.stepLarge = 20.0f;
  729. param.scalePointCount = 0;
  730. param.scalePoints = nullptr;
  731. switch (index)
  732. {
  733. case 0:
  734. hints |= PARAMETER_IS_AUTOMABLE;
  735. param.name = "LFO Frequency";
  736. param.ranges.def = 50.0f;
  737. break;
  738. case 1:
  739. hints |= PARAMETER_IS_AUTOMABLE;
  740. param.name = "LFO Randomness";
  741. param.ranges.def = 0.0f;
  742. break;
  743. case 2:
  744. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN|PARAMETER_USES_SCALEPOINTS;
  745. param.name = "LFO Type";
  746. param.ranges.def = 0.0f;
  747. param.ranges.max = 1.0f;
  748. param.scalePointCount = 2;
  749. param.scalePoints = scalePoints;
  750. scalePoints[0].label = "Sine";
  751. scalePoints[1].label = "Triangle";
  752. scalePoints[0].value = 0.0f;
  753. scalePoints[1].value = 1.0f;
  754. break;
  755. case 3:
  756. hints |= PARAMETER_IS_AUTOMABLE;
  757. param.name = "LFO Stereo";
  758. param.ranges.def = 90.0f;
  759. break;
  760. case 4:
  761. hints |= PARAMETER_IS_AUTOMABLE;
  762. param.name = "Depth";
  763. param.ranges.def = 40.0f;
  764. break;
  765. case 5:
  766. hints |= PARAMETER_IS_AUTOMABLE;
  767. param.name = "Delay";
  768. param.ranges.def = 85.0f;
  769. break;
  770. case 6:
  771. hints |= PARAMETER_IS_AUTOMABLE;
  772. param.name = "Feedback";
  773. param.ranges.def = 64.0f;
  774. break;
  775. case 7:
  776. hints |= PARAMETER_IS_AUTOMABLE;
  777. param.name = "L/R Cross";
  778. param.ranges.def = 119.0f;
  779. break;
  780. case 8:
  781. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN;
  782. param.name = "Flange Mode";
  783. param.ranges.def = 0.0f;
  784. param.ranges.max = 1.0f;
  785. break;
  786. case 9:
  787. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN;
  788. param.name = "Subtract Output";
  789. param.ranges.def = 0.0f;
  790. param.ranges.max = 1.0f;
  791. break;
  792. }
  793. param.hints = static_cast<ParameterHints>(hints);
  794. return &param;
  795. }
  796. // -------------------------------------------------------------------
  797. // Plugin midi-program calls
  798. const MidiProgram* getMidiProgramInfo(const uint32_t index) override
  799. {
  800. if (index >= kProgramCount)
  801. return nullptr;
  802. static MidiProgram midiProg;
  803. midiProg.bank = 0;
  804. midiProg.program = index;
  805. switch (index)
  806. {
  807. case 0:
  808. midiProg.name = "Chorus1";
  809. break;
  810. case 1:
  811. midiProg.name = "Chorus2";
  812. break;
  813. case 2:
  814. midiProg.name = "Chorus3";
  815. break;
  816. case 3:
  817. midiProg.name = "Celeste1";
  818. break;
  819. case 4:
  820. midiProg.name = "Celeste2";
  821. break;
  822. case 5:
  823. midiProg.name = "Flange1";
  824. break;
  825. case 6:
  826. midiProg.name = "Flange2";
  827. break;
  828. case 7:
  829. midiProg.name = "Flange3";
  830. break;
  831. case 8:
  832. midiProg.name = "Flange4";
  833. break;
  834. case 9:
  835. midiProg.name = "Flange5";
  836. break;
  837. default:
  838. midiProg.name = nullptr;
  839. break;
  840. }
  841. return &midiProg;
  842. }
  843. ZynPluginDescriptorClassEND(FxChorusPlugin)
  844. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxChorusPlugin)
  845. };
  846. // -----------------------------------------------------------------------
  847. class FxDistortionPlugin : public FxAbstractPlugin
  848. {
  849. public:
  850. FxDistortionPlugin(const HostDescriptor* const host)
  851. : FxAbstractPlugin(host, 11, 6)
  852. {
  853. fEffect = new Distorsion(false, efxoutl, efxoutr);
  854. }
  855. protected:
  856. // -------------------------------------------------------------------
  857. // Plugin parameter calls
  858. const Parameter* getParameterInfo(const uint32_t index) override
  859. {
  860. if (index >= kParamCount)
  861. return nullptr;
  862. static Parameter param;
  863. static ParameterScalePoint scalePoints[14];
  864. int hints = PARAMETER_IS_ENABLED|PARAMETER_IS_INTEGER;
  865. param.name = nullptr;
  866. param.unit = nullptr;
  867. param.ranges.def = 1.0f;
  868. param.ranges.min = 0.0f;
  869. param.ranges.max = 127.0f;
  870. param.ranges.step = 1.0f;
  871. param.ranges.stepSmall = 1.0f;
  872. param.ranges.stepLarge = 20.0f;
  873. param.scalePointCount = 0;
  874. param.scalePoints = nullptr;
  875. switch (index)
  876. {
  877. case 0:
  878. hints |= PARAMETER_IS_AUTOMABLE;
  879. param.name = "L/R Cross";
  880. param.ranges.def = 35.0f;
  881. break;
  882. case 1:
  883. hints |= PARAMETER_IS_AUTOMABLE;
  884. param.name = "Drive";
  885. param.ranges.def = 56.0f;
  886. break;
  887. case 2:
  888. hints |= PARAMETER_IS_AUTOMABLE;
  889. param.name = "Level";
  890. param.ranges.def = 70.0f;
  891. break;
  892. case 3:
  893. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_USES_SCALEPOINTS;
  894. param.name = "Type";
  895. param.ranges.def = 0.0f;
  896. param.ranges.max = 13.0f;
  897. param.scalePointCount = 14;
  898. param.scalePoints = scalePoints;
  899. scalePoints[ 0].label = "Arctangent";
  900. scalePoints[ 1].label = "Asymmetric";
  901. scalePoints[ 2].label = "Pow";
  902. scalePoints[ 3].label = "Sine";
  903. scalePoints[ 4].label = "Quantisize";
  904. scalePoints[ 5].label = "Zigzag";
  905. scalePoints[ 6].label = "Limiter";
  906. scalePoints[ 7].label = "Upper Limiter";
  907. scalePoints[ 8].label = "Lower Limiter";
  908. scalePoints[ 9].label = "Inverse Limiter";
  909. scalePoints[10].label = "Clip";
  910. scalePoints[11].label = "Asym2";
  911. scalePoints[12].label = "Pow2";
  912. scalePoints[13].label = "sigmoid";
  913. scalePoints[ 0].value = 0.0f;
  914. scalePoints[ 1].value = 1.0f;
  915. scalePoints[ 2].value = 2.0f;
  916. scalePoints[ 3].value = 3.0f;
  917. scalePoints[ 4].value = 4.0f;
  918. scalePoints[ 5].value = 5.0f;
  919. scalePoints[ 6].value = 6.0f;
  920. scalePoints[ 7].value = 7.0f;
  921. scalePoints[ 8].value = 8.0f;
  922. scalePoints[ 9].value = 9.0f;
  923. scalePoints[10].value = 10.0f;
  924. scalePoints[11].value = 11.0f;
  925. scalePoints[12].value = 12.0f;
  926. scalePoints[13].value = 13.0f;
  927. break;
  928. case 4:
  929. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN;
  930. param.name = "Negate";
  931. param.ranges.def = 0.0f;
  932. param.ranges.max = 1.0f;
  933. break;
  934. case 5:
  935. hints |= PARAMETER_IS_AUTOMABLE;
  936. param.name = "lpf";
  937. param.ranges.def = 96.0f;
  938. break;
  939. case 6:
  940. hints |= PARAMETER_IS_AUTOMABLE;
  941. param.name = "hpf";
  942. param.ranges.def = 0.0f;
  943. break;
  944. case 7:
  945. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN;
  946. param.name = "Stereo";
  947. param.ranges.def = 0.0f;
  948. param.ranges.max = 1.0f;
  949. break;
  950. case 8:
  951. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN;
  952. param.name = "Pre-Filtering";
  953. param.ranges.def = 0.0f;
  954. param.ranges.max = 1.0f;
  955. break;
  956. }
  957. param.hints = static_cast<ParameterHints>(hints);
  958. return &param;
  959. }
  960. // -------------------------------------------------------------------
  961. // Plugin midi-program calls
  962. const MidiProgram* getMidiProgramInfo(const uint32_t index) override
  963. {
  964. if (index >= kProgramCount)
  965. return nullptr;
  966. static MidiProgram midiProg;
  967. midiProg.bank = 0;
  968. midiProg.program = index;
  969. switch (index)
  970. {
  971. case 0:
  972. midiProg.name = "Overdrive 1";
  973. break;
  974. case 1:
  975. midiProg.name = "Overdrive 2";
  976. break;
  977. case 2:
  978. midiProg.name = "A. Exciter 1";
  979. break;
  980. case 3:
  981. midiProg.name = "A. Exciter 2";
  982. break;
  983. case 4:
  984. midiProg.name = "Guitar Amp";
  985. break;
  986. case 5:
  987. midiProg.name = "Quantisize";
  988. break;
  989. default:
  990. midiProg.name = nullptr;
  991. break;
  992. }
  993. return &midiProg;
  994. }
  995. ZynPluginDescriptorClassEND(FxDistortionPlugin)
  996. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxDistortionPlugin)
  997. };
  998. // -----------------------------------------------------------------------
  999. class FxReverbPlugin : public FxAbstractPlugin
  1000. {
  1001. public:
  1002. FxReverbPlugin(const HostDescriptor* const host)
  1003. : FxAbstractPlugin(host, 13, 13)
  1004. {
  1005. fEffect = new Reverb(false, efxoutl, efxoutr);
  1006. }
  1007. protected:
  1008. // -------------------------------------------------------------------
  1009. // Plugin parameter calls
  1010. const Parameter* getParameterInfo(const uint32_t index) override
  1011. {
  1012. if (index >= kParamCount)
  1013. return nullptr;
  1014. static Parameter param;
  1015. int hints = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER;
  1016. param.name = nullptr;
  1017. param.unit = nullptr;
  1018. param.ranges.def = 1.0f;
  1019. param.ranges.min = 0.0f;
  1020. param.ranges.max = 127.0f;
  1021. param.ranges.step = 1.0f;
  1022. param.ranges.stepSmall = 1.0f;
  1023. param.ranges.stepLarge = 20.0f;
  1024. param.scalePointCount = 0;
  1025. param.scalePoints = nullptr;
  1026. switch (index)
  1027. {
  1028. case 0:
  1029. hints |= PARAMETER_IS_AUTOMABLE;
  1030. param.name = "Time";
  1031. param.ranges.def = 63.0f;
  1032. break;
  1033. case 1:
  1034. param.name = "Delay";
  1035. param.ranges.def = 24.0f;
  1036. break;
  1037. case 2:
  1038. hints |= PARAMETER_IS_AUTOMABLE;
  1039. param.name = "Feedback";
  1040. param.ranges.def = 0.0f;
  1041. break;
  1042. case 3:
  1043. hints = 0x0;
  1044. param.name = "unused1";
  1045. break;
  1046. case 4:
  1047. hints = 0x0;
  1048. param.name = "unused2";
  1049. break;
  1050. case 5:
  1051. param.name = "Low-Pass Filter";
  1052. param.ranges.def = 85.0f;
  1053. break;
  1054. case 6:
  1055. param.name = "High-Pass Filter";
  1056. param.ranges.def = 5.0f;
  1057. break;
  1058. case 7:
  1059. hints |= PARAMETER_IS_AUTOMABLE;
  1060. param.name = "Damp";
  1061. param.ranges.def = 83.0f;
  1062. break;
  1063. case 8:
  1064. param.name = "Type";
  1065. param.ranges.def = 1.0f;
  1066. param.ranges.max = 2.0f;
  1067. break;
  1068. case 9:
  1069. param.name = "Room size";
  1070. param.ranges.def = 64.0f;
  1071. break;
  1072. case 10:
  1073. param.name = "Bandwidth";
  1074. param.ranges.def = 20.0f;
  1075. break;
  1076. }
  1077. param.hints = static_cast<ParameterHints>(hints);
  1078. return &param;
  1079. }
  1080. // -------------------------------------------------------------------
  1081. // Plugin midi-program calls
  1082. const MidiProgram* getMidiProgramInfo(const uint32_t index) override
  1083. {
  1084. if (index >= kProgramCount)
  1085. return nullptr;
  1086. static MidiProgram midiProg;
  1087. midiProg.bank = 0;
  1088. midiProg.program = index;
  1089. switch (index)
  1090. {
  1091. case 0:
  1092. midiProg.name = "Cathedral1";
  1093. break;
  1094. case 1:
  1095. midiProg.name = "Cathedral2";
  1096. break;
  1097. case 2:
  1098. midiProg.name = "Cathedral3";
  1099. break;
  1100. case 3:
  1101. midiProg.name = "Hall1";
  1102. break;
  1103. case 4:
  1104. midiProg.name = "Hall2";
  1105. break;
  1106. case 5:
  1107. midiProg.name = "Room1";
  1108. break;
  1109. case 6:
  1110. midiProg.name = "Room2";
  1111. break;
  1112. case 7:
  1113. midiProg.name = "Basement";
  1114. break;
  1115. case 8:
  1116. midiProg.name = "Tunnel";
  1117. break;
  1118. case 9:
  1119. midiProg.name = "Echoed1";
  1120. break;
  1121. case 10:
  1122. midiProg.name = "Echoed2";
  1123. break;
  1124. case 11:
  1125. midiProg.name = "VeryLong1";
  1126. break;
  1127. case 12:
  1128. midiProg.name = "VeryLong2";
  1129. break;
  1130. default:
  1131. midiProg.name = nullptr;
  1132. break;
  1133. }
  1134. return &midiProg;
  1135. }
  1136. ZynPluginDescriptorClassEND(FxReverbPlugin)
  1137. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxReverbPlugin)
  1138. };
  1139. // -----------------------------------------------------------------------
  1140. class ZynAddSubFxPlugin : public PluginDescriptorClass
  1141. {
  1142. public:
  1143. enum Parameters {
  1144. PARAMETER_COUNT = 0
  1145. };
  1146. ZynAddSubFxPlugin(const HostDescriptor* const host)
  1147. : PluginDescriptorClass(host),
  1148. fMaster(new Master()),
  1149. fSampleRate(getSampleRate()),
  1150. fIsActive(false),
  1151. fThread(fMaster, host)
  1152. {
  1153. fThread.start();
  1154. for (int i = 0; i < NUM_MIDI_PARTS; ++i)
  1155. fMaster->partonoff(i, 1);
  1156. sPrograms.init();
  1157. }
  1158. ~ZynAddSubFxPlugin() override
  1159. {
  1160. //ensure that everything has stopped
  1161. pthread_mutex_lock(&fMaster->mutex);
  1162. pthread_mutex_unlock(&fMaster->mutex);
  1163. fThread.stop();
  1164. fThread.wait();
  1165. delete fMaster;
  1166. fMaster = nullptr;
  1167. }
  1168. protected:
  1169. // -------------------------------------------------------------------
  1170. // Plugin parameter calls
  1171. uint32_t getParameterCount() override
  1172. {
  1173. return PARAMETER_COUNT;
  1174. }
  1175. const Parameter* getParameterInfo(const uint32_t index) override
  1176. {
  1177. CARLA_ASSERT(index < getParameterCount());
  1178. //if (index >= PARAMETER_COUNT)
  1179. return nullptr;
  1180. static Parameter param;
  1181. param.ranges.step = PARAMETER_RANGES_DEFAULT_STEP;
  1182. param.ranges.stepSmall = PARAMETER_RANGES_DEFAULT_STEP_SMALL;
  1183. param.ranges.stepLarge = PARAMETER_RANGES_DEFAULT_STEP_LARGE;
  1184. param.scalePointCount = 0;
  1185. param.scalePoints = nullptr;
  1186. switch (index)
  1187. {
  1188. #if 0
  1189. case PARAMETER_MASTER:
  1190. param.hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE;
  1191. param.name = "Master Volume";
  1192. param.unit = nullptr;
  1193. param.ranges.min = 0.0f;
  1194. param.ranges.max = 100.0f;
  1195. param.ranges.def = 100.0f;
  1196. break;
  1197. #endif
  1198. }
  1199. return &param;
  1200. }
  1201. float getParameterValue(const uint32_t index) override
  1202. {
  1203. CARLA_ASSERT(index < getParameterCount());
  1204. switch (index)
  1205. {
  1206. #if 0
  1207. case PARAMETER_MASTER:
  1208. return fMaster->Pvolume;
  1209. #endif
  1210. default:
  1211. return 0.0f;
  1212. }
  1213. }
  1214. // -------------------------------------------------------------------
  1215. // Plugin midi-program calls
  1216. uint32_t getMidiProgramCount() override
  1217. {
  1218. return sPrograms.count();
  1219. }
  1220. const MidiProgram* getMidiProgramInfo(const uint32_t index) override
  1221. {
  1222. return sPrograms.getInfo(index);
  1223. }
  1224. // -------------------------------------------------------------------
  1225. // Plugin state calls
  1226. void setParameterValue(const uint32_t index, const float value) override
  1227. {
  1228. CARLA_ASSERT(index < getParameterCount());
  1229. switch (index)
  1230. {
  1231. }
  1232. return;
  1233. // unused, TODO
  1234. (void)value;
  1235. }
  1236. void setMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program) override
  1237. {
  1238. if (bank >= fMaster->bank.banks.size())
  1239. return;
  1240. if (program >= BANK_SIZE)
  1241. return;
  1242. if (isOffline() || ! fIsActive)
  1243. {
  1244. sPrograms.load(fMaster, channel, bank, program);
  1245. #ifdef WANT_ZYNADDSUBFX_UI
  1246. fThread.uiRepaint();
  1247. #endif
  1248. }
  1249. else
  1250. fThread.loadProgramLater(channel, bank, program);
  1251. }
  1252. void setCustomData(const char* const key, const char* const value) override
  1253. {
  1254. CARLA_ASSERT(key != nullptr);
  1255. CARLA_ASSERT(value != nullptr);
  1256. if (std::strcmp(key, "CarlaAlternateFile1") == 0) // xmz
  1257. fMaster->loadXML(value);
  1258. else if (std::strcmp(key, "CarlaAlternateFile2") == 0) // xiz
  1259. fMaster->part[0]->loadXMLinstrument(value);
  1260. }
  1261. // -------------------------------------------------------------------
  1262. // Plugin process calls
  1263. void activate() override
  1264. {
  1265. fIsActive = true;
  1266. }
  1267. void deactivate() override
  1268. {
  1269. fIsActive = false;
  1270. }
  1271. void process(float**, float** const outBuffer, const uint32_t frames, const uint32_t midiEventCount, const MidiEvent* const midiEvents) override
  1272. {
  1273. if (pthread_mutex_trylock(&fMaster->mutex) != 0)
  1274. {
  1275. carla_zeroFloat(outBuffer[0], frames);
  1276. carla_zeroFloat(outBuffer[1], frames);
  1277. return;
  1278. }
  1279. for (uint32_t i=0; i < midiEventCount; ++i)
  1280. {
  1281. const MidiEvent* const midiEvent(&midiEvents[i]);
  1282. const uint8_t status = MIDI_GET_STATUS_FROM_DATA(midiEvent->data);
  1283. const uint8_t channel = MIDI_GET_CHANNEL_FROM_DATA(midiEvent->data);
  1284. if (MIDI_IS_STATUS_NOTE_OFF(status))
  1285. {
  1286. const uint8_t note = midiEvent->data[1];
  1287. fMaster->noteOff(channel, note);
  1288. }
  1289. else if (MIDI_IS_STATUS_NOTE_ON(status))
  1290. {
  1291. const uint8_t note = midiEvent->data[1];
  1292. const uint8_t velo = midiEvent->data[2];
  1293. fMaster->noteOn(channel, note, velo);
  1294. }
  1295. else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status))
  1296. {
  1297. const uint8_t note = midiEvent->data[1];
  1298. const uint8_t pressure = midiEvent->data[2];
  1299. fMaster->polyphonicAftertouch(channel, note, pressure);
  1300. }
  1301. else if (MIDI_IS_STATUS_CONTROL_CHANGE(status))
  1302. {
  1303. const uint8_t control = midiEvent->data[1];
  1304. const uint8_t value = midiEvent->data[2];
  1305. fMaster->setController(channel, control, value);
  1306. }
  1307. else if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status))
  1308. {
  1309. const uint8_t lsb = midiEvent->data[1];
  1310. const uint8_t msb = midiEvent->data[2];
  1311. const int value = ((msb << 7) | lsb) - 8192;
  1312. fMaster->setController(channel, C_pitchwheel, value);
  1313. }
  1314. }
  1315. fMaster->GetAudioOutSamples(frames, fSampleRate, outBuffer[0], outBuffer[1]);
  1316. pthread_mutex_unlock(&fMaster->mutex);
  1317. }
  1318. #ifdef WANT_ZYNADDSUBFX_UI
  1319. // -------------------------------------------------------------------
  1320. // Plugin UI calls
  1321. void uiShow(const bool show) override
  1322. {
  1323. if (show)
  1324. fThread.uiShow();
  1325. else
  1326. fThread.uiHide();
  1327. }
  1328. #endif
  1329. // -------------------------------------------------------------------
  1330. // Plugin state calls
  1331. char* getState() override
  1332. {
  1333. config.save();
  1334. char* data = nullptr;
  1335. fMaster->getalldata(&data);
  1336. return data;
  1337. }
  1338. void setState(const char* const data) override
  1339. {
  1340. fThread.stopLoadProgramLater();
  1341. fMaster->putalldata((char*)data, 0);
  1342. fMaster->applyparameters(true);
  1343. }
  1344. // -------------------------------------------------------------------
  1345. // Plugin dispatcher
  1346. intptr_t pluginDispatcher(const PluginDispatcherOpcode opcode, const int32_t index, const intptr_t value, void* const ptr, const float) override
  1347. {
  1348. switch (opcode)
  1349. {
  1350. case PLUGIN_OPCODE_NULL:
  1351. break;
  1352. case PLUGIN_OPCODE_BUFFER_SIZE_CHANGED:
  1353. // TODO
  1354. break;
  1355. case PLUGIN_OPCODE_SAMPLE_RATE_CHANGED:
  1356. // TODO
  1357. break;
  1358. case PLUGIN_OPCODE_OFFLINE_CHANGED:
  1359. break;
  1360. case PLUGIN_OPCODE_UI_NAME_CHANGED:
  1361. #ifdef WANT_ZYNADDSUBFX_UI
  1362. // TODO
  1363. #endif
  1364. break;
  1365. }
  1366. return 0;
  1367. // unused
  1368. (void)index;
  1369. (void)value;
  1370. (void)ptr;
  1371. }
  1372. // -------------------------------------------------------------------
  1373. private:
  1374. Master* fMaster;
  1375. unsigned fSampleRate;
  1376. bool fIsActive;
  1377. ZynAddSubFxThread fThread;
  1378. ZynPluginDescriptorClassEND(ZynAddSubFxPlugin)
  1379. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ZynAddSubFxPlugin)
  1380. };
  1381. // -----------------------------------------------------------------------
  1382. static const PluginDescriptor fxAlienWahDesc = {
  1383. /* category */ PLUGIN_CATEGORY_MODULATOR,
  1384. /* hints */ static_cast<PluginHints>(PLUGIN_IS_RTSAFE|PLUGIN_USES_PANNING|PLUGIN_USES_STATIC_BUFFERS),
  1385. /* supports */ static_cast<PluginSupports>(0x0),
  1386. /* audioIns */ 2,
  1387. /* audioOuts */ 2,
  1388. /* midiIns */ 0,
  1389. /* midiOuts */ 0,
  1390. /* paramIns */ 11-1,
  1391. /* paramOuts */ 0,
  1392. /* name */ "ZynAlienWah",
  1393. /* label */ "zynAlienWah",
  1394. /* maker */ "falkTX",
  1395. /* copyright */ "GNU GPL v2+",
  1396. PluginDescriptorFILL(FxAlienWahPlugin)
  1397. };
  1398. static const PluginDescriptor fxChorusDesc = {
  1399. /* category */ PLUGIN_CATEGORY_MODULATOR,
  1400. /* hints */ static_cast<PluginHints>(PLUGIN_IS_RTSAFE|PLUGIN_USES_PANNING|PLUGIN_USES_STATIC_BUFFERS),
  1401. /* supports */ static_cast<PluginSupports>(0x0),
  1402. /* audioIns */ 2,
  1403. /* audioOuts */ 2,
  1404. /* midiIns */ 0,
  1405. /* midiOuts */ 0,
  1406. /* paramIns */ 12-1,
  1407. /* paramOuts */ 0,
  1408. /* name */ "ZynChorus",
  1409. /* label */ "zynChorus",
  1410. /* maker */ "falkTX",
  1411. /* copyright */ "GNU GPL v2+",
  1412. PluginDescriptorFILL(FxChorusPlugin)
  1413. };
  1414. static const PluginDescriptor fxDistortionDesc = {
  1415. /* category */ PLUGIN_CATEGORY_MODULATOR,
  1416. /* hints */ static_cast<PluginHints>(PLUGIN_USES_PANNING|PLUGIN_USES_STATIC_BUFFERS),
  1417. /* supports */ static_cast<PluginSupports>(0x0),
  1418. /* audioIns */ 2,
  1419. /* audioOuts */ 2,
  1420. /* midiIns */ 0,
  1421. /* midiOuts */ 0,
  1422. /* paramIns */ 11-1,
  1423. /* paramOuts */ 0,
  1424. /* name */ "ZynDistortion",
  1425. /* label */ "zynDistortion",
  1426. /* maker */ "falkTX",
  1427. /* copyright */ "GNU GPL v2+",
  1428. PluginDescriptorFILL(FxDistortionPlugin)
  1429. };
  1430. #if 0
  1431. static const PluginDescriptor fxDynamicFilterDesc = {
  1432. /* category */ PLUGIN_CATEGORY_FILTER,
  1433. /* hints */ static_cast<PluginHints>(PLUGIN_USES_PANNING|PLUGIN_USES_STATIC_BUFFERS),
  1434. /* supports */ static_cast<PluginSupports>(0x0),
  1435. /* audioIns */ 2,
  1436. /* audioOuts */ 2,
  1437. /* midiIns */ 0,
  1438. /* midiOuts */ 0,
  1439. /* paramIns */ FxDynamicFilterPlugin::kParamCount,
  1440. /* paramOuts */ 0,
  1441. /* name */ "ZynDynamicFilter",
  1442. /* label */ "zynDynamicFilter",
  1443. /* maker */ "falkTX",
  1444. /* copyright */ "GNU GPL v2+",
  1445. PluginDescriptorFILL(FxDynamicFilterPlugin)
  1446. };
  1447. static const PluginDescriptor fxEchoDesc = {
  1448. /* category */ PLUGIN_CATEGORY_DELAY,
  1449. /* hints */ static_cast<PluginHints>(PLUGIN_USES_PANNING|PLUGIN_USES_STATIC_BUFFERS),
  1450. /* supports */ static_cast<PluginSupports>(0x0),
  1451. /* audioIns */ 2,
  1452. /* audioOuts */ 2,
  1453. /* midiIns */ 0,
  1454. /* midiOuts */ 0,
  1455. /* paramIns */ FxEchoPlugin::kParamCount,
  1456. /* paramOuts */ 0,
  1457. /* name */ "ZynEcho",
  1458. /* label */ "zynEcho",
  1459. /* maker */ "falkTX",
  1460. /* copyright */ "GNU GPL v2+",
  1461. PluginDescriptorFILL(FxEchoPlugin)
  1462. };
  1463. static const PluginDescriptor fxPhaserDesc = {
  1464. /* category */ PLUGIN_CATEGORY_MODULATOR,
  1465. /* hints */ static_cast<PluginHints>(PLUGIN_USES_PANNING|PLUGIN_USES_STATIC_BUFFERS),
  1466. /* supports */ static_cast<PluginSupports>(0x0),
  1467. /* audioIns */ 2,
  1468. /* audioOuts */ 2,
  1469. /* midiIns */ 0,
  1470. /* midiOuts */ 0,
  1471. /* paramIns */ FxPhaserPlugin::kParamCount,
  1472. /* paramOuts */ 0,
  1473. /* name */ "ZynPhaser",
  1474. /* label */ "zynPhaser",
  1475. /* maker */ "falkTX",
  1476. /* copyright */ "GNU GPL v2+",
  1477. PluginDescriptorFILL(FxPhaserPlugin)
  1478. };
  1479. #endif
  1480. static const PluginDescriptor fxReverbDesc = {
  1481. /* category */ PLUGIN_CATEGORY_DELAY,
  1482. /* hints */ static_cast<PluginHints>(PLUGIN_USES_PANNING|PLUGIN_USES_STATIC_BUFFERS),
  1483. /* supports */ static_cast<PluginSupports>(0x0),
  1484. /* audioIns */ 2,
  1485. /* audioOuts */ 2,
  1486. /* midiIns */ 0,
  1487. /* midiOuts */ 0,
  1488. /* paramIns */ 13-1,
  1489. /* paramOuts */ 0,
  1490. /* name */ "ZynReverb",
  1491. /* label */ "zynReverb",
  1492. /* maker */ "falkTX",
  1493. /* copyright */ "GNU GPL v2+",
  1494. PluginDescriptorFILL(FxReverbPlugin)
  1495. };
  1496. static const PluginDescriptor zynaddsubfxDesc = {
  1497. /* category */ PLUGIN_CATEGORY_SYNTH,
  1498. #ifdef WANT_ZYNADDSUBFX_UI
  1499. /* hints */ static_cast<PluginHints>(PLUGIN_IS_SYNTH|PLUGIN_HAS_GUI|PLUGIN_USES_STATE),
  1500. #else
  1501. /* hints */ static_cast<PluginHints>(PLUGIN_IS_SYNTH|PLUGIN_USES_STATE),
  1502. #endif
  1503. /* supports */ static_cast<PluginSupports>(PLUGIN_SUPPORTS_CONTROL_CHANGES|PLUGIN_SUPPORTS_NOTE_AFTERTOUCH|PLUGIN_SUPPORTS_PITCHBEND|PLUGIN_SUPPORTS_ALL_SOUND_OFF),
  1504. /* audioIns */ 0,
  1505. /* audioOuts */ 2,
  1506. /* midiIns */ 1,
  1507. /* midiOuts */ 0,
  1508. /* paramIns */ ZynAddSubFxPlugin::PARAMETER_COUNT,
  1509. /* paramOuts */ 0,
  1510. /* name */ "ZynAddSubFX",
  1511. /* label */ "zynaddsubfx",
  1512. /* maker */ "falkTX",
  1513. /* copyright */ "GNU GPL v2+",
  1514. PluginDescriptorFILL(ZynAddSubFxPlugin)
  1515. };
  1516. // -----------------------------------------------------------------------
  1517. void carla_register_native_plugin_zynaddsubfx()
  1518. {
  1519. carla_register_native_plugin(&fxAlienWahDesc);
  1520. carla_register_native_plugin(&fxChorusDesc);
  1521. carla_register_native_plugin(&fxDistortionDesc);
  1522. #if 0
  1523. carla_register_native_plugin(&fxDynamicFilterDesc);
  1524. carla_register_native_plugin(&fxEchoDesc);
  1525. carla_register_native_plugin(&fxPhaserDesc);
  1526. #endif
  1527. carla_register_native_plugin(&fxReverbDesc);
  1528. carla_register_native_plugin(&zynaddsubfxDesc);
  1529. }
  1530. // -----------------------------------------------------------------------