11 #define FMT_MULTI_TRACK 1
12 #define FMT_MULTI_SEQ 2
17 #define META_COPYRIGHT 2
23 #define META_CHANPREFIX 32
24 #define META_END_TRACK 47
26 #define META_SMPTE_OFFS 84
28 #define META_KEYSIG 89
29 #define META_SPECIFIC 127
31 #define CHUNK_HDR_SIZE 8
35 unsigned char data[1];
39 uint16_t fmt; /* 0: single, 1: multi-track, 2: multiple independent */
43 } __attribute__ ((packed));
45 static void destroy_track(struct midi_track *trk);
46 static int read_track(struct midi *midi, struct chunk_hdr *chunk);
47 static long read_vardata(unsigned char **pptr);
48 static int read_meta_event(struct midi *midi, struct midi_track *trk, unsigned char **pptr);
49 static int read_sysex_event(struct midi *midi, unsigned char **pptr);
50 static int ischunk(struct chunk_hdr *chunk, const char *name);
51 static struct chunk_hdr *mkchunk(void *ptr);
52 static struct chunk_hdr *skip_chunk(struct chunk_hdr *chunk);
53 static struct midi_hdr *mkmidi(void *ptr);
54 static void bigend(void *ptr, int sz);
55 static void *map_file(const char *fname, int *size);
56 static void unmap_file(void *mem, int size);
58 #define IS_VALID_EVTYPE(x) ((x) >= MIDI_NOTE_OFF && (x) <= MIDI_PITCH_BEND)
60 /* XXX the event arity table must match the MIDI_* defines in midi.h */
61 static int ev_arity[] = {
62 0, 0, 0, 0, 0, 0, 0, 0,
63 2, /* note off (note, velocity)*/
64 2, /* note on (note, velocity)*/
65 2, /* note aftertouch (note, aftertouch value) */
66 2, /* controller (controller number, value) */
67 1, /* prog change (prog number) */
68 1, /* channel aftertouch (aftertouch value) */
69 2 /* pitch bend (pitch LSB, pitch MSB) */
73 struct midi *midi_load(const char *fname)
78 struct chunk_hdr *chunk;
81 if(!(mem = map_file(fname, &size))) {
86 if(!ischunk(chunk, "MThd") || chunk->size != 6) {
87 fprintf(stderr, "invalid or corrupted midi file: %s\n", fname);
90 hdr = mkmidi(chunk->data);
92 if(!(midi = malloc(sizeof *midi))) {
93 perror("failed to allocate memory");
97 if((hdr->tm_div & 0x8000) == 0) {
98 /* division is in pulses / quarter note */
99 midi->ppqn = hdr->tm_div;
100 midi->fps = midi->ticks_per_frame = -1;
102 /* division in frames / sec */
103 midi->fps = (hdr->tm_div & 0x7f00) >> 8;
104 midi->ticks_per_frame = hdr->tm_div & 0xff;
108 if(!(midi->tracks = malloc(hdr->num_tracks * sizeof *midi->tracks))) {
109 perror("failed to allocate memory");
112 midi->num_tracks = 0;
114 while((chunk = skip_chunk(chunk)) && ((char*)chunk < mem + size)) {
115 if(ischunk(chunk, "MTrk")) {
116 if(read_track(midi, chunk) == -1) {
117 fprintf(stderr, "failed to read track\n");
122 unmap_file(mem, size);
126 unmap_file(mem, size);
131 void midi_free(struct midi *midi)
137 for(i=0; i<midi->num_tracks; i++) {
138 destroy_track(midi->tracks + i);
145 int midi_num_tracks(struct midi *midi)
147 return midi->num_tracks;
150 struct midi_track *midi_track(struct midi *midi, int idx)
152 if(idx < 0 || idx >= midi->num_tracks) {
155 return midi->tracks + idx;
158 static void destroy_track(struct midi_track *trk)
162 void *tmp = trk->head;
163 trk->head = trk->head->next;
168 static int read_track(struct midi *midi, struct chunk_hdr *chunk)
171 struct midi_track trk = {0, 0, 0, 0};
172 unsigned char prev_stat = 0;
174 struct midi_event *ev;
176 if(!ischunk(chunk, "MTrk")) {
181 while(ptr < chunk->data + chunk->size) {
185 dt = read_vardata(&ptr);
189 read_meta_event(midi, &trk, &ptr);
190 } else if(stat == 0xf0) {
191 read_sysex_event(midi, &ptr);
194 /* not a status byte, assume running status */
198 type = (stat >> 4) & 0xf;
200 if(!IS_VALID_EVTYPE(type) || !(ev = malloc(sizeof *ev))) {
201 /* unkwown message, skip all data bytes */
202 while(ptr < chunk->data + chunk->size && !(*ptr & 0x80)) {
219 ev->channel = stat & 0xf;
222 if(ev_arity[ev->type] > 1) {
226 if(ev->type == MIDI_NOTE_ON && ev->arg[1] == 0) {
227 ev->type = MIDI_NOTE_OFF;
234 /* if we did actually add any events ... */
236 midi->tracks[midi->num_tracks++] = trk;
237 /*printf("loaded track with %d events\n", trk.num_ev);*/
242 static long read_vardata(unsigned char **pptr)
246 unsigned char *ptr = *pptr;
249 res |= (long)(*ptr & 0x7f) << (i * 8);
251 /* if first bit is not set we're done */
252 if((*ptr++ & 0x80) == 0)
259 static int read_meta_event(struct midi *midi, struct midi_track *trk, unsigned char **pptr)
261 unsigned char *ptr = *pptr;
266 size = read_vardata(&ptr);
271 trk->name = malloc(size + 1);
272 memcpy(trk->name, ptr, size);
277 /* TODO add a tempo change event to the midi struct */
287 /* ignore sysex events */
288 static int read_sysex_event(struct midi *midi, unsigned char **pptr)
290 long size = read_vardata(pptr);
295 static int ischunk(struct chunk_hdr *chunk, const char *name)
297 return memcmp(chunk->id, name, 4) == 0;
300 static struct chunk_hdr *mkchunk(void *ptr)
302 struct chunk_hdr *chdr = ptr;
303 bigend(&chdr->size, sizeof chdr->size);
307 static struct chunk_hdr *skip_chunk(struct chunk_hdr *chunk)
309 return mkchunk((char*)chunk + CHUNK_HDR_SIZE + chunk->size);
312 static struct midi_hdr *mkmidi(void *ptr)
314 struct midi_hdr *midi = ptr;
316 bigend(&midi->fmt, sizeof midi->fmt);
317 bigend(&midi->num_tracks, sizeof midi->num_tracks);
318 bigend(&midi->tm_div, sizeof midi->tm_div);
322 static void bigend(void *ptr, int sz)
324 static unsigned char test[] = {0x12, 0x34};
328 if(sz < 2 || *(uint16_t*)test == 0x1234) {
334 val32 = *(uint32_t*)ptr;
335 *(uint32_t*)ptr = (val32 << 24) | (val32 >> 24) | ((val32 & 0xff00) << 8) |
336 ((val32 & 0xff0000) >> 8);
340 val16 = *(uint16_t*)ptr;
341 *(uint16_t*)ptr = (val16 >> 8) | (val16 << 8);
350 #if defined(__unix__) && defined(USE_MMAP)
353 #include <sys/mman.h>
354 #include <sys/stat.h>
356 static void *map_file(const char *fname, int *size)
362 if((fd = open(fname, O_RDONLY)) == -1) {
363 fprintf(stderr, "failed to open midi file: %s: %s\n", fname, strerror(errno));
368 if((mem = mmap(0, st.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0)) == (void*)-1) {
369 fprintf(stderr, "failed to map midi file: %s: %s\n", fname, strerror(errno));
379 static void unmap_file(void *mem, int size)
384 static void *map_file(const char *fname, int *size)
390 if(!(fp = fopen(fname, "rb"))) {
391 fprintf(stderr, "failed to open midi file: %s: %s\n", fname, strerror(errno));
394 fseek(fp, 0, SEEK_END);
398 if(!(buf = malloc(sz))) {
399 fprintf(stderr, "failed to allocate space for %s in memory (%ld bytes)\n", fname, sz);
403 if(fread(buf, 1, sz, fp) != sz) {
404 fprintf(stderr, "failed to load midi file: %s: %s\n", fname, strerror(errno));
415 static void unmap_file(void *mem, int size)