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.

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