OpenShot Library | libopenshot-audio 0.2.0
juce_MidiMessageSequence.h
1
2/** @weakgroup juce_audio_basics-midi
3 * @{
4 */
5/*
6 ==============================================================================
7
8 This file is part of the JUCE library.
9 Copyright (c) 2017 - ROLI Ltd.
10
11 JUCE is an open source library subject to commercial or open-source
12 licensing.
13
14 The code included in this file is provided under the terms of the ISC license
15 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
16 To use, copy, modify, and/or distribute this software for any purpose with or
17 without fee is hereby granted provided that the above copyright notice and
18 this permission notice appear in all copies.
19
20 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
21 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
22 DISCLAIMED.
23
24 ==============================================================================
25*/
26
27namespace juce
28{
29
30//==============================================================================
31/**
32 A sequence of timestamped midi messages.
33
34 This allows the sequence to be manipulated, and also to be read from and
35 written to a standard midi file.
36
37 @see MidiMessage, MidiFile
38
39 @tags{Audio}
40*/
42{
43public:
44 //==============================================================================
45 /** Creates an empty midi sequence object. */
47
48 /** Creates a copy of another sequence. */
50
51 /** Replaces this sequence with another one. */
52 MidiMessageSequence& operator= (const MidiMessageSequence&);
53
54 /** Move constructor */
56
57 /** Move assignment operator */
58 MidiMessageSequence& operator= (MidiMessageSequence&&) noexcept;
59
60 /** Destructor. */
62
63 //==============================================================================
64 /** Structure used to hold midi events in the sequence.
65
66 These structures act as 'handles' on the events as they are moved about in
67 the list, and make it quick to find the matching note-offs for note-on events.
68
69 @see MidiMessageSequence::getEventPointer
70 */
72 {
73 public:
74 //==============================================================================
75 /** Destructor. */
77
78 /** The message itself, whose timestamp is used to specify the event's time. */
80
81 /** The matching note-off event (if this is a note-on event).
82
83 If this isn't a note-on, this pointer will be nullptr.
84
85 Use the MidiMessageSequence::updateMatchedPairs() method to keep these
86 note-offs up-to-date after events have been moved around in the sequence
87 or deleted.
88 */
89 MidiEventHolder* noteOffObject = nullptr;
90
91 private:
92 //==============================================================================
93 friend class MidiMessageSequence;
96 JUCE_LEAK_DETECTOR (MidiEventHolder)
97 };
98
99 //==============================================================================
100 /** Clears the sequence. */
101 void clear();
102
103 /** Returns the number of events in the sequence. */
104 int getNumEvents() const noexcept;
105
106 /** Returns a pointer to one of the events. */
107 MidiEventHolder* getEventPointer (int index) const noexcept;
108
109 /** Iterator for the list of MidiEventHolders */
110 MidiEventHolder** begin() const noexcept;
111
112 /** Iterator for the list of MidiEventHolders */
113 MidiEventHolder** end() const noexcept;
114
115 /** Returns the time of the note-up that matches the note-on at this index.
116 If the event at this index isn't a note-on, it'll just return 0.
117 @see MidiMessageSequence::MidiEventHolder::noteOffObject
118 */
119 double getTimeOfMatchingKeyUp (int index) const noexcept;
120
121 /** Returns the index of the note-up that matches the note-on at this index.
122 If the event at this index isn't a note-on, it'll just return -1.
123 @see MidiMessageSequence::MidiEventHolder::noteOffObject
124 */
125 int getIndexOfMatchingKeyUp (int index) const noexcept;
126
127 /** Returns the index of an event. */
128 int getIndexOf (const MidiEventHolder* event) const noexcept;
129
130 /** Returns the index of the first event on or after the given timestamp.
131 If the time is beyond the end of the sequence, this will return the
132 number of events.
133 */
134 int getNextIndexAtTime (double timeStamp) const noexcept;
135
136 //==============================================================================
137 /** Returns the timestamp of the first event in the sequence.
138 @see getEndTime
139 */
140 double getStartTime() const noexcept;
141
142 /** Returns the timestamp of the last event in the sequence.
143 @see getStartTime
144 */
145 double getEndTime() const noexcept;
146
147 /** Returns the timestamp of the event at a given index.
148 If the index is out-of-range, this will return 0.0
149 */
150 double getEventTime (int index) const noexcept;
151
152 //==============================================================================
153 /** Inserts a midi message into the sequence.
154
155 The index at which the new message gets inserted will depend on its timestamp,
156 because the sequence is kept sorted.
157
158 Remember to call updateMatchedPairs() after adding note-on events.
159
160 @param newMessage the new message to add (an internal copy will be made)
161 @param timeAdjustment an optional value to add to the timestamp of the message
162 that will be inserted
163 @see updateMatchedPairs
164 */
165 MidiEventHolder* addEvent (const MidiMessage& newMessage, double timeAdjustment = 0);
166
167 /** Inserts a midi message into the sequence.
168
169 The index at which the new message gets inserted will depend on its timestamp,
170 because the sequence is kept sorted.
171
172 Remember to call updateMatchedPairs() after adding note-on events.
173
174 @param newMessage the new message to add (an internal copy will be made)
175 @param timeAdjustment an optional value to add to the timestamp of the message
176 that will be inserted
177 @see updateMatchedPairs
178 */
179 MidiEventHolder* addEvent (MidiMessage&& newMessage, double timeAdjustment = 0);
180
181 /** Deletes one of the events in the sequence.
182
183 Remember to call updateMatchedPairs() after removing events.
184
185 @param index the index of the event to delete
186 @param deleteMatchingNoteUp whether to also remove the matching note-off
187 if the event you're removing is a note-on
188 */
189 void deleteEvent (int index, bool deleteMatchingNoteUp);
190
191 /** Merges another sequence into this one.
192 Remember to call updateMatchedPairs() after using this method.
193
194 @param other the sequence to add from
195 @param timeAdjustmentDelta an amount to add to the timestamps of the midi events
196 as they are read from the other sequence
197 @param firstAllowableDestTime events will not be added if their time is earlier
198 than this time. (This is after their time has been adjusted
199 by the timeAdjustmentDelta)
200 @param endOfAllowableDestTimes events will not be added if their time is equal to
201 or greater than this time. (This is after their time has
202 been adjusted by the timeAdjustmentDelta)
203 */
204 void addSequence (const MidiMessageSequence& other,
205 double timeAdjustmentDelta,
206 double firstAllowableDestTime,
207 double endOfAllowableDestTimes);
208
209 /** Merges another sequence into this one.
210 Remember to call updateMatchedPairs() after using this method.
211
212 @param other the sequence to add from
213 @param timeAdjustmentDelta an amount to add to the timestamps of the midi events
214 as they are read from the other sequence
215 */
216 void addSequence (const MidiMessageSequence& other,
217 double timeAdjustmentDelta);
218
219 //==============================================================================
220 /** Makes sure all the note-on and note-off pairs are up-to-date.
221
222 Call this after re-ordering messages or deleting/adding messages, and it
223 will scan the list and make sure all the note-offs in the MidiEventHolder
224 structures are pointing at the correct ones.
225 */
226 void updateMatchedPairs() noexcept;
227
228 /** Forces a sort of the sequence.
229 You may need to call this if you've manually modified the timestamps of some
230 events such that the overall order now needs updating.
231 */
232 void sort() noexcept;
233
234 //==============================================================================
235 /** Copies all the messages for a particular midi channel to another sequence.
236
237 @param channelNumberToExtract the midi channel to look for, in the range 1 to 16
238 @param destSequence the sequence that the chosen events should be copied to
239 @param alsoIncludeMetaEvents if true, any meta-events (which don't apply to a specific
240 channel) will also be copied across.
241 @see extractSysExMessages
242 */
243 void extractMidiChannelMessages (int channelNumberToExtract,
244 MidiMessageSequence& destSequence,
245 bool alsoIncludeMetaEvents) const;
246
247 /** Copies all midi sys-ex messages to another sequence.
248 @param destSequence this is the sequence to which any sys-exes in this sequence
249 will be added
250 @see extractMidiChannelMessages
251 */
252 void extractSysExMessages (MidiMessageSequence& destSequence) const;
253
254 /** Removes any messages in this sequence that have a specific midi channel.
255 @param channelNumberToRemove the midi channel to look for, in the range 1 to 16
256 */
257 void deleteMidiChannelMessages (int channelNumberToRemove);
258
259 /** Removes any sys-ex messages from this sequence. */
260 void deleteSysExMessages();
261
262 /** Adds an offset to the timestamps of all events in the sequence.
263 @param deltaTime the amount to add to each timestamp.
264 */
265 void addTimeToMessages (double deltaTime) noexcept;
266
267 //==============================================================================
268 /** Scans through the sequence to determine the state of any midi controllers at
269 a given time.
270
271 This will create a sequence of midi controller changes that can be
272 used to set all midi controllers to the state they would be in at the
273 specified time within this sequence.
274
275 As well as controllers, it will also recreate the midi program number
276 and pitch bend position.
277
278 @param channelNumber the midi channel to look for, in the range 1 to 16. Controllers
279 for other channels will be ignored.
280 @param time the time at which you want to find out the state - there are
281 no explicit units for this time measurement, it's the same units
282 as used for the timestamps of the messages
283 @param resultMessages an array to which midi controller-change messages will be added. This
284 will be the minimum number of controller changes to recreate the
285 state at the required time.
286 */
287 void createControllerUpdatesForTime (int channelNumber, double time,
288 Array<MidiMessage>& resultMessages);
289
290 //==============================================================================
291 /** Swaps this sequence with another one. */
292 void swapWith (MidiMessageSequence&) noexcept;
293
294private:
295 //==============================================================================
296 friend class MidiFile;
298
299 MidiEventHolder* addEvent (MidiEventHolder*, double);
300
301 JUCE_LEAK_DETECTOR (MidiMessageSequence)
302};
303
304} // namespace juce
305
306/** @}*/
Holds a resizable array of primitive or copy-by-value objects.
Definition juce_Array.h:60
Reads/writes standard midi format files.
Structure used to hold midi events in the sequence.
MidiMessage message
The message itself, whose timestamp is used to specify the event's time.
A sequence of timestamped midi messages.
Encapsulates a MIDI message.
An array designed for holding objects.
#define JUCE_API
This macro is added to all JUCE public class declarations.