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.

351 lines
10KB

  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_native.hpp"
  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. enum Parameters {
  27. PARAMETER_MASTER,
  28. PARAMETER_MAX
  29. };
  30. ZynAddSubFxPlugin(const HostDescriptor* host)
  31. : PluginDescriptorClass(host)
  32. {
  33. qDebug("ZynAddSubFxPlugin::ZynAddSubFxPlugin(), s_instanceCount=%i", s_instanceCount);
  34. m_master = new Master;
  35. // refresh banks
  36. m_master->bank.rescanforbanks();
  37. for (size_t i=0, size = m_master->bank.banks.size(); i < size; i++)
  38. {
  39. if (m_master->bank.banks[i].dir.empty())
  40. continue;
  41. m_master->bank.loadbank(m_master->bank.banks[i].dir);
  42. for (unsigned int instrument = 0; instrument < BANK_SIZE; instrument++)
  43. {
  44. const std::string insName = m_master->bank.getname(instrument);
  45. if (insName.empty() || insName[0] == '\0' || insName[0] == ' ')
  46. continue;
  47. ProgramInfo pInfo;
  48. pInfo.bank = i;
  49. pInfo.prog = instrument;
  50. pInfo.name = insName;
  51. m_programs.push_back(pInfo);
  52. }
  53. }
  54. }
  55. ~ZynAddSubFxPlugin()
  56. {
  57. qDebug("ZynAddSubFxPlugin::~ZynAddSubFxPlugin(), s_instanceCount=%i", s_instanceCount);
  58. m_programs.clear();
  59. delete m_master;
  60. }
  61. protected:
  62. // -------------------------------------------------------------------
  63. // Plugin parameter calls
  64. uint32_t getParameterCount()
  65. {
  66. return PARAMETER_MAX;
  67. }
  68. const Parameter* getParameterInfo(uint32_t index)
  69. {
  70. CARLA_ASSERT(index < getParameterCount());
  71. if (index >= PARAMETER_MAX)
  72. return nullptr;
  73. static Parameter param;
  74. param.ranges.step = PARAMETER_RANGES_DEFAULT_STEP;
  75. param.ranges.stepSmall = PARAMETER_RANGES_DEFAULT_STEP_SMALL;
  76. param.ranges.stepLarge = PARAMETER_RANGES_DEFAULT_STEP_LARGE;
  77. param.scalePointCount = 0;
  78. param.scalePoints = nullptr;
  79. switch (index)
  80. {
  81. case PARAMETER_MASTER:
  82. param.hints = PARAMETER_IS_ENABLED | PARAMETER_IS_AUTOMABLE;
  83. param.name = "Master Volume";
  84. param.unit = nullptr;
  85. param.ranges.min = 0.0f;
  86. param.ranges.max = 100.0f;
  87. param.ranges.def = 100.0f;
  88. break;
  89. }
  90. return &param;
  91. }
  92. float getParameterValue(uint32_t index)
  93. {
  94. switch (index)
  95. {
  96. case PARAMETER_MASTER:
  97. return m_master->Pvolume;
  98. default:
  99. return 0.0f;
  100. }
  101. }
  102. // -------------------------------------------------------------------
  103. // Plugin midi-program calls
  104. uint32_t getMidiProgramCount()
  105. {
  106. return m_programs.size();
  107. }
  108. const MidiProgram* getMidiProgramInfo(uint32_t index)
  109. {
  110. CARLA_ASSERT(index < getMidiProgramCount());
  111. if (index >= m_programs.size())
  112. return nullptr;
  113. const ProgramInfo pInfo(m_programs[index]);
  114. static MidiProgram midiProgram;
  115. midiProgram.bank = pInfo.bank;
  116. midiProgram.program = pInfo.prog;
  117. midiProgram.name = pInfo.name.c_str();
  118. return &midiProgram;
  119. }
  120. // -------------------------------------------------------------------
  121. // Plugin state calls
  122. void setParameterValue(uint32_t index, float value)
  123. {
  124. switch (index)
  125. {
  126. case PARAMETER_MASTER:
  127. m_master->setPvolume((char)rint(value));
  128. break;
  129. }
  130. }
  131. void setMidiProgram(uint32_t bank, uint32_t program)
  132. {
  133. if (bank >= m_master->bank.banks.size())
  134. return;
  135. if (program >= BANK_SIZE)
  136. return;
  137. const std::string bankdir = m_master->bank.banks[bank].dir;
  138. if (! bankdir.empty())
  139. {
  140. pthread_mutex_lock(&m_master->mutex);
  141. m_master->bank.loadbank(bankdir);
  142. m_master->bank.loadfromslot(program, m_master->part[0]);
  143. pthread_mutex_unlock(&m_master->mutex);
  144. }
  145. }
  146. // -------------------------------------------------------------------
  147. // Plugin process calls
  148. void activate()
  149. {
  150. m_master->setController(0, MIDI_CONTROL_ALL_SOUND_OFF, 0);
  151. }
  152. void process(float**, float** outBuffer, uint32_t frames, uint32_t midiEventCount, MidiEvent* midiEvents)
  153. {
  154. unsigned long from_frame = 0;
  155. unsigned long event_index = 0;
  156. unsigned long next_event_frame = 0;
  157. unsigned long to_frame = 0;
  158. pthread_mutex_lock(&m_master->mutex);
  159. do {
  160. /* Find the time of the next event, if any */
  161. if (event_index >= midiEventCount)
  162. next_event_frame = ULONG_MAX;
  163. else
  164. next_event_frame = midiEvents[event_index].time;
  165. /* find the end of the sub-sample to be processed this time round... */
  166. /* if the next event falls within the desired sample interval... */
  167. if ((next_event_frame < frames) && (next_event_frame >= to_frame))
  168. /* set the end to be at that event */
  169. to_frame = next_event_frame;
  170. else
  171. /* ...else go for the whole remaining sample */
  172. to_frame = frames;
  173. if (from_frame < to_frame)
  174. {
  175. // call master to fill from `from_frame` to `to_frame`:
  176. m_master->GetAudioOutSamples(to_frame - from_frame, (int)getSampleRate(), &outBuffer[0][from_frame], &outBuffer[1][from_frame]);
  177. // next sub-sample please...
  178. from_frame = to_frame;
  179. }
  180. // Now process any event(s) at the current timing point
  181. while (event_index < midiEventCount && midiEvents[event_index].time == to_frame)
  182. {
  183. uint8_t status = midiEvents[event_index].data[0];
  184. uint8_t channel = status & 0x0F;
  185. if (MIDI_IS_STATUS_NOTE_OFF(status))
  186. {
  187. uint8_t note = midiEvents[event_index].data[1];
  188. m_master->noteOff(channel, note);
  189. }
  190. else if (MIDI_IS_STATUS_NOTE_ON(status))
  191. {
  192. uint8_t note = midiEvents[event_index].data[1];
  193. uint8_t velo = midiEvents[event_index].data[2];
  194. m_master->noteOn(channel, note, velo);
  195. }
  196. else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status))
  197. {
  198. uint8_t note = midiEvents[event_index].data[1];
  199. uint8_t pressure = midiEvents[event_index].data[2];
  200. m_master->polyphonicAftertouch(channel, note, pressure);
  201. }
  202. event_index++;
  203. }
  204. // Keep going until we have the desired total length of sample...
  205. } while (to_frame < frames);
  206. pthread_mutex_unlock(&m_master->mutex);
  207. }
  208. // -------------------------------------------------------------------
  209. private:
  210. struct ProgramInfo {
  211. uint32_t bank;
  212. uint32_t prog;
  213. std::string name;
  214. };
  215. std::vector<ProgramInfo> m_programs;
  216. Master* m_master;
  217. public:
  218. static int s_instanceCount;
  219. static PluginHandle _instantiate(const PluginDescriptor*, HostDescriptor* host)
  220. {
  221. if (s_instanceCount++ == 0)
  222. {
  223. synth = new SYNTH_T;
  224. synth->buffersize = host->get_buffer_size(host->handle);
  225. synth->samplerate = host->get_sample_rate(host->handle);
  226. synth->alias();
  227. config.init();
  228. config.cfg.SoundBufferSize = synth->buffersize;
  229. config.cfg.SampleRate = synth->samplerate;
  230. config.cfg.GzipCompression = 0;
  231. sprng(time(NULL));
  232. denormalkillbuf = new float [synth->buffersize];
  233. for (int i=0; i < synth->buffersize; i++)
  234. denormalkillbuf[i] = (RND - 0.5f) * 1e-16;
  235. Master::getInstance();
  236. }
  237. return new ZynAddSubFxPlugin(host);
  238. }
  239. static void _cleanup(PluginHandle handle)
  240. {
  241. delete (ZynAddSubFxPlugin*)handle;
  242. if (--s_instanceCount == 0)
  243. {
  244. Master::deleteInstance();
  245. delete[] denormalkillbuf;
  246. denormalkillbuf = nullptr;
  247. delete synth;
  248. synth = nullptr;
  249. }
  250. }
  251. };
  252. int ZynAddSubFxPlugin::s_instanceCount = 0;
  253. // -----------------------------------------------------------------------
  254. static PluginDescriptor zynAddSubFxDesc = {
  255. /* category */ PLUGIN_CATEGORY_SYNTH,
  256. #ifdef WANT_ZYNADDSUBFX_GUI
  257. /* hints */ PLUGIN_IS_SYNTH | PLUGIN_HAS_GUI | PLUGIN_USES_SINGLE_THREAD,
  258. #else
  259. /* hints */ PLUGIN_IS_SYNTH | PLUGIN_USES_SINGLE_THREAD,
  260. #endif
  261. /* audioIns */ 2,
  262. /* audioOuts */ 2,
  263. /* midiIns */ 1,
  264. /* midiOuts */ 0,
  265. /* paramIns */ ZynAddSubFxPlugin::PARAMETER_MAX,
  266. /* paramOuts */ 0,
  267. /* name */ "ZynAddSubFX",
  268. /* label */ "zynaddsubfx",
  269. /* maker */ "falkTX",
  270. /* copyright */ "GNU GPL v2+",
  271. PluginDescriptorFILL(ZynAddSubFxPlugin)
  272. };
  273. // -----------------------------------------------------------------------
  274. void carla_register_native_plugin_zynaddsubfx()
  275. {
  276. carla_register_native_plugin(&zynAddSubFxDesc);
  277. }
  278. // -----------------------------------------------------------------------