3
* File: midiread.m - Read in a midi file.
5
* Copyright (C) 1999 Steve Ratcliffe
7
* This program is free software; you can redistribute it and/or modify
8
* it under the terms of the GNU General Public License version 2 as
9
* published by the Free Software Foundation.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
27
* This structure is used to keep track of the state while
28
* reading in a midi file.
31
FILE *fp; /* File being read */
32
int current_time; /* Current midi time */
33
int port; /* Midi port number */
34
int device; /* Midi device number */
35
int track_count; /* Count of current track */
36
int chunk_size; /* Size of current chunk */
37
int chunk_count; /* Count within current chunk */
38
GPtrArray *notes; /* Currently on notes */
40
struct tempomapElement *tempo_map; /* The tempo map */
43
static struct rootElement *read_head(struct midistate *msp);
44
static struct trackElement *read_track(struct midistate *msp);
45
static void handle_status(struct midistate *msp, struct trackElement *track,
47
static struct metaElement *handle_meta(struct midistate *msp, int type,
49
static int read_int(struct midistate *msp, int n);
50
static unsigned char *read_data(struct midistate *msp, int length);
51
static gint32 read_var(struct midistate *msp);
52
static void put_back(struct midistate *msp, char c);
53
static struct element *save_note(struct midistate *msp, int note, int vel);
54
static void finish_note(struct midistate *msp, int note, int vel);
55
static void skip_chunk(struct midistate *msp);
58
* Read in a midi file from the specified open file pointer, fp
59
* and return an mtree structure tree representing the file.
62
* fp - Input file pointer
67
struct midistate mState;
68
struct midistate *msp;
69
struct rootElement *root;
75
msp->tempo_map = md_tempomap_new();
76
msp->notes = g_ptr_array_new();
79
root = read_head(msp);
80
md_add(MD_CONTAINER(root), NULL); /* Leave room for the tempo map */
81
for (i = 0; i < root->tracks; i++) {
82
el = MD_ELEMENT(read_track(msp));
84
/* If format 1 then the first track is really the tempo map */
87
&& MD_CONTAINER(el)->elements->len == 0) {
88
/* It will be added after the loop */
93
md_add(MD_CONTAINER(root), el);
96
g_ptr_array_index(MD_CONTAINER(root)->elements, 0) = msp->tempo_map;
97
msp->tempo_map = NULL;
99
g_ptr_array_free(msp->notes, 1);
105
* Read in a midi file from the specified file name.
108
* name - File name to read
111
midi_read_file(char *name)
114
struct rootElement *root;
116
fp = fopen(name, "rb");
118
except(ioError, _("Could not open file %s"), name);
120
root = midi_read(fp);
128
* Read the header information from a midi file
131
* msp - current midi state
133
static struct rootElement *
134
read_head(struct midistate *msp)
138
struct rootElement *root;
140
root = md_root_new();
142
/* The first word just identifies the file as a midi file */
143
magic = read_int(msp, 4);
144
if (magic != MIDI_HEAD_MAGIC)
145
except(formatError, _("Bad header (%x), probably not a real midi file"),
148
/* The header chunk should be 6 bytes, (perhaps longer in the future) */
149
length = read_int(msp, 4);
151
except(formatError, _("Bad header length, probably not a real midi file"));
153
root->format = read_int(msp, 2);
154
root->tracks = read_int(msp, 2);
155
root->time_base = read_int(msp, 2);
157
/* Should skip any extra bytes, (may not be seekable) */
160
(void) getc(msp->fp);
167
* Read in one track from the file, and return an element tree
173
static struct trackElement *
174
read_track(struct midistate *msp)
176
int status, laststatus;
180
struct trackElement *track;
184
head = read_int(msp, 4);
185
if (head != MIDI_TRACK_MAGIC)
187
_("Bad track header (%x), probably not a midi file"),
190
length = read_int(msp, 4);
191
msp->chunk_size = length;
192
msp->chunk_count = 0; /* nothing read yet */
194
track = md_track_new();
196
msp->current_time = 0;
197
while (msp->chunk_count < msp->chunk_size) {
199
delta_time = read_var(msp);
200
msp->current_time += delta_time;
202
status = read_int(msp, 1);
203
if ((status & 0x80) == 0) {
206
* This is not a status byte and so running status is being
207
* used. Re-use the previous status and push back this byte.
209
put_back(msp, status);
215
handle_status(msp, track, status);
219
for (i = 0; i < msp->notes->len; i++) {
220
struct noteElement *ns;
221
ns = g_ptr_array_index(msp->notes, i);
222
msp->device = MD_ELEMENT(ns)->device_channel;
223
printf("Left over note, finishing\n");
224
finish_note(msp, ns->note, 0);
234
* Complete the reading of the status byte. The parsed midi
235
* command will be added to the specified track .
238
* msp - Current midi file status
239
* track - Current track
240
* status - Status byte, ie. current command
243
handle_status(struct midistate *msp, struct trackElement *track, int status)
249
short note, vel, control;
255
type = status & 0xf0;
258
* Do not set the device if the type is 0xf0 as these commands are
259
* not channel specific
263
device = (msp->port<<4) + ch;
264
msp->device = device;
270
note = read_int(msp, 1);
271
vel = read_int(msp, 1);
273
finish_note(msp, note, vel);
277
note = read_int(msp, 1);
278
vel = read_int(msp, 1);
281
/* This is really a note off */
282
finish_note(msp, note, vel);
284
/* Save the start, so it can be matched with the note off */
285
el = save_note(msp, note, vel);
289
case MIDI_KEY_AFTERTOUCH:
290
note = read_int(msp, 1);
291
vel = read_int(msp, 1);
293
/* new aftertouchElement */
294
el = MD_ELEMENT(md_keytouch_new(note, vel));
298
control = read_int(msp, 1);
299
val = read_int(msp, 1);
300
el = MD_ELEMENT(md_control_new(control, val));
305
val = read_int(msp, 1);
306
el = MD_ELEMENT(md_program_new(val));
309
case MIDI_CHANNEL_AFTERTOUCH:
310
val = read_int(msp, 1);
311
el = MD_ELEMENT(md_pressure_new(val));
313
case MIDI_PITCH_WHEEL:
314
val = read_int(msp, 1);
315
val |= read_int(msp, 1) << 7;
316
val -= 0x2000; /* Center it around zero */
317
el = MD_ELEMENT(md_pitch_new(val));
320
/* Now for all the non-channel specific ones */
322
/* Deal with the end of track event first */
324
type = read_int(msp, 1);
326
/* End of track - skip to end of real track */
327
track->final_time = msp->current_time;
333
/* Get the length of the following data */
334
length = read_var(msp);
335
data = read_data(msp, length);
337
el = (struct element *)handle_meta(msp, type, data);
339
el = (struct element *)md_sysex_new(status, data, length);
343
except(formatError, _("Bad status type 0x%x"), type);
348
el->element_time = msp->current_time;
349
el->device_channel = device;
351
md_add(MD_CONTAINER(track), el);
356
* Do extra handling of meta events. We want to save time
357
* signature and key for use elsewhere, for example. This
358
* routine create the correct type of class and returns it.
361
* msp - The midi file state
362
* type - The meta event type
363
* data - The data for the event
365
static struct metaElement *
366
handle_meta(struct midistate *msp, int type, unsigned char *data)
368
struct metaElement *el = NULL;
369
struct mapElement *map = NULL;
373
case MIDI_META_SEQUENCE:
376
case MIDI_META_COPYRIGHT:
377
case MIDI_META_TRACKNAME:
378
case MIDI_META_INSTRUMENT:
379
case MIDI_META_LYRIC:
380
case MIDI_META_MARKER:
382
/* Text based events */
383
el = MD_META(md_text_new(type, (char*)data));
385
case MIDI_META_CHANNEL:
393
case MIDI_META_TEMPO:
394
micro_tempo = ((data[0]<<16) & 0xff0000)
395
+ ((data[1]<<8) & 0xff00) + (data[2] & 0xff);
396
map = MD_MAP(md_tempo_new(micro_tempo));
399
case MIDI_META_SMPTE_OFFSET:
400
el = MD_META(md_smpteoffset_new(data[0], data[1], data[2], data[3],
404
map = MD_MAP(md_timesig_new(data[0], 1<<data[1],
409
map = MD_MAP(md_keysig_new(data[0], (data[1]==1)? 1: 0));
413
/* Proprietry sequencer specific event */
414
/* Just throw it out */
417
g_warning(_("Meta event %d not implemented\n"), type);
421
/* If this affected the tempo map then add it */
423
MD_ELEMENT(map)->element_time = msp->current_time;
424
md_add(MD_CONTAINER(msp->tempo_map), MD_ELEMENT(map));
431
* Reads an interger from the midi file. The number of bytes to
432
* be read is specified in n .
435
* msp - Midi file state
436
* n - Number of bytes to read
439
read_int(struct midistate *msp, int n)
447
for (i = 0; i < n; i++) {
452
except(formatError, _("Unexpected end of file"));
461
* Read in a specified amount of data from the file. The return
462
* is allocated data which must be freed by the caller. An extra
463
* null byte is appended for the sake of text events.
465
* msp - Midifile state
466
* length - Length of data to read
468
static unsigned char *
469
read_data(struct midistate *msp, int length)
472
unsigned char *data = g_malloc(length+1);
479
if (fread(data, length, 1, msp->fp) == 1) {
480
msp->chunk_count += length;
484
except(formatError, _("Unexpected end of file"));
491
* Read a variable length integer from the midifile and return
492
* it. Returns an int32 so cannot really deal with more than
496
* msp - Midi file state
499
read_var(struct midistate *msp)
509
except(formatError, _("Unexpected end of file"));
512
} while ((c & 0x80) == 0x80);
518
* Push back a character. Have to also keep track of the
521
* msp - Midi input state
522
* c - Character to push back
525
put_back(struct midistate *msp, char c)
532
* Save the initial note-on message. This will later be paired
533
* with a note off message. We have to keep track of channel and
534
* device that the note-on is for so that it can be correctly
538
* msp - Midi file state
542
static struct element *
543
save_note(struct midistate *msp, int note, int vel)
545
struct noteElement *n;
547
/* Create a new note and set its length to -1
548
* this will be filled in later, when the note-off arrives
550
n = md_note_new(note, vel, -1);
552
/* Save it so that we match up with the note off */
553
g_ptr_array_add(msp->notes, n);
555
return MD_ELEMENT(n);
559
* Called when a note off is seen. Finds the corresponding note
560
* on and constructs a note element.
563
* msp - Midi file state
565
* vel - Note velocity
568
finish_note(struct midistate *msp, int note, int vel)
572
struct noteElement *n;
577
for (i = notes->len-1; i >= 0; i--) {
578
n = g_ptr_array_index(notes, i);
579
if (n->note == note && MD_ELEMENT(n)->device_channel == msp->device) {
580
len = msp->current_time - MD_ELEMENT(n)->element_time;
584
printf("Len neg: msp->time%d, s->time%d, note=%d, s.vel%d\n",
585
msp->current_time, MD_ELEMENT(n)->element_time,
589
g_ptr_array_remove_index_fast(notes, i);
596
* Skip to the end of the chunk. Note that the input may not be
597
* seekable, so we just read bytes until at the end of the chunk.
600
* msp - Midi file state
603
skip_chunk(struct midistate *msp)
605
while (msp->chunk_count < msp->chunk_size)
606
(void) read_int(msp, 1);