LMMS
Loading...
Searching...
No Matches
juce_MidiBuffer.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2022 - Raw Material Software Limited
6
7 JUCE is an open source library subject to commercial or open-source
8 licensing.
9
10 The code included in this file is provided under the terms of the ISC license
11 http://www.isc.org/downloads/software-support-policy/isc-license. Permission
12 To use, copy, modify, and/or distribute this software for any purpose with or
13 without fee is hereby granted provided that the above copyright notice and
14 this permission notice appear in all copies.
15
16 JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
17 EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
18 DISCLAIMED.
19
20 ==============================================================================
21*/
22
23namespace juce
24{
25
27{
28 inline int getEventTime (const void* d) noexcept
29 {
30 return readUnaligned<int32> (d);
31 }
32
33 inline uint16 getEventDataSize (const void* d) noexcept
34 {
35 return readUnaligned<uint16> (static_cast<const char*> (d) + sizeof (int32));
36 }
37
38 inline uint16 getEventTotalSize (const void* d) noexcept
39 {
40 return (uint16) (getEventDataSize (d) + sizeof (int32) + sizeof (uint16));
41 }
42
43 static int findActualEventLength (const uint8* data, int maxBytes) noexcept
44 {
45 auto byte = (unsigned int) *data;
46
47 if (byte == 0xf0 || byte == 0xf7)
48 {
49 int i = 1;
50
51 while (i < maxBytes)
52 if (data[i++] == 0xf7)
53 break;
54
55 return i;
56 }
57
58 if (byte == 0xff)
59 {
60 if (maxBytes == 1)
61 return 1;
62
63 const auto var = MidiMessage::readVariableLengthValue (data + 1, maxBytes - 1);
64 return jmin (maxBytes, var.value + 2 + var.bytesUsed);
65 }
66
67 if (byte >= 0x80)
68 return jmin (maxBytes, MidiMessage::getMessageLengthFromFirstByte ((uint8) byte));
69
70 return 0;
71 }
72
73 static uint8* findEventAfter (uint8* d, uint8* endData, int samplePosition) noexcept
74 {
75 while (d < endData && getEventTime (d) <= samplePosition)
77
78 return d;
79 }
80}
81
82//==============================================================================
84{
85 data += sizeof (int32) + sizeof (uint16) + size_t (MidiBufferHelpers::getEventDataSize (data));
86 return *this;
87}
88
89MidiBufferIterator MidiBufferIterator::operator++ (int) noexcept
90{
91 auto copy = *this;
92 ++(*this);
93 return copy;
94}
95
102
103//==============================================================================
105{
106 addEvent (message, 0);
107}
108
109void MidiBuffer::swapWith (MidiBuffer& other) noexcept { data.swapWith (other.data); }
110void MidiBuffer::clear() noexcept { data.clearQuick(); }
111void MidiBuffer::ensureSize (size_t minimumNumBytes) { data.ensureStorageAllocated ((int) minimumNumBytes); }
112bool MidiBuffer::isEmpty() const noexcept { return data.size() == 0; }
113
114void MidiBuffer::clear (int startSample, int numSamples)
115{
116 auto start = MidiBufferHelpers::findEventAfter (data.begin(), data.end(), startSample - 1);
117 auto end = MidiBufferHelpers::findEventAfter (start, data.end(), startSample + numSamples - 1);
118
119 data.removeRange ((int) (start - data.begin()), (int) (end - start));
120}
121
122bool MidiBuffer::addEvent (const MidiMessage& m, int sampleNumber)
123{
124 return addEvent (m.getRawData(), m.getRawDataSize(), sampleNumber);
125}
126
127bool MidiBuffer::addEvent (const void* newData, int maxBytes, int sampleNumber)
128{
129 auto numBytes = MidiBufferHelpers::findActualEventLength (static_cast<const uint8*> (newData), maxBytes);
130
131 if (numBytes <= 0)
132 return true;
133
134 if (std::numeric_limits<uint16>::max() < numBytes)
135 {
136 // This method only supports messages smaller than (1 << 16) bytes
137 return false;
138 }
139
140 auto newItemSize = (size_t) numBytes + sizeof (int32) + sizeof (uint16);
141 auto offset = (int) (MidiBufferHelpers::findEventAfter (data.begin(), data.end(), sampleNumber) - data.begin());
142
143 data.insertMultiple (offset, 0, (int) newItemSize);
144
145 auto* d = data.begin() + offset;
146 writeUnaligned<int32> (d, sampleNumber);
147 d += sizeof (int32);
148 writeUnaligned<uint16> (d, static_cast<uint16> (numBytes));
149 d += sizeof (uint16);
150 memcpy (d, newData, (size_t) numBytes);
151
152 return true;
153}
154
155void MidiBuffer::addEvents (const MidiBuffer& otherBuffer,
156 int startSample, int numSamples, int sampleDeltaToAdd)
157{
158 for (auto i = otherBuffer.findNextSamplePosition (startSample); i != otherBuffer.cend(); ++i)
159 {
160 const auto metadata = *i;
161
162 if (metadata.samplePosition >= startSample + numSamples && numSamples >= 0)
163 break;
164
165 addEvent (metadata.data, metadata.numBytes, metadata.samplePosition + sampleDeltaToAdd);
166 }
167}
168
170{
171 int n = 0;
172 auto end = data.end();
173
174 for (auto d = data.begin(); d < end; ++n)
176
177 return n;
178}
179
181{
182 return data.size() > 0 ? MidiBufferHelpers::getEventTime (data.begin()) : 0;
183}
184
186{
187 if (data.size() == 0)
188 return 0;
189
190 auto endData = data.end();
191
192 for (auto d = data.begin();;)
193 {
194 auto nextOne = d + MidiBufferHelpers::getEventTotalSize (d);
195
196 if (nextOne >= endData)
198
199 d = nextOne;
200 }
201}
202
204{
205 return std::find_if (cbegin(), cend(), [&] (const MidiMessageMetadata& metadata) noexcept
206 {
207 return metadata.samplePosition >= samplePosition;
208 });
209}
210
211//==============================================================================
212JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")
214
219
220void MidiBuffer::Iterator::setNextSamplePosition (int samplePosition) noexcept
221{
222 iterator = buffer.findNextSamplePosition (samplePosition);
223}
224
225bool MidiBuffer::Iterator::getNextEvent (const uint8*& midiData, int& numBytes, int& samplePosition) noexcept
226{
227 if (iterator == buffer.cend())
228 return false;
229
230 const auto metadata = *iterator++;
231 midiData = metadata.data;
232 numBytes = metadata.numBytes;
233 samplePosition = metadata.samplePosition;
234 return true;
235}
236
237bool MidiBuffer::Iterator::getNextEvent (MidiMessage& result, int& samplePosition) noexcept
238{
239 if (iterator == buffer.cend())
240 return false;
241
242 const auto metadata = *iterator++;
243 result = metadata.getMessage();
244 samplePosition = metadata.samplePosition;
245 return true;
246}
247
250
251//==============================================================================
252//==============================================================================
253#if JUCE_UNIT_TESTS
254
255struct MidiBufferTest : public UnitTest
256{
257 MidiBufferTest()
258 : UnitTest ("MidiBuffer", UnitTestCategories::midi)
259 {}
260
261 void runTest() override
262 {
263 beginTest ("Clear messages");
264 {
265 const auto message = MidiMessage::noteOn (1, 64, 0.5f);
266
267 const auto testBuffer = [&]
268 {
269 MidiBuffer buffer;
270 buffer.addEvent (message, 0);
271 buffer.addEvent (message, 10);
272 buffer.addEvent (message, 20);
273 buffer.addEvent (message, 30);
274 return buffer;
275 }();
276
277 {
278 auto buffer = testBuffer;
279 buffer.clear (10, 0);
280 expectEquals (buffer.getNumEvents(), 4);
281 }
282
283 {
284 auto buffer = testBuffer;
285 buffer.clear (10, 1);
286 expectEquals (buffer.getNumEvents(), 3);
287 }
288
289 {
290 auto buffer = testBuffer;
291 buffer.clear (10, 10);
292 expectEquals (buffer.getNumEvents(), 3);
293 }
294
295 {
296 auto buffer = testBuffer;
297 buffer.clear (10, 20);
298 expectEquals (buffer.getNumEvents(), 2);
299 }
300
301 {
302 auto buffer = testBuffer;
303 buffer.clear (10, 30);
304 expectEquals (buffer.getNumEvents(), 1);
305 }
306
307 {
308 auto buffer = testBuffer;
309 buffer.clear (10, 300);
310 expectEquals (buffer.getNumEvents(), 1);
311 }
312 }
313 }
314};
315
316static MidiBufferTest midiBufferTest;
317
318#endif
319
320} // namespace juce
#define copy(x)
Definition ADnoteParameters.cpp:1011
Type jmin(const Type a, const Type b)
Definition MathsFunctions.h:60
#define noexcept
Definition DistrhoDefines.h:72
static void message(int level, const char *fmt,...)
Definition adplugdb.cpp:120
void setNextSamplePosition(int samplePosition) noexcept
Definition MidiBuffer.cpp:203
bool getNextEvent(MidiMessage &result, int &samplePosition) noexcept
Definition MidiBuffer.cpp:226
int getLastEventTime() const noexcept
Definition MidiBuffer.cpp:175
void addEvent(const MidiMessage &midiMessage, int sampleNumber)
Definition MidiBuffer.cpp:118
void addEvents(const MidiBuffer &otherBuffer, int startSample, int numSamples, int sampleDeltaToAdd)
Definition MidiBuffer.cpp:141
int getFirstEventTime() const noexcept
Definition MidiBuffer.cpp:170
void ensureSize(size_t minimumNumBytes)
Definition MidiBuffer.cpp:107
bool isEmpty() const noexcept
Definition MidiBuffer.cpp:108
MidiBuffer() noexcept
Definition MidiBuffer.cpp:89
int getNumEvents() const noexcept
Definition MidiBuffer.cpp:159
void clear() noexcept
Definition MidiBuffer.cpp:106
void swapWith(MidiBuffer &) noexcept
Definition MidiBuffer.cpp:105
static MidiMessage noteOn(int channel, int noteNumber, float velocity) noexcept
Definition MidiMessage.cpp:534
Iterator(const MidiBuffer &b) noexcept
Definition juce_MidiBuffer.cpp:215
const MidiBuffer & buffer
Definition juce_MidiBuffer.h:330
MidiBufferIterator iterator
Definition juce_MidiBuffer.h:331
Definition juce_MidiBuffer.h:145
MidiBufferIterator cbegin() const noexcept
Definition juce_MidiBuffer.h:265
MidiBufferIterator findNextSamplePosition(int samplePosition) const noexcept
Definition juce_MidiBuffer.cpp:203
MidiBufferIterator cend() const noexcept
Definition juce_MidiBuffer.h:268
bool addEvent(const MidiMessage &midiMessage, int sampleNumber)
Definition juce_MidiBuffer.cpp:122
MidiBuffer() noexcept=default
Array< uint8 > data
Definition juce_MidiBuffer.h:339
MidiBufferIterator begin() const noexcept
Definition juce_MidiBuffer.h:259
MidiBufferIterator end() const noexcept
Definition juce_MidiBuffer.h:262
Definition juce_MidiBuffer.h:79
MidiMessageMetadata reference
Definition juce_MidiBuffer.h:97
MidiBufferIterator & operator++() noexcept
Definition juce_MidiBuffer.cpp:83
Ptr data
Definition juce_MidiBuffer.h:125
reference operator*() const noexcept
Definition juce_MidiBuffer.cpp:96
Definition juce_MidiMessage.h:35
static int getMessageLengthFromFirstByte(uint8 firstByte) noexcept
Definition juce_MidiMessage.cpp:104
static VariableLengthValue readVariableLengthValue(const uint8 *data, int maxBytesToUse) noexcept
Definition juce_MidiMessage.cpp:60
Definition juce_UnitTest.h:70
Definition juce_Variant.h:42
ValueUnion value
Definition juce_Variant.h:314
unsigned * m
Definition inflate.c:1559
unsigned d
Definition inflate.c:940
register unsigned i
Definition inflate.c:1575
virtual ASIOError start()=0
JSAMPIMAGE data
Definition jpeglib.h:945
#define JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE(...)
Definition juce_CompilerWarnings.h:181
#define JUCE_END_IGNORE_WARNINGS_GCC_LIKE
Definition juce_CompilerWarnings.h:182
#define JUCE_BEGIN_IGNORE_WARNINGS_MSVC(warnings)
Definition juce_CompilerWarnings.h:198
#define JUCE_END_IGNORE_WARNINGS_MSVC
Definition juce_CompilerWarnings.h:199
Definition juce_MidiBuffer.cpp:27
uint16 getEventTotalSize(const void *d) noexcept
Definition juce_MidiBuffer.cpp:38
static uint8 * findEventAfter(uint8 *d, uint8 *endData, int samplePosition) noexcept
Definition juce_MidiBuffer.cpp:73
static int findActualEventLength(const uint8 *data, int maxBytes) noexcept
Definition juce_MidiBuffer.cpp:43
int getEventTime(const void *d) noexcept
Definition juce_MidiBuffer.cpp:28
uint16 getEventDataSize(const void *d) noexcept
Definition juce_MidiBuffer.cpp:33
Definition juce_UnitTestCategories.h:27
JOCTET * buffer
Definition juce_JPEGLoader.cpp:302
Definition carla_juce.cpp:31
unsigned short uint16
Definition juce_MathsFunctions.h:41
Type readUnaligned(const void *srcPtr) noexcept
Definition juce_Memory.h:65
signed int int32
Definition juce_MathsFunctions.h:43
void writeUnaligned(void *dstPtr, Type value) noexcept
Definition juce_Memory.h:74
unsigned char uint8
Definition juce_MathsFunctions.h:37
Definition juce_MidiBuffer.h:37
int samplePosition
Definition juce_MidiBuffer.h:58
int n
Definition crypt.c:458
memcpy(hh, h, RAND_HEAD_LEN)
b
Definition crypt.c:628
int result
Definition process.c:1455
typedef int(UZ_EXP MsgFn)()
#define const
Definition zconf.h:137