1 // Emacs style mode select -*- C++ -*-
2 //-----------------------------------------------------------------------------
3 //
4 // Copyright(C) 2009 Simon Howard
5 //
6 // This program is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU General Public License
8 // as published by the Free Software Foundation; either version 2
9 // of the License, or (at your option) any later version.
10 //
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.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
19 // 02111-1307, USA.
20 //
21 // DESCRIPTION:
22 // Reading of MIDI files.
23 //
24 //-----------------------------------------------------------------------------
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30
31 #ifndef TEST
32 #include "doomdef.h"
33 #include "doomtype.h"
34 #else
35 typedef enum {false, true} dboolean;
36 typedef unsigned char byte;
37 #define PACKEDATTR __attribute__((packed))
38 #endif
39 #include "lprintf.h"
40 #include "midifile.h"
41
42 #define HEADER_CHUNK_ID "MThd"
43 #define TRACK_CHUNK_ID "MTrk"
44 #define MAX_BUFFER_SIZE 0x10000
45
46
47
48
49
50 #ifdef HAVE_CONFIG_H
51 #include "config.h"
52 #endif
53
54 #ifndef ntohl
55 #ifdef WORDS_BIGENDIAN
56 #define ntohl
57 #define ntohs
58 #else // WORDS_BIGENDIAN
59
60 #define ntohl(x) \
61 (/*(long int)*/((((unsigned long int)(x) & 0x000000ffU) << 24) | \
62 (((unsigned long int)(x) & 0x0000ff00U) << 8) | \
63 (((unsigned long int)(x) & 0x00ff0000U) >> 8) | \
64 (((unsigned long int)(x) & 0xff000000U) >> 24)))
65
66 #define ntohs(x) \
67 (/*(short int)*/((((unsigned short int)(x) & 0x00ff) << 8) | \
68 (((unsigned short int)(x) & 0xff00) >> 8)))
69 #endif // WORDS_BIGENDIAN
70 #endif // ntohl
71
72
73 #ifdef _MSC_VER
74 #pragma pack(push, 1)
75 #endif
76
77 typedef struct
78 {
79 byte chunk_id[4];
80 unsigned int chunk_size;
81 } PACKEDATTR chunk_header_t;
82
83 typedef struct
84 {
85 chunk_header_t chunk_header;
86 unsigned short format_type;
87 unsigned short num_tracks;
88 unsigned short time_division;
89 } PACKEDATTR midi_header_t;
90
91 #ifdef _MSC_VER
92 #pragma pack(pop)
93 #endif
94
95 typedef struct
96 {
97 // Length in bytes:
98
99 unsigned int data_len;
100
101 // Events in this track:
102
103 midi_event_t *events;
104 unsigned int num_events;
105 unsigned int num_event_mem; // NSM track size of structure
106 } midi_track_t;
107
108 struct midi_track_iter_s
109 {
110 midi_track_t *track;
111 unsigned int position;
112 };
113
114 struct midi_file_s
115 {
116 midi_header_t header;
117
118 // All tracks in this file:
119 midi_track_t *tracks;
120 unsigned int num_tracks;
121
122 // Data buffer used to store data read for SysEx or meta events:
123 byte *buffer;
124 unsigned int buffer_size;
125 };
126
127
128
129 // Check the header of a chunk:
130
CheckChunkHeader(chunk_header_t * chunk,const char * expected_id)131 static dboolean CheckChunkHeader(chunk_header_t *chunk,
132 const char *expected_id)
133 {
134 dboolean result;
135
136 result = (memcmp((char *) chunk->chunk_id, expected_id, 4) == 0);
137
138 if (!result)
139 {
140 lprintf (LO_WARN, "CheckChunkHeader: Expected '%s' chunk header, "
141 "got '%c%c%c%c'\n",
142 expected_id,
143 chunk->chunk_id[0], chunk->chunk_id[1],
144 chunk->chunk_id[2], chunk->chunk_id[3]);
145 }
146
147 return result;
148 }
149
150 // Read a single byte. Returns false on error.
151
ReadByte(byte * result,midimem_t * mf)152 static dboolean ReadByte(byte *result, midimem_t *mf)
153 {
154 if (mf->pos >= mf->len)
155 {
156 lprintf (LO_WARN, "ReadByte: Unexpected end of file\n");
157 return false;
158 }
159
160 *result = mf->data[mf->pos++];
161 return true;
162 }
163
ReadMultipleBytes(void * dest,size_t len,midimem_t * mf)164 static dboolean ReadMultipleBytes (void *dest, size_t len, midimem_t *mf)
165 {
166 byte *cdest = (byte *) dest;
167 unsigned i;
168 for (i = 0; i < len; i++)
169 {
170 if (!ReadByte (cdest + i, mf))
171 {
172 lprintf (LO_WARN, "ReadMultipleBytes: Unexpected end of file\n");
173 return false;
174 }
175 }
176 return true;
177 }
178
179 // Read a variable-length value.
180
ReadVariableLength(unsigned int * result,midimem_t * mf)181 static dboolean ReadVariableLength(unsigned int *result, midimem_t *mf)
182 {
183 int i;
184 byte b;
185
186 *result = 0;
187
188 for (i=0; i<4; ++i)
189 {
190 if (!ReadByte(&b, mf))
191 {
192 lprintf (LO_WARN, "ReadVariableLength: Error while reading "
193 "variable-length value\n");
194 return false;
195 }
196
197 // Insert the bottom seven bits from this byte.
198
199 *result <<= 7;
200 *result |= b & 0x7f;
201
202 // If the top bit is not set, this is the end.
203
204 if ((b & 0x80) == 0)
205 {
206 return true;
207 }
208 }
209
210 lprintf (LO_WARN, "ReadVariableLength: Variable-length value too "
211 "long: maximum of four bytes\n");
212 return false;
213 }
214
215 // Read a byte sequence into the data buffer.
216
ReadByteSequence(unsigned int num_bytes,midimem_t * mf)217 static void *ReadByteSequence(unsigned int num_bytes, midimem_t *mf)
218 {
219 unsigned int i;
220 byte *result;
221
222 // events can be length 0. malloc(0) is not portable (can return NULL)
223 if (!num_bytes)
224 return malloc (4);
225
226 // Allocate a buffer:
227
228 result = malloc(num_bytes);
229
230 if (result == NULL)
231 {
232 lprintf (LO_WARN, "ReadByteSequence: Failed to allocate buffer %u bytes\n", num_bytes);
233 return NULL;
234 }
235
236 // Read the data:
237
238 for (i=0; i<num_bytes; ++i)
239 {
240 if (!ReadByte(&result[i], mf))
241 {
242 lprintf (LO_WARN, "ReadByteSequence: Error while reading byte %u\n", i);
243 free(result);
244 return NULL;
245 }
246 }
247
248 return result;
249 }
250
251 // Read a MIDI channel event.
252 // two_param indicates that the event type takes two parameters
253 // (three byte) otherwise it is single parameter (two byte)
254
ReadChannelEvent(midi_event_t * event,byte event_type,dboolean two_param,midimem_t * mf)255 static dboolean ReadChannelEvent(midi_event_t *event,
256 byte event_type, dboolean two_param,
257 midimem_t *mf)
258 {
259 byte b;
260
261 // Set basics:
262
263 event->event_type = event_type & 0xf0;
264 event->data.channel.channel = event_type & 0x0f;
265
266 // Read parameters:
267
268 if (!ReadByte(&b, mf))
269 {
270 lprintf (LO_WARN, "ReadChannelEvent: Error while reading channel "
271 "event parameters\n");
272 return false;
273 }
274
275 event->data.channel.param1 = b;
276
277 // Second parameter:
278
279 if (two_param)
280 {
281 if (!ReadByte(&b, mf))
282 {
283 lprintf (LO_WARN, "ReadChannelEvent: Error while reading channel "
284 "event parameters\n");
285 return false;
286 }
287
288 event->data.channel.param2 = b;
289 }
290
291 return true;
292 }
293
294 // Read sysex event:
295
ReadSysExEvent(midi_event_t * event,int event_type,midimem_t * mf)296 static dboolean ReadSysExEvent(midi_event_t *event, int event_type,
297 midimem_t *mf)
298 {
299 event->event_type = event_type;
300
301 if (!ReadVariableLength(&event->data.sysex.length, mf))
302 {
303 lprintf (LO_WARN, "ReadSysExEvent: Failed to read length of "
304 "SysEx block\n");
305 return false;
306 }
307
308 // Read the byte sequence:
309
310 event->data.sysex.data = ReadByteSequence(event->data.sysex.length, mf);
311
312 if (event->data.sysex.data == NULL)
313 {
314 lprintf (LO_WARN, "ReadSysExEvent: Failed while reading SysEx event\n");
315 return false;
316 }
317
318 return true;
319 }
320
321 // Read meta event:
322
ReadMetaEvent(midi_event_t * event,midimem_t * mf)323 static dboolean ReadMetaEvent(midi_event_t *event, midimem_t *mf)
324 {
325 byte b;
326
327 event->event_type = MIDI_EVENT_META;
328
329 // Read meta event type:
330
331 if (!ReadByte(&b, mf))
332 {
333 lprintf (LO_WARN, "ReadMetaEvent: Failed to read meta event type\n");
334 return false;
335 }
336
337 event->data.meta.type = b;
338
339 // Read length of meta event data:
340
341 if (!ReadVariableLength(&event->data.meta.length, mf))
342 {
343 lprintf (LO_WARN, "ReadMetaEvent: Failed to read length of "
344 "MetaEvent block\n");
345 return false;
346 }
347
348 // Read the byte sequence:
349
350 event->data.meta.data = ReadByteSequence(event->data.meta.length, mf);
351
352 if (event->data.meta.data == NULL)
353 {
354 lprintf (LO_WARN, "ReadMetaEvent: Failed while reading MetaEvent\n");
355 return false;
356 }
357
358 return true;
359 }
360
ReadEvent(midi_event_t * event,unsigned int * last_event_type,midimem_t * mf)361 static dboolean ReadEvent(midi_event_t *event, unsigned int *last_event_type,
362 midimem_t *mf)
363 {
364 byte event_type;
365
366 if (!ReadVariableLength(&event->delta_time, mf))
367 {
368 lprintf (LO_WARN, "ReadEvent: Failed to read event timestamp\n");
369 return false;
370 }
371
372 if (!ReadByte(&event_type, mf))
373 {
374 lprintf (LO_WARN, "ReadEvent: Failed to read event type\n");
375 return false;
376 }
377
378 // All event types have their top bit set. Therefore, if
379 // the top bit is not set, it is because we are using the "same
380 // as previous event type" shortcut to save a byte. Skip back
381 // a byte so that we read this byte again.
382
383 if ((event_type & 0x80) == 0)
384 {
385 event_type = *last_event_type;
386 mf->pos--;
387 }
388 else
389 {
390 *last_event_type = event_type;
391 }
392
393 // Check event type:
394
395 switch (event_type & 0xf0)
396 {
397 // Two parameter channel events:
398
399 case MIDI_EVENT_NOTE_OFF:
400 case MIDI_EVENT_NOTE_ON:
401 case MIDI_EVENT_AFTERTOUCH:
402 case MIDI_EVENT_CONTROLLER:
403 case MIDI_EVENT_PITCH_BEND:
404 return ReadChannelEvent(event, event_type, true, mf);
405
406 // Single parameter channel events:
407
408 case MIDI_EVENT_PROGRAM_CHANGE:
409 case MIDI_EVENT_CHAN_AFTERTOUCH:
410 return ReadChannelEvent(event, event_type, false, mf);
411
412 default:
413 break;
414 }
415
416 // Specific value?
417
418 switch (event_type)
419 {
420 case MIDI_EVENT_SYSEX:
421 case MIDI_EVENT_SYSEX_SPLIT:
422 return ReadSysExEvent(event, event_type, mf);
423
424 case MIDI_EVENT_META:
425 return ReadMetaEvent(event, mf);
426
427 default:
428 break;
429 }
430
431 lprintf (LO_WARN, "ReadEvent: Unknown MIDI event type: 0x%x\n", event_type);
432 return false;
433 }
434
435 // Free an event:
436
FreeEvent(midi_event_t * event)437 static void FreeEvent(midi_event_t *event)
438 {
439 // Some event types have dynamically allocated buffers assigned
440 // to them that must be freed.
441
442 switch (event->event_type)
443 {
444 case MIDI_EVENT_SYSEX:
445 case MIDI_EVENT_SYSEX_SPLIT:
446 free(event->data.sysex.data);
447 break;
448
449 case MIDI_EVENT_META:
450 free(event->data.meta.data);
451 break;
452
453 default:
454 // Nothing to do.
455 break;
456 }
457 }
458
459 // Read and check the track chunk header
460
ReadTrackHeader(midi_track_t * track,midimem_t * mf)461 static dboolean ReadTrackHeader(midi_track_t *track, midimem_t *mf)
462 {
463 size_t records_read;
464 chunk_header_t chunk_header;
465
466 records_read = ReadMultipleBytes(&chunk_header, sizeof(chunk_header_t), mf);
467
468 if (records_read < 1)
469 {
470 return false;
471 }
472
473 if (!CheckChunkHeader(&chunk_header, TRACK_CHUNK_ID))
474 {
475 return false;
476 }
477
478 track->data_len = ntohl(chunk_header.chunk_size);
479
480 return true;
481 }
482
ReadTrack(midi_track_t * track,midimem_t * mf)483 static dboolean ReadTrack(midi_track_t *track, midimem_t *mf)
484 {
485 midi_event_t *new_events = NULL;
486 midi_event_t *event;
487 unsigned int last_event_type;
488
489 track->num_events = 0;
490 track->events = NULL;
491 track->num_event_mem = 0; // NSM
492
493 // Read the header:
494
495 if (!ReadTrackHeader(track, mf))
496 {
497 return false;
498 }
499
500 // Then the events:
501
502 last_event_type = 0;
503
504 for (;;)
505 {
506 // Resize the track slightly larger to hold another event:
507 /*
508 new_events = realloc(track->events,
509 sizeof(midi_event_t) * (track->num_events + 1));
510 */
511 if (track->num_events == track->num_event_mem)
512 { // depending on the state of the heap and the malloc implementation, realloc()
513 // one more event at a time can be VERY slow. 10sec+ in MSVC
514 track->num_event_mem += 100;
515 new_events = realloc (track->events, sizeof (midi_event_t) * track->num_event_mem);
516 }
517
518 if (new_events == NULL)
519 {
520 return false;
521 }
522
523 track->events = new_events;
524
525 // Read the next event:
526
527 event = &track->events[track->num_events];
528 if (!ReadEvent(event, &last_event_type, mf))
529 {
530 return false;
531 }
532
533 ++track->num_events;
534
535 // End of track?
536
537 if (event->event_type == MIDI_EVENT_META
538 && event->data.meta.type == MIDI_META_END_OF_TRACK)
539 {
540 break;
541 }
542 }
543
544 return true;
545 }
546
547 // Free a track:
548
FreeTrack(midi_track_t * track)549 static void FreeTrack(midi_track_t *track)
550 {
551 unsigned i;
552
553 for (i=0; i<track->num_events; ++i)
554 {
555 FreeEvent(&track->events[i]);
556 }
557
558 free(track->events);
559 }
560
ReadAllTracks(midi_file_t * file,midimem_t * mf)561 static dboolean ReadAllTracks(midi_file_t *file, midimem_t *mf)
562 {
563 unsigned int i;
564
565 // Allocate list of tracks and read each track:
566
567 file->tracks = malloc(sizeof(midi_track_t) * file->num_tracks);
568
569 if (file->tracks == NULL)
570 {
571 return false;
572 }
573
574 memset(file->tracks, 0, sizeof(midi_track_t) * file->num_tracks);
575
576 // Read each track:
577
578 for (i=0; i<file->num_tracks; ++i)
579 {
580 if (!ReadTrack(&file->tracks[i], mf))
581 {
582 return false;
583 }
584 }
585
586 return true;
587 }
588
589 // Read and check the header chunk.
590
ReadFileHeader(midi_file_t * file,midimem_t * mf)591 static dboolean ReadFileHeader(midi_file_t *file, midimem_t *mf)
592 {
593 size_t records_read;
594 unsigned int format_type;
595
596 records_read = ReadMultipleBytes (&file->header, sizeof(midi_header_t), mf);
597
598 if (records_read < 1)
599 {
600 return false;
601 }
602
603 if (!CheckChunkHeader(&file->header.chunk_header, HEADER_CHUNK_ID)
604 || ntohl(file->header.chunk_header.chunk_size) != 6)
605 {
606 lprintf (LO_WARN, "ReadFileHeader: Invalid MIDI chunk header! "
607 "chunk_size=%ld\n",
608 ntohl(file->header.chunk_header.chunk_size));
609 return false;
610 }
611
612 format_type = ntohs(file->header.format_type);
613 file->num_tracks = ntohs(file->header.num_tracks);
614
615 if ((format_type != 0 && format_type != 1)
616 || file->num_tracks < 1)
617 {
618 lprintf (LO_WARN, "ReadFileHeader: Only type 0/1 "
619 "MIDI files supported!\n");
620 return false;
621 }
622 // NSM
623 file->header.time_division = ntohs (file->header.time_division);
624
625
626 return true;
627 }
628
MIDI_FreeFile(midi_file_t * file)629 void MIDI_FreeFile(midi_file_t *file)
630 {
631 unsigned i;
632
633 if (file->tracks != NULL)
634 {
635 for (i=0; i<file->num_tracks; ++i)
636 {
637 FreeTrack(&file->tracks[i]);
638 }
639
640 free(file->tracks);
641 }
642
643 free(file);
644 }
645
MIDI_LoadFile(midimem_t * mf)646 midi_file_t *MIDI_LoadFile (midimem_t *mf)
647 {
648 midi_file_t *file;
649
650 file = malloc(sizeof(midi_file_t));
651
652 if (file == NULL)
653 {
654 return NULL;
655 }
656
657 file->tracks = NULL;
658 file->num_tracks = 0;
659 file->buffer = NULL;
660 file->buffer_size = 0;
661
662 // Read MIDI file header
663
664 if (!ReadFileHeader(file, mf))
665 {
666 MIDI_FreeFile(file);
667 return NULL;
668 }
669
670 // Read all tracks:
671
672 if (!ReadAllTracks(file, mf))
673 {
674 MIDI_FreeFile(file);
675 return NULL;
676 }
677
678 return file;
679 }
680
681 // Get the number of tracks in a MIDI file.
682
MIDI_NumTracks(const midi_file_t * file)683 unsigned int MIDI_NumTracks(const midi_file_t *file)
684 {
685 return file->num_tracks;
686 }
687
688 // Start iterating over the events in a track.
689
MIDI_IterateTrack(const midi_file_t * file,unsigned int track)690 midi_track_iter_t *MIDI_IterateTrack(const midi_file_t *file, unsigned int track)
691 {
692 midi_track_iter_t *iter;
693
694 assert(track < file->num_tracks);
695
696 iter = malloc(sizeof(*iter));
697 iter->track = &file->tracks[track];
698 iter->position = 0;
699
700 return iter;
701 }
702
MIDI_FreeIterator(midi_track_iter_t * iter)703 void MIDI_FreeIterator(midi_track_iter_t *iter)
704 {
705 free(iter);
706 }
707
708 // Get the time until the next MIDI event in a track.
709
MIDI_GetDeltaTime(midi_track_iter_t * iter)710 unsigned int MIDI_GetDeltaTime(midi_track_iter_t *iter)
711 {
712 if (iter->position < iter->track->num_events)
713 {
714 midi_event_t *next_event;
715
716 next_event = &iter->track->events[iter->position];
717
718 return next_event->delta_time;
719 }
720 else
721 {
722 return 0;
723 }
724 }
725
726 // Get a pointer to the next MIDI event.
727
MIDI_GetNextEvent(midi_track_iter_t * iter,midi_event_t ** event)728 int MIDI_GetNextEvent(midi_track_iter_t *iter, midi_event_t **event)
729 {
730 if (iter->position < iter->track->num_events)
731 {
732 *event = &iter->track->events[iter->position];
733 ++iter->position;
734
735 return 1;
736 }
737 else
738 {
739 return 0;
740 }
741 }
742
MIDI_GetFileTimeDivision(const midi_file_t * file)743 unsigned int MIDI_GetFileTimeDivision(const midi_file_t *file)
744 {
745 return file->header.time_division;
746 }
747
MIDI_RestartIterator(midi_track_iter_t * iter)748 void MIDI_RestartIterator(midi_track_iter_t *iter)
749 {
750 iter->position = 0;
751 }
752
753
754
MIDI_PrintFlatListDBG(const midi_event_t ** evs)755 static void MIDI_PrintFlatListDBG (const midi_event_t **evs)
756 {
757 const midi_event_t *event;
758
759 while (1)
760 {
761 event = *evs++;
762
763 if (event->delta_time > 0)
764 printf("Delay: %i ticks\n", event->delta_time);
765
766
767 switch (event->event_type)
768 {
769 case MIDI_EVENT_NOTE_OFF:
770 printf ("MIDI_EVENT_NOTE_OFF\n");break;
771 case MIDI_EVENT_NOTE_ON:
772 printf ("MIDI_EVENT_NOTE_ON\n");break;
773 case MIDI_EVENT_AFTERTOUCH:
774 printf ("MIDI_EVENT_AFTERTOUCH\n");break;
775 case MIDI_EVENT_CONTROLLER:
776 printf ("MIDI_EVENT_CONTROLLER\n");break;
777 case MIDI_EVENT_PROGRAM_CHANGE:
778 printf ("MIDI_EVENT_PROGRAM_CHANGE\n");break;
779 case MIDI_EVENT_CHAN_AFTERTOUCH:
780 printf ("MIDI_EVENT_CHAN_AFTERTOUCH\n");break;
781 case MIDI_EVENT_PITCH_BEND:
782 printf ("MIDI_EVENT_PITCH_BEND\n");break;
783 case MIDI_EVENT_SYSEX:
784 printf ("MIDI_EVENT_SYSEX\n");break;
785 case MIDI_EVENT_SYSEX_SPLIT:
786 printf ("MIDI_EVENT_SYSEX_SPLIT\n");break;
787 case MIDI_EVENT_META:
788 printf ("MIDI_EVENT_META\n");break;
789
790 default:
791 printf ("(unknown)\n");break;
792 }
793 switch(event->event_type)
794 {
795 case MIDI_EVENT_NOTE_OFF:
796 case MIDI_EVENT_NOTE_ON:
797 case MIDI_EVENT_AFTERTOUCH:
798 case MIDI_EVENT_CONTROLLER:
799 case MIDI_EVENT_PROGRAM_CHANGE:
800 case MIDI_EVENT_CHAN_AFTERTOUCH:
801 case MIDI_EVENT_PITCH_BEND:
802 printf("\tChannel: %i\n", event->data.channel.channel);
803 printf("\tParameter 1: %i\n", event->data.channel.param1);
804 printf("\tParameter 2: %i\n", event->data.channel.param2);
805 break;
806
807 case MIDI_EVENT_SYSEX:
808 case MIDI_EVENT_SYSEX_SPLIT:
809 printf("\tLength: %i\n", event->data.sysex.length);
810 break;
811
812 case MIDI_EVENT_META:
813 printf("\tMeta type: %i\n", event->data.meta.type);
814 printf("\tLength: %i\n", event->data.meta.length);
815 break;
816 }
817 if (event->event_type == MIDI_EVENT_META &&
818 event->data.meta.type == MIDI_META_END_OF_TRACK)
819 {
820 printf ("gotta go!\n");
821 return;
822 }
823 }
824 }
825
826
827
828
829
830
831 // NSM: an alternate iterator tool.
832
MIDI_GenerateFlatList(midi_file_t * file)833 midi_event_t **MIDI_GenerateFlatList (midi_file_t *file)
834 {
835 int totalevents = 0;
836 unsigned i, delta;
837 int nextrk;
838
839 int totaldelta = 0;
840
841 int *trackpos = calloc (file->num_tracks, sizeof (int));
842 int *tracktime = calloc (file->num_tracks, sizeof (int));
843 int trackactive = file->num_tracks;
844
845 midi_event_t **ret;
846 midi_event_t **epos;
847
848 for (i = 0; i < file->num_tracks; i++)
849 totalevents += file->tracks[i].num_events;
850
851 ret = malloc (totalevents * sizeof (midi_event_t **));
852
853 epos = ret;
854
855 while (trackactive)
856 {
857 delta = 0x10000000;
858 nextrk = -1;
859 for (i = 0; i < file->num_tracks; i++)
860 {
861 if (trackpos[i] != -1 && file->tracks[i].events[trackpos[i]].delta_time - tracktime[i] < delta)
862 {
863 delta = file->tracks[i].events[trackpos[i]].delta_time - tracktime[i];
864 nextrk = i;
865 }
866 }
867 if (nextrk == -1) // unexpected EOF (not every track got end track)
868 break;
869
870 *epos = file->tracks[nextrk].events + trackpos[nextrk];
871
872 for (i = 0; i < file->num_tracks; i++)
873 {
874 if (i == (unsigned) nextrk)
875 {
876 tracktime[i] = 0;
877 trackpos[i]++;
878 }
879 else
880 tracktime[i] += delta;
881 }
882 // yes, this clobbers the original timecodes
883 epos[0]->delta_time = delta;
884 totaldelta += delta;
885
886 if (epos[0]->event_type == MIDI_EVENT_META
887 && epos[0]->data.meta.type == MIDI_META_END_OF_TRACK)
888 { // change end of track into no op
889 trackactive--;
890 trackpos[nextrk] = -1;
891 epos[0]->data.meta.type = MIDI_META_TEXT;
892 }
893 else if ((unsigned) trackpos[nextrk] == file->tracks[nextrk].num_events)
894 {
895 lprintf (LO_WARN, "MIDI_GenerateFlatList: Unexpected end of track\n");
896 free (trackpos);
897 free (tracktime);
898 free (ret);
899 return NULL;
900 }
901 epos++;
902 }
903
904 if (trackactive)
905 { // unexpected EOF
906 lprintf (LO_WARN, "MIDI_GenerateFlatList: Unexpected end of midi file\n");
907 free (trackpos);
908 free (tracktime);
909 free (ret);
910 return NULL;
911 }
912
913 // last end of track event is preserved though
914 epos[-1]->data.meta.type = MIDI_META_END_OF_TRACK;
915
916 free (trackpos);
917 free (tracktime);
918
919 if (totaldelta < 100)
920 {
921 lprintf (LO_WARN, "MIDI_GeneratFlatList: very short file %i\n", totaldelta);
922 free (ret);
923 return NULL;
924 }
925
926
927 //MIDI_PrintFlatListDBG (ret);
928
929 return ret;
930 }
931
932
933
MIDI_DestroyFlatList(midi_event_t ** evs)934 void MIDI_DestroyFlatList (midi_event_t **evs)
935 {
936 free (evs);
937 }
938
939
940
941 // NSM: timing assist functions
942 // they compute samples per midi clock, where midi clock is the units
943 // that the time deltas are in, and samples is an arbitrary unit of which
944 // "sndrate" of them occur per second
945
946
compute_spmc_normal(unsigned mpq,unsigned tempo,unsigned sndrate)947 static double compute_spmc_normal (unsigned mpq, unsigned tempo, unsigned sndrate)
948 { // returns samples per midi clock
949
950 // inputs: mpq (midi clocks per quarternote, from header)
951 // tempo (from tempo event, in microseconds per quarternote)
952 // sndrate (sound sample rate in hz)
953
954 // samples quarternote microsec samples second
955 // ------- = ----------- * ----------- * ------- * --------
956 // midiclk midiclk quarternote second microsec
957
958 // return = (1 / mpq) * tempo * sndrate * (1 / 1000000)
959
960 return (double) tempo / 1000000 * sndrate / mpq;
961
962 }
963
compute_spmc_smpte(unsigned smpte_fps,unsigned mpf,unsigned sndrate)964 static double compute_spmc_smpte (unsigned smpte_fps, unsigned mpf, unsigned sndrate)
965 { // returns samples per midi clock
966
967 // inputs: smpte_fps (24, 25, 29, 30)
968 // mpf (midi clocks per frame, 0-255)
969 // sndrate (sound sample rate in hz)
970
971 // tempo is ignored here
972
973 // samples frame seconds samples
974 // ------- = --------- * --------- * -------
975 // midiclk midiclk frame second
976
977 // return = (1 / mpf) * (1 / fps) * sndrate
978
979
980 double fps; // actual frames per second
981 switch (smpte_fps)
982 {
983 case 24:
984 case 25:
985 case 30:
986 fps = smpte_fps;
987 break;
988 case 29:
989 // i hate NTSC, i really do
990 fps = smpte_fps * 1000.0 / 1001.0;
991 break;
992 default:
993 lprintf (LO_WARN, "MIDI_spmc: Unexpected SMPTE timestamp %i\n", smpte_fps);
994 // assume
995 fps = 30.0;
996 break;
997 }
998
999 return (double) sndrate / fps / mpf;
1000
1001 }
1002
1003 // if event is NULL, compute with default starting tempo (120BPM)
1004
MIDI_spmc(const midi_file_t * file,const midi_event_t * ev,unsigned sndrate)1005 double MIDI_spmc (const midi_file_t *file, const midi_event_t *ev, unsigned sndrate)
1006 {
1007 int smpte_fps;
1008 unsigned tempo;
1009 unsigned headerval = MIDI_GetFileTimeDivision (file);
1010
1011 if (headerval & 0x8000) // SMPTE
1012 { // i don't really have any files to test this on...
1013 smpte_fps = -(short) headerval >> 8;
1014 return compute_spmc_smpte (smpte_fps, headerval & 0xff, sndrate);
1015 }
1016
1017 // normal timing
1018 tempo = 500000; // default 120BPM
1019 if (ev)
1020 {
1021 if (ev->event_type == MIDI_EVENT_META)
1022 {
1023 if (ev->data.meta.length == 3)
1024 {
1025 tempo = (unsigned) ev->data.meta.data[0] << 16 |
1026 (unsigned) ev->data.meta.data[1] << 8 |
1027 (unsigned) ev->data.meta.data[2];
1028 }
1029 else
1030 lprintf (LO_WARN, "MIDI_spmc: wrong length tempo meta message in midi file\n");
1031 }
1032 else
1033 lprintf (LO_WARN, "MIDI_spmc: passed non-meta event\n");
1034 }
1035
1036 return compute_spmc_normal (headerval, tempo, sndrate);
1037 }
1038
1039 /*
1040 The timing system used by the OPL driver is very interesting. But there are too many edge cases
1041 in multitrack (type 1) midi tempo changes that it simply can't handle without a major rework.
1042 The alternative is that we recook the file into a single track file with no tempo changes at
1043 load time.
1044 */
1045
MIDI_LoadFileSpecial(midimem_t * mf)1046 midi_file_t *MIDI_LoadFileSpecial (midimem_t *mf)
1047 {
1048 midi_event_t **flatlist;
1049 midi_file_t *base = MIDI_LoadFile (mf);
1050 midi_file_t *ret;
1051
1052 double opi;
1053
1054 int epos = 0;
1055
1056 if (!base)
1057 return NULL;
1058
1059 flatlist = MIDI_GenerateFlatList (base);
1060 if (!flatlist)
1061 {
1062 MIDI_FreeFile (base);
1063 return NULL;
1064 }
1065
1066 ret = malloc (sizeof (midi_file_t));
1067
1068 ret->header.format_type = 0;
1069 ret->header.num_tracks = 1;
1070 ret->header.time_division = 10000;
1071 ret->num_tracks = 1;
1072 ret->buffer_size = 0;
1073 ret->buffer = NULL;
1074 ret->tracks = malloc (sizeof (midi_track_t));
1075
1076 ret->tracks->num_events = 0;
1077 ret->tracks->num_event_mem = 0;
1078 ret->tracks->events = NULL;
1079
1080 opi = MIDI_spmc (base, NULL, 20000);
1081
1082
1083 while (1)
1084 {
1085 midi_event_t *oldev;
1086 midi_event_t *nextev;
1087
1088 if (ret->tracks->num_events == ret->tracks->num_event_mem)
1089 {
1090 ret->tracks->num_event_mem += 100;
1091 ret->tracks->events = realloc (ret->tracks->events, sizeof (midi_event_t) * ret->tracks->num_event_mem);
1092 }
1093
1094 oldev = flatlist[epos];
1095 nextev = ret->tracks->events + ret->tracks->num_events;
1096
1097
1098 // figure delta time
1099 nextev->delta_time = (unsigned int)(opi * oldev->delta_time);
1100
1101 if (oldev->event_type == MIDI_EVENT_SYSEX ||
1102 oldev->event_type == MIDI_EVENT_SYSEX_SPLIT)
1103 // opl player can't process any sysex...
1104 {
1105 epos++;
1106 continue;
1107 }
1108
1109 if (oldev->event_type == MIDI_EVENT_META)
1110 {
1111 if (oldev->data.meta.type == MIDI_META_SET_TEMPO)
1112 { // adjust future tempo scaling
1113 opi = MIDI_spmc (base, oldev, 20000);
1114 // insert event as dummy
1115 nextev->event_type = MIDI_EVENT_META;
1116 nextev->data.meta.type = MIDI_META_TEXT;
1117 nextev->data.meta.length = 0;
1118 nextev->data.meta.data = malloc (4);
1119 epos++;
1120 ret->tracks->num_events++;
1121 continue;
1122 }
1123 if (oldev->data.meta.type == MIDI_META_END_OF_TRACK)
1124 { // reproduce event and break
1125 nextev->event_type = MIDI_EVENT_META;
1126 nextev->data.meta.type = MIDI_META_END_OF_TRACK;
1127 nextev->data.meta.length = 0;
1128 nextev->data.meta.data = malloc (4);
1129 epos++;
1130 ret->tracks->num_events++;
1131 break;
1132 }
1133 // other meta events not needed
1134 epos++;
1135 continue;
1136 }
1137 // non meta events can simply be copied (excluding delta time)
1138 memcpy (&nextev->event_type, &oldev->event_type, sizeof (midi_event_t) - sizeof (unsigned));
1139 epos++;
1140 ret->tracks->num_events++;
1141 }
1142
1143 MIDI_DestroyFlatList (flatlist);
1144 MIDI_FreeFile (base);
1145 return ret;
1146 }
1147
1148
1149
1150 #ifdef TEST
1151
MIDI_EventTypeToString(midi_event_type_t event_type)1152 static char *MIDI_EventTypeToString(midi_event_type_t event_type)
1153 {
1154 switch (event_type)
1155 {
1156 case MIDI_EVENT_NOTE_OFF:
1157 return "MIDI_EVENT_NOTE_OFF";
1158 case MIDI_EVENT_NOTE_ON:
1159 return "MIDI_EVENT_NOTE_ON";
1160 case MIDI_EVENT_AFTERTOUCH:
1161 return "MIDI_EVENT_AFTERTOUCH";
1162 case MIDI_EVENT_CONTROLLER:
1163 return "MIDI_EVENT_CONTROLLER";
1164 case MIDI_EVENT_PROGRAM_CHANGE:
1165 return "MIDI_EVENT_PROGRAM_CHANGE";
1166 case MIDI_EVENT_CHAN_AFTERTOUCH:
1167 return "MIDI_EVENT_CHAN_AFTERTOUCH";
1168 case MIDI_EVENT_PITCH_BEND:
1169 return "MIDI_EVENT_PITCH_BEND";
1170 case MIDI_EVENT_SYSEX:
1171 return "MIDI_EVENT_SYSEX";
1172 case MIDI_EVENT_SYSEX_SPLIT:
1173 return "MIDI_EVENT_SYSEX_SPLIT";
1174 case MIDI_EVENT_META:
1175 return "MIDI_EVENT_META";
1176
1177 default:
1178 return "(unknown)";
1179 }
1180 }
1181
PrintTrack(midi_track_t * track)1182 void PrintTrack (midi_track_t *track)
1183 {
1184 midi_event_t *event;
1185 unsigned int i;
1186
1187 for (i=0; i<track->num_events; ++i)
1188 {
1189 event = &track->events[i];
1190
1191 if (event->delta_time > 0)
1192 {
1193 printf("Delay: %i ticks\n", event->delta_time);
1194 }
1195
1196 printf("Event type: %s (%i)\n",
1197 MIDI_EventTypeToString(event->event_type),
1198 event->event_type);
1199
1200 switch(event->event_type)
1201 {
1202 case MIDI_EVENT_NOTE_OFF:
1203 case MIDI_EVENT_NOTE_ON:
1204 case MIDI_EVENT_AFTERTOUCH:
1205 case MIDI_EVENT_CONTROLLER:
1206 case MIDI_EVENT_PROGRAM_CHANGE:
1207 case MIDI_EVENT_CHAN_AFTERTOUCH:
1208 case MIDI_EVENT_PITCH_BEND:
1209 printf("\tChannel: %i\n", event->data.channel.channel);
1210 printf("\tParameter 1: %i\n", event->data.channel.param1);
1211 printf("\tParameter 2: %i\n", event->data.channel.param2);
1212 break;
1213
1214 case MIDI_EVENT_SYSEX:
1215 case MIDI_EVENT_SYSEX_SPLIT:
1216 printf("\tLength: %i\n", event->data.sysex.length);
1217 break;
1218
1219 case MIDI_EVENT_META:
1220 printf("\tMeta type: %i\n", event->data.meta.type);
1221 printf("\tLength: %i\n", event->data.meta.length);
1222 break;
1223 }
1224 }
1225 }
1226
main(int argc,char * argv[])1227 int main(int argc, char *argv[])
1228 {
1229 FILE *f;
1230 midimem_t mf;
1231 midi_file_t *file;
1232 unsigned int i;
1233
1234 if (argc < 2)
1235 {
1236 printf("Usage: %s <filename>\n", argv[0]);
1237 exit(1);
1238 }
1239 f = fopen (argv[1], "rb");
1240 if (!f)
1241 {
1242 fprintf(stderr, "Failed to open %s\n", argv[1]);
1243 exit(1);
1244 }
1245 fseek (f, 0, SEEK_END);
1246 mf.len = ftell (f);
1247 mf.pos = 0;
1248 rewind (f);
1249 mf.data = malloc (mf.len);
1250 fread (mf.data, 1, mf.len, f);
1251 fclose (f);
1252
1253 file = MIDI_LoadFile (&mf);
1254
1255 if (file == NULL)
1256 {
1257 fprintf(stderr, "Failed to open %s\n", argv[1]);
1258 exit(1);
1259 }
1260
1261 for (i=0; i<file->num_tracks; ++i)
1262 {
1263 printf("\n== Track %i ==\n\n", i);
1264
1265 PrintTrack(&file->tracks[i]);
1266 }
1267
1268 return 0;
1269 }
1270
1271 #endif
1272
1273