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.

1241 lines
43KB

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