LMMS
Loading...
Searching...
No Matches
MidiBuffer.cpp
Go to the documentation of this file.
1/*
2 ==============================================================================
3
4 This file is part of the Water library.
5 Copyright (c) 2016 ROLI Ltd.
6 Copyright (C) 2017 Filipe Coelho <falktx@falktx.com>
7
8 Permission is granted to use this software under the terms of the ISC license
9 http://www.isc.org/downloads/software-support-policy/isc-license/
10
11 Permission to use, copy, modify, and/or distribute this software for any
12 purpose with or without fee is hereby granted, provided that the above
13 copyright notice and this permission notice appear in all copies.
14
15 THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH REGARD
16 TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT,
18 OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
19 USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
20 TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
21 OF THIS SOFTWARE.
22
23 ==============================================================================
24*/
25
26#include "MidiBuffer.h"
27#include "MidiMessage.h"
28
29#include "CarlaUtils.hpp"
30
31namespace water {
32
34{
35 inline int getEventTime (const void* const d) noexcept
36 {
37 return readUnaligned<int32> (d);
38 }
39
40 inline uint16 getEventDataSize (const void* const d) noexcept
41 {
42 return readUnaligned<uint16> (static_cast<const char*> (d) + sizeof (int32));
43 }
44
45 inline uint16 getEventTotalSize (const void* const d) noexcept
46 {
47 return getEventDataSize (d) + sizeof (int32) + sizeof (uint16);
48 }
49
50 static int findActualEventLength (const uint8* const data, const int maxBytes) noexcept
51 {
52 unsigned int byte = (unsigned int) *data;
53 int size = 0;
54
55 if (byte == 0xf0 || byte == 0xf7)
56 {
57 const uint8* d = data + 1;
58
59 while (d < data + maxBytes)
60 if (*d++ == 0xf7)
61 break;
62
63 size = (int) (d - data);
64 }
65 else if (byte == 0xff)
66 {
67 int n;
68 const int bytesLeft = MidiMessage::readVariableLengthVal (data + 1, n);
69 size = jmin (maxBytes, n + 2 + bytesLeft);
70 }
71 else if (byte >= 0x80)
72 {
74 }
75
76 return size;
77 }
78
79 static uint8* findEventAfter (uint8* d, uint8* endData, const int samplePosition) noexcept
80 {
81 while (d < endData && getEventTime (d) <= samplePosition)
83
84 return d;
85 }
86}
87
88//==============================================================================
91
92MidiBuffer::MidiBuffer (const MidiBuffer& other) noexcept : data (other.data) {}
93
95{
96 data = other.data;
97 return *this;
98}
99
101{
102 addEvent (message, 0);
103}
104
105void MidiBuffer::swapWith (MidiBuffer& other) noexcept { data.swapWith (other.data); }
106void MidiBuffer::clear() noexcept { data.clearQuick(); }
107void MidiBuffer::ensureSize (size_t minimumNumBytes) { data.ensureStorageAllocated ((int) minimumNumBytes); }
108bool MidiBuffer::isEmpty() const noexcept { return data.size() == 0; }
109
110void MidiBuffer::clear (const int startSample, const int numSamples)
111{
112 uint8* const start = MidiBufferHelpers::findEventAfter (data.begin(), data.end(), startSample - 1);
113 uint8* const end = MidiBufferHelpers::findEventAfter (start, data.end(), startSample + numSamples - 1);
114
115 data.removeRange ((int) (start - data.begin()), (int) (end - data.begin()));
116}
117
118void MidiBuffer::addEvent (const MidiMessage& m, const int sampleNumber)
119{
120 addEvent (m.getRawData(), m.getRawDataSize(), sampleNumber);
121}
122
123void MidiBuffer::addEvent (const void* const newData, const int maxBytes, const int sampleNumber)
124{
125 const int numBytes = MidiBufferHelpers::findActualEventLength (static_cast<const uint8*> (newData), maxBytes);
126
127 if (numBytes > 0)
128 {
129 const size_t newItemSize = (size_t) numBytes + sizeof (int32) + sizeof (uint16);
130 const int offset = (int) (MidiBufferHelpers::findEventAfter (data.begin(), data.end(), sampleNumber) - data.begin());
131
132 data.insertMultiple (offset, 0, (int) newItemSize);
133
134 uint8* const d = data.begin() + offset;
135 writeUnaligned<int32> (d, sampleNumber);
136 writeUnaligned<uint16> (d + 4, static_cast<uint16> (numBytes));
137 memcpy (d + 6, newData, (size_t) numBytes);
138 }
139}
140
141void MidiBuffer::addEvents (const MidiBuffer& otherBuffer,
142 const int startSample,
143 const int numSamples,
144 const int sampleDeltaToAdd)
145{
146 Iterator i (otherBuffer);
147 i.setNextSamplePosition (startSample);
148
149 const uint8* eventData;
150 int eventSize, position;
151
152 while (i.getNextEvent (eventData, eventSize, position)
153 && (position < startSample + numSamples || numSamples < 0))
154 {
155 addEvent (eventData, eventSize, position + sampleDeltaToAdd);
156 }
157}
158
160{
161 int n = 0;
162 const uint8* const end = data.end();
163
164 for (const uint8* d = data.begin(); d < end; ++n)
166
167 return n;
168}
169
171{
172 return data.size() > 0 ? MidiBufferHelpers::getEventTime (data.begin()) : 0;
173}
174
176{
177 if (data.size() == 0)
178 return 0;
179
180 const uint8* const endData = data.end();
181
182 for (const uint8* d = data.begin();;)
183 {
184 const uint8* const nextOne = d + MidiBufferHelpers::getEventTotalSize (d);
185
186 if (nextOne >= endData)
188
189 d = nextOne;
190 }
191}
192
193//==============================================================================
195 : buffer (b), data (b.data.begin())
196{
197}
198
202
203void MidiBuffer::Iterator::setNextSamplePosition (const int samplePosition) noexcept
204{
205 data = buffer.data.begin();
206 const uint8* const dataEnd = buffer.data.end();
207
208 while (data < dataEnd && MidiBufferHelpers::getEventTime (data) < samplePosition)
210}
211
212bool MidiBuffer::Iterator::getNextEvent (const uint8* &midiData, int& numBytes, int& samplePosition) noexcept
213{
214 if (data >= buffer.data.end())
215 return false;
216
217 samplePosition = MidiBufferHelpers::getEventTime (data);
218 const int itemSize = MidiBufferHelpers::getEventDataSize (data);
219 numBytes = itemSize;
220 midiData = data + sizeof (int32) + sizeof (uint16);
221 data += sizeof (int32) + sizeof (uint16) + (size_t) itemSize;
222
223 return true;
224}
225
226bool MidiBuffer::Iterator::getNextEvent (MidiMessage& result, int& samplePosition) noexcept
227{
228 if (data >= buffer.data.end())
229 return false;
230
231 samplePosition = MidiBufferHelpers::getEventTime (data);
232 const int itemSize = MidiBufferHelpers::getEventDataSize (data);
233 result = MidiMessage (data + sizeof (int32) + sizeof (uint16), itemSize, samplePosition);
234 data += sizeof (int32) + sizeof (uint16) + (size_t) itemSize;
235
236 return true;
237}
238
239}
#define noexcept
Definition DistrhoDefines.h:72
static void message(int level, const char *fmt,...)
Definition adplugdb.cpp:120
Definition MidiBuffer.h:176
Iterator(const MidiBuffer &) noexcept
Definition MidiBuffer.cpp:194
const uint8 * data
Definition MidiBuffer.h:223
void setNextSamplePosition(int samplePosition) noexcept
Definition MidiBuffer.cpp:203
const MidiBuffer & buffer
Definition MidiBuffer.h:222
bool getNextEvent(MidiMessage &result, int &samplePosition) noexcept
Definition MidiBuffer.cpp:226
~Iterator() noexcept
Definition MidiBuffer.cpp:199
int getLastEventTime() const noexcept
Definition MidiBuffer.cpp:175
~MidiBuffer()
Definition MidiBuffer.cpp:90
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
MidiBuffer & operator=(const MidiBuffer &) noexcept
Definition MidiBuffer.cpp:94
void ensureSize(size_t minimumNumBytes)
Definition MidiBuffer.cpp:107
Array< uint8 > data
Definition MidiBuffer.h:232
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
Definition MidiMessage.h:40
static int readVariableLengthVal(const uint8 *data, int &numBytesUsed) noexcept
Definition MidiMessage.cpp:63
static int getMessageLengthFromFirstByte(uint8 firstByte) noexcept
Definition MidiMessage.cpp:82
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
Definition MidiBuffer.cpp:34
uint16 getEventDataSize(const void *const d) noexcept
Definition MidiBuffer.cpp:40
uint16 getEventTotalSize(const void *const d) noexcept
Definition MidiBuffer.cpp:45
static uint8 * findEventAfter(uint8 *d, uint8 *endData, const int samplePosition) noexcept
Definition MidiBuffer.cpp:79
static int findActualEventLength(const uint8 *const data, const int maxBytes) noexcept
Definition MidiBuffer.cpp:50
int getEventTime(const void *const d) noexcept
Definition MidiBuffer.cpp:35
Definition AudioSampleBuffer.h:33
Type readUnaligned(const void *srcPtr) noexcept
Definition Memory.h:73
void writeUnaligned(void *dstPtr, Type value) noexcept
Definition Memory.h:83
Type jmin(const Type a, const Type b)
Definition MathsFunctions.h:60
unsigned short uint16
Definition water.h:94
unsigned char uint8
Definition water.h:90
signed int int32
Definition water.h:96
int n
Definition crypt.c:458
memcpy(hh, h, RAND_HEAD_LEN)
b
Definition crypt.c:628
ulg size
Definition extract.c:2350
int result
Definition process.c:1455
typedef int(UZ_EXP MsgFn)()
#define const
Definition zconf.h:137