Collection of tools useful for audio production
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.

408 lines
11KB

  1. /*
  2. * Carla Native Plugins
  3. * Copyright (C) 2012 Filipe Coelho <falktx@falktx.com>
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of the GNU General Public License as published by
  7. * the Free Software Foundation; either version 2 of the License, or
  8. * 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 COPYING file
  16. */
  17. #include "carla_midi.h"
  18. #include "carla_nativemm.h"
  19. #include "zynaddsubfx/Misc/Master.h"
  20. #include "zynaddsubfx/Misc/Util.h"
  21. #include <climits>
  22. SYNTH_T* synth = nullptr;
  23. class ZynAddSubFxPlugin : public PluginDescriptorClass
  24. {
  25. public:
  26. ZynAddSubFxPlugin(const PluginDescriptorClass* master)
  27. : PluginDescriptorClass(master)
  28. {
  29. zyn_master = nullptr;
  30. // first init, ignore
  31. if (! master)
  32. return;
  33. if (s_instanceCount == 0)
  34. {
  35. synth = new SYNTH_T;
  36. synth->buffersize = getBufferSize();
  37. synth->samplerate = getSampleRate();
  38. synth->alias();
  39. config.init();
  40. config.cfg.SoundBufferSize = getBufferSize();
  41. config.cfg.SampleRate = getSampleRate();
  42. config.cfg.GzipCompression = 0;
  43. sprng(time(NULL));
  44. denormalkillbuf = new float [synth->buffersize];
  45. for (int i=0; i < synth->buffersize; i++)
  46. denormalkillbuf[i] = (RND - 0.5f) * 1e-16;
  47. }
  48. zyn_master = new Master();
  49. zyn_master->defaults();
  50. zyn_master->swaplr = false;
  51. // refresh banks
  52. zyn_master->bank.rescanforbanks();
  53. for (size_t i=0, size = zyn_master->bank.banks.size(); i < size; i++)
  54. {
  55. if (! zyn_master->bank.banks[i].dir.empty())
  56. {
  57. zyn_master->bank.loadbank(zyn_master->bank.banks[i].dir);
  58. for (unsigned int instrument = 0; instrument < BANK_SIZE; instrument++)
  59. {
  60. const std::string insName = zyn_master->bank.getname(instrument);
  61. if (insName.empty() || insName[0] == '\0' || insName[0] == ' ')
  62. continue;
  63. ProgramInfo pInfo;
  64. pInfo.bank = i;
  65. pInfo.prog = instrument;
  66. pInfo.name = insName;
  67. programs.push_back(pInfo);
  68. }
  69. }
  70. }
  71. s_instanceCount++;
  72. }
  73. ~ZynAddSubFxPlugin()
  74. {
  75. if (! zyn_master)
  76. return;
  77. programs.clear();
  78. delete zyn_master;
  79. if (--s_instanceCount == 0)
  80. {
  81. delete[] denormalkillbuf;
  82. denormalkillbuf = nullptr;
  83. delete synth;
  84. synth = nullptr;
  85. }
  86. }
  87. // -------------------------------------------------------------------
  88. protected:
  89. PluginDescriptorClass* createMe()
  90. {
  91. return new ZynAddSubFxPlugin(this);
  92. }
  93. void deleteMe()
  94. {
  95. delete this;
  96. }
  97. // -------------------------------------------------------------------
  98. PluginCategory getCategory()
  99. {
  100. return PLUGIN_CATEGORY_SYNTH;
  101. }
  102. uint32_t getHints()
  103. {
  104. return (PLUGIN_IS_SYNTH | PLUGIN_HAS_GUI | PLUGIN_USES_SINGLE_THREAD);
  105. }
  106. const char* getName()
  107. {
  108. return "ZynAddSubFX";
  109. }
  110. const char* getLabel()
  111. {
  112. return "zynaddsubfx";
  113. }
  114. const char* getMaker()
  115. {
  116. return "falkTX";
  117. }
  118. const char* getCopyright()
  119. {
  120. return "GNU GPL v2+";
  121. }
  122. // -------------------------------------------------------------------
  123. uint32_t getPortCount()
  124. {
  125. return PORT_MAX;
  126. }
  127. PortType getPortType(uint32_t index)
  128. {
  129. switch (index)
  130. {
  131. case ZYN_PORT_INPUT_MIDI:
  132. return PORT_TYPE_MIDI;
  133. case ZYN_PORT_OUTPUT_AUDIO_L:
  134. case ZYN_PORT_OUTPUT_AUDIO_R:
  135. return PORT_TYPE_AUDIO;
  136. default:
  137. return PORT_TYPE_PARAMETER;
  138. }
  139. }
  140. uint32_t getPortHints(uint32_t index)
  141. {
  142. switch (index)
  143. {
  144. case ZYN_PORT_INPUT_MIDI:
  145. return 0;
  146. case ZYN_PORT_OUTPUT_AUDIO_L:
  147. case ZYN_PORT_OUTPUT_AUDIO_R:
  148. return PORT_HINT_IS_OUTPUT;
  149. default:
  150. return (PORT_HINT_IS_ENABLED | PORT_HINT_IS_AUTOMABLE);
  151. }
  152. }
  153. const char* getPortName(const uint32_t index)
  154. {
  155. switch (index)
  156. {
  157. case ZYN_PORT_INPUT_MIDI:
  158. return "midi-in";
  159. case ZYN_PORT_OUTPUT_AUDIO_L:
  160. return "output-left";
  161. case ZYN_PORT_OUTPUT_AUDIO_R:
  162. return "output-right";
  163. case ZYN_PARAMETER_MASTER:
  164. return "Master Volume";
  165. default:
  166. return "";
  167. }
  168. }
  169. void getParameterRanges(uint32_t index, ParameterRanges* const ranges)
  170. {
  171. switch (index)
  172. {
  173. case ZYN_PARAMETER_MASTER:
  174. ranges->min = 0.0f;
  175. ranges->max = 100.0f;
  176. ranges->def = 100.0f;
  177. break;
  178. }
  179. }
  180. double getParameterValue(uint32_t index)
  181. {
  182. if (! zyn_master)
  183. return 0.0;
  184. switch (index)
  185. {
  186. case ZYN_PARAMETER_MASTER:
  187. return zyn_master->Pvolume;
  188. default:
  189. return 0.0;
  190. }
  191. }
  192. const char* getParameterUnit(uint32_t index)
  193. {
  194. switch (index)
  195. {
  196. case ZYN_PARAMETER_MASTER:
  197. return "dB - test";
  198. default:
  199. return nullptr;
  200. }
  201. }
  202. // -------------------------------------------------------------------
  203. const MidiProgram* getMidiProgram(uint32_t index)
  204. {
  205. if (index >= programs.size())
  206. return nullptr;
  207. const ProgramInfo pInfo(programs[index]);
  208. static MidiProgram midiProgram;
  209. midiProgram.bank = pInfo.bank;
  210. midiProgram.program = pInfo.prog;
  211. midiProgram.name = pInfo.name.c_str();
  212. return &midiProgram;
  213. }
  214. void setParameterValue(uint32_t index, double value)
  215. {
  216. if (! zyn_master)
  217. return;
  218. switch (index)
  219. {
  220. case ZYN_PARAMETER_MASTER:
  221. zyn_master->setPvolume((char)rint(value));
  222. break;
  223. }
  224. }
  225. // -------------------------------------------------------------------
  226. void setMidiProgram(uint32_t bank, uint32_t program)
  227. {
  228. if (! zyn_master)
  229. return;
  230. if (bank >= zyn_master->bank.banks.size())
  231. return;
  232. if (program >= BANK_SIZE)
  233. return;
  234. const std::string bankdir = zyn_master->bank.banks[bank].dir;
  235. if (! bankdir.empty())
  236. {
  237. pthread_mutex_lock(&zyn_master->mutex);
  238. zyn_master->bank.loadbank(bankdir);
  239. zyn_master->bank.loadfromslot(program, zyn_master->part[0]);
  240. pthread_mutex_unlock(&zyn_master->mutex);
  241. }
  242. }
  243. // -------------------------------------------------------------------
  244. void activate()
  245. {
  246. if (! zyn_master)
  247. return;
  248. zyn_master->setController(0, MIDI_CONTROL_ALL_SOUND_OFF, 0);
  249. }
  250. // -------------------------------------------------------------------
  251. void process(float**, float** outBuffer, uint32_t frames, uint32_t midiEventCount, MidiEvent* midiEvents)
  252. {
  253. if (! zyn_master)
  254. return;
  255. unsigned long from_frame = 0;
  256. unsigned long event_index = 0;
  257. unsigned long next_event_frame = 0;
  258. unsigned long to_frame = 0;
  259. pthread_mutex_lock(&zyn_master->mutex);
  260. do {
  261. /* Find the time of the next event, if any */
  262. if (event_index >= midiEventCount)
  263. next_event_frame = ULONG_MAX;
  264. else
  265. next_event_frame = midiEvents[event_index].time;
  266. /* find the end of the sub-sample to be processed this time round... */
  267. /* if the next event falls within the desired sample interval... */
  268. if ((next_event_frame < frames) && (next_event_frame >= to_frame))
  269. /* set the end to be at that event */
  270. to_frame = next_event_frame;
  271. else
  272. /* ...else go for the whole remaining sample */
  273. to_frame = frames;
  274. if (from_frame < to_frame)
  275. {
  276. // call master to fill from `from_frame` to `to_frame`:
  277. zyn_master->GetAudioOutSamples(to_frame - from_frame, (int)getSampleRate(), &outBuffer[0][from_frame], &outBuffer[1][from_frame]);
  278. // next sub-sample please...
  279. from_frame = to_frame;
  280. }
  281. // Now process any event(s) at the current timing point
  282. while (event_index < midiEventCount && midiEvents[event_index].time == to_frame)
  283. {
  284. uint8_t status = midiEvents[event_index].data[0];
  285. uint8_t channel = status & 0x0F;
  286. if (MIDI_IS_STATUS_NOTE_OFF(status))
  287. {
  288. uint8_t note = midiEvents[event_index].data[1];
  289. zyn_master->noteOff(channel, note);
  290. }
  291. else if (MIDI_IS_STATUS_NOTE_ON(status))
  292. {
  293. uint8_t note = midiEvents[event_index].data[1];
  294. uint8_t velo = midiEvents[event_index].data[2];
  295. zyn_master->noteOn(channel, note, velo);
  296. }
  297. else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status))
  298. {
  299. uint8_t note = midiEvents[event_index].data[1];
  300. uint8_t pressure = midiEvents[event_index].data[2];
  301. zyn_master->polyphonicAftertouch(channel, note, pressure);
  302. }
  303. event_index++;
  304. }
  305. // Keep going until we have the desired total length of sample...
  306. } while (to_frame < frames);
  307. pthread_mutex_unlock(&zyn_master->mutex);
  308. }
  309. // -------------------------------------------------------------------
  310. private:
  311. enum Ports {
  312. ZYN_PORT_INPUT_MIDI = 0,
  313. ZYN_PORT_OUTPUT_AUDIO_L,
  314. ZYN_PORT_OUTPUT_AUDIO_R,
  315. ZYN_PARAMETER_MASTER,
  316. PORT_MAX
  317. };
  318. struct ProgramInfo {
  319. uint32_t bank;
  320. uint32_t prog;
  321. std::string name;
  322. };
  323. std::vector<ProgramInfo> programs;
  324. Master* zyn_master;
  325. static int s_instanceCount;
  326. };
  327. int ZynAddSubFxPlugin::s_instanceCount = 0;
  328. static ZynAddSubFxPlugin zynAddSubFxPlugin(nullptr);
  329. CARLA_REGISTER_NATIVE_PLUGIN_MM(zynAddSubFx, zynAddSubFxPlugin)