26namespace MidiBufferHelpers
28 inline int getEventTime (
const void* d)
noexcept
30 return readUnaligned<int32> (d);
33 inline uint16 getEventDataSize (
const void* d)
noexcept
35 return readUnaligned<uint16> (
static_cast<const char*
> (d) +
sizeof (int32));
38 inline uint16 getEventTotalSize (
const void* d)
noexcept
40 return (uint16) (getEventDataSize (d) +
sizeof (int32) +
sizeof (uint16));
43 static int findActualEventLength (
const uint8* data,
int maxBytes)
noexcept
45 auto byte = (
unsigned int) *data;
47 if (
byte == 0xf0 ||
byte == 0xf7)
52 if (data[i++] == 0xf7)
64 return jmin (maxBytes, var.value + 2 + var.bytesUsed);
73 static uint8* findEventAfter (uint8* d, uint8* endData,
int samplePosition)
noexcept
75 while (d < endData && getEventTime (d) <= samplePosition)
76 d += getEventTotalSize (d);
85 data +=
sizeof (int32) +
sizeof (uint16) + size_t (MidiBufferHelpers::getEventDataSize (data));
98 return { data +
sizeof (int32) +
sizeof (uint16),
99 MidiBufferHelpers::getEventDataSize (data),
100 MidiBufferHelpers::getEventTime (data) };
106 addEvent (message, 0);
116 auto start = MidiBufferHelpers::findEventAfter (
data.
begin(),
data.
end(), startSample - 1);
117 auto end = MidiBufferHelpers::findEventAfter (start,
data.
end(), startSample + numSamples - 1);
129 auto numBytes = MidiBufferHelpers::findActualEventLength (
static_cast<const uint8*
> (newData), maxBytes);
134 if (std::numeric_limits<uint16>::max() < numBytes)
140 auto newItemSize = (size_t) numBytes +
sizeof (int32) +
sizeof (uint16);
146 writeUnaligned<int32> (d, sampleNumber);
148 writeUnaligned<uint16> (d,
static_cast<uint16
> (numBytes));
149 d +=
sizeof (uint16);
150 memcpy (d, newData, (
size_t) numBytes);
156 int startSample,
int numSamples,
int sampleDeltaToAdd)
160 const auto metadata = *i;
162 if (metadata.samplePosition >= startSample + numSamples && numSamples >= 0)
165 addEvent (metadata.data, metadata.numBytes, metadata.samplePosition + sampleDeltaToAdd);
175 d += MidiBufferHelpers::getEventTotalSize (d);
194 auto nextOne = d + MidiBufferHelpers::getEventTotalSize (d);
196 if (nextOne >= endData)
197 return MidiBufferHelpers::getEventTime (d);
212JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE (
"-Wdeprecated-declarations")
213JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)
216 : buffer (b), iterator (b.data.begin())
222 iterator = buffer.findNextSamplePosition (samplePosition);
227 if (iterator == buffer.cend())
230 const auto metadata = *iterator++;
231 midiData = metadata.data;
232 numBytes = metadata.numBytes;
233 samplePosition = metadata.samplePosition;
239 if (iterator == buffer.cend())
242 const auto metadata = *iterator++;
243 result = metadata.getMessage();
244 samplePosition = metadata.samplePosition;
248JUCE_END_IGNORE_WARNINGS_MSVC
249JUCE_END_IGNORE_WARNINGS_GCC_LIKE
255struct MidiBufferTest final :
public UnitTest
258 :
UnitTest (
"MidiBuffer", UnitTestCategories::midi)
261 void runTest()
override
263 beginTest (
"Clear messages");
267 const auto testBuffer = [&]
278 auto buffer = testBuffer;
279 buffer.
clear (10, 0);
284 auto buffer = testBuffer;
285 buffer.
clear (10, 1);
290 auto buffer = testBuffer;
291 buffer.
clear (10, 10);
296 auto buffer = testBuffer;
297 buffer.
clear (10, 20);
302 auto buffer = testBuffer;
303 buffer.
clear (10, 30);
308 auto buffer = testBuffer;
309 buffer.
clear (10, 300);
316static MidiBufferTest midiBufferTest;
void ensureStorageAllocated(int minNumElements)
int size() const noexcept
void removeRange(int startIndex, int numberToRemove)
ElementType * begin() noexcept
ElementType * end() noexcept
void insertMultiple(int indexToInsertAt, ParameterType newElement, int numberOfTimesToInsertIt)
MidiBufferIterator & operator++() noexcept
reference operator*() const noexcept
void setNextSamplePosition(int samplePosition) noexcept
bool getNextEvent(MidiMessage &result, int &samplePosition) noexcept
int getFirstEventTime() const noexcept
int getLastEventTime() const noexcept
void ensureSize(size_t minimumNumBytes)
int getNumEvents() const noexcept
MidiBufferIterator findNextSamplePosition(int samplePosition) const noexcept
MidiBufferIterator cend() const noexcept
bool isEmpty() const noexcept
void swapWith(MidiBuffer &) noexcept
bool addEvent(const MidiMessage &midiMessage, int sampleNumber)
MidiBuffer() noexcept=default
void addEvents(const MidiBuffer &otherBuffer, int startSample, int numSamples, int sampleDeltaToAdd)
MidiBufferIterator end() const noexcept
const uint8 * getRawData() const noexcept
static MidiMessage noteOn(int channel, int noteNumber, float velocity) noexcept
static int getMessageLengthFromFirstByte(uint8 firstByte) noexcept
static VariableLengthValue readVariableLengthValue(const uint8 *data, int maxBytesToUse) noexcept
int getRawDataSize() const noexcept