Massive UI work
[juce-lv2.git] / juce / source / src / audio / midi / juce_MidiBuffer.cpp
blobd26217da5ba08fa134f5d9d1fcf282d76fc6e172
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../../core/juce_StandardHeader.h"
28 BEGIN_JUCE_NAMESPACE
30 #include "juce_MidiBuffer.h"
33 //==============================================================================
34 MidiBuffer::MidiBuffer() noexcept
35 : bytesUsed (0)
39 MidiBuffer::MidiBuffer (const MidiMessage& message) noexcept
40 : bytesUsed (0)
42 addEvent (message, 0);
45 MidiBuffer::MidiBuffer (const MidiBuffer& other) noexcept
46 : data (other.data),
47 bytesUsed (other.bytesUsed)
51 MidiBuffer& MidiBuffer::operator= (const MidiBuffer& other) noexcept
53 bytesUsed = other.bytesUsed;
54 data = other.data;
56 return *this;
59 void MidiBuffer::swapWith (MidiBuffer& other) noexcept
61 data.swapWith (other.data);
62 std::swap (bytesUsed, other.bytesUsed);
65 MidiBuffer::~MidiBuffer()
69 inline uint8* MidiBuffer::getData() const noexcept
71 return static_cast <uint8*> (data.getData());
74 inline int MidiBuffer::getEventTime (const void* const d) noexcept
76 return *static_cast <const int*> (d);
79 inline uint16 MidiBuffer::getEventDataSize (const void* const d) noexcept
81 return *reinterpret_cast <const uint16*> (static_cast <const char*> (d) + sizeof (int));
84 inline uint16 MidiBuffer::getEventTotalSize (const void* const d) noexcept
86 return getEventDataSize (d) + sizeof (int) + sizeof (uint16);
89 void MidiBuffer::clear() noexcept
91 bytesUsed = 0;
94 void MidiBuffer::clear (const int startSample, const int numSamples)
96 uint8* const start = findEventAfter (getData(), startSample - 1);
97 uint8* const end = findEventAfter (start, startSample + numSamples - 1);
99 if (end > start)
101 const int bytesToMove = bytesUsed - (int) (end - getData());
103 if (bytesToMove > 0)
104 memmove (start, end, bytesToMove);
106 bytesUsed -= (int) (end - start);
110 void MidiBuffer::addEvent (const MidiMessage& m, const int sampleNumber)
112 addEvent (m.getRawData(), m.getRawDataSize(), sampleNumber);
115 namespace MidiBufferHelpers
117 int findActualEventLength (const uint8* const data, const int maxBytes) noexcept
119 unsigned int byte = (unsigned int) *data;
120 int size = 0;
122 if (byte == 0xf0 || byte == 0xf7)
124 const uint8* d = data + 1;
126 while (d < data + maxBytes)
127 if (*d++ == 0xf7)
128 break;
130 size = (int) (d - data);
132 else if (byte == 0xff)
134 int n;
135 const int bytesLeft = MidiMessage::readVariableLengthVal (data + 1, n);
136 size = jmin (maxBytes, n + 2 + bytesLeft);
138 else if (byte >= 0x80)
140 size = jmin (maxBytes, MidiMessage::getMessageLengthFromFirstByte ((uint8) byte));
143 return size;
147 void MidiBuffer::addEvent (const void* const newData, const int maxBytes, const int sampleNumber)
149 const int numBytes = MidiBufferHelpers::findActualEventLength (static_cast <const uint8*> (newData), maxBytes);
151 if (numBytes > 0)
153 int spaceNeeded = bytesUsed + numBytes + sizeof (int) + sizeof (uint16);
154 data.ensureSize ((spaceNeeded + spaceNeeded / 2 + 8) & ~7);
156 uint8* d = findEventAfter (getData(), sampleNumber);
157 const int bytesToMove = bytesUsed - (int) (d - getData());
159 if (bytesToMove > 0)
160 memmove (d + numBytes + sizeof (int) + sizeof (uint16), d, bytesToMove);
162 *reinterpret_cast <int*> (d) = sampleNumber;
163 d += sizeof (int);
164 *reinterpret_cast <uint16*> (d) = (uint16) numBytes;
165 d += sizeof (uint16);
167 memcpy (d, newData, numBytes);
169 bytesUsed += numBytes + sizeof (int) + sizeof (uint16);
173 void MidiBuffer::addEvents (const MidiBuffer& otherBuffer,
174 const int startSample,
175 const int numSamples,
176 const int sampleDeltaToAdd)
178 Iterator i (otherBuffer);
179 i.setNextSamplePosition (startSample);
181 const uint8* eventData;
182 int eventSize, position;
184 while (i.getNextEvent (eventData, eventSize, position)
185 && (position < startSample + numSamples || numSamples < 0))
187 addEvent (eventData, eventSize, position + sampleDeltaToAdd);
191 void MidiBuffer::ensureSize (size_t minimumNumBytes)
193 data.ensureSize (minimumNumBytes);
196 bool MidiBuffer::isEmpty() const noexcept
198 return bytesUsed == 0;
201 int MidiBuffer::getNumEvents() const noexcept
203 int n = 0;
204 const uint8* d = getData();
205 const uint8* const end = d + bytesUsed;
207 while (d < end)
209 d += getEventTotalSize (d);
210 ++n;
213 return n;
216 int MidiBuffer::getFirstEventTime() const noexcept
218 return bytesUsed > 0 ? getEventTime (data.getData()) : 0;
221 int MidiBuffer::getLastEventTime() const noexcept
223 if (bytesUsed == 0)
224 return 0;
226 const uint8* d = getData();
227 const uint8* const endData = d + bytesUsed;
229 for (;;)
231 const uint8* const nextOne = d + getEventTotalSize (d);
233 if (nextOne >= endData)
234 return getEventTime (d);
236 d = nextOne;
240 uint8* MidiBuffer::findEventAfter (uint8* d, const int samplePosition) const noexcept
242 const uint8* const endData = getData() + bytesUsed;
244 while (d < endData && getEventTime (d) <= samplePosition)
245 d += getEventTotalSize (d);
247 return d;
250 //==============================================================================
251 MidiBuffer::Iterator::Iterator (const MidiBuffer& buffer_) noexcept
252 : buffer (buffer_),
253 data (buffer_.getData())
257 MidiBuffer::Iterator::~Iterator() noexcept
261 //==============================================================================
262 void MidiBuffer::Iterator::setNextSamplePosition (const int samplePosition) noexcept
264 data = buffer.getData();
265 const uint8* dataEnd = data + buffer.bytesUsed;
267 while (data < dataEnd && getEventTime (data) < samplePosition)
268 data += getEventTotalSize (data);
271 bool MidiBuffer::Iterator::getNextEvent (const uint8* &midiData, int& numBytes, int& samplePosition) noexcept
273 if (data >= buffer.getData() + buffer.bytesUsed)
274 return false;
276 samplePosition = getEventTime (data);
277 numBytes = getEventDataSize (data);
278 data += sizeof (int) + sizeof (uint16);
279 midiData = data;
280 data += numBytes;
282 return true;
285 bool MidiBuffer::Iterator::getNextEvent (MidiMessage& result, int& samplePosition) noexcept
287 if (data >= buffer.getData() + buffer.bytesUsed)
288 return false;
290 samplePosition = getEventTime (data);
291 const int numBytes = getEventDataSize (data);
292 data += sizeof (int) + sizeof (uint16);
293 result = MidiMessage (data, numBytes, samplePosition);
294 data += numBytes;
296 return true;
300 END_JUCE_NAMESPACE