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
10KB

  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 "CarlaNative.hpp"
  21. #include "CarlaMIDI.h"
  22. #include "CarlaString.hpp"
  23. #include "RtList.hpp"
  24. #include "zynaddsubfx/Misc/Master.h"
  25. #include "zynaddsubfx/Misc/Util.h"
  26. #include <ctime>
  27. // TODO - free sPrograms
  28. // Dummy variables and functions for linking purposes
  29. const char* instance_name = nullptr;
  30. class WavFile;
  31. namespace Nio {
  32. bool start(void){return 1;}
  33. void stop(void){}
  34. void waveNew(WavFile*){}
  35. void waveStart(void){}
  36. void waveStop(void){}
  37. void waveEnd(void){}
  38. }
  39. SYNTH_T* synth = nullptr;
  40. class ZynAddSubFxPlugin : public PluginDescriptorClass
  41. {
  42. public:
  43. enum Parameters {
  44. PARAMETER_COUNT = 0
  45. };
  46. ZynAddSubFxPlugin(const HostDescriptor* const host)
  47. : PluginDescriptorClass(host),
  48. kMaster(new Master()),
  49. kSampleRate(getSampleRate())
  50. {
  51. _maybeInitPrograms(kMaster);
  52. }
  53. ~ZynAddSubFxPlugin()
  54. {
  55. //ensure that everything has stopped
  56. pthread_mutex_lock(&kMaster->mutex);
  57. pthread_mutex_unlock(&kMaster->mutex);
  58. delete kMaster;
  59. }
  60. protected:
  61. // -------------------------------------------------------------------
  62. // Plugin parameter calls
  63. uint32_t getParameterCount()
  64. {
  65. return PARAMETER_COUNT;
  66. }
  67. const Parameter* getParameterInfo(const uint32_t index)
  68. {
  69. CARLA_ASSERT(index < getParameterCount());
  70. //if (index >= PARAMETER_COUNT)
  71. return nullptr;
  72. static Parameter param;
  73. param.ranges.step = PARAMETER_RANGES_DEFAULT_STEP;
  74. param.ranges.stepSmall = PARAMETER_RANGES_DEFAULT_STEP_SMALL;
  75. param.ranges.stepLarge = PARAMETER_RANGES_DEFAULT_STEP_LARGE;
  76. param.scalePointCount = 0;
  77. param.scalePoints = nullptr;
  78. switch (index)
  79. {
  80. #if 0
  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. #endif
  90. }
  91. return &param;
  92. }
  93. float getParameterValue(const uint32_t index)
  94. {
  95. CARLA_ASSERT(index < getParameterCount());
  96. switch (index)
  97. {
  98. #if 0
  99. case PARAMETER_MASTER:
  100. return kMaster->Pvolume;
  101. #endif
  102. default:
  103. return 0.0f;
  104. }
  105. }
  106. // -------------------------------------------------------------------
  107. // Plugin midi-program calls
  108. uint32_t getMidiProgramCount()
  109. {
  110. return sPrograms.count();
  111. }
  112. const MidiProgram* getMidiProgramInfo(const uint32_t index)
  113. {
  114. CARLA_ASSERT(index < getMidiProgramCount());
  115. if (index >= sPrograms.count())
  116. return nullptr;
  117. const ProgramInfo* const pInfo(sPrograms.getAt(index));
  118. static MidiProgram midiProgram;
  119. midiProgram.bank = pInfo->bank;
  120. midiProgram.program = pInfo->prog;
  121. midiProgram.name = pInfo->name;
  122. return &midiProgram;
  123. }
  124. // -------------------------------------------------------------------
  125. // Plugin state calls
  126. void setParameterValue(const uint32_t index, const float value)
  127. {
  128. CARLA_ASSERT(index < getParameterCount());
  129. switch (index)
  130. {
  131. }
  132. return;
  133. // unused, TODO
  134. (void)value;
  135. }
  136. void setMidiProgram(const uint32_t bank, const uint32_t program)
  137. {
  138. if (bank >= kMaster->bank.banks.size())
  139. return;
  140. if (program >= BANK_SIZE)
  141. return;
  142. const std::string bankdir(kMaster->bank.banks[bank].dir);
  143. if (! bankdir.empty())
  144. {
  145. pthread_mutex_lock(&kMaster->mutex);
  146. kMaster->bank.loadbank(bankdir);
  147. kMaster->bank.loadfromslot(program, kMaster->part[0]);
  148. pthread_mutex_unlock(&kMaster->mutex);
  149. }
  150. }
  151. // -------------------------------------------------------------------
  152. // Plugin process calls
  153. void activate()
  154. {
  155. kMaster->setController(0, MIDI_CONTROL_ALL_SOUND_OFF, 0);
  156. }
  157. void process(float**, float** const outBuffer, const uint32_t frames, const uint32_t midiEventCount, const MidiEvent* const midiEvents)
  158. {
  159. if (pthread_mutex_trylock(&kMaster->mutex) != 0)
  160. {
  161. carla_zeroFloat(outBuffer[0], frames);
  162. carla_zeroFloat(outBuffer[1], frames);
  163. return;
  164. }
  165. for (uint32_t i=0; i < midiEventCount; i++)
  166. {
  167. const MidiEvent* const midiEvent = &midiEvents[i];
  168. const uint8_t status = MIDI_GET_STATUS_FROM_DATA(midiEvent->data);
  169. const uint8_t channel = MIDI_GET_CHANNEL_FROM_DATA(midiEvent->data);
  170. if (MIDI_IS_STATUS_NOTE_OFF(status))
  171. {
  172. const uint8_t note = midiEvent->data[1];
  173. kMaster->noteOff(channel, note);
  174. }
  175. else if (MIDI_IS_STATUS_NOTE_ON(status))
  176. {
  177. const uint8_t note = midiEvent->data[1];
  178. const uint8_t velo = midiEvent->data[2];
  179. kMaster->noteOn(channel, note, velo);
  180. }
  181. else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status))
  182. {
  183. const uint8_t note = midiEvent->data[1];
  184. const uint8_t pressure = midiEvent->data[2];
  185. kMaster->polyphonicAftertouch(channel, note, pressure);
  186. }
  187. }
  188. kMaster->GetAudioOutSamples(frames, kSampleRate, outBuffer[0], outBuffer[1]);
  189. pthread_mutex_unlock(&kMaster->mutex);
  190. }
  191. // -------------------------------------------------------------------
  192. private:
  193. struct ProgramInfo {
  194. uint32_t bank;
  195. uint32_t prog;
  196. const char* name;
  197. ProgramInfo(uint32_t bank_, uint32_t prog_, const char* name_)
  198. : bank(bank_),
  199. prog(prog_),
  200. name(carla_strdup(name_)) {}
  201. ~ProgramInfo()
  202. {
  203. if (name != nullptr)
  204. {
  205. delete[] name;
  206. name = nullptr;
  207. }
  208. }
  209. ProgramInfo() = delete;
  210. ProgramInfo(ProgramInfo&) = delete;
  211. ProgramInfo(const ProgramInfo&) = delete;
  212. };
  213. Master* const kMaster;
  214. const unsigned kSampleRate;
  215. public:
  216. static int sInstanceCount;
  217. static NonRtList<ProgramInfo*> sPrograms;
  218. static PluginHandle _instantiate(const PluginDescriptor*, HostDescriptor* host)
  219. {
  220. if (sInstanceCount++ == 0)
  221. {
  222. synth = new SYNTH_T;
  223. synth->buffersize = host->get_buffer_size(host->handle);
  224. synth->samplerate = host->get_sample_rate(host->handle);
  225. synth->alias();
  226. config.init();
  227. config.cfg.SoundBufferSize = synth->buffersize;
  228. config.cfg.SampleRate = synth->samplerate;
  229. //config.cfg.GzipCompression = 0;
  230. sprng(std::time(nullptr));
  231. denormalkillbuf = new float[synth->buffersize];
  232. for (int i=0; i < synth->buffersize; i++)
  233. denormalkillbuf[i] = (RND - 0.5f) * 1e-16;
  234. }
  235. return new ZynAddSubFxPlugin(host);
  236. }
  237. static void _cleanup(PluginHandle handle)
  238. {
  239. delete (ZynAddSubFxPlugin*)handle;
  240. if (--sInstanceCount == 0)
  241. {
  242. delete[] denormalkillbuf;
  243. denormalkillbuf = nullptr;
  244. delete synth;
  245. synth = nullptr;
  246. }
  247. }
  248. static void _maybeInitPrograms(Master* const master)
  249. {
  250. static bool doSearch = true;
  251. if (! doSearch)
  252. return;
  253. doSearch = false;
  254. pthread_mutex_lock(&master->mutex);
  255. #if 0
  256. // refresh banks
  257. master->bank.rescanforbanks();
  258. for (uint32_t i=0, size = master->bank.banks.size(); i < size; i++)
  259. {
  260. if (master->bank.banks[i].dir.empty())
  261. continue;
  262. master->bank.loadbank(master->bank.banks[i].dir);
  263. for (unsigned int instrument = 0; instrument < BANK_SIZE; instrument++)
  264. {
  265. const std::string insName(master->bank.getname(instrument));
  266. if (insName.empty() || insName[0] == '\0' || insName[0] == ' ')
  267. continue;
  268. sPrograms.append(new ProgramInfo(i, instrument, insName.c_str()));
  269. }
  270. }
  271. #endif
  272. pthread_mutex_unlock(&master->mutex);
  273. }
  274. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ZynAddSubFxPlugin)
  275. };
  276. int ZynAddSubFxPlugin::sInstanceCount = 0;
  277. NonRtList<ZynAddSubFxPlugin::ProgramInfo*> ZynAddSubFxPlugin::sPrograms;
  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. // -----------------------------------------------------------------------