2 midi.c -- implement Python midi parser module
4 source file of the GNU LilyPond music typesetter
6 (c) 2001 Han-Wen Nienhuys <hanwen@cs.uu.nl>
7 Jan Nieuwenhuizen <janneke@gnu.org>
15 s = open ("s.midi").read ()
21 #include <python2.0/Python.h>
26 #define debug_print(f, args...) fprintf (stderr, "%s:%d: track: %p :" f, __FUNCTION__, __LINE__, *track, ##args)
28 #define debug_print(f, args...)
31 static PyObject *Midi_error;
32 static PyObject *Midi_warning;
37 PyErr_SetString (Midi_error, s);
42 midi_warning (char *s)
44 PyErr_SetString (Midi_warning, s);
49 typedef struct message {
54 message_t channelVoiceMessages[] = {
57 0xA0, "POLYPHONIC_KEY_PRESSURE",
58 0xB0, "CONTROLLER_CHANGE",
59 0xC0, "PROGRAM_CHANGE",
60 0xD0, "CHANNEL_KEY_PRESSURE",
65 message_t channelModeMessages[] = {
66 0x78, "ALL_SOUND_OFF",
67 0x79, "RESET_ALL_CONTROLLERS",
68 0x7A, "LOCAL_CONTROL",
69 0x7B, "ALL_NOTES_OFF",
70 0x7C, "OMNI_MODE_OFF",
77 message_t metaEvents[] = {
78 0x00, "SEQUENCE_NUMBER",
80 0x02, "COPYRIGHT_NOTICE",
81 0x03, "SEQUENCE_TRACK_NAME",
82 0x04, "INSTRUMENT_NAME",
86 0x20, "MIDI_CHANNEL_PREFIX",
91 0x58, "TIME_SIGNATURE",
92 0x59, "KEY_SIGNATURE",
93 0x7F, "SEQUENCER_SPECIFIC_META_EVENT",
98 get_number (char * str, char * end_str, int length)
100 /* # MIDI uses big-endian for everything */
104 for (; i < length; i++)
105 sum = (sum << 8) + (unsigned char) str[i];
107 debug_print ("%d:\n", sum);
112 get_variable_length_number (char **str, char * end_str)
116 while (*str < end_str)
118 unsigned char x = **str;
120 sum = (sum << 7) + (x & 0x7F);
124 debug_print ("%d:\n", sum);
129 read_unimplemented_event (char **track, char *end, unsigned long time,
130 unsigned char x, unsigned char z)
132 debug_print ("%x:%s", z, "unimplemented MIDI event\n");
134 return Py_BuildValue ("(iii)", z, *((*track) -2), *((*track) -1));
138 read_one_byte (char **track, char *end, unsigned long time,
139 unsigned char x, unsigned char z)
141 debug_print ("%x:%s", z, "event\n");
143 return Py_BuildValue ("(ii)", z, *((*track) -1));
147 read_two_bytes (char **track, char *end, unsigned long time,
148 unsigned char x, unsigned char z)
150 debug_print ("%x:%s", z, "event\n");
152 return Py_BuildValue ("(iii)", z, *((*track) -2), *((*track) -1));
156 read_three_bytes (char **track, char *end, unsigned long time,
157 unsigned char x, unsigned char z)
159 debug_print ("%x:%s", z, "event\n");
161 return Py_BuildValue ("(iiii)", z, *((*track) -3), *((*track) -2), *((*track) -1));
165 read_string (char **track, char *end, unsigned long time,
166 unsigned char x, unsigned char z)
168 unsigned long length = get_variable_length_number (track, end);
169 if (length < *track - end)
170 debug_print ("%s", "zero length string\n");
172 debug_print ("%x:%s", length, "string\n");
173 return Py_BuildValue ("(is)", z, *((*track) -length));
176 typedef PyObject* (*Read_midi_event)
177 (char **track, char *end, unsigned long time,
178 unsigned char x, unsigned char z);
180 Read_midi_event read_ff_byte [16] =
182 read_three_bytes, // 0
189 read_two_bytes, // 70
190 read_two_bytes, // 80
191 read_two_bytes, // 90
192 read_two_bytes, // a0
193 read_two_bytes, // b0
195 read_two_bytes, // d0
196 read_two_bytes, // e0
197 read_two_bytes, // e0
202 read_f0_byte (char **track, char *end, unsigned long time,
203 unsigned char x, unsigned char z)
206 debug_print ("%x:%s", z, "event\n");
209 unsigned char zz = *(*track)++;
210 debug_print ("%x:%s", zz, "f0-event\n");
211 if (zz == 0x01 && **track <= 0x07)
212 return read_string (track, end, time, x, zz);
213 else if (zz == 0x2f && **track == 0x00)
216 debug_print ("%s", "done\n");
220 return read_unimplemented_event (track, end, time, x, zz);
224 return read_string (track, end, time, x, z);
227 Read_midi_event read_midi_event [16] =
236 read_two_bytes, // 70
237 read_two_bytes, // 80
238 read_two_bytes, // 90
239 read_two_bytes, // a0
240 read_two_bytes, // b0
242 read_two_bytes, // d0
243 read_two_bytes, // e0
248 read_event (char **track, char *end, unsigned long time,
249 unsigned char *running_status)
251 int rsb_skip = ((**track & 0x80)) ? 1 :0;
253 unsigned char x = (rsb_skip) ? (*track)[0]: *running_status;
254 // unsigned char y = x & 0xf0;
255 unsigned char z = (*track)[1 + rsb_skip];
257 debug_print ("%x:%s", z, "event\n");
258 *track += 2 + rsb_skip;
260 return (*read_midi_event[z >> 4]) (track, end, time, x, z);
264 midi_parse_track (char **track, char *track_end)
266 unsigned int time = 0;
267 unsigned char running_status;
268 unsigned long track_len, track_size;
269 PyObject *pytrack = 0;
271 debug_print ("%s", "\n");
273 track_size = track_end - *track;
274 /* need this for direct midi.parse_track (s) on midi file */
275 if (strcmp (*track, "MTrk"))
276 *track = memmem (*track, track_size - 1, "MTrk", 4);
277 debug_print ("%s", "\n");
278 assert (!strcmp (*track, "MTrk"));
281 track_len = get_number (*track, *track + 4, 4);
284 debug_print ("track_len: %u\n", track_len);
285 debug_print ("track_size: %u\n", track_size);
286 debug_print ("track begin: %p\n", track);
287 debug_print ("track end: %p\n", track + track_len);
289 //assert (track_len <= track_size);
291 pytrack = PyList_New (0);
293 track_end = *track + track_len;
295 while (*track < track_end)
297 long dt = get_variable_length_number(track, track_end);
299 PyList_Append (pytrack, read_event (track, track_end, time,
309 pymidi_parse_track (PyObject *self, PyObject *args)
311 char *track, *track_end;
312 unsigned long track_size, track_len;
314 PyObject * sobj = PyTuple_GetItem (args, 0);
316 debug_print ("%s", "\n");
317 if (!PyArg_ParseTuple (args, "s#", &track, &track_size))
321 return midi_error ("negative track size");
323 track_end = track + track_size;
325 return midi_parse_track (&track, track_end);
329 midi_parse (char **midi, char *midi_end)
331 PyObject *pymidi = 0;
332 unsigned long header_len;
333 unsigned format, tracks;
337 debug_print ("%s", "\n");
340 header_len = get_number (*midi, *midi + 4, 4);
344 return midi_error ("header too short");
346 format = get_number (*midi, *midi + 2, 2);
349 tracks = get_number (*midi, *midi + 2, 2);
353 return midi_error ("too many tracks");
355 division = get_number (*midi, *midi + 2, 2) * 4;
359 /* return midi_error ("can't handle non-metrical time"); */
361 *midi += header_len - 6;
363 pymidi = PyList_New (0);
364 PyList_Append (pymidi, Py_BuildValue ("(iii)", format, tracks, division));
367 for (i = 0; i < tracks; i++)
368 PyList_Append (pymidi, midi_parse_track (midi, midi_end));
374 pymidi_parse (PyObject *self, PyObject *args)
376 char *midi, *midi_end;
377 unsigned long midi_size, midi_len;
379 PyObject *sobj = PyTuple_GetItem (args, 0);
381 debug_print ("%s", "\n");
382 if (!PyArg_ParseTuple (args, "s#", &midi, &midi_size))
385 if (strcmp (midi, "MThd"))
386 return midi_error ("MThd expected");
390 midi_end = midi + midi_size;
392 return midi_parse (&midi, midi_end);
396 static PyMethodDef MidiMethods[] =
398 {"parse", pymidi_parse, 1},
399 {"parse_track", pymidi_parse_track, 1},
400 {0, 0} /* Sentinel */
406 m = Py_InitModule ("midi", MidiMethods);
407 d = PyModule_GetDict (m);
409 Midi_error = PyString_FromString ("midi.error");
410 PyDict_SetItemString (d, "error", Midi_error);
411 Midi_warning = PyString_FromString ("midi.warning");
412 PyDict_SetItemString (d, "warning", Midi_warning);