summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon Howard2009-04-15 19:00:25 +0000
committerSimon Howard2009-04-15 19:00:25 +0000
commitd8ada5c41da3eec5ef163d9efac9cb5dbdc2cb6b (patch)
tree32a7b2b8f76a03cfa13aea30fbcb455523e9aba7
parent3dd7e1db9bf26e1e50bc13f6b176e54d63f2da85 (diff)
downloadchocolate-doom-d8ada5c41da3eec5ef163d9efac9cb5dbdc2cb6b.tar.gz
chocolate-doom-d8ada5c41da3eec5ef163d9efac9cb5dbdc2cb6b.tar.bz2
chocolate-doom-d8ada5c41da3eec5ef163d9efac9cb5dbdc2cb6b.zip
Parse MIDI events that reuse the event type from the previous event.
Subversion-branch: /branches/opl-branch Subversion-revision: 1499
-rw-r--r--src/midifile.c70
-rw-r--r--src/midifile.h14
2 files changed, 57 insertions, 27 deletions
diff --git a/src/midifile.c b/src/midifile.c
index cca0189e..1be6ec75 100644
--- a/src/midifile.c
+++ b/src/midifile.c
@@ -198,8 +198,8 @@ static boolean ReadChannelEvent(midi_event_t *event,
// Set basics:
- event->event_type = event_type >> 4;
- event->data.channel.channel = event_type & 0xf;
+ event->event_type = event_type & 0xf0;
+ event->data.channel.channel = event_type & 0x0f;
// Read parameters:
@@ -296,7 +296,8 @@ static boolean ReadMetaEvent(midi_event_t *event, FILE *stream)
return true;
}
-static boolean ReadEvent(midi_event_t *event, FILE *stream)
+static boolean ReadEvent(midi_event_t *event, unsigned int *last_event_type,
+ FILE *stream)
{
byte event_type;
@@ -312,9 +313,29 @@ static boolean ReadEvent(midi_event_t *event, FILE *stream)
return false;
}
+ // All event types have their top bit set. Therefore, if
+ // the top bit is not set, it is because we are using the "same
+ // as previous event type" shortcut to save a byte. Skip back
+ // a byte so that we read this byte again.
+
+ if ((event_type & 0x80) == 0)
+ {
+ event_type = *last_event_type;
+
+ if (fseek(stream, -1, SEEK_CUR) < 0)
+ {
+ fprintf(stderr, "ReadEvent: Unable to seek in stream\n");
+ return false;
+ }
+ }
+ else
+ {
+ *last_event_type = event_type;
+ }
+
// Check event type:
- switch (event_type >> 4)
+ switch (event_type & 0xf0)
{
// Two parameter channel events:
@@ -331,26 +352,27 @@ static boolean ReadEvent(midi_event_t *event, FILE *stream)
case MIDI_EVENT_CHAN_AFTERTOUCH:
return ReadChannelEvent(event, event_type, false, stream);
- // Other event types:
+ default:
+ break;
+ }
+
+ // Specific value?
- case 0xf:
- if (event_type == MIDI_EVENT_SYSEX
- || event_type == MIDI_EVENT_SYSEX_SPLIT)
- {
- return ReadSysExEvent(event, event_type, stream);
- }
- else if (event_type == MIDI_EVENT_META)
- {
- return ReadMetaEvent(event, stream);
- }
+ switch (event_type)
+ {
+ case MIDI_EVENT_SYSEX:
+ case MIDI_EVENT_SYSEX_SPLIT:
+ return ReadSysExEvent(event, event_type, stream);
- // --- Fall-through deliberate ---
- // Other 0xfx event types are unknown
+ case MIDI_EVENT_META:
+ return ReadMetaEvent(event, stream);
default:
- fprintf(stderr, "Unknown MIDI event type: 0x%x\n", event_type);
- return false;
+ break;
}
+
+ fprintf(stderr, "ReadEvent: Unknown MIDI event type: 0x%x\n", event_type);
+ return false;
}
// Free an event:
@@ -405,6 +427,7 @@ static boolean ReadTrack(midi_track_t *track, FILE *stream)
{
midi_event_t *new_events;
midi_event_t *event;
+ unsigned int last_event_type;
track->num_events = 0;
track->events = NULL;
@@ -418,6 +441,8 @@ static boolean ReadTrack(midi_track_t *track, FILE *stream)
// Then the events:
+ last_event_type = 0;
+
for (;;)
{
// Resize the track slightly larger to hold another event:
@@ -435,7 +460,7 @@ static boolean ReadTrack(midi_track_t *track, FILE *stream)
// Read the next event:
event = &track->events[track->num_events];
- if (!ReadEvent(event, stream))
+ if (!ReadEvent(event, &last_event_type, stream))
{
return false;
}
@@ -642,6 +667,11 @@ void PrintTrack(midi_track_t *track)
{
event = &track->events[i];
+ if (event->delta_time > 0)
+ {
+ printf("Delay: %i ticks\n", event->delta_time);
+ }
+
printf("Event type: %s (%i)\n",
MIDI_EventTypeToString(event->event_type),
event->event_type);
diff --git a/src/midifile.h b/src/midifile.h
index 16f911e7..490b0171 100644
--- a/src/midifile.h
+++ b/src/midifile.h
@@ -30,13 +30,13 @@ typedef struct midi_file_s midi_file_t;
typedef enum
{
- MIDI_EVENT_NOTE_OFF = 0x8,
- MIDI_EVENT_NOTE_ON = 0x9,
- MIDI_EVENT_AFTERTOUCH = 0xa,
- MIDI_EVENT_CONTROLLER = 0xb,
- MIDI_EVENT_PROGRAM_CHANGE = 0xc,
- MIDI_EVENT_CHAN_AFTERTOUCH = 0xd,
- MIDI_EVENT_PITCH_BEND = 0xe,
+ MIDI_EVENT_NOTE_OFF = 0x80,
+ MIDI_EVENT_NOTE_ON = 0x90,
+ MIDI_EVENT_AFTERTOUCH = 0xa0,
+ MIDI_EVENT_CONTROLLER = 0xb0,
+ MIDI_EVENT_PROGRAM_CHANGE = 0xc0,
+ MIDI_EVENT_CHAN_AFTERTOUCH = 0xd0,
+ MIDI_EVENT_PITCH_BEND = 0xe0,
MIDI_EVENT_SYSEX = 0xf0,
MIDI_EVENT_SYSEX_SPLIT = 0xf7,