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