shithub: choc

Download patch

ref: 9b192c44f932542ccd835936d593c43ce3e9e9e3
parent: c4f640be999e80351f1c89c893a0d5ce39c20cd9
author: Simon Howard <fraggle@gmail.com>
date: Fri Apr 3 15:58:08 EDT 2009

Fix up MIDI reading code; add test code.

Subversion-branch: /branches/opl-branch
Subversion-revision: 1494

--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -195,3 +195,6 @@
 
 endif
 
+midiread : midifile.c
+	$(CC) -DTEST $(CFLAGS) @LDFLAGS@ $^ -o $@
+
--- a/src/midifile.c
+++ b/src/midifile.c
@@ -27,6 +27,7 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "doomdef.h"
 #include "doomtype.h"
 #include "i_swap.h"
 #include "midifile.h"
@@ -39,7 +40,7 @@
 {
     byte chunk_id[4];
     unsigned int chunk_size;
-} chunk_header_t;
+} PACKEDATTR chunk_header_t;
 
 typedef struct
 {
@@ -46,8 +47,8 @@
     chunk_header_t chunk_header;
     unsigned short format_type;
     unsigned short num_tracks;
-    unsigned int time_division;
-} midi_header_t;
+    unsigned short time_division;
+} PACKEDATTR midi_header_t;
 
 struct midi_file_s
 {
@@ -65,12 +66,15 @@
 {
     boolean result;
     
-    result = (strcmp((char *) chunk->chunk_id, expected_id) == 0);
+    result = (memcmp((char *) chunk->chunk_id, expected_id, 4) == 0);
 
     if (!result)
     {
-        fprintf(stderr, "CheckChunkHeader: Expected '%s' chunk header\n",
-                        expected_id);
+        fprintf(stderr, "CheckChunkHeader: Expected '%s' chunk header, "
+                        "got '%c%c%c%c'\n",
+                        expected_id,
+                        chunk->chunk_id[0], chunk->chunk_id[1],
+                        chunk->chunk_id[2], chunk->chunk_id[3]);
     }
 
     return result;
@@ -80,24 +84,26 @@
 
 static boolean ReadHeaderChunk(midi_file_t *file)
 {
-    size_t bytes_read;
+    size_t records_read;
 
-    bytes_read = fread(&file->header, sizeof(midi_header_t), 1, file->stream);
+    records_read = fread(&file->header, sizeof(midi_header_t), 1, file->stream);
 
-    if (bytes_read < sizeof(midi_header_t))
+    if (records_read < 1)
     {
         return false;
     }
 
     if (!CheckChunkHeader(&file->header.chunk_header, HEADER_CHUNK_ID)
-     || LONG(file->header.chunk_header.chunk_size) != 6)
+     || SDL_SwapBE32(file->header.chunk_header.chunk_size) != 6)
     {
-        fprintf(stderr, "ReadHeaderChunk: Invalid MIDI chunk header!\n");
+        fprintf(stderr, "ReadHeaderChunk: Invalid MIDI chunk header! "
+                        "chunk_size=%i\n",
+                        SDL_SwapBE32(file->header.chunk_header.chunk_size));
         return false;
     }
 
-    if (SHORT(file->header.format_type) != 0
-     || SHORT(file->header.num_tracks) != 1)
+    if (SDL_SwapBE16(file->header.format_type) != 0
+     || SDL_SwapBE16(file->header.num_tracks) != 1)
     {
         fprintf(stderr, "ReadHeaderChunk: Only single track, "
                                         "type 0 MIDI files supported!\n");
@@ -111,12 +117,12 @@
 
 static boolean ReadTrackChunk(midi_file_t *file)
 {
-    size_t bytes_read;
+    size_t records_read;
     chunk_header_t chunk_header;
 
-    bytes_read = fread(&chunk_header, sizeof(chunk_header_t), 1, file->stream);
+    records_read = fread(&chunk_header, sizeof(chunk_header_t), 1, file->stream);
 
-    if (bytes_read < sizeof(chunk_header))
+    if (records_read < 1)
     {
         return false;
     }
@@ -126,7 +132,7 @@
         return false;
     }
 
-    file->data_len = LONG(chunk_header.chunk_size);
+    file->data_len = SDL_SwapBE32(chunk_header.chunk_size);
 
     return true;
 }
@@ -375,6 +381,8 @@
 {
     byte b;
 
+    event->event_type = MIDI_EVENT_META;
+
     // Read meta event type:
 
     if (!ReadByte(file, &b))
@@ -463,4 +471,66 @@
             return false;
     }
 }
+
+#ifdef TEST
+
+int main(int argc, char *argv[])
+{
+    midi_file_t *file;
+    midi_event_t event;
+
+    if (argc < 2)
+    {
+        printf("Usage: %s <filename>\n", argv[0]);
+        exit(1);
+    }
+
+    file = MIDI_OpenFile(argv[1]);
+
+    if (file == NULL)
+    {
+        fprintf(stderr, "Failed to open %s\n", argv[1]);
+        exit(1);
+    }
+
+    while (MIDI_ReadEvent(file, &event))
+    {
+        printf("Event type: %i\n", event.event_type);
+
+        switch(event.event_type)
+        {
+            case MIDI_EVENT_NOTE_OFF:
+            case MIDI_EVENT_NOTE_ON:
+            case MIDI_EVENT_AFTERTOUCH:
+            case MIDI_EVENT_CONTROLLER:
+            case MIDI_EVENT_PROGRAM_CHANGE:
+            case MIDI_EVENT_CHAN_AFTERTOUCH:
+            case MIDI_EVENT_PITCH_BEND:
+                printf("\tChannel: %i\n", event.data.channel.channel);
+                printf("\tParameter 1: %i\n", event.data.channel.param1);
+                printf("\tParameter 2: %i\n", event.data.channel.param2);
+                break;
+
+            case MIDI_EVENT_SYSEX:
+            case MIDI_EVENT_SYSEX_SPLIT:
+                printf("\tLength: %i\n", event.data.sysex.length);
+                break;
+
+            case MIDI_EVENT_META:
+                printf("\tMeta type: %i\n", event.data.meta.type);
+                printf("\tLength: %i\n", event.data.meta.length);
+                break;
+        }
+
+        if (event.event_type == MIDI_EVENT_META
+         && event.data.meta.type == MIDI_META_END_OF_TRACK)
+        {
+            break;
+        }
+    }
+
+    return 0;
+}
+
+#endif
 
--- a/src/midifile.h
+++ b/src/midifile.h
@@ -65,13 +65,14 @@
     MIDI_META_MARKER                = 0x6,
     MIDI_META_CUE_POINT             = 0x7,
 
-    MIDI_META_CHANNEL_PREFIX        = 0x8,
-    MIDI_META_END_OF_TRACK          = 0x9,
-    MIDI_META_SET_TEMPO             = 0xa,
-    MIDI_META_SMPTE_OFFSET          = 0xb,
-    MIDI_META_TIME_SIGNATURE        = 0xc,
-    MIDI_META_KEY_SIGNATURE         = 0xd,
-    MIDI_META_SEQUENCER_SPECIFIC    = 0xe,
+    MIDI_META_CHANNEL_PREFIX        = 0x20,
+    MIDI_META_END_OF_TRACK          = 0x2f,
+
+    MIDI_META_SET_TEMPO             = 0x51,
+    MIDI_META_SMPTE_OFFSET          = 0x54,
+    MIDI_META_TIME_SIGNATURE        = 0x58,
+    MIDI_META_KEY_SIGNATURE         = 0x59,
+    MIDI_META_SEQUENCER_SPECIFIC    = 0x7f,
 } midi_meta_event_type_t;
 
 typedef struct