openshot-audio  0.1.7
juce_MidiDataConcatenator.h
Go to the documentation of this file.
1 /*
2  ==============================================================================
3 
4  This file is part of the JUCE library.
5  Copyright (c) 2015 - ROLI Ltd.
6 
7  Permission is granted to use this software under the terms of either:
8  a) the GPL v2 (or any later version)
9  b) the Affero GPL v3
10 
11  Details of these licenses can be found at: www.gnu.org/licenses
12 
13  JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
14  WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
15  A PARTICULAR PURPOSE. See the GNU General Public License for more details.
16 
17  ------------------------------------------------------------------------------
18 
19  To release a closed-source product which uses JUCE, commercial licenses are
20  available: visit www.juce.com for more information.
21 
22  ==============================================================================
23 */
24 
25 #ifndef JUCE_MIDIDATACONCATENATOR_H_INCLUDED
26 #define JUCE_MIDIDATACONCATENATOR_H_INCLUDED
27 
28 //==============================================================================
34 {
35 public:
36  //==============================================================================
37  MidiDataConcatenator (const int initialBufferSize)
38  : pendingData ((size_t) initialBufferSize),
39  pendingDataTime (0), pendingBytes (0), runningStatus (0)
40  {
41  }
42 
43  void reset()
44  {
45  pendingBytes = 0;
46  runningStatus = 0;
47  pendingDataTime = 0;
48  }
49 
50  template <typename UserDataType, typename CallbackType>
51  void pushMidiData (const void* inputData, int numBytes, double time,
52  UserDataType* input, CallbackType& callback)
53  {
54  const uint8* d = static_cast <const uint8*> (inputData);
55 
56  while (numBytes > 0)
57  {
58  if (pendingBytes > 0 || d[0] == 0xf0)
59  {
60  processSysex (d, numBytes, time, input, callback);
61  runningStatus = 0;
62  }
63  else
64  {
65  int len = 0;
66  uint8 data[3];
67 
68  while (numBytes > 0)
69  {
70  // If there's a realtime message embedded in the middle of
71  // the normal message, handle it now..
72  if (*d >= 0xf8 && *d <= 0xfe)
73  {
74  const MidiMessage m (*d++, time);
75  callback.handleIncomingMidiMessage (input, m);
76  --numBytes;
77  }
78  else
79  {
80  if (len == 0 && *d < 0x80 && runningStatus >= 0x80)
81  data[len++] = runningStatus;
82 
83  data[len++] = *d++;
84  --numBytes;
85 
86  if (len >= MidiMessage::getMessageLengthFromFirstByte (data[0]))
87  break;
88  }
89  }
90 
91  if (len > 0)
92  {
93  int used = 0;
94  const MidiMessage m (data, len, used, 0, time);
95 
96  if (used <= 0)
97  break; // malformed message..
98 
99  jassert (used == len);
100  callback.handleIncomingMidiMessage (input, m);
101  runningStatus = data[0];
102  }
103  }
104  }
105  }
106 
107 private:
108  template <typename UserDataType, typename CallbackType>
109  void processSysex (const uint8*& d, int& numBytes, double time,
110  UserDataType* input, CallbackType& callback)
111  {
112  if (*d == 0xf0)
113  {
114  pendingBytes = 0;
115  pendingDataTime = time;
116  }
117 
118  pendingData.ensureSize ((size_t) (pendingBytes + numBytes), false);
119  uint8* totalMessage = static_cast<uint8*> (pendingData.getData());
120  uint8* dest = totalMessage + pendingBytes;
121 
122  do
123  {
124  if (pendingBytes > 0 && *d >= 0x80)
125  {
126  if (*d == 0xf7)
127  {
128  *dest++ = *d++;
129  ++pendingBytes;
130  --numBytes;
131  break;
132  }
133 
134  if (*d >= 0xfa || *d == 0xf8)
135  {
136  callback.handleIncomingMidiMessage (input, MidiMessage (*d, time));
137  ++d;
138  --numBytes;
139  }
140  else
141  {
142  pendingBytes = 0;
143  int used = 0;
144  const MidiMessage m (d, numBytes, used, 0, time);
145 
146  if (used > 0)
147  {
148  callback.handleIncomingMidiMessage (input, m);
149  numBytes -= used;
150  d += used;
151  }
152 
153  break;
154  }
155  }
156  else
157  {
158  *dest++ = *d++;
159  ++pendingBytes;
160  --numBytes;
161  }
162  }
163  while (numBytes > 0);
164 
165  if (pendingBytes > 0)
166  {
167  if (totalMessage [pendingBytes - 1] == 0xf7)
168  {
169  callback.handleIncomingMidiMessage (input, MidiMessage (totalMessage, pendingBytes, pendingDataTime));
170  pendingBytes = 0;
171  }
172  else
173  {
174  callback.handlePartialSysexMessage (input, totalMessage, pendingBytes, pendingDataTime);
175  }
176  }
177  }
178 
179  MemoryBlock pendingData;
180  double pendingDataTime;
181  int pendingBytes;
182  uint8 runningStatus;
183 
185 };
186 
187 #endif // JUCE_MIDIDATACONCATENATOR_H_INCLUDED
static int getMessageLengthFromFirstByte(const uint8 firstByte) noexcept
Definition: juce_MidiMessage.cpp:58
Definition: juce_MidiDataConcatenator.h:33
void pushMidiData(const void *inputData, int numBytes, double time, UserDataType *input, CallbackType &callback)
Definition: juce_MidiDataConcatenator.h:51
Definition: juce_MemoryBlock.h:38
MidiDataConcatenator(const int initialBufferSize)
Definition: juce_MidiDataConcatenator.h:37
void * getData() const noexcept
Definition: juce_MemoryBlock.h:96
void ensureSize(const size_t minimumSize, bool initialiseNewSpaceToZero=false)
Definition: juce_MemoryBlock.cpp:157
#define jassert(a)
Definition: juce_PlatformDefs.h:146
void reset()
Definition: juce_MidiDataConcatenator.h:43
#define JUCE_DECLARE_NON_COPYABLE(className)
Definition: juce_PlatformDefs.h:191
unsigned char uint8
Definition: juce_MathsFunctions.h:43
Definition: juce_MidiMessage.h:35