44* Midi utilities library for angelscript
55*
66* Created by Blue Cat Audio <[email protected] > 7- * Copyright 2011-2017 Blue Cat Audio. All rights reserved.
7+ * Copyright 2011-2025 Blue Cat Audio. All rights reserved.
88*
99*/
1010
@@ -20,6 +20,13 @@ enum MidiEventType
2020 kMidiPitchWheel , // /< Pitch Wheel Event
2121 kMidiNoteAfterTouch , // /< Note after touch
2222 kMidiChannelAfterTouch , // /< Channel after touch
23+ kSysexStart , // /< Sysex stream start event (may also contain beginning of data stream)
24+ kSysexEnd , // /< Sysex stream end event (may also contain end of data stream)
25+ kBeatClock , // /< MIDI Beat Clock Event
26+ kStart , // /< MIDI Start Event
27+ kSongPointer , // /< MIDI Song Pointer Position Event
28+ kContinue , // /< MIDI Continue Event
29+ kStop , // /< MIDI Stop Event
2330 kUnknown // /< Other Events
2431};
2532
@@ -35,6 +42,7 @@ namespace MidiEventUtils
3542 MidiEventType getType (const MidiEvent& evt)
3643 {
3744 MidiEventType type=kUnknown ;
45+ // Channel Events
3846 switch (evt.byte0 & 0xF0 )
3947 {
4048 case 0x80 :
@@ -59,6 +67,49 @@ namespace MidiEventUtils
5967 type=kMidiChannelAfterTouch ;
6068 break ;
6169 }
70+
71+ // None of these? Check full byte
72+ if (type == kUnknown )
73+ {
74+ // channel-independent messages
75+ switch (evt.byte0 )
76+ {
77+ case 0xF0 :
78+ type = kSysexStart ;
79+ break ;
80+ case 0xF7 :
81+ type = kSysexEnd ;
82+ break ;
83+ case 0xF8 :
84+ type = kBeatClock ;
85+ break ;
86+ case 0xFA :
87+ type = kStart ;
88+ break ;
89+ case 0xFB :
90+ type = kContinue ;
91+ break ;
92+ case 0xFC :
93+ type = kStop ;
94+ break ;
95+ case 0xF2 :
96+ type = kSongPointer ;
97+ break ;
98+ }
99+
100+ if (type == kUnknown )
101+ {
102+ // sysex end can be anywhere else in the event
103+ for (int i = 1 ; i < 4 ; i++)
104+ {
105+ if (getEventByte (evt,i) == 0xF7 )
106+ {
107+ type = kSysexEnd ;
108+ break ;
109+ }
110+ }
111+ }
112+ }
62113 return type;
63114 }
64115
@@ -90,6 +141,27 @@ namespace MidiEventUtils
90141 case kMidiChannelAfterTouch :
91142 evt.byte0 =0xD0 |(evt.byte0 & 0x0F );
92143 break ;
144+ case kSysexStart :
145+ evt.byte0 = 0xF0 ;
146+ break ;
147+ case kSysexEnd :
148+ evt.byte0 = 0xF7 ;
149+ break ;
150+ case kBeatClock :
151+ evt.byte0 = 0xF8 ;
152+ break ;
153+ case kStart :
154+ evt.byte0 = 0xFA ;
155+ break ;
156+ case kContinue :
157+ evt.byte0 = 0xFB ;
158+ break ;
159+ case kStop :
160+ evt.byte0 = 0xFC ;
161+ break ;
162+ case kSongPointer :
163+ evt.byte0 = 0xF2 ;
164+ break ;
93165 }
94166 }
95167
@@ -223,4 +295,110 @@ namespace MidiEventUtils
223295 {
224296 evt.byte1 =(value&0x7F );;
225297 }
298+
299+
300+ /* * Utility function to read event bytes programmatically.
301+ *
302+ */
303+ uint8 getEventByte (const MidiEvent& event, uint index)
304+ {
305+ switch (index)
306+ {
307+ case 0 :
308+ return event.byte0 ;
309+ case 1 :
310+ return event.byte1 ;
311+ case 2 :
312+ return event.byte2 ;
313+ case 3 :
314+ return event.byte3 ;
315+ }
316+ return 0 ;
317+ }
318+
319+ /* * Utility function to set event bytes programmatically.
320+ *
321+ */
322+ void setEventByte (MidiEvent& event, uint index, uint8 value)
323+ {
324+ switch (index)
325+ {
326+ case 0 :
327+ event.byte0 = value;
328+ break ;
329+ case 1 :
330+ event.byte1 = value;
331+ break ;
332+ case 2 :
333+ event.byte2 = value;
334+ break ;
335+ case 3 :
336+ event.byte3 = value;
337+ break ;
338+ }
339+ }
340+
341+ /* * Utility function to finish a sysex stream in a midi event.
342+ * Returns true is there was enough room left in the event to write Sysex stream end
343+ */
344+ bool finishSysex (MidiEvent& event, uint nextByteIndex)
345+ {
346+ bool done = false ;
347+ // finish Sysex stream with 0xF7 status byte
348+ if (nextByteIndex < 4 )
349+ {
350+ setEventByte (event, nextByteIndex, 0xF7 );
351+ done = true ;
352+ nextByteIndex++;
353+
354+ // fill other bytes with zeros
355+ while (nextByteIndex < 4 )
356+ {
357+ setEventByte (event, nextByteIndex, 0 );
358+ nextByteIndex++;
359+ }
360+ }
361+ return done;
362+ }
363+
364+ /* * Returns true if the event contains SysEx data.
365+ *
366+ */
367+ bool isSysexData (const MidiEvent& evt)
368+ {
369+ bool isSysex = true ;
370+ for (int i = 0 ; i < 4 && isSysex; i++)
371+ {
372+ const uint8 b = getEventByte (evt,i);
373+ isSysex = (b < 0x80 || b == 0xF0 || b == 0xF7 );
374+ }
375+ return isSysex;
376+ }
377+
378+ /* * Returns true for system realtime events.
379+ *
380+ */
381+ bool isSystemRealtime (const MidiEvent& evt)
382+ {
383+ const uint8 b = evt.byte0 ;
384+ bool isRT = b >= 0xfa || b == 0xf8 ;
385+ return isRT;
386+ }
387+
388+ /* * For a Song Pointer Position Event, returns the position in the song (in sixteenth notes).
389+ *
390+ */
391+ int getSongPointerPosition (const MidiEvent& evt)
392+ {
393+ return ((evt.byte1 & 0x7F ) | ((evt.byte2 & 0x7F ) << 7 ));
394+ }
395+
396+ /* * For a Song Pointer Position Event, sets the position in the song (in sixteenth notes).
397+ *
398+ */
399+ void setSongPointerPosition (MidiEvent& evt, int posIn16thNotes)
400+ {
401+ evt.byte1 = posIn16thNotes & 0x7F ;
402+ evt.byte2 = (posIn16thNotes >> 7 ) & 0x7F ;
403+ }
226404}
0 commit comments