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.

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