put example files to dedicated dir
[monster.git] / media_source_midi.c
blob1076c1b0db1d2401213a7006b12571a7c6342713
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*****************************************************************************
4 * Media source implementation that reads MIDI files.
5 * This file is part of monster
7 * Copyright (C) 2006,2007 Nedko Arnaudov <nedko@arnaudov.name>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; version 2 of the License
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
22 *****************************************************************************/
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <errno.h>
28 #include <stdio.h>
30 #define DISABLE_DEBUG_OUTPUT
32 #include "media_source.h"
33 #include "media_source_midi.h"
34 #include "log.h"
35 #include "midi_event.h"
38 * A MIDI event after being parsed/loaded from the file.
39 * There could be made a case for using snd_seq_event_t instead.
41 struct event
43 struct event * next_ptr; /* linked list */
45 struct midi_event event;
46 unsigned char sysex[0];
49 struct track
51 struct event * first_event_ptr; /* list of all events in this track */
52 int end_tick; /* length of this track */
54 struct event * current_event_ptr;
57 struct media_source_midi
59 struct media_source virtual;
61 FILE * file_handle;
62 int file_offset; /* current offset in input file */
63 int num_tracks;
64 struct track * tracks;
65 int smpte_timing;
66 signed int max_tick;
67 struct event * ppqn_event_ptr;
68 struct event * tempo_event_ptr;
69 struct event * event_ptr;
70 unsigned int counter;
73 static void cleanup_file_data(struct media_source_midi * media_source_ptr)
75 int i;
76 struct event * event_ptr;
78 if (media_source_ptr->tracks != NULL)
80 for (i = 0; i < media_source_ptr->num_tracks; ++i)
82 event_ptr = media_source_ptr->tracks[i].first_event_ptr;
83 while (event_ptr != NULL)
85 struct event * next_ptr = event_ptr->next_ptr;
86 free(event_ptr);
87 event_ptr = next_ptr;
91 media_source_ptr->num_tracks = 0;
93 free(media_source_ptr->tracks);
96 if (media_source_ptr->ppqn_event_ptr != NULL)
98 free(media_source_ptr->ppqn_event_ptr);
101 if (media_source_ptr->tempo_event_ptr != NULL)
103 free(media_source_ptr->tempo_event_ptr);
106 media_source_ptr->tracks = NULL;
109 #define media_source_ptr ((struct media_source_midi *)virtual_ptr)
111 void media_source_midi_destroy(struct media_source * virtual_ptr)
113 DEBUG_OUT("media_source_midi_destroy");
114 cleanup_file_data(media_source_ptr);
115 fclose(media_source_ptr->file_handle);
116 free(media_source_ptr);
119 int media_source_midi_format_query(struct media_source * virtual_ptr, unsigned int * format_ptr)
121 DEBUG_OUT("media_source_midi_format_query");
122 *format_ptr = MEDIA_FORMAT_MIDI_EVENT;
123 return 0;
126 int media_source_midi_get_frame_data(struct media_source * virtual_ptr, void ** buffer_ptr_ptr)
128 DEBUG_OUT("media_source_midi_get_frame_data");
130 if (media_source_ptr->counter == 0)
132 if (media_source_ptr->ppqn_event_ptr == NULL)
134 ERROR_OUT("No PPQN event!");
135 return -1;
138 *buffer_ptr_ptr = &media_source_ptr->ppqn_event_ptr->event;
139 DEBUG_OUT("Returning the PPQN event");
140 return 0;
143 if (media_source_ptr->counter == 1)
145 if (media_source_ptr->tempo_event_ptr == NULL)
147 ERROR_OUT("No tempo event!");
148 return -1;
151 *buffer_ptr_ptr = &media_source_ptr->tempo_event_ptr->event;
152 DEBUG_OUT("Returning the tempo event");
153 return 0;
156 if (media_source_ptr->event_ptr == NULL)
158 *buffer_ptr_ptr = NULL;
159 return 1;
162 *buffer_ptr_ptr = &media_source_ptr->event_ptr->event;
164 return 0;
167 void
168 media_source_midi_next_frame(struct media_source * virtual_ptr)
170 struct event * event_ptr;
171 struct track * event_track_ptr;
172 int i;
173 signed int min_tick;
175 DEBUG_OUT("media_source_midi_next_frame");
177 media_source_ptr->counter++;
179 if (media_source_ptr->counter < 2)
181 return;
184 event_ptr = NULL;
185 event_track_ptr = NULL;
186 min_tick = media_source_ptr->max_tick + 1;
188 //DEBUG_OUT("Search next event, %d tracks, max_tick = %d, min_tick = %d", media_source_ptr->num_tracks, media_source_ptr->max_tick, min_tick);
190 /* search next event */
191 for (i = 0; i < media_source_ptr->num_tracks; i++)
193 struct track * track = media_source_ptr->tracks + i;
194 struct event * e2 = track->current_event_ptr;
196 //DEBUG_OUT("Event %08X, tick = %u", (unsigned int)e2, e2 ? e2->event.tick : 0);
197 if (e2 && e2->event.tick < min_tick)
199 min_tick = e2->event.tick;
200 event_ptr = e2;
201 event_track_ptr = track;
205 if (event_ptr != NULL) /* if end of song NOT reached */
207 /* advance pointer to next event */
208 event_track_ptr->current_event_ptr = event_ptr->next_ptr;
210 else
212 DEBUG_OUT("End of song");
215 media_source_ptr->event_ptr = event_ptr;
218 #undef media_source_ptr
220 static int read_byte(struct media_source_midi * media_source_ptr)
222 media_source_ptr->file_offset++;
223 return getc(media_source_ptr->file_handle);
226 /* reads a little-endian 32-bit integer */
227 static int read_32_le(struct media_source_midi * media_source_ptr)
229 int value;
230 value = read_byte(media_source_ptr);
231 value |= read_byte(media_source_ptr) << 8;
232 value |= read_byte(media_source_ptr) << 16;
233 value |= read_byte(media_source_ptr) << 24;
234 return !feof(media_source_ptr->file_handle) ? value : -1;
237 /* reads a 4-character identifier */
238 static int read_id(struct media_source_midi * media_source_ptr)
240 int id;
242 id = read_32_le(media_source_ptr);
244 DEBUG_OUT(
245 "Chunk \"%c%c%c%c\"",
246 (char)(id & 0xFF),
247 (char)((id >> 8) & 0xFF),
248 (char)((id >> 16) & 0xFF),
249 (char)((id >> 24) & 0xFF));
251 return id;
254 #define MAKE_ID(c1, c2, c3, c4) ((c1) | ((c2) << 8) | ((c3) << 16) | ((c4) << 24))
256 /* reads a fixed-size big-endian number */
257 static int read_int(struct media_source_midi * media_source_ptr, int bytes)
259 int c, value = 0;
263 c = read_byte(media_source_ptr);
264 if (c == EOF)
265 return -1;
266 value = (value << 8) | c;
268 while (--bytes);
270 return value;
273 /* reads a variable-length number */
274 static int read_var(struct media_source_midi * media_source_ptr)
276 int value, c;
278 c = read_byte(media_source_ptr);
279 value = c & 0x7f;
280 if (c & 0x80)
282 c = read_byte(media_source_ptr);
283 value = (value << 7) | (c & 0x7f);
284 if (c & 0x80)
286 c = read_byte(media_source_ptr);
287 value = (value << 7) | (c & 0x7f);
288 if (c & 0x80)
290 c = read_byte(media_source_ptr);
291 value = (value << 7) | c;
292 if (c & 0x80)
293 return -1;
297 return !feof(media_source_ptr->file_handle) ? value : -1;
300 /* allocates a new event */
301 static
303 new_event(struct track * track_ptr, int sysex_length, struct event ** event_ptr_ptr)
305 struct event * event_ptr;
307 event_ptr = malloc(sizeof(struct event) + sysex_length);
308 if (event_ptr == NULL)
310 ERROR_OUT("malloc failed.");
311 return -1;
314 event_ptr->next_ptr = NULL;
316 /* append at the end of the track's linked list */
317 if (track_ptr->current_event_ptr != NULL)
319 track_ptr->current_event_ptr->next_ptr = event_ptr;
321 else
323 track_ptr->first_event_ptr = event_ptr;
326 track_ptr->current_event_ptr = event_ptr;
328 *event_ptr_ptr = event_ptr;
330 return 0;
333 static void skip(struct media_source_midi * media_source_ptr, int bytes)
335 while (bytes > 0)
336 read_byte(media_source_ptr), --bytes;
339 /* reads one complete track from the file */
340 static int read_track(struct media_source_midi * media_source_ptr, struct track *track, int track_end)
342 int ret;
343 int tick = 0;
344 unsigned char last_cmd = 0;
346 /* the current file position is after the track ID and length */
347 while (media_source_ptr->file_offset < track_end)
349 unsigned char cmd;
350 struct event * event_ptr;
351 int delta_ticks, len, c;
353 delta_ticks = read_var(media_source_ptr);
354 if (delta_ticks < 0)
355 break;
356 tick += delta_ticks;
358 c = read_byte(media_source_ptr);
359 if (c < 0)
360 break;
362 if (c & 0x80)
364 /* have command */
365 cmd = c;
366 if (cmd < 0xf0)
367 last_cmd = cmd;
369 else
371 /* running status */
372 ungetc(c, media_source_ptr->file_handle);
373 media_source_ptr->file_offset--;
374 cmd = last_cmd;
375 if (!cmd)
376 goto _error;
379 switch (cmd >> 4)
381 /* channel messages with 2 parameter bytes */
382 case 0x8: /* Note Off */
383 ret = new_event(track, 0, &event_ptr);
384 if (ret < 0)
386 return -1;
389 event_ptr->event.type = MIDI_EVENT_NOTE_OFF;
390 event_ptr->event.tick = tick;
391 event_ptr->event.data.note_off.channel = cmd & 0x0f;
392 event_ptr->event.data.note_off.note = read_byte(media_source_ptr) & 0x7f;
393 event_ptr->event.data.note_off.velocity = read_byte(media_source_ptr) & 0x7f;
394 break;
395 case 0x9: /* Note On */
396 ret = new_event(track, 0, &event_ptr);
397 if (ret < 0)
399 return -1;
402 event_ptr->event.type = MIDI_EVENT_NOTE_ON;
403 event_ptr->event.tick = tick;
404 event_ptr->event.data.note_on.channel = cmd & 0x0f;
405 event_ptr->event.data.note_on.note = read_byte(media_source_ptr) & 0x7f;
406 event_ptr->event.data.note_on.velocity = read_byte(media_source_ptr) & 0x7f;
407 break;
408 case 0xa: /* Polyphonic Key Pressure (Aftertouch) */
409 ret = new_event(track, 0, &event_ptr);
410 if (ret < 0)
412 return -1;
415 event_ptr->event.type = MIDI_EVENT_KEYPRESS;
416 event_ptr->event.tick = tick;
417 event_ptr->event.data.keypress.channel = cmd & 0x0f;
418 event_ptr->event.data.keypress.note = read_byte(media_source_ptr) & 0x7f;
419 event_ptr->event.data.keypress.velocity = read_byte(media_source_ptr) & 0x7f;
420 break;
421 case 0xb: /* Control Change */
422 ret = new_event(track, 0, &event_ptr);
423 if (ret < 0)
425 return -1;
428 event_ptr->event.type = MIDI_EVENT_CC;
429 event_ptr->event.tick = tick;
430 event_ptr->event.data.cc.channel = cmd & 0x0f;
431 event_ptr->event.data.cc.controller = read_byte(media_source_ptr) & 0x7f;
432 event_ptr->event.data.cc.value = read_byte(media_source_ptr) & 0x7f;
433 break;
434 case 0xe: /* Pitch Wheel Change */
435 ret = new_event(track, 0, &event_ptr);
436 if (ret < 0)
438 return -1;
441 event_ptr->event.type = MIDI_EVENT_CC;
442 event_ptr->event.tick = tick;
443 event_ptr->event.data.pitch.channel = cmd & 0x0f;
444 event_ptr->event.data.pitch.value = (read_byte(media_source_ptr) & 0x7f) | ((read_byte(media_source_ptr) & 0x7f) << 7);
445 break;
447 /* channel messages with 1 parameter byte */
448 case 0xc: /* Program Change */
449 ret = new_event(track, 0, &event_ptr);
450 if (ret < 0)
452 return -1;
455 event_ptr->event.type = MIDI_EVENT_PGMCHANGE;
456 event_ptr->event.tick = tick;
457 event_ptr->event.data.pgmchange.channel = cmd & 0x0f;
458 event_ptr->event.data.pgmchange.program = read_byte(media_source_ptr) & 0x7f;
459 break;
460 case 0xd: /* Channel Pressure (After-touch) */
461 ret = new_event(track, 0, &event_ptr);
462 if (ret < 0)
464 return -1;
467 event_ptr->event.type = MIDI_EVENT_CHANPRESS;
468 event_ptr->event.tick = tick;
469 event_ptr->event.data.chanpress.channel = cmd & 0x0f;
470 event_ptr->event.data.chanpress.value = read_byte(media_source_ptr) & 0x7f;
471 break;
473 case 0xf:
474 switch (cmd)
476 case 0xf0: /* sysex */
477 case 0xf7: /* continued sysex, or escaped commands */
478 len = read_var(media_source_ptr);
480 if (len < 0)
481 goto _error;
483 if (cmd == 0xf0)
484 ++len;
486 ret = new_event(track, len, &event_ptr);
487 if (ret < 0)
489 return -1;
492 event_ptr->event.type = MIDI_EVENT_SYSEX;
493 event_ptr->event.tick = tick;
494 event_ptr->event.data.sysex.size = len;
495 event_ptr->event.data.sysex.data = event_ptr->sysex;
496 if (cmd == 0xf0)
498 event_ptr->sysex[0] = 0xf0;
499 c = 1;
501 else
503 c = 0;
505 for (; c < len; ++c)
506 event_ptr->sysex[c] = read_byte(media_source_ptr);
507 break;
509 case 0xff: /* meta event */
510 c = read_byte(media_source_ptr);
511 len = read_var(media_source_ptr);
512 if (len < 0)
513 goto _error;
515 switch (c)
517 case 0x21: /* port number */
518 if (len < 1)
519 goto _error;
521 int port;
522 port = read_byte(media_source_ptr);
523 DEBUG_OUT("port %u", (unsigned int)port);
524 skip(media_source_ptr, len - 1);
526 break;
528 case 0x2f: /* end of track */
529 track->end_tick = tick;
530 skip(media_source_ptr, track_end - media_source_ptr->file_offset);
531 return 0;
533 case 0x51: /* tempo */
534 if (len < 3)
535 goto _error;
536 if (media_source_ptr->smpte_timing)
538 /* SMPTE timing doesn't change */
539 skip(media_source_ptr, len);
541 else
543 ret = new_event(track, 0, &event_ptr);
544 if (ret < 0)
546 return -1;
549 event_ptr->event.type = MIDI_EVENT_TEMPO;
550 event_ptr->event.tick = tick;
551 event_ptr->event.data.tempo.value = read_byte(media_source_ptr) << 16;
552 event_ptr->event.data.tempo.value |= read_byte(media_source_ptr) << 8;
553 event_ptr->event.data.tempo.value |= read_byte(media_source_ptr);
554 skip(media_source_ptr, len - 3);
556 break;
558 default: /* ignore all other meta events */
559 skip(media_source_ptr, len);
560 break;
562 break;
564 default: /* invalid Fx command */
565 goto _error;
567 break;
569 default: /* cannot happen */
570 goto _error;
573 _error:
574 ERROR_OUT("invalid MIDI data (offset %#x)", media_source_ptr->file_offset);
575 return -1;
579 set_ppqn_event(
580 struct media_source_midi * media_source_ptr,
581 unsigned int ppqn)
583 media_source_ptr->ppqn_event_ptr = malloc(sizeof(struct event));
584 if (media_source_ptr->ppqn_event_ptr == NULL)
586 ERROR_OUT("malloc failed.");
587 return -1;
590 media_source_ptr->ppqn_event_ptr->event.type = MIDI_EVENT_PPQN;
591 media_source_ptr->ppqn_event_ptr->event.tick = 0;
592 media_source_ptr->ppqn_event_ptr->event.data.ppqn.value = ppqn;
594 return 0;
598 set_tempo_event(
599 struct media_source_midi * media_source_ptr,
600 unsigned int tempo)
602 media_source_ptr->tempo_event_ptr = malloc(sizeof(struct event));
603 if (media_source_ptr->tempo_event_ptr == NULL)
605 ERROR_OUT("malloc failed.");
606 return -1;
610 media_source_ptr->tempo_event_ptr->event.type = MIDI_EVENT_TEMPO;
611 media_source_ptr->tempo_event_ptr->event.tick = 0;
612 media_source_ptr->tempo_event_ptr->event.data.tempo.value = tempo;
614 return 0;
617 /* reads an entire MIDI file */
618 static int
619 read_smf(
620 struct media_source_midi * media_source_ptr)
622 int header_len, type, time_division, i;
623 int ret;
625 /* the curren position is immediately after the "MThd" id */
626 header_len = read_int(media_source_ptr, 4);
627 if (header_len != 6)
629 ERROR_OUT("MIDI parsing error (MThd check)");
630 return -1;
633 type = read_int(media_source_ptr, 2);
635 DEBUG_OUT("Type %d", type);
637 if (type != 0 && type != 1)
639 ERROR_OUT("MIDI type %d format is not supported", type);
640 return -1;
643 media_source_ptr->num_tracks = read_int(media_source_ptr, 2);
644 if (media_source_ptr->num_tracks < 1 || media_source_ptr->num_tracks > 1000)
646 ERROR_OUT("invalid number of tracks (%d)", media_source_ptr->num_tracks);
647 media_source_ptr->num_tracks = 0;
648 return -1;
651 DEBUG_OUT("Tracks count: %d", media_source_ptr->num_tracks);
653 media_source_ptr->tracks = calloc(media_source_ptr->num_tracks, sizeof(struct track));
654 if (!media_source_ptr->tracks)
656 ERROR_OUT("out of memory");
657 media_source_ptr->num_tracks = 0;
658 return -1;
661 time_division = read_int(media_source_ptr, 2);
662 if (time_division < 0)
664 ERROR_OUT("MIDI parsing error (time division is negative)");
665 return -1;
668 /* interpret and set tempo */
669 media_source_ptr->smpte_timing = !!(time_division & 0x8000);
670 if (!media_source_ptr->smpte_timing)
672 DEBUG_OUT("PPQN: %d", time_division);
673 DEBUG_OUT("Settings default tempo, 120 bpm");
674 /* time_division is ticks per quarter */
676 ret = set_ppqn_event(media_source_ptr, time_division);
677 if (ret < 0)
679 return -1;
682 ret = set_tempo_event(media_source_ptr, 500000); /* default: 120 bpm */
683 if (ret < 0)
685 return -1;
688 else
690 /* upper byte is negative frames per second */
691 i = 0x80 - ((time_division >> 8) & 0x7f);
692 /* lower byte is ticks per frame */
693 time_division &= 0xff;
694 /* now pretend that we have quarter-note based timing */
695 switch (i)
697 case 24:
698 ret = set_tempo_event(media_source_ptr, 12 * time_division);
699 if (ret < 0)
701 return -1;
704 ret = set_ppqn_event(media_source_ptr, 500000);
705 if (ret < 0)
707 return -1;
709 break;
710 case 25:
711 ret = set_tempo_event(media_source_ptr, 10 * time_division);
712 if (ret < 0)
714 return -1;
717 ret = set_ppqn_event(media_source_ptr, 400000);
718 if (ret < 0)
720 return -1;
722 break;
723 case 29: /* 30 drop-frame */
724 ret = set_tempo_event(media_source_ptr, 2997 * time_division);
725 if (ret < 0)
727 return -1;
730 ret = set_ppqn_event(media_source_ptr, 100000000);
731 if (ret < 0)
733 return -1;
735 break;
736 case 30:
737 ret = set_tempo_event(media_source_ptr, 15 * time_division);
738 if (ret < 0)
740 return -1;
743 ret = set_ppqn_event(media_source_ptr, 500000);
744 if (ret < 0)
746 return -1;
748 break;
749 default:
750 ERROR_OUT("invalid number of SMPTE frames per second (%d)", i);
751 return -1;
755 /* read tracks */
756 for (i = 0; i < media_source_ptr->num_tracks; ++i)
758 int len;
760 /* search for MTrk chunk */
761 for (;;)
763 int id = read_id(media_source_ptr);
764 len = read_int(media_source_ptr, 4);
765 if (feof(media_source_ptr->file_handle))
767 ERROR_OUT("unexpected end of file");
768 return -1;
770 if (len < 0 || len >= 0x10000000)
772 ERROR_OUT("invalid chunk length %d", len);
773 return -1;
775 if (id == MAKE_ID('M', 'T', 'r', 'k'))
776 break;
777 skip(media_source_ptr, len);
780 ret = read_track(media_source_ptr, &media_source_ptr->tracks[i], media_source_ptr->file_offset + len);
781 if (ret < 0)
782 return -1;
785 return 0;
789 media_source_midi_load(struct media_source_midi * media_source_ptr)
791 int i;
792 int ret;
794 ret = read_smf(media_source_ptr);
795 if (ret < 0)
797 return -1;
800 /* calculate length of the entire file */
801 DEBUG_OUT("Finding max_tick....");
802 media_source_ptr->max_tick = -1;
803 for (i = 0; i < media_source_ptr->num_tracks; ++i)
805 DEBUG_OUT("track i end_tick = %d", media_source_ptr->tracks[i].end_tick);
806 if (media_source_ptr->tracks[i].end_tick > media_source_ptr->max_tick)
808 media_source_ptr->max_tick = media_source_ptr->tracks[i].end_tick;
811 DEBUG_OUT("max_tick = %d", media_source_ptr->max_tick);
813 /* initialize current position in each track */
814 for (i = 0; i < media_source_ptr->num_tracks; ++i)
816 media_source_ptr->tracks[i].current_event_ptr = media_source_ptr->tracks[i].first_event_ptr;
819 return 0;
823 media_source_midi(
824 const char * filename,
825 struct media_source ** media_source_ptr_ptr)
827 struct media_source_midi * media_source_ptr;
828 int ret;
830 DEBUG_OUT("media_source_midi");
832 media_source_ptr = (struct media_source_midi *)malloc(sizeof(struct media_source_midi));
833 if (media_source_ptr == NULL)
835 ERROR_OUT("malloc() failed.");
836 ret = -1;
837 goto exit;
840 media_source_ptr->ppqn_event_ptr = NULL;
841 media_source_ptr->tempo_event_ptr = NULL;
842 media_source_ptr->tracks = NULL;
844 media_source_ptr->file_handle = fopen(filename, "rb");
845 if (!media_source_ptr->file_handle)
847 ERROR_OUT("Cannot open %s - %s", filename, strerror(errno));
848 ret = -1;
849 goto cleanup;
852 media_source_ptr->file_offset = 0;
854 if (read_id(media_source_ptr) != MAKE_ID('M', 'T', 'h', 'd'))
856 ERROR_OUT("%s is not a Standard MIDI File", filename);
857 ret = -1;
858 goto cleanup;
861 media_source_ptr->virtual.destroy = media_source_midi_destroy;
862 media_source_ptr->virtual.format_query = media_source_midi_format_query;
863 media_source_ptr->virtual.get_frame_data = media_source_midi_get_frame_data;
864 media_source_ptr->virtual.next_frame = media_source_midi_next_frame;
866 ret = media_source_midi_load(media_source_ptr);
867 if (ret < 0)
869 ERROR_OUT("media_source_midi_load() failed.");
870 goto cleanup;
873 media_source_ptr->counter = 0;
875 *media_source_ptr_ptr = &media_source_ptr->virtual;
877 ret = 0;
878 goto exit;
880 cleanup:
881 cleanup_file_data(media_source_ptr);
882 goto exit;
884 exit:
885 return ret;