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.

2171 lines
60KB

  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 doc/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 "zynaddsubfx/Misc/Master.h"
  25. #include "zynaddsubfx/Misc/Part.h"
  26. #include "zynaddsubfx/Misc/Util.h"
  27. #include "zynaddsubfx/Effects/Alienwah.h"
  28. #include "zynaddsubfx/Effects/Chorus.h"
  29. #include "zynaddsubfx/Effects/Distorsion.h"
  30. #include "zynaddsubfx/Effects/DynamicFilter.h"
  31. #include "zynaddsubfx/Effects/Echo.h"
  32. #include "zynaddsubfx/Effects/Phaser.h"
  33. #include "zynaddsubfx/Effects/Reverb.h"
  34. #ifdef WANT_ZYNADDSUBFX_UI
  35. # ifdef override
  36. # define override_hack
  37. # undef override
  38. # endif
  39. # include "zynaddsubfx/UI/common.H"
  40. # include "zynaddsubfx/UI/MasterUI.h"
  41. # include <FL/Fl_Shared_Image.H>
  42. # include <FL/Fl_Tiled_Image.H>
  43. # include <FL/Fl_Theme.H>
  44. # ifdef override_hack
  45. # define override
  46. # undef override_hack
  47. # endif
  48. #endif
  49. #include <ctime>
  50. #include <set>
  51. #include <string>
  52. // Dummy variables and functions for linking purposes
  53. const char* instance_name = nullptr;
  54. class WavFile;
  55. namespace Nio {
  56. bool start(void){return 1;}
  57. void stop(void){}
  58. bool setSource(std::string){return true;}
  59. bool setSink(std::string){return true;}
  60. std::set<std::string> getSources(void){return std::set<std::string>();}
  61. std::set<std::string> getSinks(void){return std::set<std::string>();}
  62. std::string getSource(void){return "";}
  63. std::string getSink(void){return "";}
  64. void waveNew(WavFile*){}
  65. void waveStart(void){}
  66. void waveStop(void){}
  67. void waveEnd(void){}
  68. }
  69. SYNTH_T* synth = nullptr;
  70. #ifdef WANT_ZYNADDSUBFX_UI
  71. #define PIXMAP_PATH "/resources/zynaddsubfx/"
  72. static Fl_Tiled_Image* gModuleBackdrop = nullptr;
  73. static CarlaString gPixmapPath;
  74. extern CarlaString gUiPixmapPath;
  75. void set_module_parameters(Fl_Widget* o)
  76. {
  77. CARLA_ASSERT(gModuleBackdrop != nullptr);
  78. o->box(FL_DOWN_FRAME);
  79. o->align(o->align() | FL_ALIGN_IMAGE_BACKDROP);
  80. o->color(FL_BLACK);
  81. o->labeltype(FL_SHADOW_LABEL);
  82. if (gModuleBackdrop != nullptr)
  83. o->image(gModuleBackdrop);
  84. }
  85. #endif
  86. // -----------------------------------------------------------------------
  87. class ZynAddSubFxPrograms
  88. {
  89. public:
  90. ZynAddSubFxPrograms()
  91. : fInitiated(false)
  92. {
  93. }
  94. ~ZynAddSubFxPrograms()
  95. {
  96. if (! fInitiated)
  97. return;
  98. for (auto it = fPrograms.begin(); it.valid(); it.next())
  99. {
  100. const ProgramInfo*& pInfo(*it);
  101. delete pInfo;
  102. }
  103. fPrograms.clear();
  104. }
  105. void init()
  106. {
  107. if (fInitiated)
  108. return;
  109. fInitiated = true;
  110. fPrograms.append(new ProgramInfo(0, 0, "default"));
  111. Master& master(Master::getInstance());
  112. pthread_mutex_lock(&master.mutex);
  113. // refresh banks
  114. master.bank.rescanforbanks();
  115. for (uint32_t i=0, size = master.bank.banks.size(); i < size; ++i)
  116. {
  117. if (master.bank.banks[i].dir.empty())
  118. continue;
  119. master.bank.loadbank(master.bank.banks[i].dir);
  120. for (unsigned int instrument = 0; instrument < BANK_SIZE; ++instrument)
  121. {
  122. const std::string insName(master.bank.getname(instrument));
  123. if (insName.empty() || insName[0] == '\0' || insName[0] == ' ')
  124. continue;
  125. fPrograms.append(new ProgramInfo(i+1, instrument, insName.c_str()));
  126. }
  127. }
  128. pthread_mutex_unlock(&master.mutex);
  129. }
  130. void load(Master* const master, const uint8_t channel, const uint32_t bank, const uint32_t program)
  131. {
  132. if (bank == 0)
  133. {
  134. pthread_mutex_lock(&master->mutex);
  135. master->partonoff(channel, 1);
  136. master->part[channel]->defaults();
  137. master->part[channel]->applyparameters(false);
  138. pthread_mutex_unlock(&master->mutex);
  139. return;
  140. }
  141. const std::string& bankdir(master->bank.banks[bank-1].dir);
  142. if (! bankdir.empty())
  143. {
  144. pthread_mutex_lock(&master->mutex);
  145. master->partonoff(channel, 1);
  146. master->bank.loadbank(bankdir);
  147. master->bank.loadfromslot(program, master->part[channel]);
  148. master->part[channel]->applyparameters(false);
  149. pthread_mutex_unlock(&master->mutex);
  150. }
  151. }
  152. uint32_t count()
  153. {
  154. return fPrograms.count();
  155. }
  156. const MidiProgram* getInfo(const uint32_t index)
  157. {
  158. if (index >= fPrograms.count())
  159. return nullptr;
  160. const ProgramInfo*& pInfo(fPrograms.getAt(index));
  161. fRetProgram.bank = pInfo->bank;
  162. fRetProgram.program = pInfo->prog;
  163. fRetProgram.name = pInfo->name;
  164. return &fRetProgram;
  165. }
  166. private:
  167. struct ProgramInfo {
  168. uint32_t bank;
  169. uint32_t prog;
  170. const char* name;
  171. ProgramInfo(uint32_t bank_, uint32_t prog_, const char* name_)
  172. : bank(bank_),
  173. prog(prog_),
  174. name(carla_strdup(name_)) {}
  175. ~ProgramInfo()
  176. {
  177. if (name != nullptr)
  178. {
  179. delete[] name;
  180. name = nullptr;
  181. }
  182. }
  183. #ifdef CARLA_PROPER_CPP11_SUPPORT
  184. ProgramInfo() = delete;
  185. ProgramInfo(ProgramInfo&) = delete;
  186. ProgramInfo(const ProgramInfo&) = delete;
  187. ProgramInfo& operator=(ProgramInfo&);
  188. ProgramInfo& operator=(const ProgramInfo&);
  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->resourceDir;
  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 juce::Thread
  280. {
  281. public:
  282. ZynAddSubFxThread(Master* const master, const HostDescriptor* const host)
  283. : juce::Thread("ZynAddSubFxThread"),
  284. fMaster(master),
  285. kHost(host),
  286. #ifdef WANT_ZYNADDSUBFX_UI
  287. fUi(nullptr),
  288. fUiClosed(0),
  289. fNextUiAction(-1),
  290. #endif
  291. fChangeProgram(false),
  292. fNextChannel(0),
  293. fNextBank(0),
  294. fNextProgram(0)
  295. {
  296. }
  297. ~ZynAddSubFxThread()
  298. {
  299. #ifdef WANT_ZYNADDSUBFX_UI
  300. // must be closed by now
  301. CARLA_ASSERT(fUi == nullptr);
  302. #endif
  303. }
  304. void loadProgramLater(const uint8_t channel, const uint32_t bank, const uint32_t program)
  305. {
  306. fNextChannel = channel;
  307. fNextBank = bank;
  308. fNextProgram = program;
  309. fChangeProgram = true;
  310. }
  311. void stopLoadProgramLater()
  312. {
  313. fChangeProgram = false;
  314. fNextChannel = 0;
  315. fNextBank = 0;
  316. fNextProgram = 0;
  317. }
  318. void setMaster(Master* const master)
  319. {
  320. fMaster = master;
  321. }
  322. #ifdef WANT_ZYNADDSUBFX_UI
  323. void uiHide()
  324. {
  325. fNextUiAction = 0;
  326. }
  327. void uiShow()
  328. {
  329. fNextUiAction = 1;
  330. }
  331. void uiRepaint()
  332. {
  333. if (fUi != nullptr)
  334. fNextUiAction = 2;
  335. }
  336. #endif
  337. protected:
  338. void run() override
  339. {
  340. while (! threadShouldExit())
  341. {
  342. #ifdef WANT_ZYNADDSUBFX_UI
  343. Fl::lock();
  344. if (fNextUiAction == 2) // repaint
  345. {
  346. CARLA_ASSERT(fUi != nullptr);
  347. if (fUi != nullptr)
  348. fUi->refresh_master_ui();
  349. }
  350. else if (fNextUiAction == 1) // init/show
  351. {
  352. static bool initialized = false;
  353. if (! initialized)
  354. {
  355. initialized = true;
  356. fl_register_images();
  357. Fl_Dial::default_style(Fl_Dial::PIXMAP_DIAL);
  358. if (Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "knob.png"))
  359. Fl_Dial::default_image(img);
  360. if (Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "window_backdrop.png"))
  361. Fl::scheme_bg(new Fl_Tiled_Image(img));
  362. if(Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "module_backdrop.png"))
  363. gModuleBackdrop = new Fl_Tiled_Image(img);
  364. Fl::background(50, 50, 50);
  365. Fl::background2(70, 70, 70);
  366. Fl::foreground(255, 255, 255);
  367. Fl_Theme::set("Cairo");
  368. }
  369. CARLA_ASSERT(fUi == nullptr);
  370. if (fUi == nullptr)
  371. {
  372. fUiClosed = 0;
  373. fUi = new MasterUI(fMaster, &fUiClosed);
  374. fUi->masterwindow->label(kHost->uiName);
  375. fUi->showUI();
  376. }
  377. }
  378. else if (fNextUiAction == 0) // close
  379. {
  380. CARLA_ASSERT(fUi != nullptr);
  381. if (fUi != nullptr)
  382. {
  383. delete fUi;
  384. fUi = nullptr;
  385. }
  386. }
  387. fNextUiAction = -1;
  388. if (fUiClosed != 0)
  389. {
  390. fUiClosed = 0;
  391. fNextUiAction = 0;
  392. kHost->ui_closed(kHost->handle);
  393. }
  394. Fl::check();
  395. Fl::unlock();
  396. #endif
  397. if (fChangeProgram)
  398. {
  399. fChangeProgram = false;
  400. sPrograms.load(fMaster, fNextChannel, fNextBank, fNextProgram);
  401. fNextChannel = 0;
  402. fNextBank = 0;
  403. fNextProgram = 0;
  404. #ifdef WANT_ZYNADDSUBFX_UI
  405. if (fUi != nullptr)
  406. {
  407. Fl::lock();
  408. fUi->refresh_master_ui();
  409. Fl::unlock();
  410. }
  411. #endif
  412. carla_msleep(15);
  413. }
  414. else
  415. {
  416. carla_msleep(30);
  417. }
  418. }
  419. #ifdef WANT_ZYNADDSUBFX_UI
  420. if (threadShouldExit() && fUi != nullptr)
  421. {
  422. Fl::lock();
  423. delete fUi;
  424. fUi = nullptr;
  425. Fl::check();
  426. Fl::unlock();
  427. }
  428. #endif
  429. }
  430. private:
  431. Master* fMaster;
  432. const HostDescriptor* const kHost;
  433. #ifdef WANT_ZYNADDSUBFX_UI
  434. MasterUI* fUi;
  435. int fUiClosed;
  436. volatile int fNextUiAction;
  437. #endif
  438. volatile bool fChangeProgram;
  439. volatile uint8_t fNextChannel;
  440. volatile uint32_t fNextBank;
  441. volatile uint32_t fNextProgram;
  442. };
  443. // -----------------------------------------------------------------------
  444. #define ZynPluginClassEND(ClassName) \
  445. public: \
  446. static PluginHandle _instantiate(const HostDescriptor* host) \
  447. { \
  448. sInstanceCount.addOne(host); \
  449. return new ClassName(host); \
  450. } \
  451. static void _cleanup(PluginHandle handle) \
  452. { \
  453. delete (ClassName*)handle; \
  454. sInstanceCount.removeOne(); \
  455. }
  456. // -----------------------------------------------------------------------
  457. class FxAbstractPlugin : public PluginClass
  458. {
  459. protected:
  460. FxAbstractPlugin(const HostDescriptor* const host, const uint32_t paramCount, const uint32_t programCount)
  461. : PluginClass(host),
  462. fEffect(nullptr),
  463. efxoutl(new float[synth->buffersize]),
  464. efxoutr(new float[synth->buffersize]),
  465. fFirstInit(true),
  466. kParamCount(paramCount-2), // volume and pan handled by host
  467. kProgramCount(programCount)
  468. {
  469. carla_zeroFloat(efxoutl, synth->buffersize);
  470. carla_zeroFloat(efxoutr, synth->buffersize);
  471. }
  472. ~FxAbstractPlugin() override
  473. {
  474. CARLA_ASSERT(fEffect != nullptr);
  475. if (efxoutl != nullptr)
  476. {
  477. delete[] efxoutl;
  478. efxoutl = nullptr;
  479. }
  480. if (efxoutr != nullptr)
  481. {
  482. delete[] efxoutr;
  483. efxoutr = nullptr;
  484. }
  485. if (fEffect != nullptr)
  486. {
  487. delete fEffect;
  488. fEffect = nullptr;
  489. }
  490. }
  491. // -------------------------------------------------------------------
  492. // Plugin parameter calls
  493. uint32_t getParameterCount() const final
  494. {
  495. return kParamCount;
  496. }
  497. float getParameterValue(const uint32_t index) const final
  498. {
  499. return fEffect->getpar(index+2);
  500. }
  501. // -------------------------------------------------------------------
  502. // Plugin midi-program calls
  503. uint32_t getMidiProgramCount() const final
  504. {
  505. return kProgramCount;
  506. }
  507. // -------------------------------------------------------------------
  508. // Plugin state calls
  509. void setParameterValue(const uint32_t index, const float value) final
  510. {
  511. fEffect->changepar(index+2, value);
  512. fFirstInit = false;
  513. }
  514. void setMidiProgram(const uint8_t, const uint32_t, const uint32_t program) final
  515. {
  516. fEffect->setpreset(program);
  517. const float volume(float(fEffect->getpar(0))/127.0f);
  518. hostSetVolume(volume);
  519. const unsigned char pan(fEffect->getpar(1));
  520. const float panning(float(pan)/63.5f-1.0f);
  521. hostSetPanning(panning);
  522. fEffect->changepar(0, 127);
  523. fEffect->changepar(1, 64);
  524. }
  525. // -------------------------------------------------------------------
  526. // Plugin process calls
  527. void activate() final
  528. {
  529. fEffect->cleanup();
  530. if (fFirstInit)
  531. {
  532. fFirstInit = false;
  533. hostSetDryWet(0.5f);
  534. }
  535. }
  536. void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const MidiEvent* const, const uint32_t) final
  537. {
  538. CARLA_ASSERT(synth->buffersize == static_cast<int>(frames));
  539. fEffect->out(Stereo<float*>(inBuffer[0], inBuffer[1]));
  540. carla_copyFloat(outBuffer[0], efxoutl, frames);
  541. carla_copyFloat(outBuffer[1], efxoutr, frames);
  542. }
  543. // -------------------------------------------------------------------
  544. // Plugin dispatcher
  545. void bufferSizeChanged(const uint32_t bufferSize) final
  546. {
  547. delete[] efxoutl;
  548. delete[] efxoutr;
  549. efxoutl = new float[bufferSize];
  550. efxoutr = new float[bufferSize];
  551. carla_zeroFloat(efxoutl, synth->buffersize);
  552. carla_zeroFloat(efxoutr, synth->buffersize);
  553. *((float**)&fEffect->efxoutl) = efxoutl;
  554. *((float**)&fEffect->efxoutr) = efxoutr;
  555. sInstanceCount.maybeReinit(getHostHandle());
  556. }
  557. void sampleRateChanged(const double) final
  558. {
  559. sInstanceCount.maybeReinit(getHostHandle());
  560. }
  561. Effect* fEffect;
  562. float* efxoutl;
  563. float* efxoutr;
  564. bool fFirstInit;
  565. const uint32_t kParamCount;
  566. const uint32_t kProgramCount;
  567. };
  568. // -----------------------------------------------------------------------
  569. class FxAlienWahPlugin : public FxAbstractPlugin
  570. {
  571. public:
  572. FxAlienWahPlugin(const HostDescriptor* const host)
  573. : FxAbstractPlugin(host, 11, 4)
  574. {
  575. fEffect = new Alienwah(false, efxoutl, efxoutr);
  576. }
  577. protected:
  578. // -------------------------------------------------------------------
  579. // Plugin parameter calls
  580. const Parameter* getParameterInfo(const uint32_t index) const override
  581. {
  582. if (index >= kParamCount)
  583. return nullptr;
  584. static Parameter param;
  585. static ParameterScalePoint scalePoints[2];
  586. int hints = PARAMETER_IS_ENABLED|PARAMETER_IS_INTEGER;
  587. param.name = nullptr;
  588. param.unit = nullptr;
  589. param.ranges.def = 1.0f;
  590. param.ranges.min = 0.0f;
  591. param.ranges.max = 127.0f;
  592. param.ranges.step = 1.0f;
  593. param.ranges.stepSmall = 1.0f;
  594. param.ranges.stepLarge = 20.0f;
  595. param.scalePointCount = 0;
  596. param.scalePoints = nullptr;
  597. switch (index)
  598. {
  599. case 0:
  600. hints |= PARAMETER_IS_AUTOMABLE;
  601. param.name = "LFO Frequency";
  602. param.ranges.def = 70.0f;
  603. break;
  604. case 1:
  605. hints |= PARAMETER_IS_AUTOMABLE;
  606. param.name = "LFO Randomness";
  607. param.ranges.def = 0.0f;
  608. break;
  609. case 2:
  610. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN|PARAMETER_USES_SCALEPOINTS;
  611. param.name = "LFO Type";
  612. param.ranges.def = 0.0f;
  613. param.ranges.max = 1.0f;
  614. param.scalePointCount = 2;
  615. param.scalePoints = scalePoints;
  616. scalePoints[0].label = "Sine";
  617. scalePoints[1].label = "Triangle";
  618. scalePoints[0].value = 0.0f;
  619. scalePoints[1].value = 1.0f;
  620. break;
  621. case 3:
  622. hints |= PARAMETER_IS_AUTOMABLE;
  623. param.name = "LFO Stereo";
  624. param.ranges.def = 62.0f;
  625. break;
  626. case 4:
  627. hints |= PARAMETER_IS_AUTOMABLE;
  628. param.name = "Depth";
  629. param.ranges.def = 60.0f;
  630. break;
  631. case 5:
  632. hints |= PARAMETER_IS_AUTOMABLE;
  633. param.name = "Feedback";
  634. param.ranges.def = 105.0f;
  635. break;
  636. case 6:
  637. param.name = "Delay";
  638. param.ranges.def = 25.0f;
  639. param.ranges.min = 1.0f;
  640. param.ranges.max = 100.0f;
  641. break;
  642. case 7:
  643. hints |= PARAMETER_IS_AUTOMABLE;
  644. param.name = "L/R Cross";
  645. param.ranges.def = 0.0f;
  646. break;
  647. case 8:
  648. hints |= PARAMETER_IS_AUTOMABLE;
  649. param.name = "Phase";
  650. param.ranges.def = 64.0f;
  651. break;
  652. }
  653. param.hints = static_cast<ParameterHints>(hints);
  654. return &param;
  655. }
  656. // -------------------------------------------------------------------
  657. // Plugin midi-program calls
  658. const MidiProgram* getMidiProgramInfo(const uint32_t index) const override
  659. {
  660. if (index >= kProgramCount)
  661. return nullptr;
  662. static MidiProgram midiProg;
  663. midiProg.bank = 0;
  664. midiProg.program = index;
  665. switch (index)
  666. {
  667. case 0:
  668. midiProg.name = "AlienWah1";
  669. break;
  670. case 1:
  671. midiProg.name = "AlienWah2";
  672. break;
  673. case 2:
  674. midiProg.name = "AlienWah3";
  675. break;
  676. case 3:
  677. midiProg.name = "AlienWah4";
  678. break;
  679. default:
  680. midiProg.name = nullptr;
  681. break;
  682. }
  683. return &midiProg;
  684. }
  685. ZynPluginClassEND(FxAlienWahPlugin)
  686. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxAlienWahPlugin)
  687. };
  688. // -----------------------------------------------------------------------
  689. class FxChorusPlugin : public FxAbstractPlugin
  690. {
  691. public:
  692. FxChorusPlugin(const HostDescriptor* const host)
  693. : FxAbstractPlugin(host, 12, 10)
  694. {
  695. fEffect = new Chorus(false, efxoutl, efxoutr);
  696. }
  697. protected:
  698. // -------------------------------------------------------------------
  699. // Plugin parameter calls
  700. const Parameter* getParameterInfo(const uint32_t index) const override
  701. {
  702. if (index >= kParamCount)
  703. return nullptr;
  704. static Parameter param;
  705. static ParameterScalePoint scalePoints[2];
  706. int hints = PARAMETER_IS_ENABLED|PARAMETER_IS_INTEGER;
  707. param.name = nullptr;
  708. param.unit = nullptr;
  709. param.ranges.def = 1.0f;
  710. param.ranges.min = 0.0f;
  711. param.ranges.max = 127.0f;
  712. param.ranges.step = 1.0f;
  713. param.ranges.stepSmall = 1.0f;
  714. param.ranges.stepLarge = 20.0f;
  715. param.scalePointCount = 0;
  716. param.scalePoints = nullptr;
  717. switch (index)
  718. {
  719. case 0:
  720. hints |= PARAMETER_IS_AUTOMABLE;
  721. param.name = "LFO Frequency";
  722. param.ranges.def = 50.0f;
  723. break;
  724. case 1:
  725. hints |= PARAMETER_IS_AUTOMABLE;
  726. param.name = "LFO Randomness";
  727. param.ranges.def = 0.0f;
  728. break;
  729. case 2:
  730. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN|PARAMETER_USES_SCALEPOINTS;
  731. param.name = "LFO Type";
  732. param.ranges.def = 0.0f;
  733. param.ranges.max = 1.0f;
  734. param.scalePointCount = 2;
  735. param.scalePoints = scalePoints;
  736. scalePoints[0].label = "Sine";
  737. scalePoints[1].label = "Triangle";
  738. scalePoints[0].value = 0.0f;
  739. scalePoints[1].value = 1.0f;
  740. break;
  741. case 3:
  742. hints |= PARAMETER_IS_AUTOMABLE;
  743. param.name = "LFO Stereo";
  744. param.ranges.def = 90.0f;
  745. break;
  746. case 4:
  747. hints |= PARAMETER_IS_AUTOMABLE;
  748. param.name = "Depth";
  749. param.ranges.def = 40.0f;
  750. break;
  751. case 5:
  752. hints |= PARAMETER_IS_AUTOMABLE;
  753. param.name = "Delay";
  754. param.ranges.def = 85.0f;
  755. break;
  756. case 6:
  757. hints |= PARAMETER_IS_AUTOMABLE;
  758. param.name = "Feedback";
  759. param.ranges.def = 64.0f;
  760. break;
  761. case 7:
  762. hints |= PARAMETER_IS_AUTOMABLE;
  763. param.name = "L/R Cross";
  764. param.ranges.def = 119.0f;
  765. break;
  766. case 8:
  767. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN;
  768. param.name = "Flange Mode";
  769. param.ranges.def = 0.0f;
  770. param.ranges.max = 1.0f;
  771. break;
  772. case 9:
  773. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN;
  774. param.name = "Subtract Output";
  775. param.ranges.def = 0.0f;
  776. param.ranges.max = 1.0f;
  777. break;
  778. }
  779. param.hints = static_cast<ParameterHints>(hints);
  780. return &param;
  781. }
  782. // -------------------------------------------------------------------
  783. // Plugin midi-program calls
  784. const MidiProgram* getMidiProgramInfo(const uint32_t index) const override
  785. {
  786. if (index >= kProgramCount)
  787. return nullptr;
  788. static MidiProgram midiProg;
  789. midiProg.bank = 0;
  790. midiProg.program = index;
  791. switch (index)
  792. {
  793. case 0:
  794. midiProg.name = "Chorus1";
  795. break;
  796. case 1:
  797. midiProg.name = "Chorus2";
  798. break;
  799. case 2:
  800. midiProg.name = "Chorus3";
  801. break;
  802. case 3:
  803. midiProg.name = "Celeste1";
  804. break;
  805. case 4:
  806. midiProg.name = "Celeste2";
  807. break;
  808. case 5:
  809. midiProg.name = "Flange1";
  810. break;
  811. case 6:
  812. midiProg.name = "Flange2";
  813. break;
  814. case 7:
  815. midiProg.name = "Flange3";
  816. break;
  817. case 8:
  818. midiProg.name = "Flange4";
  819. break;
  820. case 9:
  821. midiProg.name = "Flange5";
  822. break;
  823. default:
  824. midiProg.name = nullptr;
  825. break;
  826. }
  827. return &midiProg;
  828. }
  829. ZynPluginClassEND(FxChorusPlugin)
  830. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxChorusPlugin)
  831. };
  832. // -----------------------------------------------------------------------
  833. class FxDistortionPlugin : public FxAbstractPlugin
  834. {
  835. public:
  836. FxDistortionPlugin(const HostDescriptor* const host)
  837. : FxAbstractPlugin(host, 11, 6)
  838. {
  839. fEffect = new Distorsion(false, efxoutl, efxoutr);
  840. }
  841. protected:
  842. // -------------------------------------------------------------------
  843. // Plugin parameter calls
  844. const Parameter* getParameterInfo(const uint32_t index) const override
  845. {
  846. if (index >= kParamCount)
  847. return nullptr;
  848. static Parameter param;
  849. static ParameterScalePoint scalePoints[14];
  850. int hints = PARAMETER_IS_ENABLED|PARAMETER_IS_INTEGER;
  851. param.name = nullptr;
  852. param.unit = nullptr;
  853. param.ranges.def = 1.0f;
  854. param.ranges.min = 0.0f;
  855. param.ranges.max = 127.0f;
  856. param.ranges.step = 1.0f;
  857. param.ranges.stepSmall = 1.0f;
  858. param.ranges.stepLarge = 20.0f;
  859. param.scalePointCount = 0;
  860. param.scalePoints = nullptr;
  861. switch (index)
  862. {
  863. case 0:
  864. hints |= PARAMETER_IS_AUTOMABLE;
  865. param.name = "L/R Cross";
  866. param.ranges.def = 35.0f;
  867. break;
  868. case 1:
  869. hints |= PARAMETER_IS_AUTOMABLE;
  870. param.name = "Drive";
  871. param.ranges.def = 56.0f;
  872. break;
  873. case 2:
  874. hints |= PARAMETER_IS_AUTOMABLE;
  875. param.name = "Level";
  876. param.ranges.def = 70.0f;
  877. break;
  878. case 3:
  879. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_USES_SCALEPOINTS;
  880. param.name = "Type";
  881. param.ranges.def = 0.0f;
  882. param.ranges.max = 13.0f;
  883. param.scalePointCount = 14;
  884. param.scalePoints = scalePoints;
  885. scalePoints[ 0].label = "Arctangent";
  886. scalePoints[ 1].label = "Asymmetric";
  887. scalePoints[ 2].label = "Pow";
  888. scalePoints[ 3].label = "Sine";
  889. scalePoints[ 4].label = "Quantisize";
  890. scalePoints[ 5].label = "Zigzag";
  891. scalePoints[ 6].label = "Limiter";
  892. scalePoints[ 7].label = "Upper Limiter";
  893. scalePoints[ 8].label = "Lower Limiter";
  894. scalePoints[ 9].label = "Inverse Limiter";
  895. scalePoints[10].label = "Clip";
  896. scalePoints[11].label = "Asym2";
  897. scalePoints[12].label = "Pow2";
  898. scalePoints[13].label = "Sigmoid";
  899. scalePoints[ 0].value = 0.0f;
  900. scalePoints[ 1].value = 1.0f;
  901. scalePoints[ 2].value = 2.0f;
  902. scalePoints[ 3].value = 3.0f;
  903. scalePoints[ 4].value = 4.0f;
  904. scalePoints[ 5].value = 5.0f;
  905. scalePoints[ 6].value = 6.0f;
  906. scalePoints[ 7].value = 7.0f;
  907. scalePoints[ 8].value = 8.0f;
  908. scalePoints[ 9].value = 9.0f;
  909. scalePoints[10].value = 10.0f;
  910. scalePoints[11].value = 11.0f;
  911. scalePoints[12].value = 12.0f;
  912. scalePoints[13].value = 13.0f;
  913. break;
  914. case 4:
  915. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN;
  916. param.name = "Negate";
  917. param.ranges.def = 0.0f;
  918. param.ranges.max = 1.0f;
  919. break;
  920. case 5:
  921. hints |= PARAMETER_IS_AUTOMABLE;
  922. param.name = "Low-Pass Filter";
  923. param.ranges.def = 96.0f;
  924. break;
  925. case 6:
  926. hints |= PARAMETER_IS_AUTOMABLE;
  927. param.name = "High-Pass Filter";
  928. param.ranges.def = 0.0f;
  929. break;
  930. case 7:
  931. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN;
  932. param.name = "Stereo";
  933. param.ranges.def = 0.0f;
  934. param.ranges.max = 1.0f;
  935. break;
  936. case 8:
  937. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN;
  938. param.name = "Pre-Filtering";
  939. param.ranges.def = 0.0f;
  940. param.ranges.max = 1.0f;
  941. break;
  942. }
  943. param.hints = static_cast<ParameterHints>(hints);
  944. return &param;
  945. }
  946. // -------------------------------------------------------------------
  947. // Plugin midi-program calls
  948. const MidiProgram* getMidiProgramInfo(const uint32_t index) const override
  949. {
  950. if (index >= kProgramCount)
  951. return nullptr;
  952. static MidiProgram midiProg;
  953. midiProg.bank = 0;
  954. midiProg.program = index;
  955. switch (index)
  956. {
  957. case 0:
  958. midiProg.name = "Overdrive 1";
  959. break;
  960. case 1:
  961. midiProg.name = "Overdrive 2";
  962. break;
  963. case 2:
  964. midiProg.name = "A. Exciter 1";
  965. break;
  966. case 3:
  967. midiProg.name = "A. Exciter 2";
  968. break;
  969. case 4:
  970. midiProg.name = "Guitar Amp";
  971. break;
  972. case 5:
  973. midiProg.name = "Quantisize";
  974. break;
  975. default:
  976. midiProg.name = nullptr;
  977. break;
  978. }
  979. return &midiProg;
  980. }
  981. ZynPluginClassEND(FxDistortionPlugin)
  982. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxDistortionPlugin)
  983. };
  984. // -----------------------------------------------------------------------
  985. class FxDynamicFilterPlugin : public FxAbstractPlugin
  986. {
  987. public:
  988. FxDynamicFilterPlugin(const HostDescriptor* const host)
  989. : FxAbstractPlugin(host, 10, 5)
  990. {
  991. fEffect = new DynamicFilter(false, efxoutl, efxoutr);
  992. }
  993. protected:
  994. // -------------------------------------------------------------------
  995. // Plugin parameter calls
  996. const Parameter* getParameterInfo(const uint32_t index) const override
  997. {
  998. if (index >= kParamCount)
  999. return nullptr;
  1000. static Parameter param;
  1001. static ParameterScalePoint scalePoints[2];
  1002. int hints = PARAMETER_IS_ENABLED|PARAMETER_IS_INTEGER;
  1003. param.name = nullptr;
  1004. param.unit = nullptr;
  1005. param.ranges.def = 1.0f;
  1006. param.ranges.min = 0.0f;
  1007. param.ranges.max = 127.0f;
  1008. param.ranges.step = 1.0f;
  1009. param.ranges.stepSmall = 1.0f;
  1010. param.ranges.stepLarge = 20.0f;
  1011. param.scalePointCount = 0;
  1012. param.scalePoints = nullptr;
  1013. switch (index)
  1014. {
  1015. case 0:
  1016. hints |= PARAMETER_IS_AUTOMABLE;
  1017. param.name = "LFO Frequency";
  1018. param.ranges.def = 80.0f;
  1019. break;
  1020. case 1:
  1021. hints |= PARAMETER_IS_AUTOMABLE;
  1022. param.name = "LFO Randomness";
  1023. param.ranges.def = 0.0f;
  1024. break;
  1025. case 2:
  1026. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN|PARAMETER_USES_SCALEPOINTS;
  1027. param.name = "LFO Type";
  1028. param.ranges.def = 0.0f;
  1029. param.ranges.max = 1.0f;
  1030. param.scalePointCount = 2;
  1031. param.scalePoints = scalePoints;
  1032. scalePoints[0].label = "Sine";
  1033. scalePoints[1].label = "Triangle";
  1034. scalePoints[0].value = 0.0f;
  1035. scalePoints[1].value = 1.0f;
  1036. break;
  1037. case 3:
  1038. hints |= PARAMETER_IS_AUTOMABLE;
  1039. param.name = "LFO Stereo";
  1040. param.ranges.def = 64.0f;
  1041. break;
  1042. case 4:
  1043. hints |= PARAMETER_IS_AUTOMABLE;
  1044. param.name = "LFO Depth";
  1045. param.ranges.def = 0.0f;
  1046. break;
  1047. case 5:
  1048. hints |= PARAMETER_IS_AUTOMABLE;
  1049. param.name = "Amp sns";
  1050. param.ranges.def = 90.0f;
  1051. break;
  1052. case 6:
  1053. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN;
  1054. param.name = "Amp sns inv";
  1055. param.ranges.def = 0.0f;
  1056. param.ranges.max = 1.0f;
  1057. break;
  1058. case 7:
  1059. hints |= PARAMETER_IS_AUTOMABLE;
  1060. param.name = "Amp Smooth";
  1061. param.ranges.def = 60.0f;
  1062. break;
  1063. }
  1064. param.hints = static_cast<ParameterHints>(hints);
  1065. return &param;
  1066. }
  1067. // -------------------------------------------------------------------
  1068. // Plugin midi-program calls
  1069. const MidiProgram* getMidiProgramInfo(const uint32_t index) const override
  1070. {
  1071. if (index >= kProgramCount)
  1072. return nullptr;
  1073. static MidiProgram midiProg;
  1074. midiProg.bank = 0;
  1075. midiProg.program = index;
  1076. switch (index)
  1077. {
  1078. case 0:
  1079. midiProg.name = "WahWah";
  1080. break;
  1081. case 1:
  1082. midiProg.name = "AutoWah";
  1083. break;
  1084. case 2:
  1085. midiProg.name = "Sweep";
  1086. break;
  1087. case 3:
  1088. midiProg.name = "VocalMorph1";
  1089. break;
  1090. case 4:
  1091. midiProg.name = "VocalMorph2";
  1092. break;
  1093. default:
  1094. midiProg.name = nullptr;
  1095. break;
  1096. }
  1097. return &midiProg;
  1098. }
  1099. ZynPluginClassEND(FxDynamicFilterPlugin)
  1100. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxDynamicFilterPlugin)
  1101. };
  1102. // -----------------------------------------------------------------------
  1103. class FxEchoPlugin : public FxAbstractPlugin
  1104. {
  1105. public:
  1106. FxEchoPlugin(const HostDescriptor* const host)
  1107. : FxAbstractPlugin(host, 7, 9)
  1108. {
  1109. fEffect = new Echo(false, efxoutl, efxoutr);
  1110. }
  1111. protected:
  1112. // -------------------------------------------------------------------
  1113. // Plugin parameter calls
  1114. const Parameter* getParameterInfo(const uint32_t index) const override
  1115. {
  1116. if (index >= kParamCount)
  1117. return nullptr;
  1118. static Parameter param;
  1119. int hints = PARAMETER_IS_ENABLED|PARAMETER_IS_INTEGER;
  1120. param.name = nullptr;
  1121. param.unit = nullptr;
  1122. param.ranges.def = 1.0f;
  1123. param.ranges.min = 0.0f;
  1124. param.ranges.max = 127.0f;
  1125. param.ranges.step = 1.0f;
  1126. param.ranges.stepSmall = 1.0f;
  1127. param.ranges.stepLarge = 20.0f;
  1128. param.scalePointCount = 0;
  1129. param.scalePoints = nullptr;
  1130. switch (index)
  1131. {
  1132. case 0:
  1133. hints |= PARAMETER_IS_AUTOMABLE;
  1134. param.name = "Delay";
  1135. param.ranges.def = 35.0f;
  1136. break;
  1137. case 1:
  1138. hints |= PARAMETER_IS_AUTOMABLE;
  1139. param.name = "L/R Delay";
  1140. param.ranges.def = 64.0f;
  1141. break;
  1142. case 2:
  1143. hints |= PARAMETER_IS_AUTOMABLE;
  1144. param.name = "L/R Cross";
  1145. param.ranges.def = 30.0f;
  1146. break;
  1147. case 3:
  1148. hints |= PARAMETER_IS_AUTOMABLE;
  1149. param.name = "Feedback";
  1150. param.ranges.def = 59.0f;
  1151. break;
  1152. case 4:
  1153. hints |= PARAMETER_IS_AUTOMABLE;
  1154. param.name = "High Damp";
  1155. param.ranges.def = 0.0f;
  1156. break;
  1157. }
  1158. param.hints = static_cast<ParameterHints>(hints);
  1159. return &param;
  1160. }
  1161. // -------------------------------------------------------------------
  1162. // Plugin midi-program calls
  1163. const MidiProgram* getMidiProgramInfo(const uint32_t index) const override
  1164. {
  1165. if (index >= kProgramCount)
  1166. return nullptr;
  1167. static MidiProgram midiProg;
  1168. midiProg.bank = 0;
  1169. midiProg.program = index;
  1170. switch (index)
  1171. {
  1172. case 0:
  1173. midiProg.name = "Echo 1";
  1174. break;
  1175. case 1:
  1176. midiProg.name = "Echo 2";
  1177. break;
  1178. case 2:
  1179. midiProg.name = "Echo 3";
  1180. break;
  1181. case 3:
  1182. midiProg.name = "Simple Echo";
  1183. break;
  1184. case 4:
  1185. midiProg.name = "Canyon";
  1186. break;
  1187. case 5:
  1188. midiProg.name = "Panning Echo 1";
  1189. break;
  1190. case 6:
  1191. midiProg.name = "Panning Echo 2";
  1192. break;
  1193. case 7:
  1194. midiProg.name = "Panning Echo 3";
  1195. break;
  1196. case 8:
  1197. midiProg.name = "Feedback Echo";
  1198. break;
  1199. default:
  1200. midiProg.name = nullptr;
  1201. break;
  1202. }
  1203. return &midiProg;
  1204. }
  1205. ZynPluginClassEND(FxEchoPlugin)
  1206. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxEchoPlugin)
  1207. };
  1208. // -----------------------------------------------------------------------
  1209. class FxPhaserPlugin : public FxAbstractPlugin
  1210. {
  1211. public:
  1212. FxPhaserPlugin(const HostDescriptor* const host)
  1213. : FxAbstractPlugin(host, 15, 12)
  1214. {
  1215. fEffect = new Phaser(false, efxoutl, efxoutr);
  1216. }
  1217. protected:
  1218. // -------------------------------------------------------------------
  1219. // Plugin parameter calls
  1220. const Parameter* getParameterInfo(const uint32_t index) const override
  1221. {
  1222. if (index >= kParamCount)
  1223. return nullptr;
  1224. static Parameter param;
  1225. static ParameterScalePoint scalePoints[2];
  1226. int hints = PARAMETER_IS_ENABLED|PARAMETER_IS_INTEGER;
  1227. param.name = nullptr;
  1228. param.unit = nullptr;
  1229. param.ranges.def = 1.0f;
  1230. param.ranges.min = 0.0f;
  1231. param.ranges.max = 127.0f;
  1232. param.ranges.step = 1.0f;
  1233. param.ranges.stepSmall = 1.0f;
  1234. param.ranges.stepLarge = 20.0f;
  1235. param.scalePointCount = 0;
  1236. param.scalePoints = nullptr;
  1237. switch (index)
  1238. {
  1239. case 0:
  1240. hints |= PARAMETER_IS_AUTOMABLE;
  1241. param.name = "LFO Frequency";
  1242. param.ranges.def = 36.0f;
  1243. break;
  1244. case 1:
  1245. hints |= PARAMETER_IS_AUTOMABLE;
  1246. param.name = "LFO Randomness";
  1247. param.ranges.def = 0.0f;
  1248. break;
  1249. case 2:
  1250. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN|PARAMETER_USES_SCALEPOINTS;
  1251. param.name = "LFO Type";
  1252. param.ranges.def = 0.0f;
  1253. param.ranges.max = 1.0f;
  1254. param.scalePointCount = 2;
  1255. param.scalePoints = scalePoints;
  1256. scalePoints[0].label = "Sine";
  1257. scalePoints[1].label = "Triangle";
  1258. scalePoints[0].value = 0.0f;
  1259. scalePoints[1].value = 1.0f;
  1260. break;
  1261. case 3:
  1262. hints |= PARAMETER_IS_AUTOMABLE;
  1263. param.name = "LFO Stereo";
  1264. param.ranges.def = 64.0f;
  1265. break;
  1266. case 4:
  1267. hints |= PARAMETER_IS_AUTOMABLE;
  1268. param.name = "Depth";
  1269. param.ranges.def = 110.0f;
  1270. break;
  1271. case 5:
  1272. hints |= PARAMETER_IS_AUTOMABLE;
  1273. param.name = "Feedback";
  1274. param.ranges.def = 64.0f;
  1275. break;
  1276. case 6:
  1277. param.name = "Stages";
  1278. param.ranges.def = 1.0f;
  1279. param.ranges.min = 1.0f;
  1280. param.ranges.max = 12.0f;
  1281. break;
  1282. case 7:
  1283. hints |= PARAMETER_IS_AUTOMABLE;
  1284. param.name = "L/R Cross|Offset";
  1285. param.ranges.def = 0.0f;
  1286. break;
  1287. case 8:
  1288. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN;
  1289. param.name = "Subtract Output";
  1290. param.ranges.def = 0.0f;
  1291. param.ranges.max = 1.0f;
  1292. break;
  1293. case 9:
  1294. hints |= PARAMETER_IS_AUTOMABLE;
  1295. param.name = "Phase|Width";
  1296. param.ranges.def = 20.0f;
  1297. break;
  1298. case 10:
  1299. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN;
  1300. param.name = "Hyper";
  1301. param.ranges.def = 0.0f;
  1302. param.ranges.max = 1.0f;
  1303. break;
  1304. case 11:
  1305. hints |= PARAMETER_IS_AUTOMABLE;
  1306. param.name = "Distortion";
  1307. param.ranges.def = 0.0f;
  1308. break;
  1309. case 12:
  1310. hints |= PARAMETER_IS_AUTOMABLE|PARAMETER_IS_BOOLEAN;
  1311. param.name = "Analog";
  1312. param.ranges.def = 0.0f;
  1313. param.ranges.max = 1.0f;
  1314. break;
  1315. }
  1316. param.hints = static_cast<ParameterHints>(hints);
  1317. return &param;
  1318. }
  1319. // -------------------------------------------------------------------
  1320. // Plugin midi-program calls
  1321. const MidiProgram* getMidiProgramInfo(const uint32_t index) const override
  1322. {
  1323. if (index >= kProgramCount)
  1324. return nullptr;
  1325. static MidiProgram midiProg;
  1326. midiProg.bank = 0;
  1327. midiProg.program = index;
  1328. switch (index)
  1329. {
  1330. case 0:
  1331. midiProg.name = "Phaser 1";
  1332. break;
  1333. case 1:
  1334. midiProg.name = "Phaser 2";
  1335. break;
  1336. case 2:
  1337. midiProg.name = "Phaser 3";
  1338. break;
  1339. case 3:
  1340. midiProg.name = "Phaser 4";
  1341. break;
  1342. case 4:
  1343. midiProg.name = "Phaser 5";
  1344. break;
  1345. case 5:
  1346. midiProg.name = "Phaser 6";
  1347. break;
  1348. case 6:
  1349. midiProg.name = "APhaser 1";
  1350. break;
  1351. case 7:
  1352. midiProg.name = "APhaser 2";
  1353. break;
  1354. case 8:
  1355. midiProg.name = "APhaser 3";
  1356. break;
  1357. case 9:
  1358. midiProg.name = "APhaser 4";
  1359. break;
  1360. case 10:
  1361. midiProg.name = "APhaser 5";
  1362. break;
  1363. case 11:
  1364. midiProg.name = "APhaser 6";
  1365. break;
  1366. default:
  1367. midiProg.name = nullptr;
  1368. break;
  1369. }
  1370. return &midiProg;
  1371. }
  1372. ZynPluginClassEND(FxPhaserPlugin)
  1373. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxPhaserPlugin)
  1374. };
  1375. // -----------------------------------------------------------------------
  1376. class FxReverbPlugin : public FxAbstractPlugin
  1377. {
  1378. public:
  1379. FxReverbPlugin(const HostDescriptor* const host)
  1380. : FxAbstractPlugin(host, 13, 13)
  1381. {
  1382. fEffect = new Reverb(false, efxoutl, efxoutr);
  1383. }
  1384. protected:
  1385. // -------------------------------------------------------------------
  1386. // Plugin parameter calls
  1387. const Parameter* getParameterInfo(const uint32_t index) const override
  1388. {
  1389. if (index >= kParamCount)
  1390. return nullptr;
  1391. static Parameter param;
  1392. static ParameterScalePoint scalePoints[3];
  1393. int hints = PARAMETER_IS_ENABLED | PARAMETER_IS_INTEGER;
  1394. param.name = nullptr;
  1395. param.unit = nullptr;
  1396. param.ranges.def = 1.0f;
  1397. param.ranges.min = 0.0f;
  1398. param.ranges.max = 127.0f;
  1399. param.ranges.step = 1.0f;
  1400. param.ranges.stepSmall = 1.0f;
  1401. param.ranges.stepLarge = 20.0f;
  1402. param.scalePointCount = 0;
  1403. param.scalePoints = nullptr;
  1404. switch (index)
  1405. {
  1406. case 0:
  1407. hints |= PARAMETER_IS_AUTOMABLE;
  1408. param.name = "Time";
  1409. param.ranges.def = 63.0f;
  1410. break;
  1411. case 1:
  1412. param.name = "Delay";
  1413. param.ranges.def = 24.0f;
  1414. break;
  1415. case 2:
  1416. hints |= PARAMETER_IS_AUTOMABLE;
  1417. param.name = "Feedback";
  1418. param.ranges.def = 0.0f;
  1419. break;
  1420. case 3:
  1421. hints = 0x0;
  1422. param.name = "bw";
  1423. break;
  1424. case 4:
  1425. hints = 0x0;
  1426. param.name = "E/R";
  1427. break;
  1428. case 5:
  1429. param.name = "Low-Pass Filter";
  1430. param.ranges.def = 85.0f;
  1431. break;
  1432. case 6:
  1433. param.name = "High-Pass Filter";
  1434. param.ranges.def = 5.0f;
  1435. break;
  1436. case 7:
  1437. hints |= PARAMETER_IS_AUTOMABLE;
  1438. param.name = "Damp";
  1439. param.ranges.def = 83.0f;
  1440. param.ranges.min = 64.0f;
  1441. break;
  1442. case 8:
  1443. hints |= PARAMETER_USES_SCALEPOINTS;
  1444. param.name = "Type";
  1445. param.ranges.def = 1.0f;
  1446. param.ranges.max = 2.0f;
  1447. param.scalePointCount = 3;
  1448. param.scalePoints = scalePoints;
  1449. scalePoints[0].label = "Random";
  1450. scalePoints[1].label = "Freeverb";
  1451. scalePoints[2].label = "Bandwidth";
  1452. scalePoints[0].value = 0.0f;
  1453. scalePoints[1].value = 1.0f;
  1454. scalePoints[2].value = 2.0f;
  1455. break;
  1456. case 9:
  1457. param.name = "Room size";
  1458. param.ranges.def = 64.0f;
  1459. param.ranges.min = 1.0f;
  1460. break;
  1461. case 10:
  1462. param.name = "Bandwidth";
  1463. param.ranges.def = 20.0f;
  1464. break;
  1465. }
  1466. param.hints = static_cast<ParameterHints>(hints);
  1467. return &param;
  1468. }
  1469. // -------------------------------------------------------------------
  1470. // Plugin midi-program calls
  1471. const MidiProgram* getMidiProgramInfo(const uint32_t index) const override
  1472. {
  1473. if (index >= kProgramCount)
  1474. return nullptr;
  1475. static MidiProgram midiProg;
  1476. midiProg.bank = 0;
  1477. midiProg.program = index;
  1478. switch (index)
  1479. {
  1480. case 0:
  1481. midiProg.name = "Cathedral1";
  1482. break;
  1483. case 1:
  1484. midiProg.name = "Cathedral2";
  1485. break;
  1486. case 2:
  1487. midiProg.name = "Cathedral3";
  1488. break;
  1489. case 3:
  1490. midiProg.name = "Hall1";
  1491. break;
  1492. case 4:
  1493. midiProg.name = "Hall2";
  1494. break;
  1495. case 5:
  1496. midiProg.name = "Room1";
  1497. break;
  1498. case 6:
  1499. midiProg.name = "Room2";
  1500. break;
  1501. case 7:
  1502. midiProg.name = "Basement";
  1503. break;
  1504. case 8:
  1505. midiProg.name = "Tunnel";
  1506. break;
  1507. case 9:
  1508. midiProg.name = "Echoed1";
  1509. break;
  1510. case 10:
  1511. midiProg.name = "Echoed2";
  1512. break;
  1513. case 11:
  1514. midiProg.name = "VeryLong1";
  1515. break;
  1516. case 12:
  1517. midiProg.name = "VeryLong2";
  1518. break;
  1519. default:
  1520. midiProg.name = nullptr;
  1521. break;
  1522. }
  1523. return &midiProg;
  1524. }
  1525. ZynPluginClassEND(FxReverbPlugin)
  1526. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxReverbPlugin)
  1527. };
  1528. // -----------------------------------------------------------------------
  1529. class ZynAddSubFxPlugin : public PluginClass
  1530. {
  1531. public:
  1532. ZynAddSubFxPlugin(const HostDescriptor* const host)
  1533. : PluginClass(host),
  1534. fMaster(new Master()),
  1535. fSampleRate(getSampleRate()),
  1536. fIsActive(false),
  1537. fThread(fMaster, host)
  1538. {
  1539. fThread.startThread(3);
  1540. for (int i = 0; i < NUM_MIDI_PARTS; ++i)
  1541. fMaster->partonoff(i, 1);
  1542. sPrograms.init();
  1543. }
  1544. ~ZynAddSubFxPlugin() override
  1545. {
  1546. //ensure that everything has stopped
  1547. pthread_mutex_lock(&fMaster->mutex);
  1548. pthread_mutex_unlock(&fMaster->mutex);
  1549. fThread.stopThread(-1);
  1550. delete fMaster;
  1551. fMaster = nullptr;
  1552. }
  1553. protected:
  1554. // -------------------------------------------------------------------
  1555. // Plugin midi-program calls
  1556. uint32_t getMidiProgramCount() const override
  1557. {
  1558. return sPrograms.count();
  1559. }
  1560. const MidiProgram* getMidiProgramInfo(const uint32_t index) const override
  1561. {
  1562. return sPrograms.getInfo(index);
  1563. }
  1564. // -------------------------------------------------------------------
  1565. // Plugin state calls
  1566. void setMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program) override
  1567. {
  1568. if (bank >= fMaster->bank.banks.size())
  1569. return;
  1570. if (program >= BANK_SIZE)
  1571. return;
  1572. if (isOffline() || ! fIsActive)
  1573. {
  1574. sPrograms.load(fMaster, channel, bank, program);
  1575. #ifdef WANT_ZYNADDSUBFX_UI
  1576. fThread.uiRepaint();
  1577. #endif
  1578. }
  1579. else
  1580. fThread.loadProgramLater(channel, bank, program);
  1581. }
  1582. void setCustomData(const char* const key, const char* const value) override
  1583. {
  1584. CARLA_ASSERT(key != nullptr);
  1585. CARLA_ASSERT(value != nullptr);
  1586. if (std::strcmp(key, "CarlaAlternateFile1") == 0) // xmz
  1587. fMaster->loadXML(value);
  1588. else if (std::strcmp(key, "CarlaAlternateFile2") == 0) // xiz
  1589. fMaster->part[0]->loadXMLinstrument(value);
  1590. }
  1591. // -------------------------------------------------------------------
  1592. // Plugin process calls
  1593. void activate() override
  1594. {
  1595. fIsActive = true;
  1596. }
  1597. void deactivate() override
  1598. {
  1599. fIsActive = false;
  1600. }
  1601. void process(float**, float** const outBuffer, const uint32_t frames, const MidiEvent* const midiEvents, const uint32_t midiEventCount) override
  1602. {
  1603. if (pthread_mutex_trylock(&fMaster->mutex) != 0)
  1604. {
  1605. carla_zeroFloat(outBuffer[0], frames);
  1606. carla_zeroFloat(outBuffer[1], frames);
  1607. return;
  1608. }
  1609. for (uint32_t i=0; i < midiEventCount; ++i)
  1610. {
  1611. const MidiEvent* const midiEvent(&midiEvents[i]);
  1612. const uint8_t status = MIDI_GET_STATUS_FROM_DATA(midiEvent->data);
  1613. const uint8_t channel = MIDI_GET_CHANNEL_FROM_DATA(midiEvent->data);
  1614. if (MIDI_IS_STATUS_NOTE_OFF(status))
  1615. {
  1616. const uint8_t note = midiEvent->data[1];
  1617. fMaster->noteOff(channel, note);
  1618. }
  1619. else if (MIDI_IS_STATUS_NOTE_ON(status))
  1620. {
  1621. const uint8_t note = midiEvent->data[1];
  1622. const uint8_t velo = midiEvent->data[2];
  1623. fMaster->noteOn(channel, note, velo);
  1624. }
  1625. else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status))
  1626. {
  1627. const uint8_t note = midiEvent->data[1];
  1628. const uint8_t pressure = midiEvent->data[2];
  1629. fMaster->polyphonicAftertouch(channel, note, pressure);
  1630. }
  1631. else if (MIDI_IS_STATUS_CONTROL_CHANGE(status))
  1632. {
  1633. const uint8_t control = midiEvent->data[1];
  1634. const uint8_t value = midiEvent->data[2];
  1635. fMaster->setController(channel, control, value);
  1636. }
  1637. else if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status))
  1638. {
  1639. const uint8_t lsb = midiEvent->data[1];
  1640. const uint8_t msb = midiEvent->data[2];
  1641. const int value = ((msb << 7) | lsb) - 8192;
  1642. fMaster->setController(channel, C_pitchwheel, value);
  1643. }
  1644. }
  1645. fMaster->GetAudioOutSamples(frames, fSampleRate, outBuffer[0], outBuffer[1]);
  1646. pthread_mutex_unlock(&fMaster->mutex);
  1647. }
  1648. #ifdef WANT_ZYNADDSUBFX_UI
  1649. // -------------------------------------------------------------------
  1650. // Plugin UI calls
  1651. void uiShow(const bool show) override
  1652. {
  1653. if (show)
  1654. fThread.uiShow();
  1655. else
  1656. fThread.uiHide();
  1657. }
  1658. #endif
  1659. // -------------------------------------------------------------------
  1660. // Plugin state calls
  1661. char* getState() const override
  1662. {
  1663. config.save();
  1664. char* data = nullptr;
  1665. fMaster->getalldata(&data);
  1666. return data;
  1667. }
  1668. void setState(const char* const data) override
  1669. {
  1670. fThread.stopLoadProgramLater();
  1671. fMaster->putalldata((char*)data, 0);
  1672. fMaster->applyparameters(true);
  1673. }
  1674. #if 0
  1675. // -------------------------------------------------------------------
  1676. // Plugin dispatcher
  1677. intptr_t pluginDispatcher(const PluginDispatcherOpcode opcode, const int32_t index, const intptr_t value, void* const ptr, const float) override
  1678. {
  1679. switch (opcode)
  1680. {
  1681. case PLUGIN_OPCODE_NULL:
  1682. break;
  1683. case PLUGIN_OPCODE_BUFFER_SIZE_CHANGED:
  1684. // TODO
  1685. break;
  1686. case PLUGIN_OPCODE_SAMPLE_RATE_CHANGED:
  1687. // TODO
  1688. break;
  1689. case PLUGIN_OPCODE_OFFLINE_CHANGED:
  1690. break;
  1691. case PLUGIN_OPCODE_UI_NAME_CHANGED:
  1692. #ifdef WANT_ZYNADDSUBFX_UI
  1693. // TODO
  1694. #endif
  1695. break;
  1696. }
  1697. return 0;
  1698. // unused
  1699. (void)index;
  1700. (void)value;
  1701. (void)ptr;
  1702. }
  1703. #endif
  1704. // -------------------------------------------------------------------
  1705. private:
  1706. Master* fMaster;
  1707. unsigned fSampleRate;
  1708. bool fIsActive;
  1709. ZynAddSubFxThread fThread;
  1710. ZynPluginClassEND(ZynAddSubFxPlugin)
  1711. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ZynAddSubFxPlugin)
  1712. };
  1713. // -----------------------------------------------------------------------
  1714. static const PluginDescriptor fxAlienWahDesc = {
  1715. /* category */ PLUGIN_CATEGORY_MODULATOR,
  1716. /* hints */ static_cast<PluginHints>(PLUGIN_IS_RTSAFE|PLUGIN_USES_PANNING|PLUGIN_NEEDS_FIXED_BUFFERS),
  1717. /* supports */ static_cast<PluginSupports>(0x0),
  1718. /* audioIns */ 2,
  1719. /* audioOuts */ 2,
  1720. /* midiIns */ 0,
  1721. /* midiOuts */ 0,
  1722. /* paramIns */ 11-2,
  1723. /* paramOuts */ 0,
  1724. /* name */ "ZynAlienWah",
  1725. /* label */ "zynAlienWah",
  1726. /* maker */ "falkTX",
  1727. /* copyright */ "GNU GPL v2+",
  1728. PluginDescriptorFILL(FxAlienWahPlugin)
  1729. };
  1730. static const PluginDescriptor fxChorusDesc = {
  1731. /* category */ PLUGIN_CATEGORY_MODULATOR,
  1732. /* hints */ static_cast<PluginHints>(PLUGIN_IS_RTSAFE|PLUGIN_USES_PANNING|PLUGIN_NEEDS_FIXED_BUFFERS),
  1733. /* supports */ static_cast<PluginSupports>(0x0),
  1734. /* audioIns */ 2,
  1735. /* audioOuts */ 2,
  1736. /* midiIns */ 0,
  1737. /* midiOuts */ 0,
  1738. /* paramIns */ 12-2,
  1739. /* paramOuts */ 0,
  1740. /* name */ "ZynChorus",
  1741. /* label */ "zynChorus",
  1742. /* maker */ "falkTX",
  1743. /* copyright */ "GNU GPL v2+",
  1744. PluginDescriptorFILL(FxChorusPlugin)
  1745. };
  1746. static const PluginDescriptor fxDistortionDesc = {
  1747. /* category */ PLUGIN_CATEGORY_MODULATOR,
  1748. /* hints */ static_cast<PluginHints>(PLUGIN_USES_PANNING|PLUGIN_NEEDS_FIXED_BUFFERS),
  1749. /* supports */ static_cast<PluginSupports>(0x0),
  1750. /* audioIns */ 2,
  1751. /* audioOuts */ 2,
  1752. /* midiIns */ 0,
  1753. /* midiOuts */ 0,
  1754. /* paramIns */ 11-2,
  1755. /* paramOuts */ 0,
  1756. /* name */ "ZynDistortion",
  1757. /* label */ "zynDistortion",
  1758. /* maker */ "falkTX",
  1759. /* copyright */ "GNU GPL v2+",
  1760. PluginDescriptorFILL(FxDistortionPlugin)
  1761. };
  1762. static const PluginDescriptor fxDynamicFilterDesc = {
  1763. /* category */ PLUGIN_CATEGORY_FILTER,
  1764. /* hints */ static_cast<PluginHints>(PLUGIN_USES_PANNING|PLUGIN_NEEDS_FIXED_BUFFERS),
  1765. /* supports */ static_cast<PluginSupports>(0x0),
  1766. /* audioIns */ 2,
  1767. /* audioOuts */ 2,
  1768. /* midiIns */ 0,
  1769. /* midiOuts */ 0,
  1770. /* paramIns */ 10-2,
  1771. /* paramOuts */ 0,
  1772. /* name */ "ZynDynamicFilter",
  1773. /* label */ "zynDynamicFilter",
  1774. /* maker */ "falkTX",
  1775. /* copyright */ "GNU GPL v2+",
  1776. PluginDescriptorFILL(FxDynamicFilterPlugin)
  1777. };
  1778. static const PluginDescriptor fxEchoDesc = {
  1779. /* category */ PLUGIN_CATEGORY_DELAY,
  1780. /* hints */ static_cast<PluginHints>(PLUGIN_IS_RTSAFE|PLUGIN_USES_PANNING|PLUGIN_NEEDS_FIXED_BUFFERS),
  1781. /* supports */ static_cast<PluginSupports>(0x0),
  1782. /* audioIns */ 2,
  1783. /* audioOuts */ 2,
  1784. /* midiIns */ 0,
  1785. /* midiOuts */ 0,
  1786. /* paramIns */ 7-2,
  1787. /* paramOuts */ 0,
  1788. /* name */ "ZynEcho",
  1789. /* label */ "zynEcho",
  1790. /* maker */ "falkTX",
  1791. /* copyright */ "GNU GPL v2+",
  1792. PluginDescriptorFILL(FxEchoPlugin)
  1793. };
  1794. static const PluginDescriptor fxPhaserDesc = {
  1795. /* category */ PLUGIN_CATEGORY_MODULATOR,
  1796. /* hints */ static_cast<PluginHints>(PLUGIN_USES_PANNING|PLUGIN_NEEDS_FIXED_BUFFERS),
  1797. /* supports */ static_cast<PluginSupports>(0x0),
  1798. /* audioIns */ 2,
  1799. /* audioOuts */ 2,
  1800. /* midiIns */ 0,
  1801. /* midiOuts */ 0,
  1802. /* paramIns */ 15-2,
  1803. /* paramOuts */ 0,
  1804. /* name */ "ZynPhaser",
  1805. /* label */ "zynPhaser",
  1806. /* maker */ "falkTX",
  1807. /* copyright */ "GNU GPL v2+",
  1808. PluginDescriptorFILL(FxPhaserPlugin)
  1809. };
  1810. static const PluginDescriptor fxReverbDesc = {
  1811. /* category */ PLUGIN_CATEGORY_DELAY,
  1812. /* hints */ static_cast<PluginHints>(PLUGIN_USES_PANNING|PLUGIN_NEEDS_FIXED_BUFFERS),
  1813. /* supports */ static_cast<PluginSupports>(0x0),
  1814. /* audioIns */ 2,
  1815. /* audioOuts */ 2,
  1816. /* midiIns */ 0,
  1817. /* midiOuts */ 0,
  1818. /* paramIns */ 13-2,
  1819. /* paramOuts */ 0,
  1820. /* name */ "ZynReverb",
  1821. /* label */ "zynReverb",
  1822. /* maker */ "falkTX",
  1823. /* copyright */ "GNU GPL v2+",
  1824. PluginDescriptorFILL(FxReverbPlugin)
  1825. };
  1826. static const PluginDescriptor zynaddsubfxDesc = {
  1827. /* category */ PLUGIN_CATEGORY_SYNTH,
  1828. #ifdef WANT_ZYNADDSUBFX_UI
  1829. /* hints */ static_cast<PluginHints>(PLUGIN_HAS_GUI|PLUGIN_USES_STATE),
  1830. #else
  1831. /* hints */ static_cast<PluginHints>(PLUGIN_USES_STATE),
  1832. #endif
  1833. /* supports */ static_cast<PluginSupports>(PLUGIN_SUPPORTS_CONTROL_CHANGES|PLUGIN_SUPPORTS_NOTE_AFTERTOUCH|PLUGIN_SUPPORTS_PITCHBEND|PLUGIN_SUPPORTS_ALL_SOUND_OFF),
  1834. /* audioIns */ 0,
  1835. /* audioOuts */ 2,
  1836. /* midiIns */ 1,
  1837. /* midiOuts */ 0,
  1838. /* paramIns */ 0,
  1839. /* paramOuts */ 0,
  1840. /* name */ "ZynAddSubFX",
  1841. /* label */ "zynaddsubfx",
  1842. /* maker */ "falkTX",
  1843. /* copyright */ "GNU GPL v2+",
  1844. PluginDescriptorFILL(ZynAddSubFxPlugin)
  1845. };
  1846. // -----------------------------------------------------------------------
  1847. CARLA_EXPORT
  1848. void carla_register_native_plugin_zynaddsubfx()
  1849. {
  1850. carla_register_native_plugin(&fxAlienWahDesc);
  1851. carla_register_native_plugin(&fxChorusDesc);
  1852. carla_register_native_plugin(&fxDistortionDesc);
  1853. carla_register_native_plugin(&fxDynamicFilterDesc);
  1854. carla_register_native_plugin(&fxEchoDesc);
  1855. carla_register_native_plugin(&fxPhaserDesc);
  1856. carla_register_native_plugin(&fxReverbDesc);
  1857. carla_register_native_plugin(&zynaddsubfxDesc);
  1858. }
  1859. // -----------------------------------------------------------------------