OpenShot Library | libopenshot-audio  0.1.9
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 
27 namespace 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 {
43 public:
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. */
76  ~MidiEventHolder();
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 
294 private:
295  //==============================================================================
296  friend class MidiFile;
298 
299  MidiEventHolder* addEvent (MidiEventHolder*, double);
300 
301  JUCE_LEAK_DETECTOR (MidiMessageSequence)
302 };
303 
304 } // namespace juce
305 
306 /** @}*/
#define JUCE_API
This macro is added to all JUCE public class declarations.
Reads/writes standard midi format files.
Definition: juce_MidiFile.h:45
Encapsulates a MIDI message.
MidiMessage message
The message itself, whose timestamp is used to specify the event&#39;s time.
Holds a resizable array of primitive or copy-by-value objects.
Definition: juce_Array.h:59
A sequence of timestamped midi messages.
Structure used to hold midi events in the sequence.
An array designed for holding objects.