VST3: fetch midi mappings all at once, use it for note/sound-off
[carla.git] / source / modules / juce_audio_basics / midi / juce_MidiBuffer.h
blob6a2a5413f9ba871aa6f3fe7d74e02d9f68971279
1 /*
2 ==============================================================================
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
20 ==============================================================================
23 namespace juce
26 //==============================================================================
27 /**
28 A view of MIDI message data stored in a contiguous buffer.
30 Instances of this class do *not* own the midi data bytes that they point to.
31 Instead, they expect the midi data to live in a separate buffer that outlives
32 the MidiMessageMetadata instance.
34 @tags{Audio}
36 struct MidiMessageMetadata final
38 MidiMessageMetadata() noexcept = default;
40 MidiMessageMetadata (const uint8* dataIn, int numBytesIn, int positionIn) noexcept
41 : data (dataIn), numBytes (numBytesIn), samplePosition (positionIn)
45 /** Constructs a new MidiMessage instance from the data that this object is viewing.
47 Note that MidiMessage owns its data storage, whereas MidiMessageMetadata does not.
49 MidiMessage getMessage() const { return MidiMessage (data, numBytes, samplePosition); }
51 /** Pointer to the first byte of a MIDI message. */
52 const uint8* data = nullptr;
54 /** The number of bytes in the MIDI message. */
55 int numBytes = 0;
57 /** The MIDI message's timestamp. */
58 int samplePosition = 0;
61 //==============================================================================
62 /**
63 An iterator to move over contiguous raw MIDI data, which Allows iterating
64 over a MidiBuffer using C++11 range-for syntax.
66 In the following example, we log all three-byte messages in a midi buffer.
67 @code
68 void processBlock (AudioBuffer<float>&, MidiBuffer& midiBuffer) override
70 for (const MidiMessageMetadata metadata : midiBuffer)
71 if (metadata.numBytes == 3)
72 Logger::writeToLog (metadata.getMessage().getDescription());
74 @endcode
76 @tags{Audio}
78 class JUCE_API MidiBufferIterator
80 using Ptr = const uint8*;
82 public:
83 MidiBufferIterator() = default;
85 /** Constructs an iterator pointing at the message starting at the byte `dataIn`.
86 `dataIn` must point to the start of a valid MIDI message. If it does not,
87 calling other member functions on the iterator will result in undefined
88 behaviour.
90 explicit MidiBufferIterator (const uint8* dataIn) noexcept
91 : data (dataIn)
95 using difference_type = std::iterator_traits<Ptr>::difference_type;
96 using value_type = MidiMessageMetadata;
97 using reference = MidiMessageMetadata;
98 using pointer = void;
99 using iterator_category = std::input_iterator_tag;
101 /** Make this iterator point to the next message in the buffer. */
102 MidiBufferIterator& operator++() noexcept;
104 /** Create a copy of this object, make this iterator point to the next message in
105 the buffer, then return the copy.
107 MidiBufferIterator operator++ (int) noexcept;
109 /** Return true if this iterator points to the same message as another
110 iterator instance, otherwise return false.
112 bool operator== (const MidiBufferIterator& other) const noexcept { return data == other.data; }
114 /** Return false if this iterator points to the same message as another
115 iterator instance, otherwise returns true.
117 bool operator!= (const MidiBufferIterator& other) const noexcept { return ! operator== (other); }
119 /** Return an instance of MidiMessageMetadata which describes the message to which
120 the iterator is currently pointing.
122 reference operator*() const noexcept;
124 private:
125 Ptr data = nullptr;
128 //==============================================================================
130 Holds a sequence of time-stamped midi events.
132 Analogous to the AudioBuffer, this holds a set of midi events with
133 integer time-stamps. The buffer is kept sorted in order of the time-stamps.
135 If you're working with a sequence of midi events that may need to be manipulated
136 or read/written to a midi file, then MidiMessageSequence is probably a more
137 appropriate container. MidiBuffer is designed for lower-level streams of raw
138 midi data.
140 @see MidiMessage
142 @tags{Audio}
144 class JUCE_API MidiBuffer
146 public:
147 //==============================================================================
148 /** Creates an empty MidiBuffer. */
149 MidiBuffer() noexcept = default;
151 /** Creates a MidiBuffer containing a single midi message. */
152 explicit MidiBuffer (const MidiMessage& message) noexcept;
154 //==============================================================================
155 /** Removes all events from the buffer. */
156 void clear() noexcept;
158 /** Removes all events between two times from the buffer.
160 All events for which (start <= event position < start + numSamples) will
161 be removed.
163 void clear (int start, int numSamples);
165 /** Returns true if the buffer is empty.
166 To actually retrieve the events, use a MidiBufferIterator object
168 bool isEmpty() const noexcept;
170 /** Counts the number of events in the buffer.
172 This is actually quite a slow operation, as it has to iterate through all
173 the events, so you might prefer to call isEmpty() if that's all you need
174 to know.
176 int getNumEvents() const noexcept;
178 /** Adds an event to the buffer.
180 The sample number will be used to determine the position of the event in
181 the buffer, which is always kept sorted. The MidiMessage's timestamp is
182 ignored.
184 If an event is added whose sample position is the same as one or more events
185 already in the buffer, the new event will be placed after the existing ones.
187 To retrieve events, use a MidiBufferIterator object.
189 Returns true on success, or false on failure.
191 bool addEvent (const MidiMessage& midiMessage, int sampleNumber);
193 /** Adds an event to the buffer from raw midi data.
195 The sample number will be used to determine the position of the event in
196 the buffer, which is always kept sorted.
198 If an event is added whose sample position is the same as one or more events
199 already in the buffer, the new event will be placed after the existing ones.
201 The event data will be inspected to calculate the number of bytes in length that
202 the midi event really takes up, so maxBytesOfMidiData may be longer than the data
203 that actually gets stored. E.g. if you pass in a note-on and a length of 4 bytes,
204 it'll actually only store 3 bytes. If the midi data is invalid, it might not
205 add an event at all.
207 To retrieve events, use a MidiBufferIterator object.
209 Returns true on success, or false on failure.
211 bool addEvent (const void* rawMidiData,
212 int maxBytesOfMidiData,
213 int sampleNumber);
215 /** Adds some events from another buffer to this one.
217 @param otherBuffer the buffer containing the events you want to add
218 @param startSample the lowest sample number in the source buffer for which
219 events should be added. Any source events whose timestamp is
220 less than this will be ignored
221 @param numSamples the valid range of samples from the source buffer for which
222 events should be added - i.e. events in the source buffer whose
223 timestamp is greater than or equal to (startSample + numSamples)
224 will be ignored. If this value is less than 0, all events after
225 startSample will be taken.
226 @param sampleDeltaToAdd a value which will be added to the source timestamps of the events
227 that are added to this buffer
229 void addEvents (const MidiBuffer& otherBuffer,
230 int startSample,
231 int numSamples,
232 int sampleDeltaToAdd);
234 /** Returns the sample number of the first event in the buffer.
235 If the buffer's empty, this will just return 0.
237 int getFirstEventTime() const noexcept;
239 /** Returns the sample number of the last event in the buffer.
240 If the buffer's empty, this will just return 0.
242 int getLastEventTime() const noexcept;
244 //==============================================================================
245 /** Exchanges the contents of this buffer with another one.
247 This is a quick operation, because no memory allocating or copying is done, it
248 just swaps the internal state of the two buffers.
250 void swapWith (MidiBuffer&) noexcept;
252 /** Preallocates some memory for the buffer to use.
253 This helps to avoid needing to reallocate space when the buffer has messages
254 added to it.
256 void ensureSize (size_t minimumNumBytes);
258 /** Get a read-only iterator pointing to the beginning of this buffer. */
259 MidiBufferIterator begin() const noexcept { return cbegin(); }
261 /** Get a read-only iterator pointing one past the end of this buffer. */
262 MidiBufferIterator end() const noexcept { return cend(); }
264 /** Get a read-only iterator pointing to the beginning of this buffer. */
265 MidiBufferIterator cbegin() const noexcept { return MidiBufferIterator (data.begin()); }
267 /** Get a read-only iterator pointing one past the end of this buffer. */
268 MidiBufferIterator cend() const noexcept { return MidiBufferIterator (data.end()); }
270 /** Get an iterator pointing to the first event with a timestamp greater-than or
271 equal-to `samplePosition`.
273 MidiBufferIterator findNextSamplePosition (int samplePosition) const noexcept;
275 //==============================================================================
276 #ifndef DOXYGEN
277 /** This class is now deprecated in favour of MidiBufferIterator.
279 Used to iterate through the events in a MidiBuffer.
281 Note that altering the buffer while an iterator is using it will produce
282 undefined behaviour.
284 @see MidiBuffer
286 class [[deprecated]] JUCE_API Iterator
288 public:
289 //==============================================================================
290 /** Creates an Iterator for this MidiBuffer. */
291 Iterator (const MidiBuffer& b) noexcept;
293 //==============================================================================
294 /** Repositions the iterator so that the next event retrieved will be the first
295 one whose sample position is at greater than or equal to the given position.
297 void setNextSamplePosition (int samplePosition) noexcept;
299 /** Retrieves a copy of the next event from the buffer.
301 @param result on return, this will be the message. The MidiMessage's timestamp
302 is set to the same value as samplePosition.
303 @param samplePosition on return, this will be the position of the event, as a
304 sample index in the buffer
305 @returns true if an event was found, or false if the iterator has reached
306 the end of the buffer
308 bool getNextEvent (MidiMessage& result,
309 int& samplePosition) noexcept;
311 /** Retrieves the next event from the buffer.
313 @param midiData on return, this pointer will be set to a block of data containing
314 the midi message. Note that to make it fast, this is a pointer
315 directly into the MidiBuffer's internal data, so is only valid
316 temporarily until the MidiBuffer is altered.
317 @param numBytesOfMidiData on return, this is the number of bytes of data used by the
318 midi message
319 @param samplePosition on return, this will be the position of the event, as a
320 sample index in the buffer
321 @returns true if an event was found, or false if the iterator has reached
322 the end of the buffer
324 bool getNextEvent (const uint8* &midiData,
325 int& numBytesOfMidiData,
326 int& samplePosition) noexcept;
328 private:
329 //==============================================================================
330 const MidiBuffer& buffer;
331 MidiBufferIterator iterator;
333 #endif
335 /** The raw data holding this buffer.
336 Obviously access to this data is provided at your own risk. Its internal format could
337 change in future, so don't write code that relies on it!
339 Array<uint8> data;
341 private:
342 JUCE_LEAK_DETECTOR (MidiBuffer)
345 } // namespace juce