commit 9adde15788d76580f136d81e7f94f187f10a5c0d
parent 2f679331cf23420e8980c36a2b60c139e50e0ceb
Author: Alexandre Bique <bique.alexandre@gmail.com>
Date: Fri, 31 Oct 2014 11:45:41 +0100
Initial midi parser
Diffstat:
2 files changed, 154 insertions(+), 0 deletions(-)
diff --git a/include/clap/clap-midi-parser.c b/include/clap/clap-midi-parser.c
@@ -0,0 +1,65 @@
+static inline uint16_t
+clap_midi_parse_be16(const uint8_t *in)
+{
+ return (in[0] << 8) | in[1];
+}
+
+static inline uint32_t
+clap_midi_parse_be32(const uint8_t *in)
+{
+ return (in[0] << 24) | (in[1] << 16) | (in[2] << 8) | in[3];
+}
+
+static inline enum clap_midi_parser_status
+clap_midi_parse_header(struct clap_midi_parser *parser)
+{
+ if (paser->size < 14)
+ return CLAP_MIDI_PARSER_EOB;
+
+ if (memcmp(parser->in, "MThd"))
+ return CLAP_MIDI_PARSER_ERROR;
+
+ parser->header.size = clap_midi_parse_be32(parser->in + 4);
+ parser->header.format = clap_midi_parse_be16(parser->in + 8);
+ parser->header.tracks_count = clap_midi_parse_be16(parser->in + 10);
+ parser->header.time_division = clap_midi_parse_be16(parser->in + 12);
+
+ parser->in += 14;
+ parser->size -= 14;
+ parser->state = CLAP_MIDI_PARSER_HEADER;
+ return CLAP_MIDI_PARSER_HEADER;
+}
+
+static inline enum clap_midi_parser_status
+clap_midi_parse_track(struct clap_midi_parser *parser)
+{
+ if (paser->size < 8)
+ return CLAP_MIDI_PARSER_EOB;
+
+ parser->track.size = clap_midi_parse_be32(parser->in + 4);
+
+ parser->in += 8;
+ parser->size -= 8;
+ return CLAP_MIDI_PARSER_HEADER;
+}
+
+static inline enum clap_midi_parser_status
+clap_midi_parse(struct clap_midi_parser *parser)
+{
+ if (!parser->in || parser->size < 4)
+ return CLAP_MIDI_PARSER_EOB;
+
+ switch (parser->state) {
+ case CLAP_MIDI_PARSER_INIT:
+ return clap_midi_parse_header(parser);
+
+ case CLAP_MIDI_PARSER_HEADER:
+ return clap_midi_parse_track(parser);
+
+ case CLAP_MIDI_PARSER_TRACK:
+ return clap_midi_parse_event(parser);
+
+ default:
+ return CLAP_MIDI_PARSER_ERROR;
+ }
+}
diff --git a/include/clap/clap-midi-parser.h b/include/clap/clap-midi-parser.h
@@ -0,0 +1,89 @@
+#ifndef CLAP_MIDI_PARSER_H
+# define CLAP_MIDI_PARSER_H
+
+# include <stdint.h>
+# include <string.h>
+
+enum clap_midi_parser_status
+{
+ CLAP_MIDI_PARSER_EOB = -2,
+ CLAP_MIDI_PARSER_ERROR = -1,
+ CLAP_MIDI_PARSER_INIT = 0,
+ CLAP_MIDI_PARSER_HEADER = 1,
+ CLAP_MIDI_PARSER_TRACK = 2,
+ CLAP_MIDI_PARSER_CHANNEL = 3,
+ CLAP_MIDI_PARSER_META = 4,
+ CLAP_MIDI_PARSER_SYSEX = 5,
+};
+
+struct clap_midi_header
+{
+ uint32_t size;
+ uint16_t format;
+ uint16_t tracks_count;
+ uint16_t time_division;
+};
+
+struct clap_midi_track
+{
+ uint32_t size;
+};
+
+enum clap_midi_channel_event_type
+{
+ CLAP_MIDI_CHANNEL_NOTE_OFF = 0x8,
+ CLAP_MIDI_CHANNEL_NOTE_ON = 0x9,
+ CLAP_MIDI_CHANNEL_NOTE_AT = 0xA, // after touch
+ CLAP_MIDI_CHANNEL_CC = 0xB, // control change
+ CLAP_MIDI_CHANNEL_PGM_CHANGE = 0xC,
+ CLAP_MIDI_CHANNEL_CHANNEL_AT = 0xD, // after touch
+ CLAP_MIDI_CHANNEL_PITCH_BEND = 0xF,
+};
+
+struct clap_midi_channel_event
+{
+ uint64_t delta_time;
+ unsigned event_type : 4;
+ unsigned channel : 4;
+ uint8_t param1;
+ uint8_t param2;
+};
+
+struct clap_midi_meta_event
+{
+ uint8_t type;
+ uint32_t lenght;
+ const uint8_t *bytes; // reference to the input buffer
+};
+
+struct clap_midi_sysex_event
+{
+ uint8_t sysex;
+ uint8_t type;
+ uint32_t lenght;
+ const uint8_t *bytes; // reference to the input buffer
+};
+
+struct clap_midi_parser
+{
+ enum clap_midi_parser_status state;
+
+ /* input buffer */
+ const uint8_t *in;
+ uint32_t size;
+
+ union {
+ struct clap_midi_header header;
+ struct clap_midi_track track;
+ struct clap_midi_channel_event channel;
+ struct clap_midi_meta_event meta;
+ struct clap_midi_sysex_event sysex;
+ };
+};
+
+static inline enum clap_midi_parser_status
+clap_midi_parse(struct clap_midi_parser *parser);
+
+# include "clap-midi-parser.c"
+
+#endif /* !CLAP_MIDI_PARSER_H */