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