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.

266 lines
8.0KB

  1. /*
  2. * Carla Native Plugins
  3. * Copyright (C) 2012-2015 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 doc/GPL.txt file.
  16. */
  17. #include "CarlaNative.hpp"
  18. #include "midi-base.hpp"
  19. // -----------------------------------------------------------------------
  20. class MidiSequencerPlugin : public NativePluginClass,
  21. public AbstractMidiPlayer
  22. {
  23. public:
  24. MidiSequencerPlugin(const NativeHostDescriptor* const host)
  25. : NativePluginClass(host),
  26. fWantInEvents(false),
  27. fMidiOut(this)
  28. {
  29. // TEST SONG (unsorted to test RtList API)
  30. uint32_t m = 44;
  31. fMidiOut.addControl(0*m, 0, 7, 99);
  32. fMidiOut.addControl(0*m, 0, 10, 63);
  33. fMidiOut.addProgram(0*m, 0, 0, 0);
  34. // 6912 On ch=1 n=60 v=90
  35. // 7237 Off ch=1 n=60 v=90
  36. // 7296 On ch=1 n=62 v=90
  37. // 7621 Off ch=1 n=62 v=90
  38. // 7680 On ch=1 n=64 v=90
  39. // 8005 Off ch=1 n=64 v=90
  40. fMidiOut.addNote(6912*m, 0, 60, 90, 325*m);
  41. fMidiOut.addNote(7680*m, 0, 64, 90, 325*m);
  42. fMidiOut.addNote(7296*m, 0, 62, 90, 325*m);
  43. // 1152 On ch=1 n=62 v=90
  44. // 1477 Off ch=1 n=62 v=90
  45. // 1536 On ch=1 n=64 v=90
  46. // 1861 Off ch=1 n=64 v=90
  47. // 1920 On ch=1 n=64 v=90
  48. // 2245 Off ch=1 n=64 v=90
  49. fMidiOut.addNote(1152*m, 0, 62, 90, 325*m);
  50. fMidiOut.addNote(1920*m, 0, 64, 90, 325*m);
  51. fMidiOut.addNote(1536*m, 0, 64, 90, 325*m);
  52. // 3840 On ch=1 n=62 v=90
  53. // 4491 Off ch=1 n=62 v=90
  54. // 4608 On ch=1 n=64 v=90
  55. // 4933 Off ch=1 n=64 v=90
  56. // 4992 On ch=1 n=67 v=90
  57. // 5317 Off ch=1 n=67 v=90
  58. fMidiOut.addNote(3840*m, 0, 62, 90, 650*m);
  59. fMidiOut.addNote(4992*m, 0, 67, 90, 325*m);
  60. fMidiOut.addNote(4608*m, 0, 64, 90, 325*m);
  61. // 0 On ch=1 n=64 v=90
  62. // 325 Off ch=1 n=64 v=90
  63. // 384 On ch=1 n=62 v=90
  64. // 709 Off ch=1 n=62 v=90
  65. // 768 On ch=1 n=60 v=90
  66. //1093 Off ch=1 n=60 v=90
  67. fMidiOut.addNote( 0*m, 0, 64, 90, 325*m);
  68. fMidiOut.addNote(768*m, 0, 60, 90, 325*m);
  69. fMidiOut.addNote(384*m, 0, 62, 90, 325*m);
  70. // 10752 On ch=1 n=60 v=90
  71. // 12056 Off ch=1 n=60 v=90
  72. fMidiOut.addNote(10752*m, 0, 60, 90, 650*m);
  73. // 5376 On ch=1 n=67 v=90
  74. // 6027 Off ch=1 n=67 v=90
  75. // 6144 On ch=1 n=64 v=90
  76. // 6469 Off ch=1 n=64 v=90
  77. // 6528 On ch=1 n=62 v=90
  78. // 6853 Off ch=1 n=62 v=90
  79. fMidiOut.addNote(5376*m, 0, 67, 90, 650*m);
  80. fMidiOut.addNote(6144*m, 0, 64, 90, 325*m);
  81. fMidiOut.addNote(6528*m, 0, 62, 90, 325*m);
  82. // 8064 On ch=1 n=64 v=90
  83. // 8389 Off ch=1 n=64 v=90
  84. // 8448 On ch=1 n=64 v=90
  85. // 9099 Off ch=1 n=64 v=90
  86. // 9216 On ch=1 n=62 v=90
  87. // 9541 Off ch=1 n=62 v=90
  88. fMidiOut.addNote(8064*m, 0, 64, 90, 325*m);
  89. fMidiOut.addNote(8448*m, 0, 64, 90, 650*m);
  90. fMidiOut.addNote(9216*m, 0, 62, 90, 325*m);
  91. // 9600 On ch=1 n=62 v=90
  92. // 9925 Off ch=1 n=62 v=90
  93. // 9984 On ch=1 n=64 v=90
  94. // 10309 Off ch=1 n=64 v=90
  95. // 10368 On ch=1 n=62 v=90
  96. // 10693 Off ch=1 n=62 v=90
  97. fMidiOut.addNote(9600*m, 0, 62, 90, 325*m);
  98. fMidiOut.addNote(9984*m, 0, 64, 90, 325*m);
  99. fMidiOut.addNote(10368*m, 0, 62, 90, 325*m);
  100. // 2304 On ch=1 n=64 v=90
  101. // 2955 Off ch=1 n=64 v=90
  102. // 3072 On ch=1 n=62 v=90
  103. // 3397 Off ch=1 n=62 v=90
  104. // 3456 On ch=1 n=62 v=90
  105. // 3781 Off ch=1 n=62 v=90
  106. fMidiOut.addNote(2304*m, 0, 64, 90, 650*m);
  107. fMidiOut.addNote(3072*m, 0, 62, 90, 325*m);
  108. fMidiOut.addNote(3456*m, 0, 62, 90, 325*m);
  109. }
  110. ~MidiSequencerPlugin() override
  111. {
  112. }
  113. protected:
  114. // -------------------------------------------------------------------
  115. // Plugin process calls
  116. void activate() override
  117. {
  118. }
  119. void deactivate() override
  120. {
  121. }
  122. void process(float**, float**, const uint32_t frames, const NativeMidiEvent* const midiEvents, const uint32_t midiEventCount) override
  123. {
  124. const NativeTimeInfo* const timePos = getTimeInfo();
  125. if (fWantInEvents)
  126. {
  127. RawMidiEvent rawMidiEvent;
  128. for (uint32_t i=0; i < midiEventCount; ++i)
  129. {
  130. const NativeMidiEvent* const midiEvent = &midiEvents[i];
  131. rawMidiEvent.data[0] = midiEvent->data[0];
  132. rawMidiEvent.data[1] = midiEvent->data[1];
  133. rawMidiEvent.data[2] = midiEvent->data[2];
  134. rawMidiEvent.data[3] = midiEvent->data[3];
  135. rawMidiEvent.size = midiEvent->size;
  136. rawMidiEvent.time = timePos->frame + midiEvent->time;
  137. fInEvents.appendRT(rawMidiEvent);
  138. }
  139. if (fInEvents.mutex.tryLock())
  140. {
  141. fInEvents.splice();
  142. fInEvents.mutex.unlock();
  143. }
  144. }
  145. if (timePos->playing)
  146. fMidiOut.play(timePos->frame, frames);
  147. }
  148. // -------------------------------------------------------------------
  149. // Plugin process calls
  150. void writeMidiEvent(const uint8_t port, const uint32_t timePosFrame, const RawMidiEvent* const event) override
  151. {
  152. NativeMidiEvent midiEvent;
  153. midiEvent.port = port;
  154. midiEvent.time = uint32_t(event->time-timePosFrame);
  155. midiEvent.data[0] = event->data[0];
  156. midiEvent.data[1] = event->data[1];
  157. midiEvent.data[2] = event->data[2];
  158. midiEvent.data[3] = event->data[3];
  159. midiEvent.size = event->size;
  160. NativePluginClass::writeMidiEvent(&midiEvent);
  161. }
  162. private:
  163. bool fWantInEvents;
  164. struct InRtEvents {
  165. CarlaMutex mutex;
  166. RtList<RawMidiEvent>::Pool dataPool;
  167. RtList<RawMidiEvent> data;
  168. RtList<RawMidiEvent> dataPendingRT;
  169. InRtEvents()
  170. : dataPool(MIN_PREALLOCATED_EVENT_COUNT, MAX_PREALLOCATED_EVENT_COUNT),
  171. data(dataPool),
  172. dataPendingRT(dataPool) {}
  173. ~InRtEvents()
  174. {
  175. clear();
  176. }
  177. void appendRT(const RawMidiEvent& event)
  178. {
  179. dataPendingRT.append(event);
  180. }
  181. void clear()
  182. {
  183. data.clear();
  184. dataPendingRT.clear();
  185. }
  186. void splice()
  187. {
  188. dataPendingRT.spliceAppend(data);
  189. }
  190. } fInEvents;
  191. MidiPattern fMidiOut;
  192. PluginClassEND(MidiSequencerPlugin)
  193. CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(MidiSequencerPlugin)
  194. };
  195. // -----------------------------------------------------------------------
  196. static const NativePluginDescriptor midisequencerDesc = {
  197. /* category */ NATIVE_PLUGIN_CATEGORY_UTILITY,
  198. /* hints */ NATIVE_PLUGIN_IS_RTSAFE/*|NATIVE_PLUGIN_HAS_GUI*/,
  199. /* supports */ static_cast<NativePluginSupports>(0x0),
  200. /* audioIns */ 0,
  201. /* audioOuts */ 0,
  202. /* midiIns */ 1,
  203. /* midiOuts */ 1,
  204. /* paramIns */ 0,
  205. /* paramOuts */ 0,
  206. /* name */ "MIDI Sequencer",
  207. /* label */ "midisequencer",
  208. /* maker */ "falkTX",
  209. /* copyright */ "GNU GPL v2+",
  210. PluginDescriptorFILL(MidiSequencerPlugin)
  211. };
  212. // -----------------------------------------------------------------------
  213. CARLA_EXPORT
  214. void carla_register_native_plugin_midisequencer();
  215. CARLA_EXPORT
  216. void carla_register_native_plugin_midisequencer()
  217. {
  218. carla_register_native_plugin(&midisequencerDesc);
  219. }
  220. // -----------------------------------------------------------------------