commit 33870d38ec7ba6376b0c61d0c12299e591d88488
parent 5765b805215b0282fa11c47943ee0013a849a03a
Author: Alexandre Bique <bique.alexandre@gmail.com>
Date: Thu, 29 Sep 2016 15:20:41 +0200
midi helper: bug fixes and improvements
Diffstat:
3 files changed, 55 insertions(+), 8 deletions(-)
diff --git a/include/clap/helpers/midi-parser.c b/include/clap/helpers/midi-parser.c
@@ -154,15 +154,15 @@ clap_midi_parse_be32(const uint8_t *in)
return (in[0] << 24) | (in[1] << 16) | (in[2] << 8) | in[3];
}
-static inline uint32_t
+static inline uint64_t
clap_midi_parse_variable_length(struct clap_midi_parser *parser, int32_t *offset)
{
- uint32_t value = 0;
- int32_t i = *offset;
+ uint64_t value = 0;
+ int32_t i = *offset;
for (; i < parser->size; ++i) {
value = (value << 7) | (parser->in[i] & 0x7f);
- if (!(parser->in[i] & 0x8f))
+ if (!(parser->in[i] & 0x80))
break;
}
*offset = i + 1;
@@ -202,6 +202,29 @@ clap_midi_parse_track(struct clap_midi_parser *parser)
return CLAP_MIDI_PARSER_TRACK;
}
+static inline bool
+clap_midi_parse_vtime(struct clap_midi_parser * restrict parser)
+{
+ uint8_t nbytes = 0;
+ bool cont = false; // continue flag
+
+ parser->vtime = 0;
+ for (nbytes = 0; cont; ++nbytes) {
+ if (parser->size < 1 + nbytes)
+ return false;
+
+ uint8_t b = parser->in[nbytes];
+ parser->vtime = (parser->vtime << 7) | (b & 0x7f);
+
+ cont = b & 0x80;
+ }
+
+ parser->in += nbytes;
+ parser->size -= nbytes;
+
+ return true;
+}
+
static inline enum clap_midi_parser_status
clap_midi_parse_channel_event(struct clap_midi_parser *parser)
{
@@ -246,7 +269,10 @@ clap_midi_parse_meta_event(struct clap_midi_parser *parser)
static inline enum clap_midi_parser_status
clap_midi_parse_event(struct clap_midi_parser *parser)
{
- if ((parser->in[0] >> 4) <= 0xe)
+ if (!clap_midi_parse_vtime(parser))
+ return CLAP_MIDI_PARSER_EOB;
+
+ if (parser->in[0] < 0xf0)
return clap_midi_parse_channel_event(parser);
if (parser->in[0] == 0xff)
return clap_midi_parse_meta_event(parser);
diff --git a/include/clap/helpers/midi-parser.h b/include/clap/helpers/midi-parser.h
@@ -24,6 +24,23 @@ enum clap_midi_parser_status
CLAP_MIDI_PARSER_TRACK_SYSEX = 5,
};
+enum clap_midi_file_format
+{
+ CLAP_MIDI_FILE_FORMAT_SINGLE_TRACK = 0,
+ CLAP_MIDI_FILE_FORMAT_MULTIPLE_TRACKS = 1,
+ CLAP_MIDI_FILE_FORMAT_MULTIPLE_SONGS = 2,
+};
+
+static const char *
+clap_midi_file_format_name(int fmt)
+{
+ switch (fmt) {
+ case CLAP_MIDI_FILE_FORMAT_SINGLE_TRACK: return "single track";
+ case CLAP_MIDI_FILE_FORMAT_MULTIPLE_TRACKS: return "multiple tracks";
+ case CLAP_MIDI_FILE_FORMAT_MULTIPLE_SONGS: return "multiple songs";
+ }
+}
+
struct clap_midi_header
{
int32_t size;
@@ -50,7 +67,6 @@ enum clap_midi_channel_event_type
struct clap_midi_channel_event
{
- int64_t delta_time;
unsigned event_type : 4;
unsigned channel : 4;
uint8_t param1;
@@ -81,6 +97,7 @@ struct clap_midi_parser
int32_t size;
/* result */
+ int64_t vtime;
struct clap_midi_header header;
struct clap_midi_track track;
struct clap_midi_channel_event channel;
diff --git a/tests/midi-parser/midi-parser.c b/tests/midi-parser/midi-parser.c
@@ -34,18 +34,20 @@ void parse_and_dump(struct clap_midi_parser *parser)
case CLAP_MIDI_PARSER_HEADER:
printf("header\n");
printf(" size: %d\n", parser->header.size);
- printf(" format: %d\n", parser->header.format);
+ printf(" format: %d [%s]\n", parser->header.format, clap_midi_file_format_name(parser->header.format));
printf(" tracks count: %d\n", parser->header.tracks_count);
printf(" time division: %d\n", parser->header.time_division);
break;
case CLAP_MIDI_PARSER_TRACK:
puts("track");
+ printf(" length: %d\n", parser->track.size);
break;
case CLAP_MIDI_PARSER_TRACK_MIDI:
puts("track-midi");
- printf(" event type: %d\n", parser->channel.event_type);
+ printf(" time: %d\n", parser->vtime);
+ printf(" type: %d\n", parser->channel.event_type);
printf(" channel: %d\n", parser->channel.channel);
printf(" param1: %d\n", parser->channel.param1);
printf(" param2: %d\n", parser->channel.param2);
@@ -53,12 +55,14 @@ void parse_and_dump(struct clap_midi_parser *parser)
case CLAP_MIDI_PARSER_TRACK_META:
printf("track-meta\n");
+ printf(" time: %d\n", parser->vtime);
printf(" type: %d\n", parser->meta.type);
printf(" length: %d\n", parser->meta.length);
break;
case CLAP_MIDI_PARSER_TRACK_SYSEX:
puts("track-sysex");
+ printf(" time: %d\n", parser->vtime);
break;
default: