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.

379 lines
11KB

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