OpenShot Audio Library | OpenShotAudio: juce_MidiBuffer.cpp Source File

OpenShot Audio Library | OpenShotAudio 0.3.1

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//==============================================================================
84MidiBuffer::MidiBuffer() noexcept {}
85MidiBuffer::~MidiBuffer() {}
86
87 MidiBuffer::MidiBuffer (const MidiBuffer& other) noexcept : data (other.data) {}
88
89 MidiBuffer& MidiBuffer::operator= (const MidiBuffer& other) noexcept
90{
91 data = other.data;
92 return *this;
93}
94
95 MidiBuffer::MidiBuffer (const MidiMessage& message) noexcept
96{
97 addEvent (message, 0);
98}
99
100 void MidiBuffer::swapWith (MidiBuffer& other) noexcept { data.swapWith (other.data); }
101 void MidiBuffer::clear() noexcept { data.clearQuick(); }
102 void MidiBuffer::ensureSize (size_t minimumNumBytes) { data.ensureStorageAllocated ((int) minimumNumBytes); }
103 bool MidiBuffer::isEmpty() const noexcept { return data.size() == 0; }
104
105 void 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
113 void MidiBuffer::addEvent (const MidiMessage& m, int sampleNumber)
114{
115 addEvent (m.getRawData(), m.getRawDataSize(), sampleNumber);
116}
117
118 void MidiBuffer::addEvent (const void* newData, int maxBytes, int sampleNumber)
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;
130 writeUnaligned<int32> (d, sampleNumber);
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
138 void MidiBuffer::addEvents (const MidiBuffer& otherBuffer,
139 int startSample, int numSamples, int sampleDeltaToAdd)
140{
141 Iterator i (otherBuffer);
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 {
150 addEvent (eventData, eventSize, position + sampleDeltaToAdd);
151 }
152}
153
154 int MidiBuffer::getNumEvents() const noexcept
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
165 int MidiBuffer::getFirstEventTime() const noexcept
166{
167 return data.size() > 0 ? MidiBufferHelpers::getEventTime (data.begin()) : 0;
168}
169
170 int MidiBuffer::getLastEventTime() const noexcept
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//==============================================================================
189MidiBuffer::Iterator::Iterator (const MidiBuffer& b) noexcept
190 : buffer (b), data (b.data.begin())
191{
192}
193
194MidiBuffer::Iterator::~Iterator() noexcept {}
195
196 void MidiBuffer::Iterator::setNextSamplePosition (int samplePosition) noexcept
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
205 bool 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
219 bool MidiBuffer::Iterator::getNextEvent (MidiMessage& result, int& samplePosition) noexcept
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
juce::Array::ensureStorageAllocated
void ensureStorageAllocated(int minNumElements)
Definition: juce_Array.h:1062
juce::Array::clearQuick
void clearQuick()
Definition: juce_Array.h:198
juce::Array::size
int size() const noexcept
Definition: juce_Array.h:215
juce::Array::removeRange
void removeRange(int startIndex, int numberToRemove)
Definition: juce_Array.h:916
juce::Array::begin
ElementType * begin() noexcept
Definition: juce_Array.h:328
juce::Array::end
ElementType * end() noexcept
Definition: juce_Array.h:344
juce::Array::insertMultiple
void insertMultiple(int indexToInsertAt, ParameterType newElement, int numberOfTimesToInsertIt)
Definition: juce_Array.h:480
juce::Array::data
ElementType * data() noexcept
Definition: juce_Array.h:360
juce::MidiBuffer::Iterator
Definition: juce_MidiBuffer.h:171
juce::MidiBuffer::Iterator::setNextSamplePosition
void setNextSamplePosition(int samplePosition) noexcept
Definition: juce_MidiBuffer.cpp:196
juce::MidiBuffer::Iterator::~Iterator
~Iterator() noexcept
Definition: juce_MidiBuffer.cpp:194
juce::MidiBuffer::Iterator::Iterator
Iterator(const MidiBuffer &) noexcept
Definition: juce_MidiBuffer.cpp:189
juce::MidiBuffer::Iterator::getNextEvent
bool getNextEvent(MidiMessage &result, int &samplePosition) noexcept
Definition: juce_MidiBuffer.cpp:219
juce::MidiBuffer
Definition: juce_MidiBuffer.h:43
juce::MidiBuffer::getFirstEventTime
int getFirstEventTime() const noexcept
Definition: juce_MidiBuffer.cpp:165
juce::MidiBuffer::operator=
MidiBuffer & operator=(const MidiBuffer &) noexcept
Definition: juce_MidiBuffer.cpp:89
juce::MidiBuffer::addEvent
void addEvent(const MidiMessage &midiMessage, int sampleNumber)
Definition: juce_MidiBuffer.cpp:113
juce::MidiBuffer::getLastEventTime
int getLastEventTime() const noexcept
Definition: juce_MidiBuffer.cpp:170
juce::MidiBuffer::ensureSize
void ensureSize(size_t minimumNumBytes)
Definition: juce_MidiBuffer.cpp:102
juce::MidiBuffer::MidiBuffer
MidiBuffer() noexcept
Definition: juce_MidiBuffer.cpp:84
juce::MidiBuffer::getNumEvents
int getNumEvents() const noexcept
Definition: juce_MidiBuffer.cpp:154
juce::MidiBuffer::isEmpty
bool isEmpty() const noexcept
Definition: juce_MidiBuffer.cpp:103
juce::MidiBuffer::swapWith
void swapWith(MidiBuffer &) noexcept
Definition: juce_MidiBuffer.cpp:100
juce::MidiBuffer::~MidiBuffer
~MidiBuffer()
Definition: juce_MidiBuffer.cpp:85
juce::MidiBuffer::clear
void clear() noexcept
Definition: juce_MidiBuffer.cpp:101
juce::MidiBuffer::addEvents
void addEvents(const MidiBuffer &otherBuffer, int startSample, int numSamples, int sampleDeltaToAdd)
Definition: juce_MidiBuffer.cpp:138
juce::MidiBuffer::data
Array< uint8 > data
Definition: juce_MidiBuffer.h:228
juce::MidiMessage
Definition: juce_MidiMessage.h:35
juce::MidiMessage::readVariableLengthVal
static int readVariableLengthVal(const uint8 *data, int &numBytesUsed) noexcept
Definition: juce_MidiMessage.cpp:60
juce::MidiMessage::getRawData
const uint8 * getRawData() const noexcept
Definition: juce_MidiMessage.h:133
juce::MidiMessage::getMessageLengthFromFirstByte
static int getMessageLengthFromFirstByte(uint8 firstByte) noexcept
Definition: juce_MidiMessage.cpp:79
juce::MidiMessage::getRawDataSize
int getRawDataSize() const noexcept
Definition: juce_MidiMessage.h:138