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.

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