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.

425 lines
12KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCETICE project - Copyright 2008 by Lucio Asnaghi.
  4. JUCETICE is based around the JUCE library - "Jules' Utility Class Extensions"
  5. Copyright 2008 by Julian Storer.
  6. ------------------------------------------------------------------------------
  7. JUCE and JUCETICE can be redistributed and/or modified under the terms of
  8. the GNU Lesser General Public License, as published by the Free Software
  9. Foundation; either version 2 of the License, or (at your option) any later
  10. version.
  11. JUCE and JUCETICE are distributed in the hope that they will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License for more details.
  15. You should have received a copy of the GNU Lesser General Public License
  16. along with JUCE and JUCETICE; if not, visit www.gnu.org/licenses or write to
  17. Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  18. Boston, MA 02111-1307 USA
  19. ==============================================================================
  20. @author rockhardbuns
  21. @tweaker Lucio Asnaghi
  22. @tweaker falkTX
  23. ==============================================================================
  24. */
  25. #ifndef DISTRHO_VEX_SYNTH_MODULE_HEADER_INCLUDED
  26. #define DISTRHO_VEX_SYNTH_MODULE_HEADER_INCLUDED
  27. #ifndef CARLA_EXPORT
  28. #define CARLA_EXPORT
  29. #endif
  30. #ifdef CARLA_EXPORT
  31. #include "juce_audio_basics.h"
  32. #else
  33. #include "../StandardHeader.h"
  34. #endif
  35. #include "VexVoice.h"
  36. class VexSyntModule
  37. {
  38. public:
  39. VexSyntModule(const float* const p)
  40. : parameters(p),
  41. sampleRate(44100),
  42. benchwarmer(0),
  43. playCount(1),
  44. part1(false),
  45. part2(false),
  46. part3(false)
  47. {
  48. for (int i = 0; i < kNumVoices; ++i)
  49. {
  50. vo1[i] = new VexVoice(p, 0, wr1);
  51. vo2[i] = new VexVoice(p, 24, wr2);
  52. vo3[i] = new VexVoice(p, 48, wr3);
  53. }
  54. }
  55. ~VexSyntModule()
  56. {
  57. for (int i = 0; i < kNumVoices; ++i)
  58. {
  59. delete vo1[i];
  60. delete vo2[i];
  61. delete vo3[i];
  62. }
  63. }
  64. void doProcess(AudioSampleBuffer& obf, AudioSampleBuffer& ebf1, AudioSampleBuffer& ebf2, AudioSampleBuffer& ebf3)
  65. {
  66. const int numSamples = obf.getNumSamples();
  67. tmpBuf.clear();
  68. float* const outPtrL = tmpBuf.getWritePointer(0);
  69. float* const outPtrR = tmpBuf.getWritePointer(1);
  70. if (part1)
  71. {
  72. float right = parameters[86] * parameters[83];
  73. float left = parameters[86] * (1.0f - parameters[83]);
  74. for (int i = 0; i < kNumVoices; ++i)
  75. {
  76. if (vo1[i]->getIsOn())
  77. {
  78. vo1[i]->doProcess(outPtrL, outPtrR, numSamples);
  79. obf.addFrom(0, 0, tmpBuf, 0, 0, numSamples, left);
  80. obf.addFrom(1, 0, tmpBuf, 1, 0, numSamples, right);
  81. ebf1.addFrom(0, 0, tmpBuf, 0, 0, numSamples, parameters[22] * left);
  82. ebf1.addFrom(1, 0, tmpBuf, 1, 0, numSamples, parameters[22] * right);
  83. ebf2.addFrom(0, 0, tmpBuf, 0, 0, numSamples, parameters[23] * left);
  84. ebf2.addFrom(1, 0, tmpBuf, 1, 0, numSamples, parameters[23] * right);
  85. ebf3.addFrom(0, 0, tmpBuf, 0, 0, numSamples, parameters[24] * left);
  86. ebf3.addFrom(1, 0, tmpBuf, 1, 0, numSamples, parameters[24] * right);
  87. }
  88. }
  89. }
  90. if (part2)
  91. {
  92. float right = parameters[87] * parameters[84];
  93. float left = parameters[87] * (1.0f - parameters[84]);
  94. for (int i = 0; i < kNumVoices; ++i)
  95. {
  96. if (vo2[i]->getIsOn())
  97. {
  98. vo2[i]->doProcess(outPtrL, outPtrR, numSamples);
  99. obf.addFrom(0, 0, tmpBuf, 0, 0, numSamples, left);
  100. obf.addFrom(1, 0, tmpBuf, 1, 0, numSamples, right);
  101. ebf1.addFrom(0, 0, tmpBuf, 0, 0, numSamples, parameters[22 + 24] * left);
  102. ebf1.addFrom(1, 0, tmpBuf, 1, 0, numSamples, parameters[22 + 24] * right);
  103. ebf2.addFrom(0, 0, tmpBuf, 0, 0, numSamples, parameters[23 + 24] * left);
  104. ebf2.addFrom(1, 0, tmpBuf, 1, 0, numSamples, parameters[23 + 24] * right);
  105. ebf3.addFrom(0, 0, tmpBuf, 0, 0, numSamples, parameters[24 + 24] * left);
  106. ebf3.addFrom(1, 0, tmpBuf, 1, 0, numSamples, parameters[24 + 24] * right);
  107. }
  108. }
  109. }
  110. if (part3)
  111. {
  112. float right = parameters[88] * parameters[85];
  113. float left = parameters[88] * (1.0f - parameters[85]);
  114. for (int i = 0; i < kNumVoices; ++i)
  115. {
  116. if (vo3[i]->getIsOn())
  117. {
  118. vo3[i]->doProcess(outPtrL, outPtrR, numSamples);
  119. obf.addFrom(0, 0, tmpBuf, 0, 0, numSamples, left);
  120. obf.addFrom(1, 0, tmpBuf, 1, 0, numSamples, right);
  121. ebf1.addFrom(0, 0, tmpBuf, 0, 0, numSamples, parameters[22 + 48] * left);
  122. ebf1.addFrom(1, 0, tmpBuf, 1, 0, numSamples, parameters[22 + 48] * right);
  123. ebf2.addFrom(0, 0, tmpBuf, 0, 0, numSamples, parameters[23 + 48] * left);
  124. ebf2.addFrom(1, 0, tmpBuf, 1, 0, numSamples, parameters[23 + 48] * right);
  125. ebf3.addFrom(0, 0, tmpBuf, 0, 0, numSamples, parameters[24 + 48] * left);
  126. ebf3.addFrom(1, 0, tmpBuf, 1, 0, numSamples, parameters[24 + 48] * right);
  127. }
  128. }
  129. }
  130. }
  131. void setBufferSize(const int size)
  132. {
  133. tmpBuf.setSize(2, size);
  134. }
  135. void setSampleRate(const double s)
  136. {
  137. if (sampleRate == s)
  138. return;
  139. sampleRate = s;
  140. for (int i = 0; i < kNumVoices; ++i)
  141. {
  142. delete vo1[i];
  143. delete vo2[i];
  144. delete vo3[i];
  145. vo1[i] = new VexVoice(parameters, 0, wr1);
  146. vo2[i] = new VexVoice(parameters, 24, wr2);
  147. vo3[i] = new VexVoice(parameters, 48, wr3);
  148. }
  149. }
  150. void updateParameterPtr(const float* const p)
  151. {
  152. parameters = p;
  153. for (int i = 0; i < kNumVoices; ++i)
  154. {
  155. vo1[i]->updateParameterPtr(parameters);
  156. vo2[i]->updateParameterPtr(parameters);
  157. vo3[i]->updateParameterPtr(parameters);
  158. }
  159. }
  160. void playNote(const int n, const int vel, const int preroll, const int part)
  161. {
  162. VexVoice** v = nullptr;
  163. const int note = n + 12;
  164. switch (part)
  165. {
  166. case 1:
  167. if (!part1) return;
  168. v = vo1;
  169. break;
  170. case 2:
  171. if (!part2) return;
  172. v = vo2;
  173. break;
  174. case 3:
  175. if (!part3) return;
  176. v = vo3;
  177. break;
  178. }
  179. if (v == nullptr)
  180. return;
  181. int OldestOn = kNumVoices-1;
  182. int OldestOff = kNumVoices-1;
  183. int OldestReleased = kNumVoices-1;
  184. int tmpOn = 100000000;
  185. //int tmpOff = 100000000;
  186. int tmpReleased = 100000000;
  187. for (int i = 0; i < kNumVoices; ++i)
  188. {
  189. if (i == benchwarmer)
  190. continue;
  191. if (! v[i]->getIsOn())
  192. {
  193. OldestOff = i;
  194. break;
  195. }
  196. if (v[i]->getIsReleased())
  197. {
  198. OldestReleased = (v[i]->getOrdinal() < tmpReleased) ? i : OldestReleased;
  199. tmpReleased = v[OldestReleased]->getOrdinal();
  200. continue;
  201. }
  202. OldestOn = (v[i]->getOrdinal() < tmpOn) ? i : OldestOn;
  203. tmpOn = v[OldestOn]->getOrdinal();
  204. }
  205. float noteInHertz = (float)MidiMessage::getMidiNoteInHertz(note);
  206. playCount++;
  207. if (OldestOff < kNumVoices)
  208. {
  209. v[OldestOff]->start(noteInHertz, float(vel)/127.0f, note, preroll, sampleRate, playCount);
  210. return;
  211. }
  212. if (OldestReleased < kNumVoices)
  213. {
  214. v[benchwarmer]->start(noteInHertz, float(vel)/127.0f, note, preroll, sampleRate, playCount);
  215. benchwarmer = OldestReleased;
  216. v[OldestReleased]->quickRelease();
  217. return;
  218. }
  219. if (OldestOn < kNumVoices)
  220. {
  221. v[benchwarmer]->start(noteInHertz, float(vel)/127.0f, note, preroll, sampleRate, playCount);
  222. benchwarmer = OldestOn;
  223. v[OldestReleased]->quickRelease();
  224. return;
  225. }
  226. }
  227. void releaseNote(const int n, const int preroll, const int part)
  228. {
  229. VexVoice** v = nullptr;
  230. const int note = n + 12;
  231. switch (part)
  232. {
  233. case 1:
  234. if (!part1) return;
  235. v = vo1;
  236. break;
  237. case 2:
  238. if (!part2) return;
  239. v = vo2;
  240. break;
  241. case 3:
  242. if (!part3) return;
  243. v = vo3;
  244. break;
  245. }
  246. if (v == nullptr)
  247. return;
  248. for (int i = 0; i < kNumVoices; ++i)
  249. {
  250. if (v[i]->getNote() == note)
  251. v[i]->release(preroll);
  252. }
  253. }
  254. void releaseAll(const int p)
  255. {
  256. for (int i = 0; i < kNumVoices; ++i)
  257. {
  258. vo1[i]->release(p);
  259. vo2[i]->release(p);
  260. vo3[i]->release(p);
  261. }
  262. }
  263. void kill(const int what = 0)
  264. {
  265. switch (what)
  266. {
  267. case 0:
  268. for (int i = 0; i < kNumVoices; ++i)
  269. {
  270. vo1[i]->kill();
  271. vo2[i]->kill();
  272. vo3[i]->kill();
  273. }
  274. break;
  275. case 1:
  276. for (int i = 0; i < kNumVoices; ++i)
  277. vo1[i]->kill();
  278. break;
  279. case 2:
  280. for (int i = 0; i < kNumVoices; ++i)
  281. vo2[i]->kill();
  282. break;
  283. case 3:
  284. for (int i = 0; i < kNumVoices; ++i)
  285. vo3[i]->kill();
  286. break;
  287. }
  288. }
  289. String getWaveName(const int part) const
  290. {
  291. switch (part)
  292. {
  293. case 1:
  294. return wr1.getCurrentWaveName();
  295. case 2:
  296. return wr2.getCurrentWaveName();
  297. case 3:
  298. return wr3.getCurrentWaveName();
  299. default:
  300. return "";
  301. }
  302. }
  303. void setWaveLater(const int part, const String& waveName)
  304. {
  305. switch (part)
  306. {
  307. case 1:
  308. wr1.setWaveLater(waveName);
  309. kill(1);
  310. break;
  311. case 2:
  312. wr2.setWaveLater(waveName);
  313. kill(2);
  314. break;
  315. case 3:
  316. wr3.setWaveLater(waveName);
  317. kill(3);
  318. break;
  319. }
  320. }
  321. void update(const int index)
  322. {
  323. if (index == 89)
  324. {
  325. part1 = (parameters[89] > 0.5f);
  326. return;
  327. }
  328. if (index == 90)
  329. {
  330. part2 = (parameters[90] > 0.5f);
  331. return;
  332. }
  333. if (index == 91)
  334. {
  335. part3 = (parameters[91] > 0.5f);
  336. return;
  337. }
  338. for (int i = 0; i < kNumVoices; ++i)
  339. {
  340. vo1[i]->update(index);
  341. vo2[i]->update(index);
  342. vo3[i]->update(index);
  343. }
  344. }
  345. private:
  346. static const int kNumVoices = 8;
  347. const float* parameters;
  348. double sampleRate;
  349. int benchwarmer;
  350. AudioSampleBuffer tmpBuf;
  351. VexVoice* vo1[kNumVoices];
  352. VexVoice* vo2[kNumVoices];
  353. VexVoice* vo3[kNumVoices];
  354. long playCount;
  355. bool part1, part2, part3;
  356. WaveRenderer wr1;
  357. WaveRenderer wr2;
  358. WaveRenderer wr3;
  359. };
  360. #endif // DISTRHO_VEX_SYNTH_MODULE_HEADER_INCLUDED