git subrepo clone --branch=sono6good https://github.com/essej/JUCE.git deps/juce
subrepo: subdir: "deps/juce" merged: "b13f9084e" upstream: origin: "https://github.com/essej/JUCE.git" branch: "sono6good" commit: "b13f9084e" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596"
This commit is contained in:
345
deps/juce/modules/juce_audio_basics/midi/juce_MidiBuffer.h
vendored
Normal file
345
deps/juce/modules/juce_audio_basics/midi/juce_MidiBuffer.h
vendored
Normal file
@ -0,0 +1,345 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2020 - Raw Material Software Limited
|
||||
|
||||
JUCE is an open source library subject to commercial or open-source
|
||||
licensing.
|
||||
|
||||
The code included in this file is provided under the terms of the ISC license
|
||||
http://www.isc.org/downloads/software-support-policy/isc-license. Permission
|
||||
To use, copy, modify, and/or distribute this software for any purpose with or
|
||||
without fee is hereby granted provided that the above copyright notice and
|
||||
this permission notice appear in all copies.
|
||||
|
||||
JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
|
||||
EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
|
||||
DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A view of MIDI message data stored in a contiguous buffer.
|
||||
|
||||
Instances of this class do *not* own the midi data bytes that they point to.
|
||||
Instead, they expect the midi data to live in a separate buffer that outlives
|
||||
the MidiMessageMetadata instance.
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
struct MidiMessageMetadata final
|
||||
{
|
||||
MidiMessageMetadata() noexcept = default;
|
||||
|
||||
MidiMessageMetadata (const uint8* dataIn, int numBytesIn, int positionIn) noexcept
|
||||
: data (dataIn), numBytes (numBytesIn), samplePosition (positionIn)
|
||||
{
|
||||
}
|
||||
|
||||
/** Constructs a new MidiMessage instance from the data that this object is viewing.
|
||||
|
||||
Note that MidiMessage owns its data storage, whereas MidiMessageMetadata does not.
|
||||
*/
|
||||
MidiMessage getMessage() const { return MidiMessage (data, numBytes, samplePosition); }
|
||||
|
||||
/** Pointer to the first byte of a MIDI message. */
|
||||
const uint8* data = nullptr;
|
||||
|
||||
/** The number of bytes in the MIDI message. */
|
||||
int numBytes = 0;
|
||||
|
||||
/** The MIDI message's timestamp. */
|
||||
int samplePosition = 0;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
An iterator to move over contiguous raw MIDI data, which Allows iterating
|
||||
over a MidiBuffer using C++11 range-for syntax.
|
||||
|
||||
In the following example, we log all three-byte messages in a midi buffer.
|
||||
@code
|
||||
void processBlock (AudioBuffer<float>&, MidiBuffer& midiBuffer) override
|
||||
{
|
||||
for (const MidiMessageMetadata metadata : midiBuffer)
|
||||
if (metadata.numBytes == 3)
|
||||
Logger::writeToLog (metadata.getMessage().getDescription());
|
||||
}
|
||||
@endcode
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API MidiBufferIterator
|
||||
{
|
||||
using Ptr = const uint8*;
|
||||
|
||||
public:
|
||||
MidiBufferIterator() = default;
|
||||
|
||||
/** Constructs an iterator pointing at the message starting at the byte `dataIn`.
|
||||
`dataIn` must point to the start of a valid MIDI message. If it does not,
|
||||
calling other member functions on the iterator will result in undefined
|
||||
behaviour.
|
||||
*/
|
||||
explicit MidiBufferIterator (const uint8* dataIn) noexcept
|
||||
: data (dataIn)
|
||||
{
|
||||
}
|
||||
|
||||
using difference_type = std::iterator_traits<Ptr>::difference_type;
|
||||
using value_type = MidiMessageMetadata;
|
||||
using reference = MidiMessageMetadata;
|
||||
using pointer = void;
|
||||
using iterator_category = std::input_iterator_tag;
|
||||
|
||||
/** Make this iterator point to the next message in the buffer. */
|
||||
MidiBufferIterator& operator++() noexcept;
|
||||
|
||||
/** Create a copy of this object, make this iterator point to the next message in
|
||||
the buffer, then return the copy.
|
||||
*/
|
||||
MidiBufferIterator operator++ (int) noexcept;
|
||||
|
||||
/** Return true if this iterator points to the same message as another
|
||||
iterator instance, otherwise return false.
|
||||
*/
|
||||
bool operator== (const MidiBufferIterator& other) const noexcept { return data == other.data; }
|
||||
|
||||
/** Return false if this iterator points to the same message as another
|
||||
iterator instance, otherwise returns true.
|
||||
*/
|
||||
bool operator!= (const MidiBufferIterator& other) const noexcept { return ! operator== (other); }
|
||||
|
||||
/** Return an instance of MidiMessageMetadata which describes the message to which
|
||||
the iterator is currently pointing.
|
||||
*/
|
||||
reference operator*() const noexcept;
|
||||
|
||||
private:
|
||||
Ptr data = nullptr;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Holds a sequence of time-stamped midi events.
|
||||
|
||||
Analogous to the AudioBuffer, this holds a set of midi events with
|
||||
integer time-stamps. The buffer is kept sorted in order of the time-stamps.
|
||||
|
||||
If you're working with a sequence of midi events that may need to be manipulated
|
||||
or read/written to a midi file, then MidiMessageSequence is probably a more
|
||||
appropriate container. MidiBuffer is designed for lower-level streams of raw
|
||||
midi data.
|
||||
|
||||
@see MidiMessage
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API MidiBuffer
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an empty MidiBuffer. */
|
||||
MidiBuffer() noexcept = default;
|
||||
|
||||
/** Creates a MidiBuffer containing a single midi message. */
|
||||
explicit MidiBuffer (const MidiMessage& message) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Removes all events from the buffer. */
|
||||
void clear() noexcept;
|
||||
|
||||
/** Removes all events between two times from the buffer.
|
||||
|
||||
All events for which (start <= event position < start + numSamples) will
|
||||
be removed.
|
||||
*/
|
||||
void clear (int start, int numSamples);
|
||||
|
||||
/** Returns true if the buffer is empty.
|
||||
To actually retrieve the events, use a MidiBufferIterator object
|
||||
*/
|
||||
bool isEmpty() const noexcept;
|
||||
|
||||
/** Counts the number of events in the buffer.
|
||||
|
||||
This is actually quite a slow operation, as it has to iterate through all
|
||||
the events, so you might prefer to call isEmpty() if that's all you need
|
||||
to know.
|
||||
*/
|
||||
int getNumEvents() const noexcept;
|
||||
|
||||
/** Adds an event to the buffer.
|
||||
|
||||
The sample number will be used to determine the position of the event in
|
||||
the buffer, which is always kept sorted. The MidiMessage's timestamp is
|
||||
ignored.
|
||||
|
||||
If an event is added whose sample position is the same as one or more events
|
||||
already in the buffer, the new event will be placed after the existing ones.
|
||||
|
||||
To retrieve events, use a MidiBufferIterator object.
|
||||
|
||||
Returns true on success, or false on failure.
|
||||
*/
|
||||
bool addEvent (const MidiMessage& midiMessage, int sampleNumber);
|
||||
|
||||
/** Adds an event to the buffer from raw midi data.
|
||||
|
||||
The sample number will be used to determine the position of the event in
|
||||
the buffer, which is always kept sorted.
|
||||
|
||||
If an event is added whose sample position is the same as one or more events
|
||||
already in the buffer, the new event will be placed after the existing ones.
|
||||
|
||||
The event data will be inspected to calculate the number of bytes in length that
|
||||
the midi event really takes up, so maxBytesOfMidiData may be longer than the data
|
||||
that actually gets stored. E.g. if you pass in a note-on and a length of 4 bytes,
|
||||
it'll actually only store 3 bytes. If the midi data is invalid, it might not
|
||||
add an event at all.
|
||||
|
||||
To retrieve events, use a MidiBufferIterator object.
|
||||
|
||||
Returns true on success, or false on failure.
|
||||
*/
|
||||
bool addEvent (const void* rawMidiData,
|
||||
int maxBytesOfMidiData,
|
||||
int sampleNumber);
|
||||
|
||||
/** Adds some events from another buffer to this one.
|
||||
|
||||
@param otherBuffer the buffer containing the events you want to add
|
||||
@param startSample the lowest sample number in the source buffer for which
|
||||
events should be added. Any source events whose timestamp is
|
||||
less than this will be ignored
|
||||
@param numSamples the valid range of samples from the source buffer for which
|
||||
events should be added - i.e. events in the source buffer whose
|
||||
timestamp is greater than or equal to (startSample + numSamples)
|
||||
will be ignored. If this value is less than 0, all events after
|
||||
startSample will be taken.
|
||||
@param sampleDeltaToAdd a value which will be added to the source timestamps of the events
|
||||
that are added to this buffer
|
||||
*/
|
||||
void addEvents (const MidiBuffer& otherBuffer,
|
||||
int startSample,
|
||||
int numSamples,
|
||||
int sampleDeltaToAdd);
|
||||
|
||||
/** Returns the sample number of the first event in the buffer.
|
||||
If the buffer's empty, this will just return 0.
|
||||
*/
|
||||
int getFirstEventTime() const noexcept;
|
||||
|
||||
/** Returns the sample number of the last event in the buffer.
|
||||
If the buffer's empty, this will just return 0.
|
||||
*/
|
||||
int getLastEventTime() const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Exchanges the contents of this buffer with another one.
|
||||
|
||||
This is a quick operation, because no memory allocating or copying is done, it
|
||||
just swaps the internal state of the two buffers.
|
||||
*/
|
||||
void swapWith (MidiBuffer&) noexcept;
|
||||
|
||||
/** Preallocates some memory for the buffer to use.
|
||||
This helps to avoid needing to reallocate space when the buffer has messages
|
||||
added to it.
|
||||
*/
|
||||
void ensureSize (size_t minimumNumBytes);
|
||||
|
||||
/** Get a read-only iterator pointing to the beginning of this buffer. */
|
||||
MidiBufferIterator begin() const noexcept { return cbegin(); }
|
||||
|
||||
/** Get a read-only iterator pointing one past the end of this buffer. */
|
||||
MidiBufferIterator end() const noexcept { return cend(); }
|
||||
|
||||
/** Get a read-only iterator pointing to the beginning of this buffer. */
|
||||
MidiBufferIterator cbegin() const noexcept { return MidiBufferIterator (data.begin()); }
|
||||
|
||||
/** Get a read-only iterator pointing one past the end of this buffer. */
|
||||
MidiBufferIterator cend() const noexcept { return MidiBufferIterator (data.end()); }
|
||||
|
||||
/** Get an iterator pointing to the first event with a timestamp greater-than or
|
||||
equal-to `samplePosition`.
|
||||
*/
|
||||
MidiBufferIterator findNextSamplePosition (int samplePosition) const noexcept;
|
||||
|
||||
//==============================================================================
|
||||
#ifndef DOXYGEN
|
||||
/** This class is now deprecated in favour of MidiBufferIterator.
|
||||
|
||||
Used to iterate through the events in a MidiBuffer.
|
||||
|
||||
Note that altering the buffer while an iterator is using it will produce
|
||||
undefined behaviour.
|
||||
|
||||
@see MidiBuffer
|
||||
*/
|
||||
class [[deprecated]] JUCE_API Iterator
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an Iterator for this MidiBuffer. */
|
||||
Iterator (const MidiBuffer& b) noexcept;
|
||||
|
||||
//==============================================================================
|
||||
/** Repositions the iterator so that the next event retrieved will be the first
|
||||
one whose sample position is at greater than or equal to the given position.
|
||||
*/
|
||||
void setNextSamplePosition (int samplePosition) noexcept;
|
||||
|
||||
/** Retrieves a copy of the next event from the buffer.
|
||||
|
||||
@param result on return, this will be the message. The MidiMessage's timestamp
|
||||
is set to the same value as samplePosition.
|
||||
@param samplePosition on return, this will be the position of the event, as a
|
||||
sample index in the buffer
|
||||
@returns true if an event was found, or false if the iterator has reached
|
||||
the end of the buffer
|
||||
*/
|
||||
bool getNextEvent (MidiMessage& result,
|
||||
int& samplePosition) noexcept;
|
||||
|
||||
/** Retrieves the next event from the buffer.
|
||||
|
||||
@param midiData on return, this pointer will be set to a block of data containing
|
||||
the midi message. Note that to make it fast, this is a pointer
|
||||
directly into the MidiBuffer's internal data, so is only valid
|
||||
temporarily until the MidiBuffer is altered.
|
||||
@param numBytesOfMidiData on return, this is the number of bytes of data used by the
|
||||
midi message
|
||||
@param samplePosition on return, this will be the position of the event, as a
|
||||
sample index in the buffer
|
||||
@returns true if an event was found, or false if the iterator has reached
|
||||
the end of the buffer
|
||||
*/
|
||||
bool getNextEvent (const uint8* &midiData,
|
||||
int& numBytesOfMidiData,
|
||||
int& samplePosition) noexcept;
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
const MidiBuffer& buffer;
|
||||
MidiBufferIterator iterator;
|
||||
};
|
||||
#endif
|
||||
|
||||
/** The raw data holding this buffer.
|
||||
Obviously access to this data is provided at your own risk. Its internal format could
|
||||
change in future, so don't write code that relies on it!
|
||||
*/
|
||||
Array<uint8> data;
|
||||
|
||||
private:
|
||||
JUCE_LEAK_DETECTOR (MidiBuffer)
|
||||
};
|
||||
|
||||
} // namespace juce
|
Reference in New Issue
Block a user