openshot-audio  0.1.6
juce_VST3Common.h
Go to the documentation of this file.
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2015 - ROLI Ltd.
6 
7  Permission is granted to use this software under the terms of either:
8  a) the GPL v2 (or any later version)
9  b) the Affero GPL v3
10 
11  Details of these licenses can be found at: www.gnu.org/licenses
12 
13  JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
14  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15  A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 
17  ------------------------------------------------------------------------------
18 
19  To release a closed-source product which uses JUCE, commercial licenses are
20  available: visit www.juce.com for more information.
21 
22  ==============================================================================
23 */
24 
25 #ifndef JUCE_VST3COMMON_H_INCLUDED
26 #define JUCE_VST3COMMON_H_INCLUDED
27 
28 //==============================================================================
29 #define JUCE_DECLARE_VST3_COM_REF_METHODS \
30  Steinberg::uint32 PLUGIN_API addRef() override { return (Steinberg::uint32) ++refCount; } \
31  Steinberg::uint32 PLUGIN_API release() override { const int r = --refCount; if (r == 0) delete this; return (Steinberg::uint32) r; }
32 
33 #define JUCE_DECLARE_VST3_COM_QUERY_METHODS \
34  Steinberg::tresult PLUGIN_API queryInterface (const Steinberg::TUID, void** obj) override \
35  { \
36  jassertfalse; \
37  *obj = nullptr; \
38  return Steinberg::kNotImplemented; \
39  }
40 
41 static bool doUIDsMatch (const Steinberg::TUID a, const Steinberg::TUID b) noexcept
42 {
43  return std::memcmp (a, b, sizeof (Steinberg::TUID)) == 0;
44 }
45 
46 #define TEST_FOR_AND_RETURN_IF_VALID(iidToTest, ClassType) \
47  if (doUIDsMatch (iidToTest, ClassType::iid)) \
48  { \
49  addRef(); \
50  *obj = dynamic_cast<ClassType*> (this); \
51  return Steinberg::kResultOk; \
52  }
53 
54 #define TEST_FOR_COMMON_BASE_AND_RETURN_IF_VALID(iidToTest, CommonClassType, SourceClassType) \
55  if (doUIDsMatch (iidToTest, CommonClassType::iid)) \
56  { \
57  addRef(); \
58  *obj = (CommonClassType*) static_cast<SourceClassType*> (this); \
59  return Steinberg::kResultOk; \
60  }
61 
62 //==============================================================================
63 static juce::String toString (const Steinberg::char8* string) noexcept { return juce::String (string); }
64 static juce::String toString (const Steinberg::char16* string) noexcept { return juce::String (juce::CharPointer_UTF16 ((juce::CharPointer_UTF16::CharType*) string)); }
65 
66 // NB: The casts are handled by a Steinberg::UString operator
67 static juce::String toString (const Steinberg::UString128& string) noexcept { return toString (static_cast<const Steinberg::char16*> (string)); }
68 static juce::String toString (const Steinberg::UString256& string) noexcept { return toString (static_cast<const Steinberg::char16*> (string)); }
69 
70 static void toString128 (Steinberg::Vst::String128 result, const juce::String& source)
71 {
72  Steinberg::UString (result, 128).fromAscii (source.toUTF8());
73 }
74 
75 static Steinberg::Vst::TChar* toString (const juce::String& source) noexcept
76 {
77  return reinterpret_cast<Steinberg::Vst::TChar*> (source.toUTF16().getAddress());
78 }
79 
80 #if JUCE_WINDOWS
81  static const Steinberg::FIDString defaultVST3WindowType = Steinberg::kPlatformTypeHWND;
82 #else
83  static const Steinberg::FIDString defaultVST3WindowType = Steinberg::kPlatformTypeNSView;
84 #endif
85 
86 
87 //==============================================================================
88 static Steinberg::Vst::SpeakerArrangement getArrangementForBus (Steinberg::Vst::IAudioProcessor* processor,
89  bool isInput, int busIndex)
90 {
91  Steinberg::Vst::SpeakerArrangement arrangement = Steinberg::Vst::SpeakerArr::kEmpty;
92 
93  if (processor != nullptr)
94  processor->getBusArrangement (isInput ? Steinberg::Vst::kInput : Steinberg::Vst::kOutput,
95  (Steinberg::int32) busIndex, arrangement);
96 
97  return arrangement;
98 }
99 
103 static Steinberg::Vst::SpeakerArrangement getArrangementForNumChannels (int numChannels) noexcept
104 {
105  using namespace Steinberg::Vst::SpeakerArr;
106 
107  switch (numChannels)
108  {
109  case 0: return kEmpty;
110  case 1: return kMono;
111  case 2: return kStereo;
112  case 3: return k30Cine;
113  case 4: return k31Cine;
114  case 5: return k50;
115  case 6: return k51;
116  case 7: return k61Cine;
117  case 8: return k71CineFullFront;
118  case 9: return k90;
119  case 10: return k91;
120  case 11: return k101;
121  case 12: return k111;
122  case 13: return k130;
123  case 14: return k131;
124  case 24: return (Steinberg::Vst::SpeakerArrangement) 1929904127; // k222
125  default: break;
126  }
127 
128  jassert (numChannels >= 0);
129 
130  juce::BigInteger bi;
131  bi.setRange (0, jmin (numChannels, (int) (sizeof (Steinberg::Vst::SpeakerArrangement) * 8)), true);
132  return (Steinberg::Vst::SpeakerArrangement) bi.toInt64();
133 }
134 
135 //==============================================================================
136 template <class ObjectType>
138 {
139 public:
140  ComSmartPtr() noexcept : source (nullptr) {}
141  ComSmartPtr (ObjectType* object, bool autoAddRef = true) noexcept : source (object) { if (source != nullptr && autoAddRef) source->addRef(); }
142  ComSmartPtr (const ComSmartPtr& other) noexcept : source (other.source) { if (source != nullptr) source->addRef(); }
143  ~ComSmartPtr() { if (source != nullptr) source->release(); }
144 
145  operator ObjectType*() const noexcept { return source; }
146  ObjectType* get() const noexcept { return source; }
147  ObjectType& operator*() const noexcept { return *source; }
148  ObjectType* operator->() const noexcept { return source; }
149 
150  ComSmartPtr& operator= (const ComSmartPtr& other) { return operator= (other.source); }
151 
152  ComSmartPtr& operator= (ObjectType* const newObjectToTakePossessionOf)
153  {
154  ComSmartPtr p (newObjectToTakePossessionOf);
155  std::swap (p.source, source);
156  return *this;
157  }
158 
159  bool operator== (ObjectType* const other) noexcept { return source == other; }
160  bool operator!= (ObjectType* const other) noexcept { return source != other; }
161 
162  bool loadFrom (Steinberg::FUnknown* o)
163  {
164  *this = nullptr;
165  return o != nullptr && o->queryInterface (ObjectType::iid, (void**) &source) == Steinberg::kResultOk;
166  }
167 
168  bool loadFrom (Steinberg::IPluginFactory* factory, const Steinberg::TUID& uuid)
169  {
170  jassert (factory != nullptr);
171  *this = nullptr;
172  return factory->createInstance (uuid, ObjectType::iid, (void**) &source) == Steinberg::kResultOk;
173  }
174 
175 private:
176  ObjectType* source;
177 };
178 
179 //==============================================================================
180 class MidiEventList : public Steinberg::Vst::IEventList
181 {
182 public:
184  virtual ~MidiEventList() {}
185 
188 
189  //==============================================================================
190  void clear()
191  {
192  events.clearQuick();
193  }
194 
195  Steinberg::int32 PLUGIN_API getEventCount() override
196  {
197  return (Steinberg::int32) events.size();
198  }
199 
200  // NB: This has to cope with out-of-range indexes from some plugins.
201  Steinberg::tresult PLUGIN_API getEvent (Steinberg::int32 index, Steinberg::Vst::Event& e) override
202  {
203  if (isPositiveAndBelow ((int) index, events.size()))
204  {
205  e = events.getReference ((int) index);
206  return Steinberg::kResultTrue;
207  }
208 
209  return Steinberg::kResultFalse;
210  }
211 
212  Steinberg::tresult PLUGIN_API addEvent (Steinberg::Vst::Event& e) override
213  {
214  events.add (e);
215  return Steinberg::kResultTrue;
216  }
217 
218  //==============================================================================
219  static void toMidiBuffer (MidiBuffer& result, Steinberg::Vst::IEventList& eventList)
220  {
221  const int32 numEvents = eventList.getEventCount();
222 
223  for (Steinberg::int32 i = 0; i < numEvents; ++i)
224  {
225  Steinberg::Vst::Event e;
226 
227  if (eventList.getEvent (i, e) == Steinberg::kResultOk)
228  {
229  switch (e.type)
230  {
231  case Steinberg::Vst::Event::kNoteOnEvent:
232  result.addEvent (MidiMessage::noteOn (createSafeChannel (e.noteOn.channel),
233  createSafeNote (e.noteOn.pitch),
234  (Steinberg::uint8) denormaliseToMidiValue (e.noteOn.velocity)),
235  e.sampleOffset);
236  break;
237 
238  case Steinberg::Vst::Event::kNoteOffEvent:
239  result.addEvent (MidiMessage::noteOff (createSafeChannel (e.noteOff.channel),
240  createSafeNote (e.noteOff.pitch),
241  (Steinberg::uint8) denormaliseToMidiValue (e.noteOff.velocity)),
242  e.sampleOffset);
243  break;
244 
245  case Steinberg::Vst::Event::kPolyPressureEvent:
246  result.addEvent (MidiMessage::aftertouchChange (createSafeChannel (e.polyPressure.channel),
247  createSafeNote (e.polyPressure.pitch),
248  denormaliseToMidiValue (e.polyPressure.pressure)),
249  e.sampleOffset);
250  break;
251 
252  case Steinberg::Vst::Event::kDataEvent:
253  result.addEvent (MidiMessage::createSysExMessage (e.data.bytes, (int) e.data.size),
254  e.sampleOffset);
255  break;
256 
257  default:
258  break;
259  }
260  }
261  }
262  }
263 
264  static void toEventList (Steinberg::Vst::IEventList& result, MidiBuffer& midiBuffer)
265  {
266  MidiBuffer::Iterator iterator (midiBuffer);
267  MidiMessage msg;
268  int midiEventPosition = 0;
269 
270  enum { maxNumEvents = 2048 }; // Steinberg's Host Checker states that no more than 2048 events are allowed at once
271  int numEvents = 0;
272 
273  while (iterator.getNextEvent (msg, midiEventPosition))
274  {
275  if (++numEvents > maxNumEvents)
276  break;
277 
278  Steinberg::Vst::Event e = { 0 };
279 
280  if (msg.isNoteOn())
281  {
282  e.type = Steinberg::Vst::Event::kNoteOnEvent;
283  e.noteOn.channel = createSafeChannel (msg.getChannel());
284  e.noteOn.pitch = createSafeNote (msg.getNoteNumber());
285  e.noteOn.velocity = normaliseMidiValue (msg.getVelocity());
286  e.noteOn.length = 0;
287  e.noteOn.tuning = 0.0f;
288  e.noteOn.noteId = -1;
289  }
290  else if (msg.isNoteOff())
291  {
292  e.type = Steinberg::Vst::Event::kNoteOffEvent;
293  e.noteOff.channel = createSafeChannel (msg.getChannel());
294  e.noteOff.pitch = createSafeNote (msg.getNoteNumber());
295  e.noteOff.velocity = normaliseMidiValue (msg.getVelocity());
296  e.noteOff.tuning = 0.0f;
297  e.noteOff.noteId = -1;
298  }
299  else if (msg.isSysEx())
300  {
301  e.type = Steinberg::Vst::Event::kDataEvent;
302  e.data.bytes = msg.getSysExData();
303  e.data.size = (uint32) msg.getSysExDataSize();
304  e.data.type = Steinberg::Vst::DataEvent::kMidiSysEx;
305  }
306  else if (msg.isAftertouch())
307  {
308  e.type = Steinberg::Vst::Event::kPolyPressureEvent;
309  e.polyPressure.channel = createSafeChannel (msg.getChannel());
310  e.polyPressure.pitch = createSafeNote (msg.getNoteNumber());
311  e.polyPressure.pressure = normaliseMidiValue (msg.getAfterTouchValue());
312  }
313  else
314  {
315  continue;
316  }
317 
318  e.busIndex = 0;
319  e.sampleOffset = midiEventPosition;
320 
321  result.addEvent (e);
322  }
323  }
324 
325 private:
327  Atomic<int> refCount;
328 
329  static Steinberg::int16 createSafeChannel (int channel) noexcept { return (Steinberg::int16) jlimit (0, 15, channel - 1); }
330  static int createSafeChannel (Steinberg::int16 channel) noexcept { return (int) jlimit (1, 16, channel + 1); }
331 
332  static Steinberg::int16 createSafeNote (int note) noexcept { return (Steinberg::int16) jlimit (0, 127, note); }
333  static int createSafeNote (Steinberg::int16 note) noexcept { return jlimit (0, 127, (int) note); }
334 
335  static float normaliseMidiValue (int value) noexcept { return jlimit (0.0f, 1.0f, (float) value / 127.0f); }
336  static int denormaliseToMidiValue (float value) noexcept { return roundToInt (jlimit (0.0f, 127.0f, value * 127.0f)); }
337 
339 };
340 
341 //==============================================================================
343 {
346 
352  void associateBufferTo (Steinberg::Vst::AudioBusBuffers& vstBuffers,
353  Bus& bus,
355  int numChannels, int channelStartOffset,
356  int sampleOffset = 0)
357  {
358  const int channelEnd = numChannels + channelStartOffset;
359  jassert (channelEnd >= 0 && channelEnd <= buffer.getNumChannels());
360 
361  bus.clearQuick();
362 
363  for (int i = channelStartOffset; i < channelEnd; ++i)
364  bus.add (buffer.getWritePointer (i, sampleOffset));
365 
366  vstBuffers.channelBuffers32 = bus.getRawDataPointer();
367  vstBuffers.numChannels = numChannels;
368  vstBuffers.silenceFlags = 0;
369  }
370 
371  static void mapArrangementToBusses (int& channelIndexOffset, int index,
373  BusMap& busMapToUse, Steinberg::Vst::SpeakerArrangement arrangement,
374  AudioSampleBuffer& source)
375  {
376  const int numChansForBus = BigInteger ((juce::int64) arrangement).countNumberOfSetBits();
377 
378  if (index >= result.size())
379  result.add (Steinberg::Vst::AudioBusBuffers());
380 
381  if (index >= busMapToUse.size())
382  busMapToUse.add (Bus());
383 
384  if (numChansForBus > 0)
385  {
386  associateBufferTo (result.getReference (index),
387  busMapToUse.getReference (index),
388  source, numChansForBus, channelIndexOffset);
389  }
390 
391  channelIndexOffset += numChansForBus;
392  }
393 
394  static void mapBufferToBusses (Array<Steinberg::Vst::AudioBusBuffers>& result, BusMap& busMapToUse,
395  const Array<Steinberg::Vst::SpeakerArrangement>& arrangements,
396  AudioSampleBuffer& source)
397  {
398  int channelIndexOffset = 0;
399 
400  for (int i = 0; i < arrangements.size(); ++i)
401  mapArrangementToBusses (channelIndexOffset, i, result, busMapToUse,
402  arrangements.getUnchecked (i), source);
403  }
404 
405  static void mapBufferToBusses (Array<Steinberg::Vst::AudioBusBuffers>& result,
406  Steinberg::Vst::IAudioProcessor& processor,
407  BusMap& busMapToUse, bool isInput, int numBusses,
408  AudioSampleBuffer& source)
409  {
410  int channelIndexOffset = 0;
411 
412  for (int i = 0; i < numBusses; ++i)
413  mapArrangementToBusses (channelIndexOffset, i,
414  result, busMapToUse,
415  getArrangementForBus (&processor, isInput, i),
416  source);
417  }
418 }
419 
420 #endif // JUCE_VST3COMMON_H_INCLUDED
Definition: juce_AudioSampleBuffer.h:34
int getAfterTouchValue() const noexcept
Definition: juce_MidiMessage.cpp:406
ObjectType & operator*() const noexcept
Definition: juce_VST3Common.h:147
Definition: juce_BigInteger.h:43
static void toMidiBuffer(MidiBuffer &result, Steinberg::Vst::IEventList &eventList)
Definition: juce_VST3Common.h:219
void clearQuick()
Definition: juce_Array.h:211
static MidiMessage noteOn(int channel, int noteNumber, float velocity) noexcept
Definition: juce_MidiMessage.cpp:525
bool loadFrom(Steinberg::IPluginFactory *factory, const Steinberg::TUID &uuid)
Definition: juce_VST3Common.h:168
ComSmartPtr() noexcept
Definition: juce_VST3Common.h:140
ComSmartPtr(ObjectType *object, bool autoAddRef=true) noexcept
Definition: juce_VST3Common.h:141
int countNumberOfSetBits() const noexcept
Definition: juce_BigInteger.cpp:334
#define noexcept
Definition: juce_CompilerSupport.h:141
Definition: juce_Atomic.h:41
signed short int16
Definition: juce_MathsFunctions.h:45
Array< Bus > BusMap
Definition: juce_VST3Common.h:345
Type jmin(const Type a, const Type b)
Definition: juce_core.h:113
CharPointer_UTF8 toUTF8() const
Definition: juce_core.cpp:2058
bool isPositiveAndBelow(Type valueToTest, Type upperLimit) noexcept
Definition: juce_core.h:238
ComSmartPtr(const ComSmartPtr &other) noexcept
Definition: juce_VST3Common.h:142
int roundToInt(const FloatType value) noexcept
Definition: juce_core.h:418
void add(const ElementType &newElement)
Definition: juce_Array.h:392
#define JUCE_DECLARE_VST3_COM_REF_METHODS
Definition: juce_VST3Common.h:29
Definition: juce_core.h:44
long b
Definition: jpegint.h:371
int getNumChannels() const noexcept
Definition: juce_AudioSampleBuffer.h:116
bool isNoteOn(bool returnTrueForVelocity0=false) const noexcept
Definition: juce_MidiMessage.cpp:338
Definition: juce_core.h:44
ElementType & getReference(const int index) const noexcept
Definition: juce_Array.h:274
#define const
JOCTET * buffer
Definition: juce_JPEGLoader.cpp:302
void associateBufferTo(Steinberg::Vst::AudioBusBuffers &vstBuffers, Bus &bus, AudioSampleBuffer &buffer, int numChannels, int channelStartOffset, int sampleOffset=0)
Definition: juce_VST3Common.h:352
bool operator!=(ObjectType *const other) noexcept
Definition: juce_VST3Common.h:160
void addEvent(const MidiMessage &midiMessage, int sampleNumber)
Definition: juce_MidiBuffer.cpp:110
Definition: juce_VST3Common.h:137
bool getNextEvent(MidiMessage &result, int &samplePosition) noexcept
Definition: juce_MidiBuffer.cpp:218
static MidiMessage noteOff(int channel, int noteNumber, uint8 velocity=0) noexcept
Definition: juce_MidiMessage.cpp:539
int16 CharType
Definition: juce_core.h:46
JUCE_DECLARE_VST3_COM_REF_METHODS JUCE_DECLARE_VST3_COM_QUERY_METHODS void clear()
Definition: juce_VST3Common.h:190
float * getWritePointer(int channelNumber) noexcept
Definition: juce_AudioSampleBuffer.h:156
virtual ~MidiEventList()
Definition: juce_VST3Common.h:184
unsigned int uint32
Definition: juce_MathsFunctions.h:51
void setRange(int startBit, int numBits, bool shouldBeSet)
Definition: juce_core.cpp:271
static MidiMessage aftertouchChange(int channel, int noteNumber, int aftertouchAmount) noexcept
Definition: juce_MidiMessage.cpp:412
Steinberg::tresult PLUGIN_API getEvent(Steinberg::int32 index, Steinberg::Vst::Event &e) override
Definition: juce_VST3Common.h:201
ComSmartPtr & operator=(const ComSmartPtr &other)
Definition: juce_VST3Common.h:150
static MidiMessage createSysExMessage(const void *sysexData, int dataSize)
Definition: juce_MidiMessage.cpp:593
CharType * getAddress() const noexcept
Definition: juce_core.h:80
ObjectType * operator->() const noexcept
Definition: juce_VST3Common.h:148
int getChannel() const noexcept
Definition: juce_MidiMessage.cpp:307
Steinberg::int32 PLUGIN_API getEventCount() override
Definition: juce_VST3Common.h:195
Definition: juce_VST3Common.h:342
int64 toInt64() const noexcept
Definition: juce_core.cpp:161
#define JUCE_DECLARE_VST3_COM_QUERY_METHODS
Definition: juce_VST3Common.h:33
bool isNoteOff(bool returnTrueForNoteOnVelocity0=true) const noexcept
Definition: juce_MidiMessage.cpp:346
const uint8 * getSysExData() const noexcept
Definition: juce_MidiMessage.cpp:604
~ComSmartPtr()
Definition: juce_VST3Common.h:143
Type jlimit(const Type lowerLimit, const Type upperLimit, const Type valueToConstrain) noexcept
Definition: juce_MathsFunctions.h:220
bool operator==(ObjectType *const other) noexcept
Definition: juce_VST3Common.h:159
bool isSysEx() const noexcept
Definition: juce_MidiMessage.cpp:588
#define jassert(a)
Definition: juce_PlatformDefs.h:146
Definition: juce_VST3Common.h:180
uint8 getVelocity() const noexcept
Definition: juce_MidiMessage.cpp:373
Steinberg::tresult PLUGIN_API addEvent(Steinberg::Vst::Event &e) override
Definition: juce_VST3Common.h:212
bool isAftertouch() const noexcept
Definition: juce_MidiMessage.cpp:401
#define JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(className)
Definition: juce_PlatformDefs.h:198
ElementType getUnchecked(const int index) const
Definition: juce_Array.h:258
Definition: juce_core.h:40
MidiEventList()
Definition: juce_VST3Common.h:183
ElementType * getRawDataPointer() noexcept
Definition: juce_Array.h:319
Definition: juce_MidiBuffer.h:43
CharPointer_UTF16 toUTF16() const
Definition: juce_core.cpp:2059
int getSysExDataSize() const noexcept
Definition: juce_MidiMessage.cpp:609
static void toEventList(Steinberg::Vst::IEventList &result, MidiBuffer &midiBuffer)
Definition: juce_VST3Common.h:264
unsigned char uint8
Definition: juce_MathsFunctions.h:43
Definition: juce_MidiMessage.h:35
Array< float * > Bus
Definition: juce_VST3Common.h:344
Definition: juce_MidiBuffer.h:171
int size() const noexcept
Definition: juce_Array.h:221
signed int int32
Definition: juce_MathsFunctions.h:49
int getNoteNumber() const noexcept
Definition: juce_MidiMessage.cpp:362
bool loadFrom(Steinberg::FUnknown *o)
Definition: juce_VST3Common.h:162
long long int64
Definition: juce_core.h:61