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.

1310 lines
44KB

  1. /*
  2. * Carla Native Plugins
  3. * Copyright (C) 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. #include "CarlaNative.hpp"
  18. #include "juce_gui_basics.h"
  19. using namespace juce;
  20. #include "vex/VexArp.h"
  21. #include "vex/VexChorus.h"
  22. #include "vex/VexDelay.h"
  23. #include "vex/VexReverb.h"
  24. #include "vex/VexSyntModule.h"
  25. #include "vex/PeggyViewComponent.h"
  26. #include "vex/gui/SnappingSlider.h"
  27. #include "vex/lookandfeel/MyLookAndFeel.h"
  28. #include "vex/resources/Resources.h"
  29. // -----------------------------------------------------------------------
  30. // Copied from juce_AudioProcessor.cpp
  31. // magic number to identify memory blocks that we've stored as XML
  32. const uint32 magicXmlNumber = 0x21324356;
  33. void copyXmlToBinary(const XmlElement& xml, juce::MemoryBlock& destData)
  34. {
  35. const String xmlString(xml.createDocument(String::empty, true, false));
  36. const size_t stringLength = xmlString.getNumBytesAsUTF8();
  37. destData.setSize(stringLength + 9);
  38. uint32* const d = static_cast<uint32*>(destData.getData());
  39. d[0] = ByteOrder::swapIfBigEndian((const uint32) magicXmlNumber);
  40. d[1] = ByteOrder::swapIfBigEndian((const uint32) stringLength);
  41. xmlString.copyToUTF8((CharPointer_UTF8::CharType*) (d + 2), stringLength + 1);
  42. }
  43. XmlElement* getXmlFromBinary(const void* data, const int sizeInBytes)
  44. {
  45. if (sizeInBytes > 8 && ByteOrder::littleEndianInt(data) == magicXmlNumber)
  46. {
  47. const int stringLength = (int) ByteOrder::littleEndianInt (addBytesToPointer (data, 4));
  48. if (stringLength > 0)
  49. return XmlDocument::parse (String::fromUTF8 (static_cast<const char*> (data) + 8, jmin ((sizeInBytes - 8), stringLength)));
  50. }
  51. return nullptr;
  52. }
  53. // -----------------------------------------------------------------------
  54. class HelperWindow2 : public DocumentWindow
  55. {
  56. public:
  57. HelperWindow2()
  58. : DocumentWindow("PlugWindow", Colour(50, 50, 200), DocumentWindow::closeButton, false),
  59. fClosed(false)
  60. {
  61. setVisible(false);
  62. //setAlwaysOnTop(true);
  63. setOpaque(true);
  64. setResizable(false, false);
  65. setUsingNativeTitleBar(true);
  66. }
  67. void show(Component* const comp)
  68. {
  69. fClosed = false;
  70. centreWithSize(comp->getWidth(), comp->getHeight());
  71. setContentNonOwned(comp, true);
  72. if (! isOnDesktop())
  73. addToDesktop();
  74. setVisible(true);
  75. }
  76. void hide()
  77. {
  78. setVisible(false);
  79. if (isOnDesktop())
  80. removeFromDesktop();
  81. clearContentComponent();
  82. }
  83. bool wasClosedByUser() const
  84. {
  85. return fClosed;
  86. }
  87. protected:
  88. void closeButtonPressed() override
  89. {
  90. fClosed = true;
  91. }
  92. private:
  93. volatile bool fClosed;
  94. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(HelperWindow2)
  95. };
  96. // -----------------------------------------------------------------------
  97. class VexEditorComponent : public Component,
  98. public Timer,
  99. public ComboBox::Listener,
  100. public Slider::Listener,
  101. public Button::Listener,
  102. public PeggyViewComponent::Callback // ignored
  103. {
  104. public:
  105. class Callback
  106. {
  107. public:
  108. virtual ~Callback() {}
  109. virtual void getChangedParameters(bool params[92]) = 0;
  110. virtual float getFilterParameterValue(const uint32_t index) const = 0;
  111. virtual String getFilterWaveName(const int part) const = 0;
  112. virtual void editorParameterChanged(const uint32_t index, const float value) = 0;
  113. virtual void editorWaveChanged(const int part, const String& wave) = 0;
  114. };
  115. VexEditorComponent(Callback* const callback, VexArpSettings& arpSet1, VexArpSettings& arpSet2, VexArpSettings& arpSet3)
  116. : fCallback(callback),
  117. fNeedsUpdate(false)
  118. {
  119. internalCachedImage1 = ImageCache::getFromMemory(Resources::vex3_png, Resources::vex3_pngSize);
  120. // Comboboxes, wave selection
  121. addAndMakeVisible(comboBox1 = new ComboBox (String::empty));
  122. comboBox1->setEditableText(false);
  123. comboBox1->setJustificationType(Justification::centredLeft);
  124. comboBox1->setTextWhenNothingSelected(String("silent"));
  125. comboBox1->setTextWhenNoChoicesAvailable(String("silent"));
  126. comboBox1->addListener(this);
  127. comboBox1->setColour(ComboBox::backgroundColourId, Colours::black);
  128. comboBox1->setColour(ComboBox::textColourId, Colours::lightgrey);
  129. comboBox1->setColour(ComboBox::outlineColourId, Colours::grey);
  130. comboBox1->setColour(ComboBox::buttonColourId, Colours::grey);
  131. comboBox1->setWantsKeyboardFocus(false);
  132. comboBox1->setLookAndFeel(&mlaf);
  133. addAndMakeVisible(comboBox2 = new ComboBox (String::empty));
  134. comboBox2->setEditableText(false);
  135. comboBox2->setJustificationType(Justification::centredLeft);
  136. comboBox2->setTextWhenNothingSelected(String("silent"));
  137. comboBox2->setTextWhenNoChoicesAvailable(String("silent"));
  138. comboBox2->addListener(this);
  139. comboBox2->setColour(ComboBox::backgroundColourId, Colours::black);
  140. comboBox2->setColour(ComboBox::textColourId, Colours::lightgrey);
  141. comboBox2->setColour(ComboBox::outlineColourId, Colours::grey);
  142. comboBox2->setColour(ComboBox::buttonColourId, Colours::grey);
  143. comboBox2->setWantsKeyboardFocus(false);
  144. comboBox2->setLookAndFeel(&mlaf);
  145. addAndMakeVisible(comboBox3 = new ComboBox(String::empty));
  146. comboBox3->setEditableText(false);
  147. comboBox3->setJustificationType(Justification::centredLeft);
  148. comboBox3->setTextWhenNothingSelected(String("silent"));
  149. comboBox3->setTextWhenNoChoicesAvailable(String("silent"));
  150. comboBox3->addListener(this);
  151. comboBox3->setColour(ComboBox::backgroundColourId, Colours::black);
  152. comboBox3->setColour(ComboBox::textColourId, Colours::lightgrey);
  153. comboBox3->setColour(ComboBox::outlineColourId, Colours::grey);
  154. comboBox3->setColour(ComboBox::buttonColourId, Colours::grey);
  155. comboBox3->setWantsKeyboardFocus(false);
  156. comboBox3->setLookAndFeel(&mlaf);
  157. for (int i = 0, tableSize = WaveRenderer::getWaveTableSize(); i < tableSize; ++i)
  158. {
  159. String tableName(WaveRenderer::getWaveTableName(i));
  160. comboBox1->addItem(tableName, i + 1);
  161. comboBox2->addItem(tableName, i + 1);
  162. comboBox3->addItem(tableName, i + 1);
  163. }
  164. //Make sliders
  165. for (int i = 0; i < kSliderCount; ++i)
  166. {
  167. addAndMakeVisible(sliders[i] = new SnappingSlider("s"));
  168. sliders[i]->setSliderStyle(Slider::RotaryVerticalDrag);
  169. sliders[i]->setRange(0, 1, 0);
  170. sliders[i]->setSnap(0.0f, 0.0f);
  171. sliders[i]->setLookAndFeel(&mlaf);
  172. sliders[i]->addListener(this);
  173. }
  174. //Adjust the center of some
  175. sliders[1]->setRange(0, 1, 0.25f);
  176. sliders[1]->setSnap(0.5f, 0.05f);
  177. sliders[2]->setSnap(0.5f, 0.05f);
  178. sliders[3]->setSnap(0.5f, 0.05f);
  179. sliders[4]->setSnap(0.5f, 0.05f);
  180. sliders[8]->setSnap(0.5f, 0.05f);
  181. sliders[13]->setSnap(0.5f, 0.05f);
  182. sliders[18]->setSnap(0.5f, 0.05f);
  183. int tmp = 24;
  184. sliders[1 + tmp]->setRange(0, 1, 0.25f);
  185. sliders[1 + tmp]->setSnap(0.5f, 0.05f);
  186. sliders[2 + tmp]->setSnap(0.5f, 0.05f);
  187. sliders[3 + tmp]->setSnap(0.5f, 0.05f);
  188. sliders[4 + tmp]->setSnap(0.5f, 0.05f);
  189. sliders[8 + tmp]->setSnap(0.5f, 0.05f);
  190. sliders[13 + tmp]->setSnap(0.5f, 0.05f);
  191. sliders[18 + tmp]->setSnap(0.5f, 0.05f);
  192. tmp = 48;
  193. sliders[1 + tmp]->setRange(0, 1, 0.25f);
  194. sliders[1 + tmp]->setSnap(0.5f, 0.05f);
  195. sliders[2 + tmp]->setSnap(0.5f, 0.05f);
  196. sliders[3 + tmp]->setSnap(0.5f, 0.05f);
  197. sliders[4 + tmp]->setSnap(0.5f, 0.05f);
  198. sliders[8 + tmp]->setSnap(0.5f, 0.05f);
  199. sliders[13 + tmp]->setSnap(0.5f, 0.05f);
  200. sliders[18 + tmp]->setSnap(0.5f, 0.05f);
  201. sliders[83]->setSnap(0.5f, 0.05f);
  202. sliders[84]->setSnap(0.5f, 0.05f);
  203. sliders[85]->setSnap(0.5f, 0.05f);
  204. sliders[75]->setSnap(0.0f, 0.05f);
  205. sliders[78]->setSnap(0.0f, 0.05f);
  206. sliders[82]->setSnap(0.0f, 0.05f);
  207. //PART ON/OFF
  208. addAndMakeVisible(TB1 = new TextButton ("new button"));
  209. TB1->setButtonText(String::empty);
  210. TB1->addListener(this);
  211. TB1->setColour(TextButton::buttonColourId, Colours::darkred.withAlpha(0.5f));
  212. TB1->setColour(TextButton::buttonOnColourId, Colours::red);
  213. TB1->setClickingTogglesState(true);
  214. TB1->setToggleState(false, dontSendNotification);
  215. addAndMakeVisible(TB2 = new TextButton ("new button"));
  216. TB2->setButtonText(String::empty);
  217. TB2->addListener(this);
  218. TB2->setColour(TextButton::buttonColourId, Colours::darkred.withAlpha(0.5f));
  219. TB2->setColour(TextButton::buttonOnColourId, Colours::red);
  220. TB2->setClickingTogglesState(true);
  221. TB2->setToggleState(false, dontSendNotification);
  222. addAndMakeVisible(TB3 = new TextButton ("new button"));
  223. TB3->setButtonText(String::empty);
  224. TB3->addListener(this);
  225. TB3->setColour(TextButton::buttonColourId, Colours::darkred.withAlpha(0.5f));
  226. TB3->setColour(TextButton::buttonOnColourId, Colours::red);
  227. TB3->setClickingTogglesState(true);
  228. TB3->setToggleState(false, dontSendNotification);
  229. //Peggy ON/OFF
  230. addAndMakeVisible(TB4 = new TextButton ("new button"));
  231. TB4->setButtonText(String::empty);
  232. TB4->addListener(this);
  233. TB4->setColour(TextButton::buttonColourId, Colours::darkblue.withAlpha(0.5f));
  234. TB4->setColour(TextButton::buttonOnColourId, Colours::blue);
  235. TB4->setClickingTogglesState(true);
  236. TB4->setToggleState(false, dontSendNotification);
  237. addAndMakeVisible(TB5 = new TextButton ("new button"));
  238. TB5->setButtonText(String::empty);
  239. TB5->addListener(this);
  240. TB5->setColour(TextButton::buttonColourId, Colours::darkblue.withAlpha(0.5f));
  241. TB5->setColour(TextButton::buttonOnColourId, Colours::blue);
  242. TB5->setClickingTogglesState(true);
  243. TB5->setToggleState(false, dontSendNotification);
  244. addAndMakeVisible(TB6 = new TextButton ("new button"));
  245. TB6->setButtonText(String::empty);
  246. TB6->addListener(this);
  247. TB6->setColour(TextButton::buttonColourId, Colours::darkblue.withAlpha(0.5f));
  248. TB6->setColour(TextButton::buttonOnColourId, Colours::blue);
  249. TB6->setClickingTogglesState(true);
  250. TB6->setToggleState(false, dontSendNotification);
  251. addChildComponent(p1 = new PeggyViewComponent(arpSet1, this));
  252. p1->setLookAndFeel(&mlaf);
  253. addChildComponent(p2 = new PeggyViewComponent(arpSet2, this));
  254. p2->setLookAndFeel(&mlaf);
  255. addChildComponent(p3 = new PeggyViewComponent(arpSet3, this));
  256. p3->setLookAndFeel(&mlaf);
  257. setSize(800,500);
  258. updateParametersFromFilter(true);
  259. startTimer(50);
  260. }
  261. ~VexEditorComponent()
  262. {
  263. stopTimer();
  264. removeAllChildren();
  265. }
  266. void setNeedsUpdate()
  267. {
  268. fNeedsUpdate = true;
  269. }
  270. protected:
  271. void paint(Graphics& g) override
  272. {
  273. g.drawImage(internalCachedImage1,
  274. 0, 0, 800, 500,
  275. 0, 0, internalCachedImage1.getWidth(), internalCachedImage1.getHeight());
  276. }
  277. void resized() override
  278. {
  279. comboBox1->setBounds(13, 38, 173, 23);
  280. comboBox2->setBounds(213, 38, 173, 23);
  281. comboBox3->setBounds(413, 38, 173, 23);
  282. // ...
  283. sliders[73]->setBounds(623, 23, 28, 28);
  284. sliders[74]->setBounds(686, 23, 28, 28);
  285. sliders[75]->setBounds(748, 23, 28, 28);
  286. sliders[76]->setBounds(623, 98, 28, 28);
  287. sliders[77]->setBounds(686, 98, 28, 28);
  288. sliders[78]->setBounds(748, 98, 28, 28);
  289. sliders[79]->setBounds(611, 173, 28, 28);
  290. sliders[80]->setBounds(661, 173, 28, 28);
  291. sliders[81]->setBounds(711, 173, 28, 28);
  292. sliders[82]->setBounds(761, 173, 28, 28);
  293. sliders[85]->setBounds(711, 373, 28, 28);
  294. sliders[84]->setBounds(661, 373, 28, 28);
  295. sliders[83]->setBounds(611, 373, 28, 28);
  296. sliders[86]->setBounds(611, 449, 28, 28);
  297. sliders[87]->setBounds(661, 449, 28, 28);
  298. sliders[88]->setBounds(711, 449, 28, 28);
  299. sliders[0]->setBounds(761, 449, 28, 28);
  300. // ...
  301. sliders[1]->setBounds(11, 73, 28, 28);
  302. sliders[2]->setBounds(61, 73, 28, 28);
  303. sliders[3]->setBounds(111, 73, 28, 28);
  304. sliders[4]->setBounds(161, 73, 28, 28);
  305. sliders[24 + 1]->setBounds(211, 73, 28, 28);
  306. sliders[24 + 2]->setBounds(261, 73, 28, 28);
  307. sliders[24 + 3]->setBounds(311, 73, 28, 28);
  308. sliders[24 + 4]->setBounds(361, 73, 28, 28);
  309. sliders[48 + 1]->setBounds(411, 73, 28, 28);
  310. sliders[48 + 2]->setBounds(461, 73, 28, 28);
  311. sliders[48 + 3]->setBounds(511, 73, 28, 28);
  312. sliders[48 + 4]->setBounds(561, 73, 28, 28);
  313. // ...
  314. sliders[5]->setBounds(11, 149, 28, 28);
  315. sliders[6]->setBounds(61, 149, 28, 28);
  316. sliders[7]->setBounds(111, 149, 28, 28);
  317. sliders[8]->setBounds(161, 149, 28, 28);
  318. sliders[24 + 5]->setBounds(211, 149, 28, 28);
  319. sliders[24 + 6]->setBounds(261, 149, 28, 28);
  320. sliders[24 + 7]->setBounds(311, 149, 28, 28);
  321. sliders[24 + 8]->setBounds(361, 149, 28, 28);
  322. sliders[48 + 5]->setBounds(411, 149, 28, 28);
  323. sliders[48 + 6]->setBounds(461, 149, 28, 28);
  324. sliders[48 + 7]->setBounds(511, 149, 28, 28);
  325. sliders[48 + 8]->setBounds(561, 149, 28, 28);
  326. // ...
  327. sliders[9]->setBounds(11, 223, 28, 28);
  328. sliders[10]->setBounds(48, 223, 28, 28);
  329. sliders[11]->setBounds(86, 223, 28, 28);
  330. sliders[12]->setBounds(123, 223, 28, 28);
  331. sliders[13]->setBounds(161, 223, 28, 28);
  332. sliders[24 + 9]->setBounds(211, 223, 28, 28);
  333. sliders[24 + 10]->setBounds(248, 223, 28, 28);
  334. sliders[24 + 11]->setBounds(286, 223, 28, 28);
  335. sliders[24 + 12]->setBounds(323, 223, 28, 28);
  336. sliders[24 + 13]->setBounds(361, 223, 28, 28);
  337. sliders[48 + 9]->setBounds(411, 223, 28, 28);
  338. sliders[48 + 10]->setBounds(448, 223, 28, 28);
  339. sliders[48 + 11]->setBounds(486, 223, 28, 28);
  340. sliders[48 + 12]->setBounds(523, 223, 28, 28);
  341. sliders[48 + 13]->setBounds(561, 223, 28, 28);
  342. // ...
  343. sliders[14]->setBounds(11, 298, 28, 28);
  344. sliders[15]->setBounds(48, 298, 28, 28);
  345. sliders[16]->setBounds(86, 298, 28, 28);
  346. sliders[17]->setBounds(123, 298, 28, 28);
  347. sliders[18]->setBounds(161, 298, 28, 28);
  348. sliders[24 + 14]->setBounds(211, 298, 28, 28);
  349. sliders[24 + 15]->setBounds(248, 298, 28, 28);
  350. sliders[24 + 16]->setBounds(286, 298, 28, 28);
  351. sliders[24 + 17]->setBounds(323, 298, 28, 28);
  352. sliders[24 + 18]->setBounds(361, 298, 28, 28);
  353. sliders[48 + 14]->setBounds(411, 298, 28, 28);
  354. sliders[48 + 15]->setBounds(448, 298, 28, 28);
  355. sliders[48 + 16]->setBounds(486, 298, 28, 28);
  356. sliders[48 + 17]->setBounds(523, 298, 28, 28);
  357. sliders[48 + 18]->setBounds(561, 298, 28, 28);
  358. // ...
  359. sliders[19]->setBounds(11, 374, 28, 28);
  360. sliders[20]->setBounds(86, 374, 28, 28);
  361. sliders[21]->setBounds(161, 374, 28, 28);
  362. sliders[24 + 19]->setBounds(211, 374, 28, 28);
  363. sliders[24 + 20]->setBounds(286, 374, 28, 28);
  364. sliders[24 + 21]->setBounds(361, 374, 28, 28);
  365. sliders[48 + 19]->setBounds(411, 374, 28, 28);
  366. sliders[48 + 20]->setBounds(486, 374, 28, 28);
  367. sliders[48 + 21]->setBounds(561, 374, 28, 28);
  368. // ...
  369. sliders[22]->setBounds(11, 448, 28, 28);
  370. sliders[23]->setBounds(86, 448, 28, 28);
  371. sliders[24]->setBounds(161, 448, 28, 28);
  372. sliders[24 + 22]->setBounds(211, 448, 28, 28);
  373. sliders[24 + 23]->setBounds(286, 448, 28, 28);
  374. sliders[48]->setBounds(361, 448, 28, 28);
  375. sliders[48 + 22]->setBounds(411, 448, 28, 28);
  376. sliders[48 + 23]->setBounds(486, 448, 28, 28);
  377. sliders[48 + 24]->setBounds(561, 448, 28, 28);
  378. TB1->setBounds(174, 4, 13, 13);
  379. TB2->setBounds(374, 4, 13, 13);
  380. TB3->setBounds(574, 4, 13, 13);
  381. TB4->setBounds(154, 4, 13, 13);
  382. TB5->setBounds(354, 4, 13, 13);
  383. TB6->setBounds(554, 4, 13, 13);
  384. p1->setBounds(10, 20, 207, 280);
  385. p2->setBounds(210, 20, 207, 280);
  386. p3->setBounds(410, 20, 207, 280);
  387. }
  388. void timerCallback() override
  389. {
  390. if (fNeedsUpdate)
  391. {
  392. updateParametersFromFilter(true);
  393. fNeedsUpdate = false;
  394. }
  395. else
  396. {
  397. updateParametersFromFilter(false);
  398. }
  399. }
  400. void comboBoxChanged(ComboBox* comboBoxThatHasChanged) override
  401. {
  402. if (comboBoxThatHasChanged == comboBox1)
  403. fCallback->editorWaveChanged(1, comboBox1->getText());
  404. else if (comboBoxThatHasChanged == comboBox2)
  405. fCallback->editorWaveChanged(2, comboBox2->getText());
  406. else if (comboBoxThatHasChanged == comboBox3)
  407. fCallback->editorWaveChanged(3, comboBox3->getText());
  408. }
  409. void sliderValueChanged(Slider* sliderThatWasMoved) override
  410. {
  411. for (int i = 0; i < kSliderCount; ++i)
  412. {
  413. if (sliders[i] == sliderThatWasMoved)
  414. {
  415. fCallback->editorParameterChanged(i, (float)sliderThatWasMoved->getValue());
  416. return;
  417. }
  418. }
  419. }
  420. void buttonClicked(Button* buttonThatWasClicked) override
  421. {
  422. if (buttonThatWasClicked == TB1)
  423. fCallback->editorParameterChanged(89, TB1->getToggleState() ? 1.0f : 0.0f);
  424. else if (buttonThatWasClicked == TB2)
  425. fCallback->editorParameterChanged(90, TB2->getToggleState() ? 1.0f : 0.0f);
  426. else if (buttonThatWasClicked == TB3)
  427. fCallback->editorParameterChanged(91, TB3->getToggleState() ? 1.0f : 0.0f);
  428. else if (buttonThatWasClicked == TB4)
  429. p1->setVisible(!p1->isVisible());
  430. else if (buttonThatWasClicked == TB5)
  431. p2->setVisible(!p2->isVisible());
  432. else if (buttonThatWasClicked == TB6)
  433. p3->setVisible(!p3->isVisible());
  434. }
  435. void arpParameterChanged(const uint32_t) override
  436. {
  437. // unused, we don't need to register arp settings changes in synth
  438. }
  439. void updateParametersFromFilter(const bool all)
  440. {
  441. if (all)
  442. {
  443. for (int i = 0; i < kSliderCount; ++i)
  444. sliders[i]->setValue(fCallback->getFilterParameterValue(i), dontSendNotification);
  445. TB1->setToggleState(fCallback->getFilterParameterValue(89) > 0.5f ? true : false, dontSendNotification);
  446. TB2->setToggleState(fCallback->getFilterParameterValue(90) > 0.5f ? true : false, dontSendNotification);
  447. TB3->setToggleState(fCallback->getFilterParameterValue(91) > 0.5f ? true : false, dontSendNotification);
  448. comboBox1->setText(fCallback->getFilterWaveName(1), dontSendNotification);
  449. comboBox2->setText(fCallback->getFilterWaveName(2), dontSendNotification);
  450. comboBox3->setText(fCallback->getFilterWaveName(3), dontSendNotification);
  451. p1->update();
  452. p2->update();
  453. p3->update();
  454. }
  455. else
  456. {
  457. bool params[92];
  458. fCallback->getChangedParameters(params);
  459. for (int i=0; i < 89; ++i)
  460. {
  461. if (params[i])
  462. sliders[i]->setValue(fCallback->getFilterParameterValue(i), dontSendNotification);
  463. }
  464. if (params[89]) TB1->setToggleState(fCallback->getFilterParameterValue(89) > 0.5f ? true : false, dontSendNotification);
  465. if (params[90]) TB2->setToggleState(fCallback->getFilterParameterValue(90) > 0.5f ? true : false, dontSendNotification);
  466. if (params[91]) TB3->setToggleState(fCallback->getFilterParameterValue(91) > 0.5f ? true : false, dontSendNotification);
  467. }
  468. }
  469. private:
  470. static const int kSliderCount = 89;
  471. Callback* const fCallback;
  472. volatile bool fNeedsUpdate;
  473. Image internalCachedImage1;
  474. MyLookAndFeel mlaf;
  475. ScopedPointer<ComboBox> comboBox1;
  476. ScopedPointer<ComboBox> comboBox2;
  477. ScopedPointer<ComboBox> comboBox3;
  478. ScopedPointer<SnappingSlider> sliders[kSliderCount];
  479. ScopedPointer<TextButton> TB1;
  480. ScopedPointer<TextButton> TB2;
  481. ScopedPointer<TextButton> TB3;
  482. ScopedPointer<TextButton> TB4;
  483. ScopedPointer<TextButton> TB5;
  484. ScopedPointer<TextButton> TB6;
  485. ScopedPointer<PeggyViewComponent> p1;
  486. ScopedPointer<PeggyViewComponent> p2;
  487. ScopedPointer<PeggyViewComponent> p3;
  488. VexArpSettings _d;
  489. };
  490. // -----------------------------------------------------------------------
  491. class VexSynthPlugin : public PluginClass,
  492. public VexEditorComponent::Callback
  493. {
  494. public:
  495. static const unsigned int kParamCount = 92;
  496. VexSynthPlugin(const HostDescriptor* const host)
  497. : PluginClass(host),
  498. obf(nullptr),
  499. abf(nullptr),
  500. dbf1(nullptr),
  501. dbf2(nullptr),
  502. dbf3(nullptr),
  503. fArp1(&fArpSet1),
  504. fArp2(&fArpSet2),
  505. fArp3(&fArpSet3),
  506. fChorus(fParameters),
  507. fDelay(fParameters),
  508. fReverb(fParameters),
  509. fSynth(fParameters)
  510. {
  511. std::memset(fParameters, 0, sizeof(float)*kParamCount);
  512. std::memset(fParamsChanged, 0, sizeof(bool)*92);
  513. fParameters[0] = 1.0f; // main volume
  514. for (int i = 0; i < 3; ++i)
  515. {
  516. const int offset = i * 24;
  517. fParameters[offset + 1] = 0.5f;
  518. fParameters[offset + 2] = 0.5f;
  519. fParameters[offset + 3] = 0.5f;
  520. fParameters[offset + 4] = 0.5f;
  521. fParameters[offset + 5] = 0.9f;
  522. fParameters[offset + 6] = 0.0f;
  523. fParameters[offset + 7] = 1.0f;
  524. fParameters[offset + 8] = 0.5f;
  525. fParameters[offset + 9] = 0.0f;
  526. fParameters[offset + 10] = 0.2f;
  527. fParameters[offset + 11] = 0.0f;
  528. fParameters[offset + 12] = 0.5f;
  529. fParameters[offset + 13] = 0.5f;
  530. fParameters[offset + 14] = 0.0f;
  531. fParameters[offset + 15] = 0.3f;
  532. fParameters[offset + 16] = 0.7f;
  533. fParameters[offset + 17] = 0.1f;
  534. fParameters[offset + 18] = 0.5f;
  535. fParameters[offset + 19] = 0.5f;
  536. fParameters[offset + 20] = 0.0f;
  537. fParameters[offset + 21] = 0.0f;
  538. fParameters[offset + 22] = 0.5f;
  539. fParameters[offset + 23] = 0.5f;
  540. fParameters[offset + 24] = 0.5f;
  541. }
  542. // ^1 - 72
  543. fParameters[73] = 0.5f; // Delay Time
  544. fParameters[74] = 0.4f; // Delay Feedback
  545. fParameters[75] = 0.0f; // Delay Volume
  546. fParameters[76] = 0.3f; // Chorus Rate
  547. fParameters[77] = 0.6f; // Chorus Depth
  548. fParameters[78] = 0.5f; // Chorus Volume
  549. fParameters[79] = 0.6f; // Reverb Size
  550. fParameters[80] = 0.7f; // Reverb Width
  551. fParameters[81] = 0.6f; // Reverb Damp
  552. fParameters[82] = 0.0f; // Reverb Volume
  553. fParameters[83] = 0.5f; // wave1 panning
  554. fParameters[84] = 0.5f; // wave2 panning
  555. fParameters[85] = 0.5f; // wave3 panning
  556. fParameters[86] = 0.5f; // wave1 volume
  557. fParameters[87] = 0.5f; // wave2 volume
  558. fParameters[88] = 0.5f; // wave3 volume
  559. fParameters[89] = 1.0f; // wave1 on/off
  560. fParameters[90] = 0.0f; // wave2 on/off
  561. fParameters[91] = 0.0f; // wave3 on/off
  562. bufferSizeChanged(getBufferSize());
  563. sampleRateChanged(getSampleRate());
  564. for (unsigned int i = 0; i < kParamCount; ++i)
  565. fSynth.update(i);
  566. fMidiInBuffer.ensureSize(512*4);
  567. }
  568. ~VexSynthPlugin() override
  569. {
  570. delete obf;
  571. delete abf;
  572. delete dbf1;
  573. delete dbf2;
  574. delete dbf3;
  575. }
  576. protected:
  577. // -------------------------------------------------------------------
  578. // Plugin parameter calls
  579. uint32_t getParameterCount() const override
  580. {
  581. return kParamCount;
  582. }
  583. const Parameter* getParameterInfo(const uint32_t index) const override
  584. {
  585. static Parameter paramInfo;
  586. int hints = PARAMETER_IS_ENABLED|PARAMETER_IS_AUTOMABLE;
  587. paramInfo.name = nullptr;
  588. paramInfo.unit = nullptr;
  589. paramInfo.ranges.def = 0.0f;
  590. paramInfo.ranges.min = 0.0f;
  591. paramInfo.ranges.max = 1.0f;
  592. paramInfo.ranges.step = PARAMETER_RANGES_DEFAULT_STEP;
  593. paramInfo.ranges.stepSmall = PARAMETER_RANGES_DEFAULT_STEP_SMALL;
  594. paramInfo.ranges.stepLarge = PARAMETER_RANGES_DEFAULT_STEP_LARGE;
  595. paramInfo.scalePointCount = 0;
  596. paramInfo.scalePoints = nullptr;
  597. if (index >= 1 && index <= 72)
  598. {
  599. uint32_t ri = index % 24;
  600. switch (ri)
  601. {
  602. case 1:
  603. paramInfo.name = "oct";
  604. paramInfo.ranges.def = 0.5f;
  605. break;
  606. case 2:
  607. paramInfo.name = "cent";
  608. paramInfo.ranges.def = 0.5f;
  609. break;
  610. case 3:
  611. paramInfo.name = "phaseOffset";
  612. paramInfo.ranges.def = 0.5f;
  613. break;
  614. case 4:
  615. paramInfo.name = "phaseIncOffset";
  616. paramInfo.ranges.def = 0.5f;
  617. break;
  618. case 5:
  619. paramInfo.name = "filter";
  620. paramInfo.ranges.def = 0.9f;
  621. break;
  622. case 6:
  623. paramInfo.name = "filter";
  624. paramInfo.ranges.def = 0.0f;
  625. break;
  626. case 7:
  627. paramInfo.name = "filter";
  628. paramInfo.ranges.def = 1.0f;
  629. break;
  630. case 8:
  631. paramInfo.name = "filter";
  632. paramInfo.ranges.def = 0.5f;
  633. break;
  634. case 9:
  635. paramInfo.name = "F ADSR";
  636. paramInfo.ranges.def = 0.0f;
  637. break;
  638. case 10:
  639. paramInfo.name = "F ADSR";
  640. paramInfo.ranges.def = 0.2f;
  641. break;
  642. case 11:
  643. paramInfo.name = "F ADSR";
  644. paramInfo.ranges.def = 0.0f;
  645. break;
  646. case 12:
  647. paramInfo.name = "F ADSR";
  648. paramInfo.ranges.def = 0.5f;
  649. break;
  650. case 13:
  651. paramInfo.name = "F velocity";
  652. paramInfo.ranges.def = 0.5f;
  653. break;
  654. case 14:
  655. paramInfo.name = "A ADSR";
  656. paramInfo.ranges.def = 0.0f;
  657. break;
  658. case 15:
  659. paramInfo.name = "A ADSR";
  660. paramInfo.ranges.def = 0.3f;
  661. break;
  662. case 16:
  663. paramInfo.name = "A ADSR";
  664. paramInfo.ranges.def = 0.7f;
  665. break;
  666. case 17:
  667. paramInfo.name = "A ADSR";
  668. paramInfo.ranges.def = 0.1f;
  669. break;
  670. case 18:
  671. paramInfo.name = "A velocity";
  672. paramInfo.ranges.def = 0.5f;
  673. break;
  674. case 19:
  675. paramInfo.name = "lfoC";
  676. paramInfo.ranges.def = 0.5f;
  677. break;
  678. case 20:
  679. paramInfo.name = "lfoA";
  680. paramInfo.ranges.def = 0.0f;
  681. break;
  682. case 21:
  683. paramInfo.name = "lfoF";
  684. paramInfo.ranges.def = 0.0f;
  685. break;
  686. case 22:
  687. paramInfo.name = "fx vol D";
  688. paramInfo.ranges.def = 0.5f;
  689. break;
  690. case 23:
  691. paramInfo.name = "fx vol C";
  692. paramInfo.ranges.def = 0.5f;
  693. break;
  694. case 24:
  695. case 0:
  696. paramInfo.name = "fx vol R";
  697. paramInfo.ranges.def = 0.5f;
  698. break;
  699. default:
  700. paramInfo.name = "unknown2";
  701. break;
  702. }
  703. paramInfo.hints = static_cast<ParameterHints>(hints);
  704. return &paramInfo;
  705. }
  706. switch (index)
  707. {
  708. case 0:
  709. paramInfo.name = "Main volume";
  710. paramInfo.ranges.def = 1.0f;
  711. break;
  712. case 73:
  713. hints |= PARAMETER_IS_INTEGER;
  714. paramInfo.name = "Delay Time";
  715. paramInfo.unit = "steps";
  716. paramInfo.ranges.def = 4.0f;
  717. paramInfo.ranges.min = 0.0f;
  718. paramInfo.ranges.max = 8.0f;
  719. break;
  720. case 74:
  721. paramInfo.name = "Delay Feedback";
  722. paramInfo.unit = "%";
  723. paramInfo.ranges.def = 40.0f;
  724. paramInfo.ranges.min = 0.0f;
  725. paramInfo.ranges.max = 100.0f;
  726. break;
  727. case 75:
  728. paramInfo.name = "Delay Volume";
  729. paramInfo.ranges.def = 0.0f;
  730. break;
  731. case 76:
  732. paramInfo.name = "Chorus Rate";
  733. paramInfo.ranges.def = 0.3f;
  734. break;
  735. case 77:
  736. paramInfo.name = "Chorus Depth";
  737. paramInfo.ranges.def = 0.6f;
  738. break;
  739. case 78:
  740. paramInfo.name = "Chorus Volume";
  741. paramInfo.ranges.def = 0.5f;
  742. break;
  743. case 79:
  744. paramInfo.name = "Reverb Size";
  745. paramInfo.ranges.def = 0.6f;
  746. break;
  747. case 80:
  748. paramInfo.name = "Reverb Width";
  749. paramInfo.ranges.def = 0.7f;
  750. break;
  751. case 81:
  752. paramInfo.name = "Reverb Damp";
  753. paramInfo.ranges.def = 0.6f;
  754. break;
  755. case 82:
  756. paramInfo.name = "Reverb Volume";
  757. paramInfo.ranges.def = 0.0f;
  758. break;
  759. case 83:
  760. paramInfo.name = "Wave1 Panning";
  761. paramInfo.ranges.def = 0.5f;
  762. break;
  763. case 84:
  764. paramInfo.name = "Wave2 Panning";
  765. paramInfo.ranges.def = 0.5f;
  766. break;
  767. case 85:
  768. paramInfo.name = "Wave3 Panning";
  769. paramInfo.ranges.def = 0.5f;
  770. break;
  771. case 86:
  772. paramInfo.name = "Wave1 Volume";
  773. paramInfo.ranges.def = 0.5f;
  774. break;
  775. case 87:
  776. paramInfo.name = "Wave2 Volume";
  777. paramInfo.ranges.def = 0.5f;
  778. break;
  779. case 88:
  780. paramInfo.name = "Wave3 Volume";
  781. paramInfo.ranges.def = 0.5f;
  782. break;
  783. case 89:
  784. hints |= PARAMETER_IS_BOOLEAN;
  785. paramInfo.name = "Wave1 on/off";
  786. paramInfo.ranges.def = 1.0f;
  787. break;
  788. case 90:
  789. hints |= PARAMETER_IS_BOOLEAN;
  790. paramInfo.name = "Wave2 on/off";
  791. paramInfo.ranges.def = 0.0f;
  792. break;
  793. case 91:
  794. hints |= PARAMETER_IS_BOOLEAN;
  795. paramInfo.name = "Wave3 on/off";
  796. paramInfo.ranges.def = 0.0f;
  797. break;
  798. default:
  799. paramInfo.name = "unknown";
  800. break;
  801. }
  802. paramInfo.hints = static_cast<ParameterHints>(hints);
  803. return &paramInfo;
  804. }
  805. float getParameterValue(const uint32_t index) const override
  806. {
  807. if (index >= kParamCount)
  808. return 0.0f;
  809. switch (index)
  810. {
  811. case 73:
  812. return fParameters[index] * 8.0f;
  813. case 74:
  814. return fParameters[index] * 100.0f;
  815. default:
  816. return fParameters[index];
  817. }
  818. }
  819. // -------------------------------------------------------------------
  820. // Plugin state calls
  821. void setParameterValue(const uint32_t index, const float value) override
  822. {
  823. if (index >= kParamCount)
  824. return;
  825. float realValue;
  826. switch (index)
  827. {
  828. case 73:
  829. realValue = value/8.0f;
  830. break;
  831. case 74:
  832. realValue = value/100.0f;
  833. break;
  834. default:
  835. realValue = value;
  836. break;
  837. }
  838. fParameters[index] = realValue;
  839. fParamsChanged[index] = true;
  840. fSynth.update(index);
  841. }
  842. // -------------------------------------------------------------------
  843. // Plugin process calls
  844. void process(float**, float** outBuffer, const uint32_t frames, const MidiEvent* const midiEvents, const uint32_t midiEventCount) override
  845. {
  846. // Get time info
  847. const TimeInfo* const timeInfo(getTimeInfo());
  848. bool timePlaying = false;
  849. double ppqPos = 0.0;
  850. double barStartPos = 0.0;
  851. double bpm = 120.0;
  852. if (timeInfo != nullptr)
  853. {
  854. timePlaying = timeInfo->playing;
  855. if (timeInfo->bbt.valid)
  856. {
  857. double ppqBar = double(timeInfo->bbt.bar - 1) * timeInfo->bbt.beatsPerBar;
  858. double ppqBeat = double(timeInfo->bbt.beat - 1);
  859. double ppqTick = double(timeInfo->bbt.tick) / timeInfo->bbt.ticksPerBeat;
  860. ppqPos = ppqBar + ppqBeat + ppqTick;
  861. barStartPos = ppqBar;
  862. bpm = timeInfo->bbt.beatsPerMinute;
  863. }
  864. }
  865. // put carla events in juce midi buffer
  866. fMidiInBuffer.clear();
  867. for (uint32_t i=0; i < midiEventCount; ++i)
  868. {
  869. const MidiEvent* const midiEvent(&midiEvents[i]);
  870. fMidiInBuffer.addEvent(MidiMessage(midiEvent->data, midiEvent->size), midiEvent->time);
  871. }
  872. // process MIDI (arppeggiator)
  873. const MidiBuffer& part1Midi(fArpSet1.on ? fArp1.processMidi(fMidiInBuffer, timePlaying, ppqPos, barStartPos, bpm, frames) : fMidiInBuffer);
  874. const MidiBuffer& part2Midi(fArpSet2.on ? fArp2.processMidi(fMidiInBuffer, timePlaying, ppqPos, barStartPos, bpm, frames) : fMidiInBuffer);
  875. const MidiBuffer& part3Midi(fArpSet3.on ? fArp3.processMidi(fMidiInBuffer, timePlaying, ppqPos, barStartPos, bpm, frames) : fMidiInBuffer);
  876. int snum;
  877. MidiMessage midiMessage(0xf4);
  878. MidiBuffer::Iterator Iterator1(part1Midi);
  879. while (Iterator1.getNextEvent(midiMessage, snum))
  880. {
  881. if (midiMessage.isNoteOn())
  882. fSynth.playNote(midiMessage.getNoteNumber(), midiMessage.getVelocity(), snum, 1);
  883. else if (midiMessage.isNoteOff())
  884. fSynth.releaseNote(midiMessage.getNoteNumber(), snum, 1 );
  885. else if (midiMessage.isAllSoundOff())
  886. fSynth.kill();
  887. else if (midiMessage.isAllNotesOff())
  888. fSynth.releaseAll(snum);
  889. }
  890. MidiBuffer::Iterator Iterator2(part2Midi);
  891. while (Iterator2.getNextEvent(midiMessage, snum))
  892. {
  893. if (midiMessage.isNoteOn())
  894. fSynth.playNote(midiMessage.getNoteNumber(), midiMessage.getVelocity(), snum, 2);
  895. else if (midiMessage.isNoteOff())
  896. fSynth.releaseNote(midiMessage.getNoteNumber(), snum, 2 );
  897. }
  898. MidiBuffer::Iterator Iterator3(part3Midi);
  899. while (Iterator3.getNextEvent(midiMessage, snum))
  900. {
  901. if (midiMessage.isNoteOn())
  902. fSynth.playNote(midiMessage.getNoteNumber(), midiMessage.getVelocity(), snum, 3);
  903. else if (midiMessage.isNoteOff())
  904. fSynth.releaseNote(midiMessage.getNoteNumber(), snum, 3 );
  905. }
  906. fMidiInBuffer.clear();
  907. if (obf->getNumSamples() < (int)frames)
  908. {
  909. obf->setSize(2, frames, 0, 0, 1);
  910. abf->setSize(2, frames, 0, 0, 1);
  911. dbf1->setSize(2, frames, 0, 0, 1);
  912. dbf2->setSize(2, frames, 0, 0, 1);
  913. dbf3->setSize(2, frames, 0, 0, 1);
  914. }
  915. obf ->clear();
  916. dbf1->clear();
  917. dbf2->clear();
  918. dbf3->clear();
  919. fSynth.doProcess(*obf, *abf, *dbf1, *dbf2, *dbf3);
  920. if (fParameters[75] > 0.001f) fDelay.processBlock(dbf1, bpm);
  921. if (fParameters[78] > 0.001f) fChorus.processBlock(dbf2);
  922. if (fParameters[82] > 0.001f) fReverb.processBlock(dbf3);
  923. AudioSampleBuffer output(outBuffer, 2, 0, frames);
  924. output.clear();
  925. obf->addFrom(0, 0, *dbf1, 0, 0, frames, fParameters[75]);
  926. obf->addFrom(1, 0, *dbf1, 1, 0, frames, fParameters[75]);
  927. obf->addFrom(0, 0, *dbf2, 0, 0, frames, fParameters[78]);
  928. obf->addFrom(1, 0, *dbf2, 1, 0, frames, fParameters[78]);
  929. obf->addFrom(0, 0, *dbf3, 0, 0, frames, fParameters[82]);
  930. obf->addFrom(1, 0, *dbf3, 1, 0, frames, fParameters[82]);
  931. output.addFrom(0, 0, *obf, 0, 0, frames, fParameters[0]);
  932. output.addFrom(1, 0, *obf, 1, 0, frames, fParameters[0]);
  933. }
  934. // -------------------------------------------------------------------
  935. // Plugin UI calls
  936. void uiShow(const bool show) override
  937. {
  938. MessageManagerLock mmLock;
  939. if (show)
  940. {
  941. if (fWindow == nullptr)
  942. {
  943. fWindow = new HelperWindow2();
  944. fWindow->setName(getUiName());
  945. }
  946. if (fView == nullptr)
  947. fView = new VexEditorComponent(this, fArpSet1, fArpSet2, fArpSet3);
  948. fWindow->show(fView);
  949. }
  950. else if (fWindow != nullptr)
  951. {
  952. fWindow->hide();
  953. fView = nullptr;
  954. fWindow = nullptr;
  955. }
  956. }
  957. void uiIdle() override
  958. {
  959. if (fWindow == nullptr)
  960. return;
  961. if (fWindow->wasClosedByUser())
  962. {
  963. uiShow(false);
  964. uiClosed();
  965. }
  966. }
  967. // -------------------------------------------------------------------
  968. // Plugin state calls
  969. char* getState() const override
  970. {
  971. MemoryBlock destData;
  972. //destData.append(fParameters, sizeof(float) * kParamCount);
  973. destData.append(&fArpSet1, sizeof(VexArpSettings));
  974. destData.append(&fArpSet2, sizeof(VexArpSettings));
  975. destData.append(&fArpSet3, sizeof(VexArpSettings));
  976. XmlElement xmlState("VEX");
  977. xmlState.setAttribute("Wave1", fSynth.getWaveName(1));
  978. xmlState.setAttribute("Wave2", fSynth.getWaveName(2));
  979. xmlState.setAttribute("Wave3", fSynth.getWaveName(3));
  980. MemoryBlock tmp;
  981. copyXmlToBinary(xmlState, tmp);
  982. destData.append(tmp.getData(), tmp.getSize());
  983. return strdup(destData.toBase64Encoding().toRawUTF8());
  984. }
  985. void setState(const char* const data64) override
  986. {
  987. static const int kParamDataSize = 0; //sizeof(float)*kParamCount
  988. static const int xmlOffset = kParamDataSize + sizeof(VexArpSettings) * 3;
  989. MemoryBlock destData;
  990. destData.fromBase64Encoding(data64);
  991. const char* const data(&destData[0]);
  992. const size_t dataSize(destData.getSize());
  993. if (XmlElement* const xmlState = getXmlFromBinary(data + xmlOffset, dataSize - xmlOffset))
  994. {
  995. if (xmlState->hasTagName("VEX"))
  996. {
  997. fSynth.setWaveLater(1, xmlState->getStringAttribute("Wave1"));
  998. fSynth.setWaveLater(2, xmlState->getStringAttribute("Wave2"));
  999. fSynth.setWaveLater(3, xmlState->getStringAttribute("Wave3"));
  1000. //std::memcpy(fParameters, data, sizeof(float) * kParamCount);
  1001. std::memcpy(&fArpSet1, data + (kParamDataSize + sizeof(VexArpSettings)*0), sizeof(VexArpSettings));
  1002. std::memcpy(&fArpSet2, data + (kParamDataSize + sizeof(VexArpSettings)*1), sizeof(VexArpSettings));
  1003. std::memcpy(&fArpSet3, data + (kParamDataSize + sizeof(VexArpSettings)*2), sizeof(VexArpSettings));
  1004. //for (unsigned int i = 0; i < kParamCount; ++i)
  1005. // fSynth.update(i);
  1006. if (fView != nullptr)
  1007. fView->setNeedsUpdate();
  1008. }
  1009. delete xmlState;
  1010. }
  1011. }
  1012. // -------------------------------------------------------------------
  1013. // Plugin dispatcher calls
  1014. void bufferSizeChanged(const uint32_t bufferSize) override
  1015. {
  1016. delete obf;
  1017. delete abf;
  1018. delete dbf1;
  1019. delete dbf2;
  1020. delete dbf3;
  1021. obf = new AudioSampleBuffer(2, bufferSize);
  1022. abf = new AudioSampleBuffer(2, bufferSize);
  1023. dbf1 = new AudioSampleBuffer(2, bufferSize);
  1024. dbf2 = new AudioSampleBuffer(2, bufferSize);
  1025. dbf3 = new AudioSampleBuffer(2, bufferSize);
  1026. }
  1027. void sampleRateChanged(const double sampleRate) override
  1028. {
  1029. fArp1.setSampleRate(sampleRate);
  1030. fArp2.setSampleRate(sampleRate);
  1031. fArp3.setSampleRate(sampleRate);
  1032. fChorus.setSampleRate(sampleRate);
  1033. fDelay.setSampleRate(sampleRate);
  1034. fSynth.setSampleRate(sampleRate);
  1035. }
  1036. void uiNameChanged(const char* const uiName) override
  1037. {
  1038. if (fWindow == nullptr)
  1039. return;
  1040. MessageManagerLock mmLock;
  1041. fWindow->setName(uiName);
  1042. }
  1043. // -------------------------------------------------------------------
  1044. // Vex editor calls
  1045. void getChangedParameters(bool params[92]) override
  1046. {
  1047. std::memcpy(params, fParamsChanged, sizeof(bool)*92);
  1048. std::memset(fParamsChanged, 0, sizeof(bool)*92);
  1049. }
  1050. float getFilterParameterValue(const uint32_t index) const override
  1051. {
  1052. CARLA_SAFE_ASSERT_RETURN(index < kParamCount, 0.0f)
  1053. return fParameters[index];
  1054. }
  1055. String getFilterWaveName(const int part) const override
  1056. {
  1057. CARLA_SAFE_ASSERT_RETURN(part >= 1 && part <= 3, "")
  1058. return fSynth.getWaveName(part);
  1059. }
  1060. void editorParameterChanged(const uint32_t index, const float value) override
  1061. {
  1062. CARLA_SAFE_ASSERT_RETURN(index < kParamCount,)
  1063. if (fParameters[index] == value)
  1064. return;
  1065. fParameters[index] = value;
  1066. fSynth.update(index);
  1067. uiParameterChanged(index, getParameterValue(index)); // some params have specific bounds
  1068. }
  1069. void editorWaveChanged(const int part, const String& wave) override
  1070. {
  1071. CARLA_SAFE_ASSERT_RETURN(part >= 1 && part <= 3,)
  1072. fSynth.setWaveLater(part, wave);
  1073. }
  1074. private:
  1075. float fParameters[kParamCount];
  1076. bool fParamsChanged[92];
  1077. AudioSampleBuffer* obf;
  1078. AudioSampleBuffer* abf;
  1079. AudioSampleBuffer* dbf1; // delay
  1080. AudioSampleBuffer* dbf2; // chorus
  1081. AudioSampleBuffer* dbf3; // reverb
  1082. VexArpSettings fArpSet1, fArpSet2, fArpSet3;
  1083. VexArp fArp1, fArp2, fArp3;
  1084. VexChorus fChorus;
  1085. VexDelay fDelay;
  1086. VexReverb fReverb;
  1087. VexSyntModule fSynth;
  1088. ScopedPointer<VexEditorComponent> fView;
  1089. ScopedPointer<HelperWindow2> fWindow;
  1090. MidiBuffer fMidiInBuffer;
  1091. PluginClassEND(VexSynthPlugin)
  1092. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VexSynthPlugin)
  1093. };
  1094. // -----------------------------------------------------------------------
  1095. static const PluginDescriptor vexSynthDesc = {
  1096. /* category */ PLUGIN_CATEGORY_SYNTH,
  1097. /* hints */ static_cast<PluginHints>(PLUGIN_HAS_GUI|PLUGIN_NEEDS_UI_JUCE|PLUGIN_USES_STATE|PLUGIN_USES_TIME),
  1098. /* supports */ static_cast<PluginSupports>(0x0),
  1099. /* audioIns */ 0,
  1100. /* audioOuts */ 2,
  1101. /* midiIns */ 1,
  1102. /* midiOuts */ 0,
  1103. /* paramIns */ VexSynthPlugin::kParamCount,
  1104. /* paramOuts */ 0,
  1105. /* name */ "VexSynth",
  1106. /* label */ "vexSynth",
  1107. /* maker */ "falkTX",
  1108. /* copyright */ "GNU GPL v2+",
  1109. PluginDescriptorFILL(VexSynthPlugin)
  1110. };
  1111. // -----------------------------------------------------------------------
  1112. CARLA_EXPORT
  1113. void carla_register_native_plugin_vex_synth()
  1114. {
  1115. carla_register_native_plugin(&vexSynthDesc);
  1116. }
  1117. // -----------------------------------------------------------------------