1 /*         ______   ___    ___
2  *        /\  _  \ /\_ \  /\_ \
3  *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___
4  *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
5  *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
6  *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
7  *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
8  *                                           /\____/
9  *                                           \_/__/
10  *
11  *      The core MIDI file player.
12  *
13  *      By Shawn Hargreaves.
14  *
15  *      Pause and seek functions by George Foot.
16  *
17  *      get_midi_length by Elias Pschernig.
18  *
19  *      See readme.txt for copyright information.
20  */
21 
22 
23 #include <limits.h>
24 #include <string.h>
25 
26 #include "allegro.h"
27 #include "allegro/internal/aintern.h"
28 
29 
30 
31 /* maximum number of layers in a single voice */
32 #define MIDI_LAYERS  4
33 
34 /* how often the midi callback gets called maximally / second */
35 #define MIDI_TIMER_FREQUENCY 40
36 
37 
38 typedef struct MIDI_TRACK                       /* a track in the MIDI file */
39 {
40    unsigned char *pos;                          /* position in track data */
41    long timer;                                  /* time until next event */
42    unsigned char running_status;                /* last MIDI event */
43 } MIDI_TRACK;
44 
45 
46 typedef struct MIDI_CHANNEL                     /* a MIDI channel */
47 {
48    int patch;                                   /* current sound */
49    int volume;                                  /* volume controller */
50    int pan;                                     /* pan position */
51    int pitch_bend;                              /* pitch bend position */
52    int new_volume;                              /* cached volume change */
53    int new_pitch_bend;                          /* cached pitch bend */
54    int note[128][MIDI_LAYERS];                  /* status of each note */
55 } MIDI_CHANNEL;
56 
57 
58 typedef struct MIDI_VOICE                       /* a voice on the soundcard */
59 {
60    int channel;                                 /* MIDI channel */
61    int note;                                    /* note (-1 = off) */
62    int volume;                                  /* note velocity */
63    long time;                                   /* when note was triggered */
64 } MIDI_VOICE;
65 
66 
67 typedef struct WAITING_NOTE                     /* a stored note-on request */
68 {
69    int channel;
70    int note;
71    int volume;
72 } WAITING_NOTE;
73 
74 
75 typedef struct PATCH_TABLE                      /* GM -> external synth */
76 {
77    int bank1;                                   /* controller #0 */
78    int bank2;                                   /* controller #32 */
79    int prog;                                    /* program change */
80    int pitch;                                   /* pitch shift */
81 } PATCH_TABLE;
82 
83 
84 volatile long midi_pos = -1;                    /* current position in MIDI file */
85 volatile long midi_time = 0;                    /* current position in seconds */
86 static volatile long midi_timers;               /* current position in allegro-timer-ticks */
87 static long midi_pos_counter;                   /* delta for midi_pos */
88 
89 volatile long _midi_tick = 0;                   /* counter for killing notes */
90 
91 static void midi_player(void);                  /* core MIDI player routine */
92 static void prepare_to_play(MIDI *midi);
93 static void midi_lock_mem(void);
94 
95 static MIDI *midifile = NULL;                   /* the file that is playing */
96 
97 static int midi_loop = 0;                       /* repeat at eof? */
98 
99 long midi_loop_start = -1;                      /* where to loop back to */
100 long midi_loop_end = -1;                        /* loop at this position */
101 
102 static int midi_semaphore = 0;                  /* reentrancy flag */
103 static int midi_loaded_patches = FALSE;         /* loaded entire patch set? */
104 
105 static long midi_timer_speed;                   /* midi_player's timer speed */
106 static int midi_pos_speed;                      /* MIDI delta -> midi_pos */
107 static int midi_speed;                          /* MIDI delta -> timer */
108 static int midi_new_speed;                      /* for tempo change events */
109 
110 static int old_midi_volume = -1;                /* stored global volume */
111 
112 static int midi_alloc_channel;                  /* so _midi_allocate_voice */
113 static int midi_alloc_note;                     /* knows which note the */
114 static int midi_alloc_vol;                      /* sound is associated with */
115 
116 static MIDI_TRACK midi_track[MIDI_TRACKS];      /* the active tracks */
117 static MIDI_VOICE midi_voice[MIDI_VOICES];      /* synth voice status */
118 static MIDI_CHANNEL midi_channel[16];           /* MIDI channel info */
119 static WAITING_NOTE midi_waiting[MIDI_VOICES];  /* notes still to be played */
120 static PATCH_TABLE patch_table[128];            /* GM -> external synth */
121 
122 static int midi_seeking;                        /* set during seeks */
123 static int midi_looping;                        /* set during loops */
124 
125 /* hook functions */
126 void (*midi_msg_callback)(int msg, int byte1, int byte2) = NULL;
127 void (*midi_meta_callback)(int type, AL_CONST unsigned char *data, int length) = NULL;
128 void (*midi_sysex_callback)(AL_CONST unsigned char *data, int length) = NULL;
129 
130 
131 
132 /* lock_midi:
133  *  Locks a MIDI file into physical memory. Pretty important, since they
134  *  are mostly accessed inside interrupt handlers.
135  */
lock_midi(MIDI * midi)136 void lock_midi(MIDI *midi)
137 {
138    int c;
139    ASSERT(midi);
140 
141    LOCK_DATA(midi, sizeof(MIDI));
142 
143    for (c=0; c<MIDI_TRACKS; c++) {
144       if (midi->track[c].data) {
145 	 LOCK_DATA(midi->track[c].data, midi->track[c].len);
146       }
147    }
148 }
149 
150 
151 
152 /* load_midi:
153  *  Loads a standard MIDI file, returning a pointer to a MIDI structure,
154  *  or NULL on error.
155  */
load_midi(AL_CONST char * filename)156 MIDI *load_midi(AL_CONST char *filename)
157 {
158    PACKFILE *f;
159    MIDI *midi;
160    ASSERT(filename);
161 
162    f = pack_fopen(filename, F_READ);
163    if (!f)
164       return NULL;
165 
166    midi = load_midi_pf(f);
167 
168    pack_fclose(f);
169 
170    return midi;
171 }
172 
173 
174 
175 /* load_midi_pf:
176  *  Reads a standard MIDI file from the packfile given, returning a MIDI
177  *  structure, or NULL on error.
178  *
179  *  If unsuccessful the offset into the file is unspecified, i.e. you must
180  *  either reset the offset to some known place or close the packfile. The
181  *  packfile is not closed by this function.
182  */
load_midi_pf(PACKFILE * fp)183 MIDI *load_midi_pf(PACKFILE *fp)
184 {
185    int c;
186    char buf[4];
187    long data;
188    MIDI *midi;
189    int num_tracks;
190    ASSERT(fp);
191 
192    midi = _AL_MALLOC(sizeof(MIDI));              /* get some memory */
193    if (!midi)
194       return NULL;
195 
196    for (c=0; c<MIDI_TRACKS; c++) {
197       midi->track[c].data = NULL;
198       midi->track[c].len = 0;
199    }
200 
201    pack_fread(buf, 4, fp); /* read midi header */
202 
203    /* Is the midi inside a .rmi file? */
204    if (memcmp(buf, "RIFF", 4) == 0) { /* check for RIFF header */
205       pack_mgetl(fp);
206 
207       while (!pack_feof(fp)) {
208          pack_fread(buf, 4, fp); /* RMID chunk? */
209          if (memcmp(buf, "RMID", 4) == 0) break;
210 
211          pack_fseek(fp, pack_igetl(fp)); /* skip to next chunk */
212       }
213 
214       if (pack_feof(fp)) goto err;
215 
216       pack_mgetl(fp);
217       pack_mgetl(fp);
218       pack_fread(buf, 4, fp); /* read midi header */
219    }
220 
221    if (memcmp(buf, "MThd", 4))
222       goto err;
223 
224    pack_mgetl(fp);                           /* skip header chunk length */
225 
226    data = pack_mgetw(fp);                    /* MIDI file type */
227    if ((data != 0) && (data != 1))
228       goto err;
229 
230    num_tracks = pack_mgetw(fp);              /* number of tracks */
231    if ((num_tracks < 1) || (num_tracks > MIDI_TRACKS))
232       goto err;
233 
234    data = pack_mgetw(fp);                    /* beat divisions */
235    midi->divisions = ABS(data);
236 
237    for (c=0; c<num_tracks; c++) {            /* read each track */
238       pack_fread(buf, 4, fp);                /* read track header */
239       if (memcmp(buf, "MTrk", 4))
240 	 goto err;
241 
242       data = pack_mgetl(fp);                 /* length of track chunk */
243       midi->track[c].len = data;
244 
245       midi->track[c].data = _AL_MALLOC_ATOMIC(data); /* allocate memory */
246       if (!midi->track[c].data)
247 	 goto err;
248 					     /* finally, read track data */
249       if (pack_fread(midi->track[c].data, data, fp) != data)
250 	 goto err;
251    }
252 
253    lock_midi(midi);
254    return midi;
255 
256    /* oh dear... */
257    err:
258    destroy_midi(midi);
259    return NULL;
260 }
261 
262 
263 
264 /* destroy_midi:
265  *  Frees the memory being used by a MIDI file.
266  */
destroy_midi(MIDI * midi)267 void destroy_midi(MIDI *midi)
268 {
269    int c;
270 
271    if (midi == midifile)
272       stop_midi();
273 
274    if (midi) {
275       for (c=0; c<MIDI_TRACKS; c++) {
276 	 if (midi->track[c].data) {
277 	    UNLOCK_DATA(midi->track[c].data, midi->track[c].len);
278 	    _AL_FREE(midi->track[c].data);
279 	 }
280       }
281 
282       UNLOCK_DATA(midi, sizeof(MIDI));
283       _AL_FREE(midi);
284    }
285 }
286 
287 
288 
289 /* parse_var_len:
290  *  The MIDI file format is a strange thing. Time offsets are only 32 bits,
291  *  yet they are compressed in a weird variable length format. This routine
292  *  reads a variable length integer from a MIDI data stream. It returns the
293  *  number read, and alters the data pointer according to the number of
294  *  bytes it used.
295  */
parse_var_len(AL_CONST unsigned char ** data)296 static unsigned long parse_var_len(AL_CONST unsigned char **data)
297 {
298    unsigned long val = **data & 0x7F;
299 
300    while (**data & 0x80) {
301       (*data)++;
302       val <<= 7;
303       val += (**data & 0x7F);
304    }
305 
306    (*data)++;
307    return val;
308 }
309 
310 END_OF_STATIC_FUNCTION(parse_var_len);
311 
312 
313 
314 /* global_volume_fix:
315  *  Converts a note volume, adjusting it according to the global
316  *  _midi_volume variable.
317  */
global_volume_fix(int vol)318 static INLINE int global_volume_fix(int vol)
319 {
320    if (_midi_volume >= 0)
321       return (vol * _midi_volume) / 256;
322 
323    return vol;
324 }
325 
326 
327 
328 /* sort_out_volume:
329  *  Converts a note volume, adjusting it according to the channel volume
330  *  and the global _midi_volume variable.
331  */
sort_out_volume(int c,int vol)332 static INLINE int sort_out_volume(int c, int vol)
333 {
334    return global_volume_fix((vol * midi_channel[c].volume) / 128);
335 }
336 
337 
338 
339 /* raw_program_change:
340  *  Sends a program change message to a device capable of handling raw
341  *  MIDI data, using patch mapping tables. Assumes that midi_driver->raw_midi
342  *  isn't NULL, so check before calling it!
343  */
raw_program_change(int channel,int patch)344 static void raw_program_change(int channel, int patch)
345 {
346    if (channel != 9) {
347       /* bank change #1 */
348       if (patch_table[patch].bank1 >= 0) {
349 	 midi_driver->raw_midi(0xB0+channel);
350 	 midi_driver->raw_midi(0);
351 	 midi_driver->raw_midi(patch_table[patch].bank1);
352       }
353 
354       /* bank change #2 */
355       if (patch_table[patch].bank2 >= 0) {
356 	 midi_driver->raw_midi(0xB0+channel);
357 	 midi_driver->raw_midi(32);
358 	 midi_driver->raw_midi(patch_table[patch].bank2);
359       }
360 
361       /* program change */
362       midi_driver->raw_midi(0xC0+channel);
363       midi_driver->raw_midi(patch_table[patch].prog);
364 
365       /* update volume */
366       midi_driver->raw_midi(0xB0+channel);
367       midi_driver->raw_midi(7);
368       midi_driver->raw_midi(global_volume_fix(midi_channel[channel].volume-1));
369    }
370 }
371 
372 END_OF_STATIC_FUNCTION(raw_program_change);
373 
374 
375 
376 /* midi_note_off:
377  *  Processes a MIDI note-off event.
378  */
midi_note_off(int channel,int note)379 static void midi_note_off(int channel, int note)
380 {
381    int done = FALSE;
382    int voice, layer;
383    int c;
384 
385    /* can we send raw MIDI data? */
386    if (midi_driver->raw_midi) {
387       if (channel != 9)
388 	 note += patch_table[midi_channel[channel].patch].pitch;
389 
390       midi_driver->raw_midi(0x80+channel);
391       midi_driver->raw_midi(note);
392       midi_driver->raw_midi(0);
393       return;
394    }
395 
396    /* oh well, have to do it the long way... */
397    for (layer=0; layer<MIDI_LAYERS; layer++) {
398       voice = midi_channel[channel].note[note][layer];
399       if (voice >= 0) {
400 	 midi_driver->key_off(voice + midi_driver->basevoice);
401 	 midi_voice[voice].note = -1;
402 	 midi_voice[voice].time = _midi_tick;
403 	 midi_channel[channel].note[note][layer] = -1;
404 	 done = TRUE;
405       }
406    }
407 
408    /* if the note isn't playing, it must still be in the waiting room */
409    if (!done) {
410       for (c=0; c<MIDI_VOICES; c++) {
411 	 if ((midi_waiting[c].channel == channel) &&
412 	     (midi_waiting[c].note == note)) {
413 	    midi_waiting[c].note = -1;
414 	    break;
415 	 }
416       }
417    }
418 }
419 
420 END_OF_STATIC_FUNCTION(midi_note_off);
421 
422 
423 
424 /* sort_out_pitch_bend:
425  *  MIDI pitch bend range is + or - two semitones. The low-level soundcard
426  *  drivers can only handle bends up to +1 semitone. This routine converts
427  *  pitch bends from MIDI format to our own format.
428  */
sort_out_pitch_bend(int * bend,int * note)429 static INLINE void sort_out_pitch_bend(int *bend, int *note)
430 {
431    if (*bend == 0x2000) {
432       *bend = 0;
433       return;
434    }
435 
436    (*bend) -= 0x2000;
437 
438    while (*bend < 0) {
439       (*note)--;
440       (*bend) += 0x1000;
441    }
442 
443    while (*bend >= 0x1000) {
444       (*note)++;
445       (*bend) -= 0x1000;
446    }
447 }
448 
449 
450 
451 /* _midi_allocate_voice:
452  *  Allocates a MIDI voice in the range min-max (inclusive). This is
453  *  intended to be called by the key_on() handlers in the MIDI driver,
454  *  and shouldn't be used by any other code.
455  */
_midi_allocate_voice(int min,int max)456 int _midi_allocate_voice(int min, int max)
457 {
458    int c;
459    int layer;
460    int voice = -1;
461    long best_time = LONG_MAX;
462 
463    if (min < 0)
464       min = 0;
465 
466    if (max < 0)
467       max = midi_driver->voices-1;
468 
469    /* which layer can we use? */
470    for (layer=0; layer<MIDI_LAYERS; layer++)
471       if (midi_channel[midi_alloc_channel].note[midi_alloc_note][layer] < 0)
472 	 break;
473 
474    if (layer >= MIDI_LAYERS)
475       return -1;
476 
477    /* find a free voice */
478    for (c=min; c<=max; c++) {
479       if ((midi_voice[c].note < 0) &&
480 	  (midi_voice[c].time < best_time) &&
481 	  ((c < midi_driver->xmin) || (c > midi_driver->xmax))) {
482 	 voice = c;
483 	 best_time = midi_voice[c].time;
484       }
485    }
486 
487    /* if there are no free voices, kill a note to make room */
488    if (voice < 0) {
489       voice = -1;
490       best_time = LONG_MAX;
491       for (c=min; c<=max; c++) {
492 	 if ((midi_voice[c].time < best_time) &&
493 	     ((c < midi_driver->xmin) || (c > midi_driver->xmax))) {
494 	    voice = c;
495 	    best_time = midi_voice[c].time;
496 	 }
497       }
498       if (voice >= 0)
499 	 midi_note_off(midi_voice[voice].channel, midi_voice[voice].note);
500       else
501 	 return -1;
502    }
503 
504    /* ok, we got it... */
505    midi_voice[voice].channel = midi_alloc_channel;
506    midi_voice[voice].note = midi_alloc_note;
507    midi_voice[voice].volume = midi_alloc_vol;
508    midi_voice[voice].time = _midi_tick;
509    midi_channel[midi_alloc_channel].note[midi_alloc_note][layer] = voice;
510 
511    return voice + midi_driver->basevoice;
512 }
513 
514 END_OF_FUNCTION(_midi_allocate_voice);
515 
516 
517 
518 /* midi_note_on:
519  *  Processes a MIDI note-on event. Tries to find a free soundcard voice,
520  *  and if it can't either cuts off an existing note, or if 'polite' is
521  *  set, just stores the channel, note and volume in the waiting list.
522  */
midi_note_on(int channel,int note,int vol,int polite)523 static void midi_note_on(int channel, int note, int vol, int polite)
524 {
525    int c, layer, inst, bend, corrected_note;
526 
527    /* it's easy if the driver can handle raw MIDI data */
528    if (midi_driver->raw_midi) {
529       if (channel != 9)
530 	 note += patch_table[midi_channel[channel].patch].pitch;
531 
532       midi_driver->raw_midi(0x90+channel);
533       midi_driver->raw_midi(note);
534       midi_driver->raw_midi(vol);
535       return;
536    }
537 
538    /* if the note is already on, turn it off */
539    for (layer=0; layer<MIDI_LAYERS; layer++) {
540       if (midi_channel[channel].note[note][layer] >= 0) {
541 	 midi_note_off(channel, note);
542 	 return;
543       }
544    }
545 
546    /* if zero volume and the note isn't playing, we can just ignore it */
547    if (vol == 0)
548       return;
549 
550    if (channel != 9) {
551       /* are there any free voices? */
552       for (c=0; c<midi_driver->voices; c++)
553 	 if ((midi_voice[c].note < 0) &&
554 	     ((c < midi_driver->xmin) || (c > midi_driver->xmax)))
555 	    break;
556 
557       /* if there are no free voices, remember the note for later */
558       if ((c >= midi_driver->voices) && (polite)) {
559 	 for (c=0; c<MIDI_VOICES; c++) {
560 	    if (midi_waiting[c].note < 0) {
561 	       midi_waiting[c].channel = channel;
562 	       midi_waiting[c].note = note;
563 	       midi_waiting[c].volume = vol;
564 	       break;
565 	    }
566 	 }
567 	 return;
568       }
569    }
570 
571    /* drum sound? */
572    if (channel == 9) {
573       inst = 128+note;
574       corrected_note = 60;
575       bend = 0;
576    }
577    else {
578       inst = midi_channel[channel].patch;
579       corrected_note = note;
580       bend = midi_channel[channel].pitch_bend;
581       sort_out_pitch_bend(&bend, &corrected_note);
582    }
583 
584    /* play the note */
585    midi_alloc_channel = channel;
586    midi_alloc_note = note;
587    midi_alloc_vol = vol;
588 
589    midi_driver->key_on(inst, corrected_note, bend,
590 		       sort_out_volume(channel, vol),
591 		       midi_channel[channel].pan);
592 }
593 
594 END_OF_STATIC_FUNCTION(midi_note_on);
595 
596 
597 
598 /* all_notes_off:
599  *  Turns off all active notes.
600  */
all_notes_off(int channel)601 static void all_notes_off(int channel)
602 {
603    if (midi_driver->raw_midi) {
604       midi_driver->raw_midi(0xB0+channel);
605       midi_driver->raw_midi(123);
606       midi_driver->raw_midi(0);
607       return;
608    }
609    else {
610       int note, layer;
611 
612       for (note=0; note<128; note++)
613 	 for (layer=0; layer<MIDI_LAYERS; layer++)
614 	    if (midi_channel[channel].note[note][layer] >= 0)
615 	       midi_note_off(channel, note);
616    }
617 }
618 
619 END_OF_STATIC_FUNCTION(all_notes_off);
620 
621 
622 
623 /* all_sound_off:
624  *  Turns off sound.
625  */
all_sound_off(int channel)626 static void all_sound_off(int channel)
627 {
628    if (midi_driver->raw_midi) {
629       midi_driver->raw_midi(0xB0+channel);
630       midi_driver->raw_midi(120);
631       midi_driver->raw_midi(0);
632       return;
633    }
634 }
635 
636 END_OF_STATIC_FUNCTION(all_sound_off);
637 
638 
639 
640 /* reset_controllers:
641  *  Resets volume, pan, pitch bend, etc, to default positions.
642  */
reset_controllers(int channel)643 static void reset_controllers(int channel)
644 {
645    midi_channel[channel].new_volume = 128;
646    midi_channel[channel].new_pitch_bend = 0x2000;
647 
648    if (midi_driver->raw_midi) {
649       midi_driver->raw_midi(0xB0+channel);
650       midi_driver->raw_midi(121);
651       midi_driver->raw_midi(0);
652    }
653 
654    switch (channel % 3) {
655       case 0:  midi_channel[channel].pan = ((channel/3) & 1) ? 60 : 68; break;
656       case 1:  midi_channel[channel].pan = 104; break;
657       case 2:  midi_channel[channel].pan = 24; break;
658    }
659 
660    if (midi_driver->raw_midi) {
661       midi_driver->raw_midi(0xB0+channel);
662       midi_driver->raw_midi(10);
663       midi_driver->raw_midi(midi_channel[channel].pan);
664    }
665 }
666 
667 END_OF_STATIC_FUNCTION(reset_controllers);
668 
669 
670 
671 /* update_controllers:
672  *  Checks cached controller information and updates active voices.
673  */
update_controllers(void)674 static void update_controllers(void)
675 {
676    int c, c2, vol, bend, note;
677 
678    for (c=0; c<16; c++) {
679       /* check for volume controller change */
680       if ((midi_channel[c].volume != midi_channel[c].new_volume) || (old_midi_volume != _midi_volume)) {
681 	 midi_channel[c].volume = midi_channel[c].new_volume;
682 	 if (midi_driver->raw_midi) {
683 	    midi_driver->raw_midi(0xB0+c);
684 	    midi_driver->raw_midi(7);
685 	    midi_driver->raw_midi(global_volume_fix(midi_channel[c].volume-1));
686 	 }
687 	 else {
688 	    for (c2=0; c2<MIDI_VOICES; c2++) {
689 	       if ((midi_voice[c2].channel == c) && (midi_voice[c2].note >= 0)) {
690 		  vol = sort_out_volume(c, midi_voice[c2].volume);
691 		  midi_driver->set_volume(c2 + midi_driver->basevoice, vol);
692 	       }
693 	    }
694 	 }
695       }
696 
697       /* check for pitch bend change */
698       if (midi_channel[c].pitch_bend != midi_channel[c].new_pitch_bend) {
699 	 midi_channel[c].pitch_bend = midi_channel[c].new_pitch_bend;
700 	 if (midi_driver->raw_midi) {
701 	    midi_driver->raw_midi(0xE0+c);
702 	    midi_driver->raw_midi(midi_channel[c].pitch_bend & 0x7F);
703 	    midi_driver->raw_midi(midi_channel[c].pitch_bend >> 7);
704 	 }
705 	 else {
706 	    for (c2=0; c2<MIDI_VOICES; c2++) {
707 	       if ((midi_voice[c2].channel == c) && (midi_voice[c2].note >= 0)) {
708 		  bend = midi_channel[c].pitch_bend;
709 		  note = midi_voice[c2].note;
710 		  sort_out_pitch_bend(&bend, &note);
711 		  midi_driver->set_pitch(c2 + midi_driver->basevoice, note, bend);
712 	       }
713 	    }
714 	 }
715       }
716    }
717 
718    old_midi_volume = _midi_volume;
719 }
720 
721 END_OF_STATIC_FUNCTION(update_controllers);
722 
723 
724 
725 /* process_controller:
726  *  Deals with a MIDI controller message on the specified channel.
727  */
process_controller(int channel,int ctrl,int data)728 static void process_controller(int channel, int ctrl, int data)
729 {
730    switch (ctrl) {
731 
732       case 7:                                   /* main volume */
733 	 midi_channel[channel].new_volume = data+1;
734 	 break;
735 
736       case 10:                                  /* pan */
737 	 midi_channel[channel].pan = data;
738 	 if (midi_driver->raw_midi) {
739 	    midi_driver->raw_midi(0xB0+channel);
740 	    midi_driver->raw_midi(10);
741 	    midi_driver->raw_midi(data);
742 	 }
743 	 break;
744 
745       case 120:                                 /* all sound off */
746 	 all_sound_off(channel);
747 	 break;
748 
749       case 121:                                 /* reset all controllers */
750 	 reset_controllers(channel);
751 	 break;
752 
753       case 123:                                 /* all notes off */
754       case 124:                                 /* omni mode off */
755       case 125:                                 /* omni mode on */
756       case 126:                                 /* poly mode off */
757       case 127:                                 /* poly mode on */
758 	 all_notes_off(channel);
759 	 break;
760 
761       default:
762 	 if (midi_driver->raw_midi) {
763 	    midi_driver->raw_midi(0xB0+channel);
764 	    midi_driver->raw_midi(ctrl);
765 	    midi_driver->raw_midi(data);
766 	 }
767 	 break;
768    }
769 }
770 
771 END_OF_STATIC_FUNCTION(process_controller);
772 
773 
774 
775 /* process_meta_event:
776  *  Processes the next meta-event on the specified track.
777  */
process_meta_event(AL_CONST unsigned char ** pos,long * timer)778 static void process_meta_event(AL_CONST unsigned char **pos, long *timer)
779 {
780    unsigned char metatype = *((*pos)++);
781    long length = parse_var_len(pos);
782    long tempo;
783 
784    if (midi_meta_callback)
785       midi_meta_callback(metatype, *pos, length);
786 
787    if (metatype == 0x2F) {                      /* end of track */
788       *pos = NULL;
789       *timer = LONG_MAX;
790       return;
791    }
792 
793    if (metatype == 0x51) {                      /* tempo change */
794       tempo = (*pos)[0] * 0x10000L + (*pos)[1] * 0x100 + (*pos)[2];
795       midi_new_speed = (tempo/1000) * (TIMERS_PER_SECOND/1000);
796       midi_new_speed /= midifile->divisions;
797    }
798 
799    (*pos) += length;
800 }
801 
802 END_OF_STATIC_FUNCTION(process_meta_event);
803 
804 
805 
806 /* process_midi_event:
807  *  Processes the next MIDI event on the specified track.
808  */
process_midi_event(AL_CONST unsigned char ** pos,unsigned char * running_status,long * timer)809 static void process_midi_event(AL_CONST unsigned char **pos, unsigned char *running_status, long *timer)
810 {
811    unsigned char byte1, byte2;
812    int channel;
813    unsigned char event;
814    long l;
815 
816    event = *((*pos)++);
817 
818    if (event & 0x80) {                          /* regular message */
819       /* no running status for sysex and meta-events! */
820       if ((event != 0xF0) && (event != 0xF7) && (event != 0xFF))
821 	 *running_status = event;
822       byte1 = (*pos)[0];
823       byte2 = (*pos)[1];
824    }
825    else {                                       /* use running status */
826       byte1 = event;
827       byte2 = (*pos)[0];
828       event = *running_status;
829       (*pos)--;
830    }
831 
832    /* program callback? */
833    if ((midi_msg_callback) &&
834        (event != 0xF0) && (event != 0xF7) && (event != 0xFF))
835       midi_msg_callback(event, byte1, byte2);
836 
837    channel = event & 0x0F;
838 
839    switch (event>>4) {
840 
841       case 0x08:                                /* note off */
842 	 midi_note_off(channel, byte1);
843 	 (*pos) += 2;
844 	 break;
845 
846       case 0x09:                                /* note on */
847 	 midi_note_on(channel, byte1, byte2, 1);
848 	 (*pos) += 2;
849 	 break;
850 
851       case 0x0A:                                /* note aftertouch */
852 	 (*pos) += 2;
853 	 break;
854 
855       case 0x0B:                                /* control change */
856 	 process_controller(channel, byte1, byte2);
857 	 (*pos) += 2;
858 	 break;
859 
860       case 0x0C:                                /* program change */
861 	 midi_channel[channel].patch = byte1;
862 	 if (midi_driver->raw_midi)
863 	    raw_program_change(channel, byte1);
864 	 (*pos) += 1;
865 	 break;
866 
867       case 0x0D:                                /* channel aftertouch */
868 	 (*pos) += 1;
869 	 break;
870 
871       case 0x0E:                                /* pitch bend */
872 	 midi_channel[channel].new_pitch_bend = byte1 + (byte2<<7);
873 	 (*pos) += 2;
874 	 break;
875 
876       case 0x0F:                                /* special event */
877 	 switch (event) {
878 	    case 0xF0:                          /* sysex */
879 	    case 0xF7:
880 	       l = parse_var_len(pos);
881 	       if (midi_sysex_callback)
882 		  midi_sysex_callback(*pos, l);
883 	       (*pos) += l;
884 	       break;
885 
886 	    case 0xF2:                          /* song position */
887 	       (*pos) += 2;
888 	       break;
889 
890 	    case 0xF3:                          /* song select */
891 	       (*pos)++;
892 	       break;
893 
894 	    case 0xFF:                          /* meta-event */
895 	       process_meta_event(pos, timer);
896 	       break;
897 
898 	    default:
899 	       /* the other special events don't have any data bytes,
900 		  so we don't need to bother skipping past them */
901 	       break;
902 	 }
903 	 break;
904 
905       default:
906 	 /* something has gone badly wrong if we ever get to here */
907 	 break;
908    }
909 }
910 
911 END_OF_STATIC_FUNCTION(process_midi_event);
912 
913 
914 
915 /* midi_player:
916  *  The core MIDI player: to be used as a timer callback.
917  */
midi_player(void)918 static void midi_player(void)
919 {
920    int c;
921    long l;
922    int active;
923 
924    if (!midifile)
925       return;
926 
927    if (midi_semaphore) {
928       midi_timer_speed += BPS_TO_TIMER(MIDI_TIMER_FREQUENCY);
929       install_int_ex(midi_player, BPS_TO_TIMER(MIDI_TIMER_FREQUENCY));
930       return;
931    }
932 
933    midi_semaphore = TRUE;
934    _midi_tick++;
935 
936    midi_timers += midi_timer_speed;
937    midi_time = midi_timers / TIMERS_PER_SECOND;
938 
939    do_it_all_again:
940 
941    for (c=0; c<MIDI_VOICES; c++)
942       midi_waiting[c].note = -1;
943 
944    /* deal with each track in turn... */
945    for (c=0; c<MIDI_TRACKS; c++) {
946       if (midi_track[c].pos) {
947 	 midi_track[c].timer -= midi_timer_speed;
948 
949 	 /* while events are waiting, process them */
950 	 while (midi_track[c].timer <= 0) {
951 	    process_midi_event((AL_CONST unsigned char**) &midi_track[c].pos,
952 			       &midi_track[c].running_status,
953 			       &midi_track[c].timer);
954 
955 	    /* read next time offset */
956 	    if (midi_track[c].pos) {
957 	       l = parse_var_len((AL_CONST unsigned char**) &midi_track[c].pos);
958 	       l *= midi_speed;
959 	       midi_track[c].timer += l;
960 	    }
961 	 }
962       }
963    }
964 
965    /* update global position value */
966    midi_pos_counter -= midi_timer_speed;
967    while (midi_pos_counter <= 0) {
968       midi_pos_counter += midi_pos_speed;
969       midi_pos++;
970    }
971 
972    /* tempo change? */
973    if (midi_new_speed > 0) {
974       for (c=0; c<MIDI_TRACKS; c++) {
975 	 if (midi_track[c].pos) {
976 	    midi_track[c].timer /= midi_speed;
977 	    midi_track[c].timer *= midi_new_speed;
978 	 }
979       }
980       midi_pos_counter /= midi_speed;
981       midi_pos_counter *= midi_new_speed;
982 
983       midi_speed = midi_new_speed;
984       midi_pos_speed = midi_new_speed * midifile->divisions;
985       midi_new_speed = -1;
986    }
987 
988    /* figure out how long until we need to be called again */
989    active = 0;
990    midi_timer_speed = LONG_MAX;
991    for (c=0; c<MIDI_TRACKS; c++) {
992       if (midi_track[c].pos) {
993 	 active = 1;
994 	 if (midi_track[c].timer < midi_timer_speed)
995 	    midi_timer_speed = midi_track[c].timer;
996       }
997    }
998 
999    /* end of the music? */
1000    if ((!active) || ((midi_loop_end > 0) && (midi_pos >= midi_loop_end))) {
1001       if ((midi_loop) && (!midi_looping)) {
1002 	 if (midi_loop_start > 0) {
1003 	    remove_int(midi_player);
1004 	    midi_semaphore = FALSE;
1005 	    midi_looping = TRUE;
1006 	    if (midi_seek(midi_loop_start) != 0) {
1007 	       midi_looping = FALSE;
1008 	       stop_midi();
1009 	       return;
1010 	    }
1011 	    midi_looping = FALSE;
1012 	    midi_semaphore = TRUE;
1013 	    goto do_it_all_again;
1014 	 }
1015 	 else {
1016 	    for (c=0; c<16; c++) {
1017 	       all_notes_off(c);
1018 	       all_sound_off(c);
1019 	    }
1020 	    prepare_to_play(midifile);
1021 	    goto do_it_all_again;
1022 	 }
1023       }
1024       else {
1025 	 stop_midi();
1026 	 midi_semaphore = FALSE;
1027 	 return;
1028       }
1029    }
1030 
1031    /* reprogram the timer */
1032    if (midi_timer_speed < BPS_TO_TIMER(MIDI_TIMER_FREQUENCY))
1033       midi_timer_speed = BPS_TO_TIMER(MIDI_TIMER_FREQUENCY);
1034 
1035    if (!midi_seeking)
1036       install_int_ex(midi_player, midi_timer_speed);
1037 
1038    /* controller changes are cached and only processed here, so we can
1039       condense streams of controller data into just a few voice updates */
1040    update_controllers();
1041 
1042    /* and deal with any notes that are still waiting to be played */
1043    for (c=0; c<MIDI_VOICES; c++)
1044       if (midi_waiting[c].note >= 0)
1045 	 midi_note_on(midi_waiting[c].channel, midi_waiting[c].note,
1046 		      midi_waiting[c].volume, 0);
1047 
1048    midi_semaphore = FALSE;
1049 }
1050 
1051 END_OF_STATIC_FUNCTION(midi_player);
1052 
1053 
1054 
1055 /* midi_init:
1056  *  Sets up the MIDI player ready for use. Returns non-zero on failure.
1057  */
midi_init(void)1058 static int midi_init(void)
1059 {
1060    int c, c2, c3;
1061    char **argv;
1062    int argc;
1063    char buf[32], tmp[64];
1064 
1065    midi_loaded_patches = FALSE;
1066 
1067    midi_lock_mem();
1068 
1069    for (c=0; c<16; c++) {
1070       midi_channel[c].volume = midi_channel[c].new_volume = 128;
1071       midi_channel[c].pitch_bend = midi_channel[c].new_pitch_bend = 0x2000;
1072 
1073       for (c2=0; c2<128; c2++)
1074 	 for (c3=0; c3<MIDI_LAYERS; c3++)
1075 	    midi_channel[c].note[c2][c3] = -1;
1076    }
1077 
1078    for (c=0; c<MIDI_VOICES; c++) {
1079       midi_voice[c].note = -1;
1080       midi_voice[c].time = 0;
1081    }
1082 
1083    for (c=0; c<128; c++) {
1084       uszprintf(buf, sizeof(buf), uconvert_ascii("p%d", tmp), c+1);
1085       argv = get_config_argv(uconvert_ascii("midimap", tmp), buf, &argc);
1086 
1087       if ((argv) && (argc == 4)) {
1088 	 patch_table[c].bank1 = ustrtol(argv[0], NULL, 0);
1089 	 patch_table[c].bank2 = ustrtol(argv[1], NULL, 0);
1090 	 patch_table[c].prog  = ustrtol(argv[2], NULL, 0);
1091 	 patch_table[c].pitch = ustrtol(argv[3], NULL, 0);
1092       }
1093       else {
1094 	 patch_table[c].bank1 = -1;
1095 	 patch_table[c].bank2 = -1;
1096 	 patch_table[c].prog = c;
1097 	 patch_table[c].pitch = 0;
1098       }
1099    }
1100 
1101    register_datafile_object(DAT_MIDI, NULL, (void (*)(void *))destroy_midi);
1102 
1103    return 0;
1104 }
1105 
1106 
1107 
1108 /* midi_exit:
1109  *  Turns off all active notes and removes the timer handler.
1110  */
midi_exit(void)1111 static void midi_exit(void)
1112 {
1113    stop_midi();
1114 }
1115 
1116 
1117 
1118 /* load_patches:
1119  *  Scans through a MIDI file and identifies which patches it uses, passing
1120  *  them to the soundcard driver so it can load whatever samples are
1121  *  neccessary.
1122  */
load_patches(MIDI * midi)1123 static int load_patches(MIDI *midi)
1124 {
1125    char patches[128], drums[128];
1126    unsigned char *p, *end;
1127    unsigned char running_status, event;
1128    long l;
1129    int c;
1130    ASSERT(midi);
1131 
1132    for (c=0; c<128; c++)                        /* initialise to unused */
1133       patches[c] = drums[c] = FALSE;
1134 
1135    patches[0] = TRUE;                           /* always load the piano */
1136 
1137    for (c=0; c<MIDI_TRACKS; c++) {              /* for each track... */
1138       p = midi->track[c].data;
1139       end = p + midi->track[c].len;
1140       running_status = 0;
1141 
1142       while (p < end) {                         /* work through data stream */
1143 #if defined ALLEGRO_BEOS || defined ALLEGRO_HAIKU
1144          /* Is there a bug in this routine, or in gcc under BeOS/x86? --PW */
1145          { int i; for (i=1; i; i--); }
1146 #endif
1147 	 event = *p;
1148 	 if (event & 0x80) {                    /* regular message */
1149 	    p++;
1150 	    if ((event != 0xF0) && (event != 0xF7) && (event != 0xFF))
1151 	       running_status = event;
1152 	 }
1153 	 else                                   /* use running status */
1154 	    event = running_status;
1155 
1156 	 switch (event>>4) {
1157 
1158 	    case 0x0C:                          /* program change! */
1159 	       patches[*p] = TRUE;
1160 	       p++;
1161 	       break;
1162 
1163 	    case 0x09:                          /* note on, is it a drum? */
1164 	       if ((event & 0x0F) == 9)
1165 		  drums[*p] = TRUE;
1166 	       p += 2;
1167 	       break;
1168 
1169 	    case 0x08:                          /* note off */
1170 	    case 0x0A:                          /* note aftertouch */
1171 	    case 0x0B:                          /* control change */
1172 	    case 0x0E:                          /* pitch bend */
1173 	       p += 2;
1174 	       break;
1175 
1176 	    case 0x0D:                          /* channel aftertouch */
1177 	       p += 1;
1178 	       break;
1179 
1180 	    case 0x0F:                          /* special event */
1181 	       switch (event) {
1182 		  case 0xF0:                    /* sysex */
1183 		  case 0xF7:
1184 		     l = parse_var_len((AL_CONST unsigned char**) &p);
1185 		     p += l;
1186 		     break;
1187 
1188 		  case 0xF2:                    /* song position */
1189 		     p += 2;
1190 		     break;
1191 
1192 		  case 0xF3:                    /* song select */
1193 		     p++;
1194 		     break;
1195 
1196 		  case 0xFF:                    /* meta-event */
1197 		     p++;
1198 		     l = parse_var_len((AL_CONST unsigned char**) &p);
1199 		     p += l;
1200 		     break;
1201 
1202 		  default:
1203 		     /* the other special events don't have any data bytes,
1204 			so we don't need to bother skipping past them */
1205 		     break;
1206 	       }
1207 	       break;
1208 
1209 	    default:
1210 	       /* something has gone badly wrong if we ever get to here */
1211 	       break;
1212 	 }
1213 
1214 	 if (p < end)                           /* skip time offset */
1215 	    parse_var_len((AL_CONST unsigned char**) &p);
1216       }
1217    }
1218 
1219    /* tell the driver to do its stuff */
1220    return midi_driver->load_patches(patches, drums);
1221 }
1222 
1223 
1224 
1225 /* prepare_to_play:
1226  *  Sets up all the global variables needed to play the specified file.
1227  */
prepare_to_play(MIDI * midi)1228 static void prepare_to_play(MIDI *midi)
1229 {
1230    int c;
1231    ASSERT(midi);
1232 
1233    for (c=0; c<16; c++)
1234       reset_controllers(c);
1235 
1236    update_controllers();
1237 
1238    midifile = midi;
1239    midi_pos = 0;
1240    midi_timers = 0;
1241    midi_time = 0;
1242    midi_pos_counter = 0;
1243    midi_speed = TIMERS_PER_SECOND / 2 / midifile->divisions;   /* 120 bpm */
1244    midi_new_speed = -1;
1245    midi_pos_speed = midi_speed * midifile->divisions;
1246    midi_timer_speed = 0;
1247    midi_seeking = 0;
1248    midi_looping = 0;
1249 
1250    for (c=0; c<16; c++) {
1251       midi_channel[c].patch = 0;
1252       if (midi_driver->raw_midi)
1253 	 raw_program_change(c, 0);
1254    }
1255 
1256    for (c=0; c<MIDI_TRACKS; c++) {
1257       if (midi->track[c].data) {
1258 	 midi_track[c].pos = midi->track[c].data;
1259 	 midi_track[c].timer = parse_var_len((AL_CONST unsigned char**) &midi_track[c].pos);
1260 	 midi_track[c].timer *= midi_speed;
1261       }
1262       else {
1263 	 midi_track[c].pos = NULL;
1264 	 midi_track[c].timer = LONG_MAX;
1265       }
1266       midi_track[c].running_status = 0;
1267    }
1268 }
1269 
1270 END_OF_STATIC_FUNCTION(prepare_to_play);
1271 
1272 
1273 
1274 /* play_midi:
1275  *  Starts playing the specified MIDI file. If loop is set, the MIDI file
1276  *  will be repeated until replaced with something else, otherwise it will
1277  *  stop at the end of the file. Passing a NULL MIDI file will stop whatever
1278  *  music is currently playing: allegro.h defines the macro stop_midi() to
1279  *  be play_midi(NULL, FALSE); Returns non-zero if an error occurs (this
1280  *  may happen if a patch-caching wavetable driver is unable to load the
1281  *  required samples).
1282  */
play_midi(MIDI * midi,int loop)1283 int play_midi(MIDI *midi, int loop)
1284 {
1285    int c;
1286 
1287    remove_int(midi_player);
1288 
1289    for (c=0; c<16; c++) {
1290       all_notes_off(c);
1291       all_sound_off(c);
1292    }
1293 
1294    if (midi) {
1295       if (!midi_loaded_patches)
1296 	 if (load_patches(midi) != 0)
1297 	    return -1;
1298 
1299       midi_loop = loop;
1300       midi_loop_start = -1;
1301       midi_loop_end = -1;
1302 
1303       prepare_to_play(midi);
1304 
1305       /* arbitrary speed, midi_player() will adjust it */
1306       install_int(midi_player, 20);
1307    }
1308    else {
1309       midifile = NULL;
1310 
1311       if (midi_pos > 0)
1312 	 midi_pos = -midi_pos;
1313       else if (midi_pos == 0)
1314 	 midi_pos = -1;
1315    }
1316 
1317    return 0;
1318 }
1319 
1320 END_OF_FUNCTION(play_midi);
1321 
1322 
1323 
1324 /* play_looped_midi:
1325  *  Like play_midi(), but the file loops from the specified end position
1326  *  back to the specified start position (the end position can be -1 to
1327  *  indicate the end of the file).
1328  */
play_looped_midi(MIDI * midi,int loop_start,int loop_end)1329 int play_looped_midi(MIDI *midi, int loop_start, int loop_end)
1330 {
1331    if (play_midi(midi, TRUE) != 0)
1332       return -1;
1333 
1334    midi_loop_start = loop_start;
1335    midi_loop_end = loop_end;
1336 
1337    return 0;
1338 }
1339 
1340 
1341 
1342 /* stop_midi:
1343  *  Stops whatever MIDI file is currently playing.
1344  */
stop_midi(void)1345 void stop_midi(void)
1346 {
1347    play_midi(NULL, FALSE);
1348 }
1349 
1350 END_OF_FUNCTION(stop_midi);
1351 
1352 
1353 
1354 /* midi_pause:
1355  *  Pauses the currently playing MIDI file.
1356  */
midi_pause(void)1357 void midi_pause(void)
1358 {
1359    int c;
1360 
1361    if (!midifile)
1362       return;
1363 
1364    remove_int(midi_player);
1365 
1366    for (c=0; c<16; c++) {
1367       all_notes_off(c);
1368       all_sound_off(c);
1369    }
1370 }
1371 
1372 END_OF_FUNCTION(midi_pause);
1373 
1374 
1375 
1376 /* midi_resume:
1377  *  Resumes playing a paused MIDI file.
1378  */
midi_resume(void)1379 void midi_resume(void)
1380 {
1381    if (!midifile)
1382       return;
1383 
1384    install_int_ex(midi_player, midi_timer_speed);
1385 }
1386 
1387 END_OF_FUNCTION(midi_resume);
1388 
1389 
1390 
1391 /* midi_seek:
1392  *  Seeks to the given midi_pos in the current MIDI file. If the target
1393  *  is earlier in the file than the current midi_pos it seeks from the
1394  *  beginning; otherwise it seeks from the current position. Returns zero
1395  *  if successful, non-zero if it hit the end of the file (1 means it
1396  *  stopped playing, 2 means it looped back to the start).
1397  */
midi_seek(int target)1398 int midi_seek(int target)
1399 {
1400    int old_midi_loop;
1401    MIDI *old_midifile;
1402    MIDI_DRIVER *old_driver;
1403    int old_patch[16];
1404    int old_volume[16];
1405    int old_pan[16];
1406    int old_pitch_bend[16];
1407    int c;
1408 
1409    if (!midifile)
1410       return -1;
1411 
1412    /* first stop the player */
1413    midi_pause();
1414 
1415    /* store current settings */
1416    for (c=0; c<16; c++) {
1417       old_patch[c] = midi_channel[c].patch;
1418       old_volume[c] = midi_channel[c].volume;
1419       old_pan[c] = midi_channel[c].pan;
1420       old_pitch_bend[c] = midi_channel[c].pitch_bend;
1421    }
1422 
1423    /* save some variables and give temporary values */
1424    old_driver = midi_driver;
1425    midi_driver = &_midi_none;
1426    old_midi_loop = midi_loop;
1427    midi_loop = 0;
1428    old_midifile = midifile;
1429 
1430    /* set flag to tell midi_player not to reinstall itself */
1431    midi_seeking = 1;
1432 
1433    /* are we seeking backwards? If so, skip back to the start of the file */
1434    if (target <= midi_pos)
1435       prepare_to_play(midifile);
1436 
1437    /* now sit back and let midi_player get to the position */
1438    while ((midi_pos < target) && (midi_pos >= 0)) {
1439       int mmpc = midi_pos_counter;
1440       int mmp = midi_pos;
1441 
1442       mmpc -= midi_timer_speed;
1443       while (mmpc <= 0) {
1444 	 mmpc += midi_pos_speed;
1445 	 mmp++;
1446       }
1447 
1448       if (mmp >= target)
1449 	 break;
1450 
1451       midi_player();
1452    }
1453 
1454    /* restore previously saved variables */
1455    midi_loop = old_midi_loop;
1456    midi_driver = old_driver;
1457    midi_seeking = 0;
1458 
1459    if (midi_pos >= 0) {
1460       /* refresh the driver with any changed parameters */
1461       if (midi_driver->raw_midi) {
1462 	 for (c=0; c<16; c++) {
1463 	    /* program change (this sets the volume as well) */
1464 	    if ((midi_channel[c].patch != old_patch[c]) ||
1465 		(midi_channel[c].volume != old_volume[c]))
1466 	       raw_program_change(c, midi_channel[c].patch);
1467 
1468 	    /* pan */
1469 	    if (midi_channel[c].pan != old_pan[c]) {
1470 	       midi_driver->raw_midi(0xB0+c);
1471 	       midi_driver->raw_midi(10);
1472 	       midi_driver->raw_midi(midi_channel[c].pan);
1473 	    }
1474 
1475 	    /* pitch bend */
1476 	    if (midi_channel[c].pitch_bend != old_pitch_bend[c]) {
1477 	       midi_driver->raw_midi(0xE0+c);
1478 	       midi_driver->raw_midi(midi_channel[c].pitch_bend & 0x7F);
1479 	       midi_driver->raw_midi(midi_channel[c].pitch_bend >> 7);
1480 	    }
1481 	 }
1482       }
1483 
1484       /* if we didn't hit the end of the file, continue playing */
1485       if (!midi_looping)
1486 	 install_int(midi_player, 20);
1487 
1488       return 0;
1489    }
1490 
1491    if ((midi_loop) && (!midi_looping)) {  /* was file looped? */
1492       prepare_to_play(old_midifile);
1493       install_int(midi_player, 20);
1494       return 2;                           /* seek past EOF => file restarted */
1495    }
1496 
1497    return 1;                              /* seek past EOF => file stopped */
1498 }
1499 
1500 END_OF_FUNCTION(midi_seek);
1501 
1502 
1503 
1504 /* get_midi_length:
1505  *  Returns the length, in seconds, of the specified midi. This will stop any
1506  *  currently playing midi. Don't call it too often, since it simulates playing
1507  *  all of the midi to get the time even if the midi contains tempo changes.
1508  */
get_midi_length(MIDI * midi)1509 int get_midi_length(MIDI *midi)
1510 {
1511     play_midi(midi, 0);
1512     while (midi_pos < 0); /* Without this, midi_seek won't work. */
1513     midi_seek(INT_MAX);
1514     return midi_time;
1515 }
1516 
1517 
1518 
1519 /* midi_out:
1520  *  Inserts MIDI command bytes into the output stream, in realtime.
1521  */
midi_out(unsigned char * data,int length)1522 void midi_out(unsigned char *data, int length)
1523 {
1524    unsigned char *pos = data;
1525    unsigned char running_status = 0;
1526    long timer = 0;
1527    ASSERT(data);
1528 
1529    midi_semaphore = TRUE;
1530    _midi_tick++;
1531 
1532    while (pos < data+length)
1533       process_midi_event((AL_CONST unsigned char**) &pos, &running_status, &timer);
1534 
1535    update_controllers();
1536 
1537    midi_semaphore = FALSE;
1538 }
1539 
1540 
1541 
1542 /* load_midi_patches:
1543  *  Tells the MIDI driver to preload the entire sample set.
1544  */
load_midi_patches(void)1545 int load_midi_patches(void)
1546 {
1547    char patches[128], drums[128];
1548    int c, ret;
1549 
1550    for (c=0; c<128; c++)
1551       patches[c] = drums[c] = TRUE;
1552 
1553    midi_semaphore = TRUE;
1554    ret = midi_driver->load_patches(patches, drums);
1555    midi_semaphore = FALSE;
1556 
1557    midi_loaded_patches = TRUE;
1558 
1559    return ret;
1560 }
1561 
1562 
1563 
1564 /* midi_lock_mem:
1565  *  Locks all the memory that the midi player touches inside the timer
1566  *  interrupt handler (which is most of it).
1567  */
midi_lock_mem(void)1568 static void midi_lock_mem(void)
1569 {
1570    LOCK_VARIABLE(midi_pos);
1571    LOCK_VARIABLE(midi_time);
1572    LOCK_VARIABLE(midi_timers);
1573    LOCK_VARIABLE(midi_pos_counter);
1574    LOCK_VARIABLE(_midi_tick);
1575    LOCK_VARIABLE(midifile);
1576    LOCK_VARIABLE(midi_semaphore);
1577    LOCK_VARIABLE(midi_loop);
1578    LOCK_VARIABLE(midi_loop_start);
1579    LOCK_VARIABLE(midi_loop_end);
1580    LOCK_VARIABLE(midi_timer_speed);
1581    LOCK_VARIABLE(midi_pos_speed);
1582    LOCK_VARIABLE(midi_speed);
1583    LOCK_VARIABLE(midi_new_speed);
1584    LOCK_VARIABLE(old_midi_volume);
1585    LOCK_VARIABLE(midi_alloc_channel);
1586    LOCK_VARIABLE(midi_alloc_note);
1587    LOCK_VARIABLE(midi_alloc_vol);
1588    LOCK_VARIABLE(midi_track);
1589    LOCK_VARIABLE(midi_voice);
1590    LOCK_VARIABLE(midi_channel);
1591    LOCK_VARIABLE(midi_waiting);
1592    LOCK_VARIABLE(patch_table);
1593    LOCK_VARIABLE(midi_msg_callback);
1594    LOCK_VARIABLE(midi_meta_callback);
1595    LOCK_VARIABLE(midi_sysex_callback);
1596    LOCK_VARIABLE(midi_seeking);
1597    LOCK_VARIABLE(midi_looping);
1598    LOCK_FUNCTION(parse_var_len);
1599    LOCK_FUNCTION(raw_program_change);
1600    LOCK_FUNCTION(midi_note_off);
1601    LOCK_FUNCTION(_midi_allocate_voice);
1602    LOCK_FUNCTION(midi_note_on);
1603    LOCK_FUNCTION(all_notes_off);
1604    LOCK_FUNCTION(all_sound_off);
1605    LOCK_FUNCTION(reset_controllers);
1606    LOCK_FUNCTION(update_controllers);
1607    LOCK_FUNCTION(process_controller);
1608    LOCK_FUNCTION(process_meta_event);
1609    LOCK_FUNCTION(process_midi_event);
1610    LOCK_FUNCTION(midi_player);
1611    LOCK_FUNCTION(prepare_to_play);
1612    LOCK_FUNCTION(play_midi);
1613    LOCK_FUNCTION(stop_midi);
1614    LOCK_FUNCTION(midi_pause);
1615    LOCK_FUNCTION(midi_resume);
1616    LOCK_FUNCTION(midi_seek);
1617 }
1618 
1619 
1620 
1621 /* midi_constructor:
1622  *  Register my functions with the code in sound.c.
1623  */
1624 #ifdef ALLEGRO_USE_CONSTRUCTOR
1625    CONSTRUCTOR_FUNCTION(void _midi_constructor(void));
1626 #endif
1627 
1628 static struct _AL_LINKER_MIDI midi_linker = {
1629    midi_init,
1630    midi_exit
1631 };
1632 
_midi_constructor(void)1633 void _midi_constructor(void)
1634 {
1635    _al_linker_midi = &midi_linker;
1636 }
1637 
1638