mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Added some move-operators and iterators to MidiMessageSequence
This commit is contained in:
parent
680a0d671c
commit
20d0b3775f
2 changed files with 114 additions and 96 deletions
|
|
@ -20,6 +20,12 @@
|
|||
==============================================================================
|
||||
*/
|
||||
|
||||
|
||||
MidiMessageSequence::MidiEventHolder::MidiEventHolder (const MidiMessage& mm) : message (mm) {}
|
||||
MidiMessageSequence::MidiEventHolder::MidiEventHolder (MidiMessage&& mm) : message (static_cast<MidiMessage&&> (mm)) {}
|
||||
MidiMessageSequence::MidiEventHolder::~MidiEventHolder() {}
|
||||
|
||||
//==============================================================================
|
||||
MidiMessageSequence::MidiMessageSequence()
|
||||
{
|
||||
}
|
||||
|
|
@ -37,15 +43,25 @@ MidiMessageSequence& MidiMessageSequence::operator= (const MidiMessageSequence&
|
|||
return *this;
|
||||
}
|
||||
|
||||
void MidiMessageSequence::swapWith (MidiMessageSequence& other) noexcept
|
||||
MidiMessageSequence::MidiMessageSequence (MidiMessageSequence&& other) noexcept
|
||||
: list (static_cast<OwnedArray<MidiEventHolder>&&> (other.list))
|
||||
{}
|
||||
|
||||
MidiMessageSequence& MidiMessageSequence::operator= (MidiMessageSequence&& other) noexcept
|
||||
{
|
||||
list.swapWith (other.list);
|
||||
list = static_cast<OwnedArray<MidiEventHolder>&&> (other.list);
|
||||
return *this;
|
||||
}
|
||||
|
||||
MidiMessageSequence::~MidiMessageSequence()
|
||||
{
|
||||
}
|
||||
|
||||
void MidiMessageSequence::swapWith (MidiMessageSequence& other) noexcept
|
||||
{
|
||||
list.swapWith (other.list);
|
||||
}
|
||||
|
||||
void MidiMessageSequence::clear()
|
||||
{
|
||||
list.clear();
|
||||
|
|
@ -56,34 +72,37 @@ int MidiMessageSequence::getNumEvents() const noexcept
|
|||
return list.size();
|
||||
}
|
||||
|
||||
MidiMessageSequence::MidiEventHolder* MidiMessageSequence::getEventPointer (const int index) const noexcept
|
||||
MidiMessageSequence::MidiEventHolder* MidiMessageSequence::getEventPointer (int index) const noexcept
|
||||
{
|
||||
return list [index];
|
||||
return list[index];
|
||||
}
|
||||
|
||||
double MidiMessageSequence::getTimeOfMatchingKeyUp (const int index) const noexcept
|
||||
MidiMessageSequence::MidiEventHolder** MidiMessageSequence::begin() const noexcept { return list.begin(); }
|
||||
MidiMessageSequence::MidiEventHolder** MidiMessageSequence::end() const noexcept { return list.end(); }
|
||||
|
||||
double MidiMessageSequence::getTimeOfMatchingKeyUp (int index) const noexcept
|
||||
{
|
||||
if (const MidiEventHolder* const meh = list [index])
|
||||
if (auto* meh = list[index])
|
||||
if (meh->noteOffObject != nullptr)
|
||||
return meh->noteOffObject->message.getTimeStamp();
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
int MidiMessageSequence::getIndexOfMatchingKeyUp (const int index) const noexcept
|
||||
int MidiMessageSequence::getIndexOfMatchingKeyUp (int index) const noexcept
|
||||
{
|
||||
if (const MidiEventHolder* const meh = list [index])
|
||||
if (auto* meh = list [index])
|
||||
return list.indexOf (meh->noteOffObject);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int MidiMessageSequence::getIndexOf (const MidiEventHolder* const event) const noexcept
|
||||
int MidiMessageSequence::getIndexOf (const MidiEventHolder* event) const noexcept
|
||||
{
|
||||
return list.indexOf (event);
|
||||
}
|
||||
|
||||
int MidiMessageSequence::getNextIndexAtTime (const double timeStamp) const noexcept
|
||||
int MidiMessageSequence::getNextIndexAtTime (double timeStamp) const noexcept
|
||||
{
|
||||
const int numEvents = list.size();
|
||||
|
||||
|
|
@ -108,32 +127,38 @@ double MidiMessageSequence::getEndTime() const noexcept
|
|||
|
||||
double MidiMessageSequence::getEventTime (const int index) const noexcept
|
||||
{
|
||||
if (const MidiEventHolder* const meh = list [index])
|
||||
if (auto* meh = list [index])
|
||||
return meh->message.getTimeStamp();
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
MidiMessageSequence::MidiEventHolder* MidiMessageSequence::addEvent (const MidiMessage& newMessage,
|
||||
double timeAdjustment)
|
||||
MidiMessageSequence::MidiEventHolder* MidiMessageSequence::addEvent (MidiEventHolder* newEvent, double timeAdjustment)
|
||||
{
|
||||
MidiEventHolder* const newOne = new MidiEventHolder (newMessage);
|
||||
|
||||
timeAdjustment += newMessage.getTimeStamp();
|
||||
newOne->message.setTimeStamp (timeAdjustment);
|
||||
newEvent->message.addToTimeStamp (timeAdjustment);
|
||||
auto time = newEvent->message.getTimeStamp();
|
||||
|
||||
int i;
|
||||
for (i = list.size(); --i >= 0;)
|
||||
if (list.getUnchecked(i)->message.getTimeStamp() <= timeAdjustment)
|
||||
if (list.getUnchecked(i)->message.getTimeStamp() <= time)
|
||||
break;
|
||||
|
||||
list.insert (i + 1, newOne);
|
||||
return newOne;
|
||||
list.insert (i + 1, newEvent);
|
||||
return newEvent;
|
||||
}
|
||||
|
||||
void MidiMessageSequence::deleteEvent (const int index,
|
||||
const bool deleteMatchingNoteUp)
|
||||
MidiMessageSequence::MidiEventHolder* MidiMessageSequence::addEvent (const MidiMessage& newMessage, double timeAdjustment)
|
||||
{
|
||||
return addEvent (new MidiEventHolder (newMessage), timeAdjustment);
|
||||
}
|
||||
|
||||
MidiMessageSequence::MidiEventHolder* MidiMessageSequence::addEvent (MidiMessage&& newMessage, double timeAdjustment)
|
||||
{
|
||||
return addEvent (new MidiEventHolder (static_cast<MidiMessage&&> (newMessage)), timeAdjustment);
|
||||
}
|
||||
|
||||
void MidiMessageSequence::deleteEvent (int index, bool deleteMatchingNoteUp)
|
||||
{
|
||||
if (isPositiveAndBelow (index, list.size()))
|
||||
{
|
||||
|
|
@ -144,23 +169,11 @@ void MidiMessageSequence::deleteEvent (const int index,
|
|||
}
|
||||
}
|
||||
|
||||
struct MidiMessageSequenceSorter
|
||||
{
|
||||
static int compareElements (const MidiMessageSequence::MidiEventHolder* const first,
|
||||
const MidiMessageSequence::MidiEventHolder* const second) noexcept
|
||||
{
|
||||
const double diff = first->message.getTimeStamp() - second->message.getTimeStamp();
|
||||
return (diff > 0) - (diff < 0);
|
||||
}
|
||||
};
|
||||
|
||||
void MidiMessageSequence::addSequence (const MidiMessageSequence& other, double timeAdjustment)
|
||||
{
|
||||
for (int i = 0; i < other.list.size(); ++i)
|
||||
for (auto* m : other)
|
||||
{
|
||||
const MidiMessage& m = other.list.getUnchecked(i)->message;
|
||||
|
||||
MidiEventHolder* const newOne = new MidiEventHolder (m);
|
||||
auto newOne = new MidiEventHolder (m->message);
|
||||
newOne->message.addToTimeStamp (timeAdjustment);
|
||||
list.add (newOne);
|
||||
}
|
||||
|
|
@ -173,16 +186,14 @@ void MidiMessageSequence::addSequence (const MidiMessageSequence& other,
|
|||
double firstAllowableTime,
|
||||
double endOfAllowableDestTimes)
|
||||
{
|
||||
for (int i = 0; i < other.list.size(); ++i)
|
||||
for (auto* m : other)
|
||||
{
|
||||
const MidiMessage& m = other.list.getUnchecked(i)->message;
|
||||
const double t = m.getTimeStamp() + timeAdjustment;
|
||||
auto t = m->message.getTimeStamp() + timeAdjustment;
|
||||
|
||||
if (t >= firstAllowableTime && t < endOfAllowableDestTimes)
|
||||
{
|
||||
MidiEventHolder* const newOne = new MidiEventHolder (m);
|
||||
auto newOne = new MidiEventHolder (m->message);
|
||||
newOne->message.setTimeStamp (t);
|
||||
|
||||
list.add (newOne);
|
||||
}
|
||||
}
|
||||
|
|
@ -190,7 +201,16 @@ void MidiMessageSequence::addSequence (const MidiMessageSequence& other,
|
|||
sort();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
struct MidiMessageSequenceSorter
|
||||
{
|
||||
static int compareElements (const MidiMessageSequence::MidiEventHolder* first,
|
||||
const MidiMessageSequence::MidiEventHolder* second) noexcept
|
||||
{
|
||||
auto diff = first->message.getTimeStamp() - second->message.getTimeStamp();
|
||||
return (diff > 0) - (diff < 0);
|
||||
}
|
||||
};
|
||||
|
||||
void MidiMessageSequence::sort() noexcept
|
||||
{
|
||||
MidiMessageSequenceSorter sorter;
|
||||
|
|
@ -201,30 +221,32 @@ void MidiMessageSequence::updateMatchedPairs() noexcept
|
|||
{
|
||||
for (int i = 0; i < list.size(); ++i)
|
||||
{
|
||||
MidiEventHolder* const meh = list.getUnchecked(i);
|
||||
const MidiMessage& m1 = meh->message;
|
||||
auto* meh = list.getUnchecked(i);
|
||||
auto& m1 = meh->message;
|
||||
|
||||
if (m1.isNoteOn())
|
||||
{
|
||||
meh->noteOffObject = nullptr;
|
||||
const int note = m1.getNoteNumber();
|
||||
const int chan = m1.getChannel();
|
||||
const int len = list.size();
|
||||
auto note = m1.getNoteNumber();
|
||||
auto chan = m1.getChannel();
|
||||
auto len = list.size();
|
||||
|
||||
for (int j = i + 1; j < len; ++j)
|
||||
{
|
||||
const MidiMessage& m = list.getUnchecked(j)->message;
|
||||
auto* meh2 = list.getUnchecked(j);
|
||||
auto& m = meh2->message;
|
||||
|
||||
if (m.getNoteNumber() == note && m.getChannel() == chan)
|
||||
{
|
||||
if (m.isNoteOff())
|
||||
{
|
||||
meh->noteOffObject = list[j];
|
||||
meh->noteOffObject = meh2;
|
||||
break;
|
||||
}
|
||||
else if (m.isNoteOn())
|
||||
|
||||
if (m.isNoteOn())
|
||||
{
|
||||
MidiEventHolder* const newEvent = new MidiEventHolder (MidiMessage::noteOff (chan, note));
|
||||
auto newEvent = new MidiEventHolder (MidiMessage::noteOff (chan, note));
|
||||
list.insert (j, newEvent);
|
||||
newEvent->message.setTimeStamp (m.getTimeStamp());
|
||||
meh->noteOffObject = newEvent;
|
||||
|
|
@ -236,13 +258,11 @@ void MidiMessageSequence::updateMatchedPairs() noexcept
|
|||
}
|
||||
}
|
||||
|
||||
void MidiMessageSequence::addTimeToMessages (const double delta) noexcept
|
||||
void MidiMessageSequence::addTimeToMessages (double delta) noexcept
|
||||
{
|
||||
for (int i = list.size(); --i >= 0;)
|
||||
{
|
||||
MidiMessage& mm = list.getUnchecked(i)->message;
|
||||
mm.setTimeStamp (mm.getTimeStamp() + delta);
|
||||
}
|
||||
if (delta != 0)
|
||||
for (auto* m : list)
|
||||
m->message.addToTimeStamp (delta);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
@ -250,24 +270,17 @@ void MidiMessageSequence::extractMidiChannelMessages (const int channelNumberToE
|
|||
MidiMessageSequence& destSequence,
|
||||
const bool alsoIncludeMetaEvents) const
|
||||
{
|
||||
for (int i = 0; i < list.size(); ++i)
|
||||
{
|
||||
const MidiMessage& mm = list.getUnchecked(i)->message;
|
||||
|
||||
if (mm.isForChannel (channelNumberToExtract) || (alsoIncludeMetaEvents && mm.isMetaEvent()))
|
||||
destSequence.addEvent (mm);
|
||||
}
|
||||
for (auto* meh : list)
|
||||
if (meh->message.isForChannel (channelNumberToExtract)
|
||||
|| (alsoIncludeMetaEvents && meh->message.isMetaEvent()))
|
||||
destSequence.addEvent (meh->message);
|
||||
}
|
||||
|
||||
void MidiMessageSequence::extractSysExMessages (MidiMessageSequence& destSequence) const
|
||||
{
|
||||
for (int i = 0; i < list.size(); ++i)
|
||||
{
|
||||
const MidiMessage& mm = list.getUnchecked(i)->message;
|
||||
|
||||
if (mm.isSysEx())
|
||||
destSequence.addEvent (mm);
|
||||
}
|
||||
for (auto* meh : list)
|
||||
if (meh->message.isSysEx())
|
||||
destSequence.addEvent (meh->message);
|
||||
}
|
||||
|
||||
void MidiMessageSequence::deleteMidiChannelMessages (const int channelNumberToRemove)
|
||||
|
|
@ -285,15 +298,15 @@ void MidiMessageSequence::deleteSysExMessages()
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
void MidiMessageSequence::createControllerUpdatesForTime (const int channelNumber, const double time, Array<MidiMessage>& dest)
|
||||
void MidiMessageSequence::createControllerUpdatesForTime (int channelNumber, double time, Array<MidiMessage>& dest)
|
||||
{
|
||||
bool doneProg = false;
|
||||
bool donePitchWheel = false;
|
||||
bool doneControllers[128] = { 0 };
|
||||
bool doneControllers[128] = {};
|
||||
|
||||
for (int i = list.size(); --i >= 0;)
|
||||
{
|
||||
const MidiMessage& mm = list.getUnchecked(i)->message;
|
||||
auto& mm = list.getUnchecked(i)->message;
|
||||
|
||||
if (mm.isForChannel (channelNumber) && mm.getTimeStamp() <= time)
|
||||
{
|
||||
|
|
@ -321,14 +334,3 @@ void MidiMessageSequence::createControllerUpdatesForTime (const int channelNumbe
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
MidiMessageSequence::MidiEventHolder::MidiEventHolder (const MidiMessage& mm)
|
||||
: message (mm), noteOffObject (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
MidiMessageSequence::MidiEventHolder::~MidiEventHolder()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,16 +46,10 @@ public:
|
|||
MidiMessageSequence& operator= (const MidiMessageSequence&);
|
||||
|
||||
/** Move constructor */
|
||||
MidiMessageSequence (MidiMessageSequence&& other) noexcept
|
||||
: list (static_cast<OwnedArray<MidiEventHolder>&&> (other.list))
|
||||
{}
|
||||
MidiMessageSequence (MidiMessageSequence&&) noexcept;
|
||||
|
||||
/** Move assignment operator */
|
||||
MidiMessageSequence& operator= (MidiMessageSequence&& other) noexcept
|
||||
{
|
||||
list = static_cast<OwnedArray<MidiEventHolder>&&> (other.list);
|
||||
return *this;
|
||||
}
|
||||
MidiMessageSequence& operator= (MidiMessageSequence&&) noexcept;
|
||||
|
||||
/** Destructor. */
|
||||
~MidiMessageSequence();
|
||||
|
|
@ -86,12 +80,13 @@ public:
|
|||
note-offs up-to-date after events have been moved around in the sequence
|
||||
or deleted.
|
||||
*/
|
||||
MidiEventHolder* noteOffObject;
|
||||
MidiEventHolder* noteOffObject = nullptr;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
friend class MidiMessageSequence;
|
||||
MidiEventHolder (const MidiMessage&);
|
||||
MidiEventHolder (MidiMessage&&);
|
||||
JUCE_LEAK_DETECTOR (MidiEventHolder)
|
||||
};
|
||||
|
||||
|
|
@ -105,6 +100,12 @@ public:
|
|||
/** Returns a pointer to one of the events. */
|
||||
MidiEventHolder* getEventPointer (int index) const noexcept;
|
||||
|
||||
/** Iterator for the list of MidiEventHolders */
|
||||
MidiEventHolder** begin() const noexcept;
|
||||
|
||||
/** Iterator for the list of MidiEventHolders */
|
||||
MidiEventHolder** end() const noexcept;
|
||||
|
||||
/** Returns the time of the note-up that matches the note-on at this index.
|
||||
If the event at this index isn't a note-on, it'll just return 0.
|
||||
@see MidiMessageSequence::MidiEventHolder::noteOffObject
|
||||
|
|
@ -155,8 +156,21 @@ public:
|
|||
that will be inserted
|
||||
@see updateMatchedPairs
|
||||
*/
|
||||
MidiEventHolder* addEvent (const MidiMessage& newMessage,
|
||||
double timeAdjustment = 0);
|
||||
MidiEventHolder* addEvent (const MidiMessage& newMessage, double timeAdjustment = 0);
|
||||
|
||||
/** Inserts a midi message into the sequence.
|
||||
|
||||
The index at which the new message gets inserted will depend on its timestamp,
|
||||
because the sequence is kept sorted.
|
||||
|
||||
Remember to call updateMatchedPairs() after adding note-on events.
|
||||
|
||||
@param newMessage the new message to add (an internal copy will be made)
|
||||
@param timeAdjustment an optional value to add to the timestamp of the message
|
||||
that will be inserted
|
||||
@see updateMatchedPairs
|
||||
*/
|
||||
MidiEventHolder* addEvent (MidiMessage&& newMessage, double timeAdjustment = 0);
|
||||
|
||||
/** Deletes one of the events in the sequence.
|
||||
|
||||
|
|
@ -276,5 +290,7 @@ private:
|
|||
friend class MidiFile;
|
||||
OwnedArray<MidiEventHolder> list;
|
||||
|
||||
MidiEventHolder* addEvent (MidiEventHolder*, double);
|
||||
|
||||
JUCE_LEAK_DETECTOR (MidiMessageSequence)
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue