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.

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