LMMS
Loading...
Searching...
No Matches
MidiMessage.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-2022 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 "MidiMessage.h"
28#include "../memory/HeapBlock.h"
29
30namespace water {
31
32namespace MidiHelpers
33{
34 inline uint8 initialByte (const int type, const int channel) noexcept
35 {
36 return (uint8) (type | jlimit (0, 15, channel - 1));
37 }
38
39 inline uint8 validVelocity (const int v) noexcept
40 {
41 return (uint8) jlimit (0, 127, v);
42 }
43}
44
45//==============================================================================
47{
48 return MidiHelpers::validVelocity (roundToInt (v * 127.0f));
49}
50
52 const float pitchbendRange) noexcept
53{
54 // can't translate a pitchbend value that is outside of the given range!
55 wassert (std::abs (pitchbend) <= pitchbendRange);
56
57 return static_cast<uint16> (pitchbend > 0.0f
58 ? jmap (pitchbend, 0.0f, pitchbendRange, 8192.0f, 16383.0f)
59 : jmap (pitchbend, -pitchbendRange, 0.0f, 0.0f, 8192.0f));
60}
61
62//==============================================================================
63int MidiMessage::readVariableLengthVal (const uint8* data, int& numBytesUsed) noexcept
64{
65 numBytesUsed = 0;
66 int v = 0, i;
67
68 do
69 {
70 i = (int) *data++;
71
72 if (++numBytesUsed > 6)
73 break;
74
75 v = (v << 7) + (i & 0x7f);
76
77 } while (i & 0x80);
78
79 return v;
80}
81
83{
84 // this method only works for valid starting bytes of a short midi message
85 wassert (firstByte >= 0x80 && firstByte != 0xf0 && firstByte != 0xf7);
86
87 static const char messageLengths[] =
88 {
89 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
90 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
91 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
92 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
93 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
94 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
95 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
96 1, 2, 3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
97 };
98
99 return messageLengths [firstByte & 0x7f];
100}
101
102//==============================================================================
104 : timeStamp (0), size (2)
105{
106 packedData.asBytes[0] = 0xf0;
107 packedData.asBytes[1] = 0xf7;
108}
109
110MidiMessage::MidiMessage (const void* const d, const int dataSize, const double t)
111 : timeStamp (t), size (dataSize)
112{
113 wassert (dataSize > 0);
114 // this checks that the length matches the data..
115 wassert (dataSize > 3 || *(uint8*)d >= 0xf0 || getMessageLengthFromFirstByte (*(uint8*)d) == size);
116
117 memcpy (allocateSpace (dataSize), d, (size_t) dataSize);
118}
119
120MidiMessage::MidiMessage (const int byte1, const double t) noexcept
121 : timeStamp (t), size (1)
122{
123 packedData.asBytes[0] = (uint8) byte1;
124
125 // check that the length matches the data..
126 wassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 1);
127}
128
129MidiMessage::MidiMessage (const int byte1, const int byte2, const double t) noexcept
130 : timeStamp (t), size (2)
131{
132 packedData.asBytes[0] = (uint8) byte1;
133 packedData.asBytes[1] = (uint8) byte2;
134
135 // check that the length matches the data..
136 wassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 2);
137}
138
139MidiMessage::MidiMessage (const int byte1, const int byte2, const int byte3, const double t) noexcept
140 : timeStamp (t), size (3)
141{
142 packedData.asBytes[0] = (uint8) byte1;
143 packedData.asBytes[1] = (uint8) byte2;
144 packedData.asBytes[2] = (uint8) byte3;
145
146 // check that the length matches the data..
147 wassert (byte1 >= 0xf0 || getMessageLengthFromFirstByte ((uint8) byte1) == 3);
148}
149
151 : timeStamp (other.timeStamp), size (other.size)
152{
153 if (isHeapAllocated())
154 memcpy (allocateSpace (size), other.getData(), (size_t) size);
155 else
156 packedData.allocatedData = other.packedData.allocatedData;
157}
158
159MidiMessage::MidiMessage (const MidiMessage& other, const double newTimeStamp)
160 : timeStamp (newTimeStamp), size (other.size)
161{
162 if (isHeapAllocated())
163 memcpy (allocateSpace (size), other.getData(), (size_t) size);
164 else
165 packedData.allocatedData = other.packedData.allocatedData;
166}
167
168MidiMessage::MidiMessage (const void* srcData, int sz, int& numBytesUsed, const uint8 lastStatusByte,
169 double t, bool sysexHasEmbeddedLength)
170 : timeStamp (t)
171{
172 const uint8* src = static_cast<const uint8*> (srcData);
173 unsigned int byte = (unsigned int) *src;
174
175 if (byte < 0x80)
176 {
177 byte = (unsigned int) (uint8) lastStatusByte;
178 numBytesUsed = -1;
179 }
180 else
181 {
182 numBytesUsed = 0;
183 --sz;
184 ++src;
185 }
186
187 if (byte >= 0x80)
188 {
189 if (byte == 0xf0)
190 {
191 const uint8* d = src;
192 bool haveReadAllLengthBytes = ! sysexHasEmbeddedLength;
193 int numVariableLengthSysexBytes = 0;
194
195 while (d < src + sz)
196 {
197 if (*d >= 0x80)
198 {
199 if (*d == 0xf7)
200 {
201 ++d; // include the trailing 0xf7 when we hit it
202 break;
203 }
204
205 if (haveReadAllLengthBytes) // if we see a 0x80 bit set after the initial data length
206 break; // bytes, assume it's the end of the sysex
207
208 ++numVariableLengthSysexBytes;
209 }
210 else if (! haveReadAllLengthBytes)
211 {
212 haveReadAllLengthBytes = true;
213 ++numVariableLengthSysexBytes;
214 }
215
216 ++d;
217 }
218
219 src += numVariableLengthSysexBytes;
220 size = 1 + (int) (d - src);
221
222 uint8* dest = allocateSpace (size);
223 *dest = (uint8) byte;
224 memcpy (dest + 1, src, (size_t) (size - 1));
225
226 numBytesUsed += numVariableLengthSysexBytes; // (these aren't counted in the size)
227 }
228 else if (byte == 0xff)
229 {
230 int n;
231 const int bytesLeft = readVariableLengthVal (src + 1, n);
232 size = jmin (sz + 1, n + 2 + bytesLeft);
233
234 uint8* dest = allocateSpace (size);
235 *dest = (uint8) byte;
236 memcpy (dest + 1, src, (size_t) size - 1);
237 }
238 else
239 {
241 packedData.asBytes[0] = (uint8) byte;
242
243 if (size > 1)
244 {
245 packedData.asBytes[1] = src[0];
246
247 if (size > 2)
248 packedData.asBytes[2] = src[1];
249 }
250 }
251
252 numBytesUsed += size;
253 }
254 else
255 {
256 packedData.allocatedData = nullptr;
257 size = 0;
258 }
259}
260
262{
263 if (this != &other)
264 {
265 if (other.isHeapAllocated())
266 {
267 if (isHeapAllocated())
268 packedData.allocatedData = static_cast<uint8*> (std::realloc (packedData.allocatedData, (size_t) other.size));
269 else
270 packedData.allocatedData = static_cast<uint8*> (std::malloc ((size_t) other.size));
271
272 memcpy (packedData.allocatedData, other.packedData.allocatedData, (size_t) other.size);
273 }
274 else
275 {
276 if (isHeapAllocated())
277 std::free (packedData.allocatedData);
278
279 packedData.allocatedData = other.packedData.allocatedData;
280 }
281
282 timeStamp = other.timeStamp;
283 size = other.size;
284 }
285
286 return *this;
287}
288
290{
291 if (isHeapAllocated())
292 std::free (packedData.allocatedData);
293}
294
296{
297 if (bytes > (int) sizeof (packedData))
298 {
299 uint8* d = static_cast<uint8*> (std::malloc ((size_t) bytes));
300 packedData.allocatedData = d;
301 return d;
302 }
303
304 return packedData.asBytes;
305}
306
308{
309 const uint8* const data = getData();
310
311 if ((data[0] & 0xf0) != 0xf0)
312 return (data[0] & 0xf) + 1;
313
314 return 0;
315}
316
317bool MidiMessage::isForChannel (const int channel) const noexcept
318{
319 wassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16
320
321 const uint8* const data = getData();
322
323 return ((data[0] & 0xf) == channel - 1)
324 && ((data[0] & 0xf0) != 0xf0);
325}
326
327void MidiMessage::setChannel (const int channel) noexcept
328{
329 wassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16
330
331 uint8* const data = getData();
332
333 if ((data[0] & 0xf0) != (uint8) 0xf0)
334 data[0] = (uint8) ((data[0] & (uint8) 0xf0)
335 | (uint8)(channel - 1));
336}
337
338bool MidiMessage::isNoteOn (const bool returnTrueForVelocity0) const noexcept
339{
340 const uint8* const data = getData();
341
342 return ((data[0] & 0xf0) == 0x90)
343 && (returnTrueForVelocity0 || data[2] != 0);
344}
345
346bool MidiMessage::isNoteOff (const bool returnTrueForNoteOnVelocity0) const noexcept
347{
348 const uint8* const data = getData();
349
350 return ((data[0] & 0xf0) == 0x80)
351 || (returnTrueForNoteOnVelocity0 && (data[2] == 0) && ((data[0] & 0xf0) == 0x90));
352}
353
355{
356 const uint8* const data = getData();
357
358 const int d = data[0] & 0xf0;
359 return (d == 0x90) || (d == 0x80);
360}
361
363{
364 return getData()[1];
365}
366
367void MidiMessage::setNoteNumber (const int newNoteNumber) noexcept
368{
369 if (isNoteOnOrOff() || isAftertouch())
370 getData()[1] = (uint8) (newNoteNumber & 127);
371}
372
374{
375 if (isNoteOnOrOff())
376 return getData()[2];
377
378 return 0;
379}
380
382{
383 return getVelocity() * (1.0f / 127.0f);
384}
385
386void MidiMessage::setVelocity (const float newVelocity) noexcept
387{
388 if (isNoteOnOrOff())
389 getData()[2] = floatValueToMidiByte (newVelocity);
390}
391
392void MidiMessage::multiplyVelocity (const float scaleFactor) noexcept
393{
394 if (isNoteOnOrOff())
395 {
396 uint8* const data = getData();
397 data[2] = MidiHelpers::validVelocity (roundToInt (scaleFactor * data[2]));
398 }
399}
400
402{
403 return (getData()[0] & 0xf0) == 0xa0;
404}
405
411
413 const int noteNum,
414 const int aftertouchValue) noexcept
415{
416 wassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16
417 wassert (isPositiveAndBelow (noteNum, (int) 128));
418 wassert (isPositiveAndBelow (aftertouchValue, (int) 128));
419
420 return MidiMessage (MidiHelpers::initialByte (0xa0, channel),
421 noteNum & 0x7f,
422 aftertouchValue & 0x7f);
423}
424
426{
427 return (getData()[0] & 0xf0) == 0xd0;
428}
429
435
436MidiMessage MidiMessage::channelPressureChange (const int channel, const int pressure) noexcept
437{
438 wassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16
439 wassert (isPositiveAndBelow (pressure, (int) 128));
440
441 return MidiMessage (MidiHelpers::initialByte (0xd0, channel), pressure & 0x7f);
442}
443
446
449
452
453
455{
456 return (getData()[0] & 0xf0) == 0xc0;
457}
458
464
465MidiMessage MidiMessage::programChange (const int channel, const int programNumber) noexcept
466{
467 wassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16
468
469 return MidiMessage (MidiHelpers::initialByte (0xc0, channel), programNumber & 0x7f);
470}
471
473{
474 return (getData()[0] & 0xf0) == 0xe0;
475}
476
478{
480 const uint8* const data = getData();
481 return data[1] | (data[2] << 7);
482}
483
484MidiMessage MidiMessage::pitchWheel (const int channel, const int position) noexcept
485{
486 wassert (channel > 0 && channel <= 16); // valid channels are numbered 1 to 16
487 wassert (isPositiveAndBelow (position, (int) 0x4000));
488
489 return MidiMessage (MidiHelpers::initialByte (0xe0, channel),
490 position & 127, (position >> 7) & 127);
491}
492
494{
495 return (getData()[0] & 0xf0) == 0xb0;
496}
497
498bool MidiMessage::isControllerOfType (const int controllerType) const noexcept
499{
500 const uint8* const data = getData();
501 return (data[0] & 0xf0) == 0xb0 && data[1] == controllerType;
502}
503
509
515
516MidiMessage MidiMessage::controllerEvent (const int channel, const int controllerType, const int value) noexcept
517{
518 // the channel must be between 1 and 16 inclusive
519 wassert (channel > 0 && channel <= 16);
520
521 return MidiMessage (MidiHelpers::initialByte (0xb0, channel),
522 controllerType & 127, value & 127);
523}
524
525MidiMessage MidiMessage::noteOn (const int channel, const int noteNumber, const uint8 velocity) noexcept
526{
527 wassert (channel > 0 && channel <= 16);
528 wassert (isPositiveAndBelow (noteNumber, (int) 128));
529
530 return MidiMessage (MidiHelpers::initialByte (0x90, channel),
531 noteNumber & 127, MidiHelpers::validVelocity (velocity));
532}
533
534MidiMessage MidiMessage::noteOn (const int channel, const int noteNumber, const float velocity) noexcept
535{
536 return noteOn (channel, noteNumber, floatValueToMidiByte (velocity));
537}
538
539MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber, uint8 velocity) noexcept
540{
541 wassert (channel > 0 && channel <= 16);
542 wassert (isPositiveAndBelow (noteNumber, (int) 128));
543
544 return MidiMessage (MidiHelpers::initialByte (0x80, channel),
545 noteNumber & 127, MidiHelpers::validVelocity (velocity));
546}
547
548MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber, float velocity) noexcept
549{
550 return noteOff (channel, noteNumber, floatValueToMidiByte (velocity));
551}
552
553MidiMessage MidiMessage::noteOff (const int channel, const int noteNumber) noexcept
554{
555 wassert (channel > 0 && channel <= 16);
556 wassert (isPositiveAndBelow (noteNumber, (int) 128));
557
558 return MidiMessage (MidiHelpers::initialByte (0x80, channel), noteNumber & 127, 0);
559}
560
561MidiMessage MidiMessage::allNotesOff (const int channel) noexcept
562{
563 return controllerEvent (channel, 123, 0);
564}
565
567{
568 const uint8* const data = getData();
569 return (data[0] & 0xf0) == 0xb0 && data[1] == 123;
570}
571
572MidiMessage MidiMessage::allSoundOff (const int channel) noexcept
573{
574 return controllerEvent (channel, 120, 0);
575}
576
578{
579 const uint8* const data = getData();
580 return (data[0] & 0xf0) == 0xb0 && data[1] == 120;
581}
582
583MidiMessage MidiMessage::allControllersOff (const int channel) noexcept
584{
585 return controllerEvent (channel, 121, 0);
586}
587
589{
590 const int vol = jlimit (0, 0x3fff, roundToInt (volume * 0x4000));
591
592 const uint8 buf[] = { 0xf0, 0x7f, 0x7f, 0x04, 0x01,
593 (uint8) (vol & 0x7f),
594 (uint8) (vol >> 7),
595 0xf7 };
596
597 return MidiMessage (buf, 8);
598}
599
600//==============================================================================
602{
603 return *getData() == 0xf0;
604}
605
606MidiMessage MidiMessage::createSysExMessage (const void* sysexData, const int dataSize)
607{
609 CARLA_SAFE_ASSERT_RETURN(m.malloc((size_t) dataSize + 2U), MidiMessage());
610
611 m[0] = 0xf0;
612 memcpy (m + 1, sysexData, (size_t) dataSize);
613 m[dataSize + 1] = 0xf7;
614
615 return MidiMessage (m, dataSize + 2);
616}
617
619{
620 return isSysEx() ? getData() + 1 : nullptr;
621}
622
624{
625 return isSysEx() ? size - 2 : 0;
626}
627
628//==============================================================================
629bool MidiMessage::isMetaEvent() const noexcept { return *getData() == 0xff; }
631
633{
634 const uint8* const data = getData();
635 return *data != 0xff ? -1 : data[1];
636}
637
639{
640 const uint8* const data = getData();
641 if (*data == 0xff)
642 {
643 int n;
644 return jmin (size - 2, readVariableLengthVal (data + 2, n));
645 }
646
647 return 0;
648}
649
651{
653
654 int n;
655 const uint8* d = getData() + 2;
657 return d + n;
658}
659
660bool MidiMessage::isTempoMetaEvent() const noexcept { const uint8* data = getData(); return (data[1] == 81) && (*data == 0xff); }
661bool MidiMessage::isMidiChannelMetaEvent() const noexcept { const uint8* data = getData(); return (data[1] == 0x20) && (*data == 0xff) && (data[2] == 1); }
662
668
670{
671 if (! isTempoMetaEvent())
672 return 0.0;
673
674 const uint8* const d = getMetaEventData();
675
676 return (((unsigned int) d[0] << 16)
677 | ((unsigned int) d[1] << 8)
678 | d[2])
679 / 1000000.0;
680}
681
682double MidiMessage::getTempoMetaEventTickLength (const short timeFormat) const noexcept
683{
684 if (timeFormat > 0)
685 {
686 if (! isTempoMetaEvent())
687 return 0.5 / timeFormat;
688
689 return getTempoSecondsPerQuarterNote() / timeFormat;
690 }
691 else
692 {
693 const int frameCode = (-timeFormat) >> 8;
694 double framesPerSecond;
695
696 switch (frameCode)
697 {
698 case 24: framesPerSecond = 24.0; break;
699 case 25: framesPerSecond = 25.0; break;
700 case 29: framesPerSecond = 29.97; break;
701 case 30: framesPerSecond = 30.0; break;
702 default: framesPerSecond = 30.0; break;
703 }
704
705 return (1.0 / framesPerSecond) / (timeFormat & 0xff);
706 }
707}
708
709MidiMessage MidiMessage::tempoMetaEvent (int microsecondsPerQuarterNote) noexcept
710{
711 const uint8 d[] = { 0xff, 81, 3,
712 (uint8) (microsecondsPerQuarterNote >> 16),
713 (uint8) (microsecondsPerQuarterNote >> 8),
714 (uint8) microsecondsPerQuarterNote };
715
716 return MidiMessage (d, 6, 0.0);
717}
718
720{
721 const uint8* const data = getData();
722 return (data[1] == 0x58) && (*data == (uint8) 0xff);
723}
724
725void MidiMessage::getTimeSignatureInfo (int& numerator, int& denominator) const noexcept
726{
728 {
729 const uint8* const d = getMetaEventData();
730 numerator = d[0];
731 denominator = 1 << d[1];
732 }
733 else
734 {
735 numerator = 4;
736 denominator = 4;
737 }
738}
739
740MidiMessage MidiMessage::timeSignatureMetaEvent (const int numerator, const int denominator)
741{
742 int n = 1;
743 int powerOfTwo = 0;
744
745 while (n < denominator)
746 {
747 n <<= 1;
748 ++powerOfTwo;
749 }
750
751 const uint8 d[] = { 0xff, 0x58, 0x04, (uint8) numerator, (uint8) powerOfTwo, 1, 96 };
752 return MidiMessage (d, 7, 0.0);
753}
754
756{
757 const uint8 d[] = { 0xff, 0x20, 0x01, (uint8) jlimit (0, 0xff, channel - 1) };
758 return MidiMessage (d, 4, 0.0);
759}
760
765
770
775
776MidiMessage MidiMessage::keySignatureMetaEvent (int numberOfSharpsOrFlats, bool isMinorKey)
777{
778 wassert (numberOfSharpsOrFlats >= -7 && numberOfSharpsOrFlats <= 7);
779
780 const uint8 d[] = { 0xff, 0x59, 0x02, (uint8) numberOfSharpsOrFlats, isMinorKey ? (uint8) 1 : (uint8) 0 };
781 return MidiMessage (d, 5, 0.0);
782}
783
784//==============================================================================
787
788MidiMessage MidiMessage::songPositionPointer (const int positionInMidiBeats) noexcept
789{
790 return MidiMessage (0xf2,
791 positionInMidiBeats & 127,
792 (positionInMidiBeats >> 7) & 127);
793}
794
795bool MidiMessage::isMidiStart() const noexcept { return *getData() == 0xfa; }
797
800
801bool MidiMessage::isMidiStop() const noexcept { return *getData() == 0xfc; }
803
804bool MidiMessage::isMidiClock() const noexcept { return *getData() == 0xf8; }
806
809int MidiMessage::getQuarterFrameValue() const noexcept { return ((int) getData()[1]) & 0x0f; }
810
811MidiMessage MidiMessage::quarterFrame (const int sequenceNumber, const int value) noexcept
812{
813 return MidiMessage (0xf1, (sequenceNumber << 4) | value);
814}
815
817{
818 const uint8* const data = getData();
819
820 return data[0] == 0xf0
821 && data[1] == 0x7f
822 && size >= 10
823 && data[3] == 0x01
824 && data[4] == 0x01;
825}
826
827void MidiMessage::getFullFrameParameters (int& hours, int& minutes, int& seconds, int& frames,
828 MidiMessage::SmpteTimecodeType& timecodeType) const noexcept
829{
831
832 const uint8* const data = getData();
833 timecodeType = (SmpteTimecodeType) (data[5] >> 5);
834 hours = data[5] & 0x1f;
835 minutes = data[6];
836 seconds = data[7];
837 frames = data[8];
838}
839
840MidiMessage MidiMessage::fullFrame (const int hours, const int minutes,
841 const int seconds, const int frames,
843{
844 const uint8 d[] = { 0xf0, 0x7f, 0x7f, 0x01, 0x01,
845 (uint8) ((hours & 0x01f) | (timecodeType << 5)),
846 (uint8) minutes,
847 (uint8) seconds,
848 (uint8) frames,
849 0xf7 };
850
851 return MidiMessage (d, 10, 0.0);
852}
853
855{
856 const uint8* const data = getData();
857 return data[0] == 0xf0
858 && data[1] == 0x7f
859 && data[3] == 0x06
860 && size > 5;
861}
862
869
871{
872 const uint8 d[] = { 0xf0, 0x7f, 0, 6, (uint8) command, 0xf7 };
873
874 return MidiMessage (d, 6, 0.0);
875}
876
877//==============================================================================
878bool MidiMessage::isMidiMachineControlGoto (int& hours, int& minutes, int& seconds, int& frames) const noexcept
879{
880 const uint8* const data = getData();
881 if (size >= 12
882 && data[0] == 0xf0
883 && data[1] == 0x7f
884 && data[3] == 0x06
885 && data[4] == 0x44
886 && data[5] == 0x06
887 && data[6] == 0x01)
888 {
889 hours = data[7] % 24; // (that some machines send out hours > 24)
890 minutes = data[8];
891 seconds = data[9];
892 frames = data[10];
893
894 return true;
895 }
896
897 return false;
898}
899
900MidiMessage MidiMessage::midiMachineControlGoto (int hours, int minutes, int seconds, int frames)
901{
902 const uint8 d[] = { 0xf0, 0x7f, 0, 6, 0x44, 6, 1,
903 (uint8) hours,
904 (uint8) minutes,
905 (uint8) seconds,
906 (uint8) frames,
907 0xf7 };
908
909 return MidiMessage (d, 12, 0.0);
910}
911
912//==============================================================================
913double MidiMessage::getMidiNoteInHertz (const int noteNumber, const double frequencyOfA) noexcept
914{
915 return frequencyOfA * pow (2.0, (noteNumber - 69) / 12.0);
916}
917
918bool MidiMessage::isMidiNoteBlack (int noteNumber) noexcept
919{
920 return ((1 << (noteNumber % 12)) & 0x054a) != 0;
921}
922
923}
#define CARLA_SAFE_ASSERT_RETURN(cond, ret)
Definition CarlaDefines.h:190
#define noexcept
Definition DistrhoDefines.h:72
CAdPlugDatabase::CRecord::RecordType type
Definition adplugdb.cpp:93
Definition HeapBlock.h:77
bool isNoteOnOrOff() const noexcept
Definition MidiMessage.cpp:354
bool isSongPositionPointer() const noexcept
Definition MidiMessage.cpp:785
bool isForChannel(int channelNumber) const noexcept
Definition MidiMessage.cpp:317
static double getMidiNoteInHertz(int noteNumber, double frequencyOfA=440.0) noexcept
Definition MidiMessage.cpp:913
bool isSostenutoPedalOff() const noexcept
Definition MidiMessage.cpp:448
int getKeySignatureNumberOfSharpsOrFlats() const noexcept
Definition MidiMessage.cpp:766
static MidiMessage midiMachineControlGoto(int hours, int minutes, int seconds, int frames)
Definition MidiMessage.cpp:900
bool isProgramChange() const noexcept
Definition MidiMessage.cpp:454
void getTimeSignatureInfo(int &numerator, int &denominator) const noexcept
Definition MidiMessage.cpp:725
const uint8 * getSysExData() const noexcept
Definition MidiMessage.cpp:618
static MidiMessage allControllersOff(int channel) noexcept
Definition MidiMessage.cpp:583
bool isMetaEvent() const noexcept
Definition MidiMessage.cpp:629
static MidiMessage createSysExMessage(const void *sysexData, int dataSize)
Definition MidiMessage.cpp:606
bool isAftertouch() const noexcept
Definition MidiMessage.cpp:401
bool isMidiMachineControlGoto(int &hours, int &minutes, int &seconds, int &frames) const noexcept
Definition MidiMessage.cpp:878
static MidiMessage noteOn(int channel, int noteNumber, float velocity) noexcept
Definition MidiMessage.cpp:534
static MidiMessage aftertouchChange(int channel, int noteNumber, int aftertouchAmount) noexcept
Definition MidiMessage.cpp:412
int getMidiChannelMetaEventChannel() const noexcept
Definition MidiMessage.cpp:663
bool isAllSoundOff() const noexcept
Definition MidiMessage.cpp:577
MidiMessage(int byte1, int byte2, int byte3, double timeStamp=0) noexcept
Definition MidiMessage.cpp:139
void setChannel(int newChannelNumber) noexcept
Definition MidiMessage.cpp:327
static MidiMessage midiStart() noexcept
Definition MidiMessage.cpp:796
static MidiMessage midiContinue() noexcept
Definition MidiMessage.cpp:799
bool isSostenutoPedalOn() const noexcept
Definition MidiMessage.cpp:447
bool isFullFrame() const noexcept
Definition MidiMessage.cpp:816
float getFloatVelocity() const noexcept
Definition MidiMessage.cpp:381
MidiMessage & operator=(const MidiMessage &other)
Definition MidiMessage.cpp:261
static MidiMessage noteOff(int channel, int noteNumber, float velocity) noexcept
Definition MidiMessage.cpp:548
static MidiMessage songPositionPointer(int positionInMidiBeats) noexcept
Definition MidiMessage.cpp:788
static MidiMessage allSoundOff(int channel) noexcept
Definition MidiMessage.cpp:572
static uint8 floatValueToMidiByte(float valueBetween0and1) noexcept
Definition MidiMessage.cpp:46
double timeStamp
Definition MidiMessage.h:844
static uint16 pitchbendToPitchwheelPos(float pitchbendInSemitones, float pitchbendRangeInSemitones) noexcept
Definition MidiMessage.cpp:51
MidiMachineControlCommand
Definition MidiMessage.h:743
bool isTimeSignatureMetaEvent() const noexcept
Definition MidiMessage.cpp:719
bool isActiveSense() const noexcept
Definition MidiMessage.cpp:630
bool isTempoMetaEvent() const noexcept
Definition MidiMessage.cpp:660
int getControllerNumber() const noexcept
Definition MidiMessage.cpp:504
bool isKeySignatureMajorKey() const noexcept
Definition MidiMessage.cpp:771
bool isMidiStart() const noexcept
Definition MidiMessage.cpp:795
static MidiMessage controllerEvent(int channel, int controllerType, int value) noexcept
Definition MidiMessage.cpp:516
uint8 * getData() noexcept
Definition MidiMessage.h:848
void setVelocity(float newVelocity) noexcept
Definition MidiMessage.cpp:386
void getFullFrameParameters(int &hours, int &minutes, int &seconds, int &frames, SmpteTimecodeType &timecodeType) const noexcept
Definition MidiMessage.cpp:827
bool isHeapAllocated() const noexcept
Definition MidiMessage.h:847
void setNoteNumber(int newNoteNumber) noexcept
Definition MidiMessage.cpp:367
int getSysExDataSize() const noexcept
Definition MidiMessage.cpp:623
int getMetaEventLength() const noexcept
Definition MidiMessage.cpp:638
bool isKeySignatureMetaEvent() const noexcept
Definition MidiMessage.cpp:761
int getControllerValue() const noexcept
Definition MidiMessage.cpp:510
static MidiMessage midiStop() noexcept
Definition MidiMessage.cpp:802
MidiMachineControlCommand getMidiMachineControlCommand() const noexcept
Definition MidiMessage.cpp:863
static MidiMessage channelPressureChange(int channel, int pressure) noexcept
Definition MidiMessage.cpp:436
static MidiMessage pitchWheel(int channel, int position) noexcept
Definition MidiMessage.cpp:484
uint8 * allocateSpace(int)
Definition MidiMessage.cpp:295
int getNoteNumber() const noexcept
Definition MidiMessage.cpp:362
bool isMidiChannelMetaEvent() const noexcept
Definition MidiMessage.cpp:661
SmpteTimecodeType
Definition MidiMessage.h:709
bool isMidiMachineControlMessage() const noexcept
Definition MidiMessage.cpp:854
static MidiMessage programChange(int channel, int programNumber) noexcept
Definition MidiMessage.cpp:465
static int readVariableLengthVal(const uint8 *data, int &numBytesUsed) noexcept
Definition MidiMessage.cpp:63
static MidiMessage midiChannelMetaEvent(int channel) noexcept
Definition MidiMessage.cpp:755
bool isSysEx() const noexcept
Definition MidiMessage.cpp:601
MidiMessage() noexcept
Definition MidiMessage.cpp:103
int getChannel() const noexcept
Definition MidiMessage.cpp:307
PackedData packedData
Definition MidiMessage.h:843
double getTempoMetaEventTickLength(short timeFormat) const noexcept
Definition MidiMessage.cpp:682
const uint8 * getMetaEventData() const noexcept
Definition MidiMessage.cpp:650
int getSongPositionPointerMidiBeat() const noexcept
Definition MidiMessage.cpp:786
bool isSustainPedalOn() const noexcept
Definition MidiMessage.cpp:444
static int getMessageLengthFromFirstByte(uint8 firstByte) noexcept
Definition MidiMessage.cpp:82
int getQuarterFrameSequenceNumber() const noexcept
Definition MidiMessage.cpp:808
double getTempoSecondsPerQuarterNote() const noexcept
Definition MidiMessage.cpp:669
bool isAllNotesOff() const noexcept
Definition MidiMessage.cpp:566
int getQuarterFrameValue() const noexcept
Definition MidiMessage.cpp:809
bool isSustainPedalOff() const noexcept
Definition MidiMessage.cpp:445
int size
Definition MidiMessage.h:845
bool isMidiContinue() const noexcept
Definition MidiMessage.cpp:798
static bool isMidiNoteBlack(int noteNumber) noexcept
Definition MidiMessage.cpp:918
static MidiMessage timeSignatureMetaEvent(int numerator, int denominator)
Definition MidiMessage.cpp:740
bool isChannelPressure() const noexcept
Definition MidiMessage.cpp:425
~MidiMessage() noexcept
Definition MidiMessage.cpp:289
bool isControllerOfType(int controllerType) const noexcept
Definition MidiMessage.cpp:498
static MidiMessage midiMachineControlCommand(MidiMachineControlCommand command)
Definition MidiMessage.cpp:870
static MidiMessage midiClock() noexcept
Definition MidiMessage.cpp:805
static MidiMessage allNotesOff(int channel) noexcept
Definition MidiMessage.cpp:561
bool isSoftPedalOff() const noexcept
Definition MidiMessage.cpp:451
bool isNoteOff(bool returnTrueForNoteOnVelocity0=true) const noexcept
Definition MidiMessage.cpp:346
void multiplyVelocity(float scaleFactor) noexcept
Definition MidiMessage.cpp:392
bool isMidiStop() const noexcept
Definition MidiMessage.cpp:801
static MidiMessage quarterFrame(int sequenceNumber, int value) noexcept
Definition MidiMessage.cpp:811
int getProgramChangeNumber() const noexcept
Definition MidiMessage.cpp:459
bool isNoteOn(bool returnTrueForVelocity0=false) const noexcept
Definition MidiMessage.cpp:338
static MidiMessage masterVolume(float volume)
Definition MidiMessage.cpp:588
bool isSoftPedalOn() const noexcept
Definition MidiMessage.cpp:450
static MidiMessage fullFrame(int hours, int minutes, int seconds, int frames, SmpteTimecodeType timecodeType)
Definition MidiMessage.cpp:840
bool isQuarterFrame() const noexcept
Definition MidiMessage.cpp:807
static MidiMessage keySignatureMetaEvent(int numberOfSharpsOrFlats, bool isMinorKey)
Definition MidiMessage.cpp:776
int getPitchWheelValue() const noexcept
Definition MidiMessage.cpp:477
bool isMidiClock() const noexcept
Definition MidiMessage.cpp:804
int getChannelPressureValue() const noexcept
Definition MidiMessage.cpp:430
bool isPitchWheel() const noexcept
Definition MidiMessage.cpp:472
int getMetaEventType() const noexcept
Definition MidiMessage.cpp:632
bool isController() const noexcept
Definition MidiMessage.cpp:493
int getAfterTouchValue() const noexcept
Definition MidiMessage.cpp:406
static MidiMessage tempoMetaEvent(int microsecondsPerQuarterNote) noexcept
Definition MidiMessage.cpp:709
uint8 getVelocity() const noexcept
Definition MidiMessage.cpp:373
unsigned * m
Definition inflate.c:1559
struct huft * t
Definition inflate.c:943
unsigned v[N_MAX]
Definition inflate.c:1584
unsigned d
Definition inflate.c:940
register unsigned i
Definition inflate.c:1575
static PuglViewHint int value
Definition pugl.h:1708
JSAMPIMAGE data
Definition jpeglib.h:945
#define wassert(expression)
Definition MidiMessage.cpp:33
uint8 validVelocity(const int v) noexcept
Definition MidiMessage.cpp:39
uint8 initialByte(const int type, const int channel) noexcept
Definition MidiMessage.cpp:34
Definition AudioSampleBuffer.h:33
int roundToInt(const FloatType value) noexcept
Definition MathsFunctions.h:346
Type jmin(const Type a, const Type b)
Definition MathsFunctions.h:60
bool isPositiveAndBelow(Type valueToTest, Type upperLimit) noexcept
Definition MathsFunctions.h:187
Type jmap(Type value0To1, Type targetRangeMin, Type targetRangeMax)
Definition MathsFunctions.h:74
unsigned short uint16
Definition water.h:94
unsigned char uint8
Definition water.h:90
Type jlimit(const Type lowerLimit, const Type upperLimit, const Type valueToConstrain) noexcept
Definition MathsFunctions.h:169
signed char int8
Definition water.h:88
static float volume(float level)
Definition nekobee_voice_render.c:99
uint8 * allocatedData
Definition MidiMessage.h:839
int n
Definition crypt.c:458
memcpy(hh, h, RAND_HEAD_LEN)
ulg size
Definition extract.c:2350
typedef int(UZ_EXP MsgFn)()
#define const
Definition zconf.h:137