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.

191 lines
5.9KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. #pragma once
  20. #include "juce_VSTInterface.h"
  21. namespace juce
  22. {
  23. //==============================================================================
  24. /** Holds a set of VSTMidiEvent objects and makes it easy to add
  25. events to the list.
  26. This is used by both the VST hosting code and the plugin wrapper.
  27. */
  28. class VSTMidiEventList
  29. {
  30. public:
  31. //==============================================================================
  32. VSTMidiEventList()
  33. : numEventsUsed (0), numEventsAllocated (0)
  34. {
  35. }
  36. ~VSTMidiEventList()
  37. {
  38. freeEvents();
  39. }
  40. //==============================================================================
  41. void clear()
  42. {
  43. numEventsUsed = 0;
  44. if (events != nullptr)
  45. events->numberOfEvents = 0;
  46. }
  47. void addEvent (const void* const midiData, const int numBytes, const int frameOffset)
  48. {
  49. ensureSize (numEventsUsed + 1);
  50. VstMidiEvent* const e = (VstMidiEvent*) (events->events [numEventsUsed]);
  51. events->numberOfEvents = ++numEventsUsed;
  52. if (numBytes <= 4)
  53. {
  54. if (e->type == vstSysExEventType)
  55. {
  56. delete[] (((VstSysExEvent*) e)->sysExDump);
  57. e->type = vstMidiEventType;
  58. e->size = sizeof (VstMidiEvent);
  59. e->noteSampleLength = 0;
  60. e->noteSampleOffset = 0;
  61. e->tuning = 0;
  62. e->noteVelocityOff = 0;
  63. }
  64. e->sampleOffset = frameOffset;
  65. memcpy (e->midiData, midiData, (size_t) numBytes);
  66. }
  67. else
  68. {
  69. VstSysExEvent* const se = (VstSysExEvent*) e;
  70. if (se->type == vstSysExEventType)
  71. delete[] se->sysExDump;
  72. se->sysExDump = new char [(size_t) numBytes];
  73. memcpy (se->sysExDump, midiData, (size_t) numBytes);
  74. se->type = vstSysExEventType;
  75. se->size = sizeof (VstSysExEvent);
  76. se->offsetSamples = frameOffset;
  77. se->flags = 0;
  78. se->sysExDumpSize = numBytes;
  79. se->future1 = 0;
  80. se->future2 = 0;
  81. }
  82. }
  83. //==============================================================================
  84. // Handy method to pull the events out of an event buffer supplied by the host
  85. // or plugin.
  86. static void addEventsToMidiBuffer (const VstEventBlock* events, MidiBuffer& dest)
  87. {
  88. for (int i = 0; i < events->numberOfEvents; ++i)
  89. {
  90. const VstEvent* const e = events->events[i];
  91. if (e != nullptr)
  92. {
  93. if (e->type == vstMidiEventType)
  94. {
  95. dest.addEvent ((const juce::uint8*) ((const VstMidiEvent*) e)->midiData,
  96. 4, e->sampleOffset);
  97. }
  98. else if (e->type == vstSysExEventType)
  99. {
  100. dest.addEvent ((const juce::uint8*) ((const VstSysExEvent*) e)->sysExDump,
  101. (int) ((const VstSysExEvent*) e)->sysExDumpSize,
  102. e->sampleOffset);
  103. }
  104. }
  105. }
  106. }
  107. //==============================================================================
  108. void ensureSize (int numEventsNeeded)
  109. {
  110. if (numEventsNeeded > numEventsAllocated)
  111. {
  112. numEventsNeeded = (numEventsNeeded + 32) & ~31;
  113. const size_t size = 20 + sizeof (VstEvent*) * (size_t) numEventsNeeded;
  114. if (events == nullptr)
  115. events.calloc (size, 1);
  116. else
  117. events.realloc (size, 1);
  118. for (int i = numEventsAllocated; i < numEventsNeeded; ++i)
  119. events->events[i] = allocateVSTEvent();
  120. numEventsAllocated = numEventsNeeded;
  121. }
  122. }
  123. void freeEvents()
  124. {
  125. if (events != nullptr)
  126. {
  127. for (int i = numEventsAllocated; --i >= 0;)
  128. freeVSTEvent (events->events[i]);
  129. events.free();
  130. numEventsUsed = 0;
  131. numEventsAllocated = 0;
  132. }
  133. }
  134. //==============================================================================
  135. HeapBlock<VstEventBlock> events;
  136. private:
  137. int numEventsUsed, numEventsAllocated;
  138. static VstEvent* allocateVSTEvent()
  139. {
  140. auto e = (VstEvent*) std::calloc (1, sizeof (VstMidiEvent) > sizeof (VstSysExEvent) ? sizeof (VstMidiEvent)
  141. : sizeof (VstSysExEvent));
  142. e->type = vstMidiEventType;
  143. e->size = sizeof (VstMidiEvent);
  144. return e;
  145. }
  146. static void freeVSTEvent (VstEvent* e)
  147. {
  148. if (e->type == vstSysExEventType)
  149. delete[] (((VstSysExEvent*) e)->sysExDump);
  150. std::free (e);
  151. }
  152. };
  153. } // namespace juce