OpenShot Audio Library | OpenShotAudio 0.3.2
Loading...
Searching...
No Matches
juce_MidiBuffer.cpp
1/*
2 ==============================================================================
3
4 This file is part of the JUCE library.
5 Copyright (c) 2017 - ROLI Ltd.
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
26namespace MidiBufferHelpers
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 int n;
64 auto bytesLeft = MidiMessage::readVariableLengthVal (data + 1, n);
65 return jmin (maxBytes, n + 2 + bytesLeft);
66 }
67
68 if (byte >= 0x80)
69 return jmin (maxBytes, MidiMessage::getMessageLengthFromFirstByte ((uint8) byte));
70
71 return 0;
72 }
73
74 static uint8* findEventAfter (uint8* d, uint8* endData, int samplePosition) noexcept
75 {
76 while (d < endData && getEventTime (d) <= samplePosition)
77 d += getEventTotalSize (d);
78
79 return d;
80 }
81}
82
83//==============================================================================
86
88
90{
91 data = other.data;
92 return *this;
93}
94
95MidiBuffer::MidiBuffer (const MidiMessage& message) noexcept
96{
97 addEvent (message, 0);
98}
99
103bool MidiBuffer::isEmpty() const noexcept { return data.size() == 0; }
104
105void MidiBuffer::clear (int startSample, int numSamples)
106{
107 auto start = MidiBufferHelpers::findEventAfter (data.begin(), data.end(), startSample - 1);
108 auto end = MidiBufferHelpers::findEventAfter (start, data.end(), startSample + numSamples - 1);
109
110 data.removeRange ((int) (start - data.begin()), (int) (end - data.begin()));
111}
112
117
119{
120 auto numBytes = MidiBufferHelpers::findActualEventLength (static_cast<const uint8*> (newData), maxBytes);
121
122 if (numBytes > 0)
123 {
124 auto newItemSize = (size_t) numBytes + sizeof (int32) + sizeof (uint16);
125 auto offset = (int) (MidiBufferHelpers::findEventAfter (data.begin(), data.end(), sampleNumber) - data.begin());
126
127 data.insertMultiple (offset, 0, (int) newItemSize);
128
129 auto* d = data.begin() + offset;
131 d += sizeof (int32);
132 writeUnaligned<uint16> (d, static_cast<uint16> (numBytes));
133 d += sizeof (uint16);
134 memcpy (d, newData, (size_t) numBytes);
135 }
136}
137
139 int startSample, int numSamples, int sampleDeltaToAdd)
140{
142 i.setNextSamplePosition (startSample);
143
144 const uint8* eventData;
145 int eventSize, position;
146
147 while (i.getNextEvent (eventData, eventSize, position)
148 && (position < startSample + numSamples || numSamples < 0))
149 {
151 }
152}
153
155{
156 int n = 0;
157 auto end = data.end();
158
159 for (auto d = data.begin(); d < end; ++n)
160 d += MidiBufferHelpers::getEventTotalSize (d);
161
162 return n;
163}
164
166{
167 return data.size() > 0 ? MidiBufferHelpers::getEventTime (data.begin()) : 0;
168}
169
171{
172 if (data.size() == 0)
173 return 0;
174
175 auto endData = data.end();
176
177 for (auto d = data.begin();;)
178 {
179 auto nextOne = d + MidiBufferHelpers::getEventTotalSize (d);
180
181 if (nextOne >= endData)
182 return MidiBufferHelpers::getEventTime (d);
183
184 d = nextOne;
185 }
186}
187
188//==============================================================================
190 : buffer (b), data (b.data.begin())
191{
192}
193
195
197{
198 data = buffer.data.begin();
199 auto dataEnd = buffer.data.end();
200
201 while (data < dataEnd && MidiBufferHelpers::getEventTime (data) < samplePosition)
202 data += MidiBufferHelpers::getEventTotalSize (data);
203}
204
205bool MidiBuffer::Iterator::getNextEvent (const uint8*& midiData, int& numBytes, int& samplePosition) noexcept
206{
207 if (data >= buffer.data.end())
208 return false;
209
210 samplePosition = MidiBufferHelpers::getEventTime (data);
211 auto itemSize = MidiBufferHelpers::getEventDataSize (data);
212 numBytes = itemSize;
213 midiData = data + sizeof (int32) + sizeof (uint16);
214 data += sizeof (int32) + sizeof (uint16) + (size_t) itemSize;
215
216 return true;
217}
218
220{
221 if (data >= buffer.data.end())
222 return false;
223
224 samplePosition = MidiBufferHelpers::getEventTime (data);
225 auto itemSize = MidiBufferHelpers::getEventDataSize (data);
226 result = MidiMessage (data + sizeof (int32) + sizeof (uint16), itemSize, samplePosition);
227 data += sizeof (int32) + sizeof (uint16) + (size_t) itemSize;
228
229 return true;
230}
231
232} // namespace juce
void swapWith(OtherArrayType &otherArray) noexcept
Definition juce_Array.h:621
void ensureStorageAllocated(int minNumElements)
void clearQuick()
Definition juce_Array.h:198
int size() const noexcept
Definition juce_Array.h:215
void removeRange(int startIndex, int numberToRemove)
Definition juce_Array.h:916
ElementType * begin() noexcept
Definition juce_Array.h:328
ElementType * end() noexcept
Definition juce_Array.h:344
void insertMultiple(int indexToInsertAt, ParameterType newElement, int numberOfTimesToInsertIt)
Definition juce_Array.h:480
ElementType * data() noexcept
Definition juce_Array.h:360
void setNextSamplePosition(int samplePosition) noexcept
Iterator(const MidiBuffer &) noexcept
bool getNextEvent(MidiMessage &result, int &samplePosition) noexcept
int getFirstEventTime() const noexcept
MidiBuffer & operator=(const MidiBuffer &) noexcept
void addEvent(const MidiMessage &midiMessage, int sampleNumber)
int getLastEventTime() const noexcept
void ensureSize(size_t minimumNumBytes)
int getNumEvents() const noexcept
bool isEmpty() const noexcept
void swapWith(MidiBuffer &) noexcept
void clear() noexcept
void addEvents(const MidiBuffer &otherBuffer, int startSample, int numSamples, int sampleDeltaToAdd)
Array< uint8 > data
static int readVariableLengthVal(const uint8 *data, int &numBytesUsed) noexcept
const uint8 * getRawData() const noexcept
static int getMessageLengthFromFirstByte(uint8 firstByte) noexcept
int getRawDataSize() const noexcept