Cleanup
[carla.git] / source / modules / water / midi / MidiBuffer.h
blob1898ec632758ed0abfe7e8fc86c4df092179ff60
1 /*
2 ==============================================================================
4 This file is part of the Water library.
5 Copyright (c) 2016 ROLI Ltd.
6 Copyright (C) 2017-2022 Filipe Coelho <falktx@falktx.com>
8 Permission is granted to use this software under the terms of the ISC license
9 http://www.isc.org/downloads/software-support-policy/isc-license/
11 Permission to use, copy, modify, and/or distribute this software for any
12 purpose with or without fee is hereby granted, provided that the above
13 copyright notice and this permission notice appear in all copies.
15 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
16 TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
18 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
19 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21 OF THIS SOFTWARE.
23 ==============================================================================
26 #ifndef WATER_MIDIBUFFER_H_INCLUDED
27 #define WATER_MIDIBUFFER_H_INCLUDED
29 #include "../containers/Array.h"
31 namespace water {
33 //==============================================================================
34 /**
35 Holds a sequence of time-stamped midi events.
37 Analogous to the AudioSampleBuffer, this holds a set of midi events with
38 integer time-stamps. The buffer is kept sorted in order of the time-stamps.
40 If you're working with a sequence of midi events that may need to be manipulated
41 or read/written to a midi file, then MidiMessageSequence is probably a more
42 appropriate container. MidiBuffer is designed for lower-level streams of raw
43 midi data.
45 @see MidiMessage
47 class MidiBuffer
49 public:
50 //==============================================================================
51 /** Creates an empty MidiBuffer. */
52 MidiBuffer() noexcept;
54 /** Creates a MidiBuffer containing a single midi message. */
55 explicit MidiBuffer (const MidiMessage& message) noexcept;
57 /** Creates a copy of another MidiBuffer. */
58 MidiBuffer (const MidiBuffer&) noexcept;
60 /** Makes a copy of another MidiBuffer. */
61 MidiBuffer& operator= (const MidiBuffer&) noexcept;
63 /** Destructor */
64 ~MidiBuffer();
66 //==============================================================================
67 /** Removes all events from the buffer. */
68 void clear() noexcept;
70 /** Removes all events between two times from the buffer.
72 All events for which (start <= event position < start + numSamples) will
73 be removed.
75 void clear (int start, int numSamples);
77 /** Returns true if the buffer is empty.
78 To actually retrieve the events, use a MidiBuffer::Iterator object
80 bool isEmpty() const noexcept;
82 /** Counts the number of events in the buffer.
84 This is actually quite a slow operation, as it has to iterate through all
85 the events, so you might prefer to call isEmpty() if that's all you need
86 to know.
88 int getNumEvents() const noexcept;
90 /** Adds an event to the buffer.
92 The sample number will be used to determine the position of the event in
93 the buffer, which is always kept sorted. The MidiMessage's timestamp is
94 ignored.
96 If an event is added whose sample position is the same as one or more events
97 already in the buffer, the new event will be placed after the existing ones.
99 To retrieve events, use a MidiBuffer::Iterator object
101 void addEvent (const MidiMessage& midiMessage, int sampleNumber);
103 /** Adds an event to the buffer from raw midi data.
105 The sample number will be used to determine the position of the event in
106 the buffer, which is always kept sorted.
108 If an event is added whose sample position is the same as one or more events
109 already in the buffer, the new event will be placed after the existing ones.
111 The event data will be inspected to calculate the number of bytes in length that
112 the midi event really takes up, so maxBytesOfMidiData may be longer than the data
113 that actually gets stored. E.g. if you pass in a note-on and a length of 4 bytes,
114 it'll actually only store 3 bytes. If the midi data is invalid, it might not
115 add an event at all.
117 To retrieve events, use a MidiBuffer::Iterator object
119 void addEvent (const void* rawMidiData,
120 int maxBytesOfMidiData,
121 int sampleNumber);
123 /** Adds some events from another buffer to this one.
125 @param otherBuffer the buffer containing the events you want to add
126 @param startSample the lowest sample number in the source buffer for which
127 events should be added. Any source events whose timestamp is
128 less than this will be ignored
129 @param numSamples the valid range of samples from the source buffer for which
130 events should be added - i.e. events in the source buffer whose
131 timestamp is greater than or equal to (startSample + numSamples)
132 will be ignored. If this value is less than 0, all events after
133 startSample will be taken.
134 @param sampleDeltaToAdd a value which will be added to the source timestamps of the events
135 that are added to this buffer
137 void addEvents (const MidiBuffer& otherBuffer,
138 int startSample,
139 int numSamples,
140 int sampleDeltaToAdd);
142 /** Returns the sample number of the first event in the buffer.
143 If the buffer's empty, this will just return 0.
145 int getFirstEventTime() const noexcept;
147 /** Returns the sample number of the last event in the buffer.
148 If the buffer's empty, this will just return 0.
150 int getLastEventTime() const noexcept;
152 //==============================================================================
153 /** Exchanges the contents of this buffer with another one.
155 This is a quick operation, because no memory allocating or copying is done, it
156 just swaps the internal state of the two buffers.
158 void swapWith (MidiBuffer&) noexcept;
160 /** Preallocates some memory for the buffer to use.
161 This helps to avoid needing to reallocate space when the buffer has messages
162 added to it.
164 void ensureSize (size_t minimumNumBytes);
166 //==============================================================================
168 Used to iterate through the events in a MidiBuffer.
170 Note that altering the buffer while an iterator is using it isn't a
171 safe operation.
173 @see MidiBuffer
175 class Iterator
177 public:
178 //==============================================================================
179 /** Creates an Iterator for this MidiBuffer. */
180 Iterator (const MidiBuffer&) noexcept;
182 /** Destructor. */
183 ~Iterator() noexcept;
185 //==============================================================================
186 /** Repositions the iterator so that the next event retrieved will be the first
187 one whose sample position is at greater than or equal to the given position.
189 void setNextSamplePosition (int samplePosition) noexcept;
191 /** Retrieves a copy of the next event from the buffer.
193 @param result on return, this will be the message. The MidiMessage's timestamp
194 is set to the same value as samplePosition.
195 @param samplePosition on return, this will be the position of the event, as a
196 sample index in the buffer
197 @returns true if an event was found, or false if the iterator has reached
198 the end of the buffer
200 bool getNextEvent (MidiMessage& result,
201 int& samplePosition) noexcept;
203 /** Retrieves the next event from the buffer.
205 @param midiData on return, this pointer will be set to a block of data containing
206 the midi message. Note that to make it fast, this is a pointer
207 directly into the MidiBuffer's internal data, so is only valid
208 temporarily until the MidiBuffer is altered.
209 @param numBytesOfMidiData on return, this is the number of bytes of data used by the
210 midi message
211 @param samplePosition on return, this will be the position of the event, as a
212 sample index in the buffer
213 @returns true if an event was found, or false if the iterator has reached
214 the end of the buffer
216 bool getNextEvent (const uint8* &midiData,
217 int& numBytesOfMidiData,
218 int& samplePosition) noexcept;
220 private:
221 //==============================================================================
222 const MidiBuffer& buffer;
223 const uint8* data;
225 CARLA_DECLARE_NON_COPYABLE (Iterator)
228 /** The raw data holding this buffer.
229 Obviously access to this data is provided at your own risk. Its internal format could
230 change in future, so don't write code that relies on it!
232 Array<uint8> data;
237 #endif // WATER_MIDIBUFFER_H_INCLUDED