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.

338 lines
9.7KB

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