1 /* $NetBSD: midiplay.c,v 1.26 2008/04/28 20:24:14 martin Exp $ */
4 * Copyright (c) 1998, 2002 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Lennart Augustsson (augustss@NetBSD.org).
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
34 __RCSID("$NetBSD: midiplay.c,v 1.26 2008/04/28 20:24:14 martin Exp $");
44 #include <sys/types.h>
46 #include <sys/ioctl.h>
47 #include <sys/midiio.h>
49 #define DEVMUSIC "/dev/music"
52 struct track
*indirect
; /* for fast swaps in heap code */
58 #define MIDI_META 0xff
60 #define META_SEQNO 0x00
61 #define META_TEXT 0x01
62 #define META_COPYRIGHT 0x02
63 #define META_TRACK 0x03
64 #define META_INSTRUMENT 0x04
65 #define META_LYRIC 0x05
66 #define META_MARKER 0x06
68 #define META_CHPREFIX 0x20
70 #define META_SET_TEMPO 0x51
72 #define META_SMPTE 0x54
73 #define META_TIMESIGN 0x58
75 const char *metanames
[] = {
76 "", "Text", "Copyright", "Track", "Instrument",
77 "Lyric", "Marker", "Cue",
80 static int midi_lengths
[] = { 2,2,2,2,1,1,2,0 };
81 /* Number of bytes in a MIDI command */
82 #define MIDI_LENGTH(d) (midi_lengths[((d) >> 4) & 7])
85 void send_event(seq_event_t
*);
86 void dometa(u_int
, u_char
*, u_int
);
88 void send_sysex(u_char
*, u_int
);
89 u_long
getvar(struct track
*);
90 u_long
getlen(struct track
*);
91 void playfile(FILE *, const char *);
92 void playdata(u_char
*, u_int
, const char *);
93 int main(int argc
, char **argv
);
95 void Heapify(struct track
*, int, int);
96 void BuildHeap(struct track
*, int);
97 int ShrinkHeap(struct track
*, int);
100 * This sample plays at an apparent tempo of 120 bpm when the BASETEMPO is 150
101 * bpm, because the quavers are 5 divisions (4 on 1 off) rather than 4 total.
103 #define P(c) 1,0x90,c,0x7f,4,0x80,c,0
104 #define PL(c) 1,0x90,c,0x7f,8,0x80,c,0
111 'M','T','h','d', 0,0,0,6, 0,1, 0,1, 0,8,
112 'M','T','r','k', 0,0,0,4+13*8,
113 P(C
), P(C
), P(C
), P(E
), P(D
), P(D
), P(D
),
114 P(F
), P(E
), P(E
), P(D
), P(D
), PL(C
),
124 #define MARK_HEADER "MThd"
125 #define MARK_TRACK "MTrk"
128 #define RMID_SIG "RIFF"
129 #define RMID_MIDI_ID "RMID"
130 #define RMID_DATA_ID "data"
135 #define GET8(p) ((p)[0])
136 #define GET16(p) (((p)[0] << 8) | (p)[1])
137 #define GET24(p) (((p)[0] << 16) | ((p)[1] << 8) | (p)[2])
138 #define GET32(p) (((p)[0] << 24) | ((p)[1] << 16) | ((p)[2] << 8) | (p)[3])
139 #define GET32_LE(p) (((p)[3] << 24) | ((p)[2] << 16) | ((p)[1] << 8) | (p)[0])
144 printf("usage: %s [-d unit] [-f file] [-l] [-m] [-p pgm] [-q] "
145 "[-t %%tempo] [-v] [-x] [file ...]\n",
152 #define BASETEMPO 400000 /* us/beat(=24 clks or qn) (150 bpm) */
161 int svsysex
= 0; /* number of sysex bytes saved internally */
164 send_event(seq_event_t
*ev
)
167 printf("%02x %02x %02x %02x %02x %02x %02x %02x\n",
168 ev->arr[0], ev->arr[1], ev->arr[2], ev->arr[3],
169 ev->arr[4], ev->arr[5], ev->arr[6], ev->arr[7]);
172 write(fd
, ev
, sizeof *ev
);
176 getvar(struct track
*tp
)
183 r
= (r
<< 7) | (c
& 0x7f);
184 } while ((c
& 0x80) && tp
->start
< tp
->end
);
189 getlen(struct track
*tp
)
193 if (tp
->start
+ len
> tp
->end
)
194 errx(1, "bogus item length exceeds remaining track size");
199 dometa(u_int meta
, u_char
*p
, u_int len
)
201 static char const * const keys
[] = {
202 "Cb", "Gb", "Db", "Ab", "Eb", "Bb", "F",
204 "G", "D", "A", "E", "B", "F#", "C#",
205 "G#", "D#", "A#" /* for minors */
214 case META_INSTRUMENT
:
219 printf("%s: ", metanames
[meta
]);
220 fwrite(p
, len
, 1, stdout
);
225 usperbeat
= GET24(p
);
226 ev
= SEQ_MK_TIMING(TEMPO
,
227 .bpm
=(60000000. / usperbeat
) * (ttempo
/ 100.) + 0.5);
229 printf("Tempo: %u us/'beat'(24 midiclks)"
230 " at %u%%; adjusted bpm = %u\n",
231 usperbeat
, ttempo
, ev
.t_TEMPO
.bpm
);
233 warnx("tempo event ignored"
234 " in absolute-timed MIDI file");
239 send_event(&SEQ_MK_TIMING(START
));
244 ev
= SEQ_MK_TIMING(TIMESIG
,
245 .numerator
=p
[0], .lg2denom
=p
[1],
246 .clks_per_click
=p
[2], .dsq_per_24clks
=p
[3]);
248 printf("Time signature: %d/%d."
249 " Click every %d midiclk%s"
250 " (24 midiclks = %d 32nd note%s)\n",
251 ev
.t_TIMESIG
.numerator
,
252 1 << ev
.t_TIMESIG
.lg2denom
,
253 ev
.t_TIMESIG
.clks_per_click
,
254 1 == ev
.t_TIMESIG
.clks_per_click
? "" : "s",
255 ev
.t_TIMESIG
.dsq_per_24clks
,
256 1 == ev
.t_TIMESIG
.dsq_per_24clks
? "" : "s");
258 /* send_event(&ev); not implemented in sequencer */
262 printf("Key: %s %s\n",
263 keys
[((char)p
[0]) + p
[1] ? 10 : 7],
264 p
[1] ? "minor" : "major");
274 /* General MIDI reset sequence */
275 send_event(&SEQ_MK_SYSEX(unit
,[0]=0x7e, 0x7f, 0x09, 0x01, 0xf7));
278 #define SYSEX_CHUNK 6
280 send_sysex(u_char
*p
, u_int l
)
286 warnx("zero-length system-exclusive event");
291 * This block is needed only to handle the possibility that a sysex
292 * message is broken into multiple events in a MIDI file that do not
293 * have length six; the /dev/music sequencer assumes a sysex message is
294 * finished with the first SYSEX event carrying fewer than six bytes,
295 * even if the last is not MIDI_SYSEX_END. So, we need to be careful
296 * not to send a short sysex event until we have seen the end byte.
297 * Instead, save some straggling bytes in bf, and send when we have a
298 * full six (or an end byte). Note bf/saved/insysex should be per-
299 * device, if we supported output to more than one device at a time.
302 if ( l
> sizeof bf
- svsysex
) {
303 memcpy(bf
+ svsysex
, p
, sizeof bf
- svsysex
);
304 l
-= sizeof bf
- svsysex
;
305 p
+= sizeof bf
- svsysex
;
306 send_event(&SEQ_MK_SYSEX(unit
,[0]=
307 bf
[0],bf
[1],bf
[2],bf
[3],bf
[4],bf
[5]));
310 memcpy(bf
+ svsysex
, p
, l
);
313 if ( MIDI_SYSEX_END
== bf
[svsysex
-1] ) {
314 event
= SEQ_MK_SYSEX(unit
);
315 memcpy(event
.sysex
.buffer
, bf
, svsysex
);
317 svsysex
= insysex
= 0;
325 * l > 0. May as well test now whether we will be left 'insysex'
326 * after processing this event.
328 insysex
= ( MIDI_SYSEX_END
!= p
[l
-1] );
331 * If not for multi-event sysexes and chunk-size weirdness, this
332 * function could pretty much start here. :)
334 while ( l
>= SYSEX_CHUNK
) {
335 send_event(&SEQ_MK_SYSEX(unit
,[0]=
336 p
[0],p
[1],p
[2],p
[3],p
[4],p
[5]));
344 } else { /* a <6 byte chunk is ok if it's REALLY the end */
345 event
= SEQ_MK_SYSEX(unit
);
346 memcpy(event
.sysex
.buffer
, p
, l
);
353 playfile(FILE *f
, const char *name
)
356 u_int tot
, n
, size
, nread
;
359 * We need to read the whole file into memory for easy processing.
360 * Using mmap() would be nice, but some file systems do not support
361 * it, nor does reading from e.g. a pipe. The latter also precludes
362 * finding out the file size without reading it.
367 errx(1, "malloc() failed");
371 n
= fread(buf
+ tot
, 1, nread
, f
);
375 /* There must be more to read. */
377 nbuf
= realloc(buf
, size
* 2);
379 errx(1, "realloc() failed");
383 playdata(buf
, tot
, name
);
388 playdata(u_char
*buf
, u_int tot
, const char *name
)
390 int format
, ntrks
, divfmt
, ticks
, t
;
391 u_int len
, mlen
, status
, chan
;
392 u_char
*p
, *end
, byte
, meta
, *msg
;
393 struct track
*tracks
;
398 printf("Playing %s (%d bytes) ... \n", name
, tot
);
400 if (tot
< MARK_LEN
+ 4) {
401 warnx("Not a MIDI file, too short");
405 if (memcmp(buf
, RMID_SIG
, MARK_LEN
) == 0) {
407 /* Detected a RMID file, let's just check if it's
409 if ((u_int
)GET32_LE(buf
+ MARK_LEN
) != tot
- 8) {
410 warnx("Not a RMID file, bad header");
415 if (memcmp(buf
, RMID_MIDI_ID
, MARK_LEN
) != 0) {
416 warnx("Not a RMID file, bad ID");
420 /* Now look for the 'data' chunk, which contains
424 /* Test against end-8 since we must have at least 8 bytes
426 while(buf
< end
-8 && memcmp(buf
, RMID_DATA_ID
, MARK_LEN
))
427 buf
+= GET32_LE(buf
+4) + 8; /* MARK_LEN + 4 */
430 warnx("Not a valid RMID file, no data chunk");
434 buf
+= MARK_LEN
; /* "data" */
435 eod
= buf
+ 4 + GET32_LE(buf
);
437 warnx("Not a valid RMID file, bad data chunk size");
445 if (memcmp(buf
, MARK_HEADER
, MARK_LEN
) != 0) {
446 warnx("Not a MIDI file, missing header");
450 if (GET32(buf
+ MARK_LEN
) != HEADER_LEN
) {
451 warnx("Not a MIDI file, bad header");
454 format
= GET16(buf
+ MARK_LEN
+ SIZE_LEN
);
455 ntrks
= GET16(buf
+ MARK_LEN
+ SIZE_LEN
+ 2);
456 divfmt
= GET8(buf
+ MARK_LEN
+ SIZE_LEN
+ 4);
457 ticks
= GET8(buf
+ MARK_LEN
+ SIZE_LEN
+ 5);
458 p
= buf
+ MARK_LEN
+ SIZE_LEN
+ HEADER_LEN
;
460 * Set the timebase (or timebase and tempo, for absolute-timed files).
461 * PORTABILITY: some sequencers actually check the timebase against
462 * available timing sources and may adjust it accordingly (storing a
463 * new value in the ioctl arg) which would require us to compensate
464 * somehow. That possibility is ignored for now, as NetBSD's sequencer
465 * currently synthesizes all timebases, for better or worse, from the
468 * For a non-absolute file, if timebase is set to the file's divisions
469 * value, and tempo set in the obvious way, then the timing deltas in
470 * the MTrks require no scaling. A downside to this approach is that
471 * the sequencer API wants tempo in (integer) beats per minute, which
472 * limits how finely tempo can be specified. That might be got around
473 * in some cases by frobbing tempo and timebase more obscurely, but this
474 * player is meant to be simple and clear.
476 if ((divfmt
& 0x80) == 0) {
477 ticks
|= divfmt
<< 8;
478 if (ioctl(fd
, SEQUENCER_TMR_TIMEBASE
, &(int){ticks
}) < 0)
479 err(1, "SEQUENCER_TMR_TIMEBASE");
481 tempo_abs
= tempo_set
= 1;
482 divfmt
= -(int8_t)divfmt
;
484 * divfmt is frames per second; multiplying by 60 to set tempo
485 * in frames per minute could exceed sequencer's (arbitrary)
486 * tempo limits, so factor 60 as 12*5, set tempo in frames per
487 * 12 seconds, and account for the 5 in timebase.
489 send_event(&SEQ_MK_TIMING(TEMPO
,
490 .bpm
=(12*divfmt
) * (ttempo
/100.) + 0.5));
491 if (ioctl(fd
, SEQUENCER_TMR_TIMEBASE
, &(int){5*ticks
}) < 0)
492 err(1, "SEQUENCER_TMR_TIMEBASE");
496 "format=%d ntrks=%d abs fps=%u subdivs=%u\n" :
497 "format=%d ntrks=%d divisions=%u\n",
498 format
, ntrks
, tempo_abs
? divfmt
: ticks
, ticks
);
499 if (format
!= 0 && format
!= 1) {
500 warnx("Cannot play MIDI file of type %d", format
);
505 tracks
= malloc(ntrks
* sizeof(struct track
));
507 errx(1, "malloc() tracks failed");
508 for (t
= 0; t
< ntrks
; ) {
509 if (p
>= end
- MARK_LEN
- SIZE_LEN
) {
510 warnx("Cannot find track %d", t
);
513 len
= GET32(p
+ MARK_LEN
);
514 if (len
> 1000000) { /* a safe guard */
515 warnx("Crazy track length");
518 if (memcmp(p
, MARK_TRACK
, MARK_LEN
) == 0) {
519 tracks
[t
].start
= p
+ MARK_LEN
+ SIZE_LEN
;
520 tracks
[t
].end
= tracks
[t
].start
+ len
;
521 tracks
[t
].delta
= getvar(&tracks
[t
]);
522 tracks
[t
].indirect
= &tracks
[t
]; /* -> self for now */
525 p
+= MARK_LEN
+ SIZE_LEN
+ len
;
529 * Force every channel to the same patch if requested by the user.
532 for(t
= 0; t
< 16; t
++) {
533 send_event(&SEQ_MK_CHN(PGM_CHANGE
, .device
=unit
,
534 .channel
=t
, .program
=sameprogram
-1));
538 * Play MIDI events by selecting the track with the lowest
539 * delta. Execute the event, update the delta and repeat.
541 * The ticks variable is the number of ticks that make up a beat
542 * (beat: 24 MIDI clocks always, a quarter note by usual convention)
543 * and is used as a reference value for the delays between
546 BuildHeap(tracks
, ntrks
); /* tracks[0].indirect is always next */
548 tp
= tracks
[0].indirect
;
549 if ((verbose
> 2 && tp
->delta
> 0) || verbose
> 3) {
550 printf("DELAY %4ld TRACK %2td%s",
551 tp
->delta
, tp
- tracks
, verbose
>3?" ":"\n");
556 if (verbose
|| showmeta
)
557 printf("No initial tempo;"
559 dometa(META_SET_TEMPO
, (u_char
[]){
561 (BASETEMPO
>> 8) & 0xff,
565 send_event(&SEQ_MK_TIMING(WAIT_REL
,
566 .divisions
=tp
->delta
));
569 if (byte
== MIDI_META
) {
573 printf("META %02x (%d)\n", meta
, mlen
);
574 dometa(meta
, tp
->start
, mlen
);
577 if (MIDI_IS_STATUS(byte
))
581 mlen
= MIDI_LENGTH(tp
->status
);
585 printf("MIDI %02x (%d) %02x\n",
586 tp
->status
, mlen
, msg
[0]);
588 printf("MIDI %02x (%d) %02x %02x\n",
589 tp
->status
, mlen
, msg
[0], msg
[1]);
591 if (insysex
&& tp
->status
!= MIDI_SYSEX_END
) {
592 warnx("incomplete system exclusive message"
594 svsysex
= insysex
= 0;
596 status
= MIDI_GET_STATUS(tp
->status
);
597 chan
= MIDI_GET_CHAN(tp
->status
);
600 send_event(&SEQ_MK_CHN(NOTEOFF
, .device
=unit
,
601 .channel
=chan
, .key
=msg
[0], .velocity
=msg
[1]));
604 send_event(&SEQ_MK_CHN(NOTEON
, .device
=unit
,
605 .channel
=chan
, .key
=msg
[0], .velocity
=msg
[1]));
607 case MIDI_KEY_PRESSURE
:
608 send_event(&SEQ_MK_CHN(KEY_PRESSURE
,
609 .device
=unit
, .channel
=chan
,
610 .key
=msg
[0], .pressure
=msg
[1]));
612 case MIDI_CTL_CHANGE
:
613 send_event(&SEQ_MK_CHN(CTL_CHANGE
,
614 .device
=unit
, .channel
=chan
,
615 .controller
=msg
[0], .value
=msg
[1]));
617 case MIDI_PGM_CHANGE
:
619 send_event(&SEQ_MK_CHN(PGM_CHANGE
,
620 .device
=unit
, .channel
=chan
,
623 case MIDI_CHN_PRESSURE
:
624 send_event(&SEQ_MK_CHN(CHN_PRESSURE
,
625 .device
=unit
, .channel
=chan
, .pressure
=msg
[0]));
627 case MIDI_PITCH_BEND
:
628 send_event(&SEQ_MK_CHN(PITCH_BEND
,
629 .device
=unit
, .channel
=chan
,
630 .value
=(msg
[0] & 0x7f) | ((msg
[1] & 0x7f)<<7)));
632 case MIDI_SYSTEM_PREFIX
:
634 if (tp
->status
== MIDI_SYSEX_START
) {
635 send_sysex(tp
->start
, mlen
);
637 } else if (tp
->status
== MIDI_SYSEX_END
) {
638 /* SMF uses SYSEX_END as CONTINUATION/ESCAPE */
639 if (insysex
) { /* CONTINUATION */
640 send_sysex(tp
->start
, mlen
);
641 } else { /* ESCAPE */
642 for ( ; mlen
> 0 ; -- mlen
) {
653 /* Sorry, can't do this yet; FALLTHROUGH */
656 printf("MIDI event 0x%02x ignored\n",
661 if (tp
->start
>= tp
->end
) {
662 ntrks
= ShrinkHeap(tracks
, ntrks
); /* track gone */
666 tp
->delta
= getvar(tp
);
667 Heapify(tracks
, ntrks
, 0);
669 if (ioctl(fd
, SEQUENCER_SYNC
, 0) < 0)
670 err(1, "SEQUENCER_SYNC");
677 main(int argc
, char **argv
)
683 const char *file
= DEVMUSIC
;
685 struct synth_info info
;
688 if ((sunit
= getenv("MIDIUNIT")))
691 while ((ch
= getopt(argc
, argv
, "?d:f:lmp:qt:vx")) != -1) {
706 sameprogram
= atoi(optarg
);
712 ttempo
= atoi(optarg
);
731 fd
= open(file
, O_WRONLY
);
734 if (ioctl(fd
, SEQUENCER_NRMIDIS
, &nmidi
) < 0)
735 err(1, "ioctl(SEQUENCER_NRMIDIS) failed, ");
737 errx(1, "Sorry, no MIDI devices available");
739 for (info
.device
= 0; info
.device
< nmidi
; info
.device
++) {
740 if (ioctl(fd
, SEQUENCER_INFO
, &info
) < 0)
741 err(1, "ioctl(SEQUENCER_INFO) failed, ");
742 printf("%d: %s\n", info
.device
, info
.name
);
750 playdata(sample
, sizeof sample
, "<Gubben Noa>");
752 playfile(stdin
, "<stdin>");
755 f
= fopen(*argv
, "r");
769 * relative-time priority queue (min-heap). Properties:
770 * 1. The delta time at a node is relative to the node's parent's time.
771 * 2. When an event is dequeued from a track, the delta time of the new head
772 * event is relative to the time of the event just dequeued.
774 * 3. After dequeueing the head event from the track at heap root, the next
775 * event's time is directly comparable to the root's children.
776 * These properties allow the heap to be maintained with delta times throughout.
777 * Insert is also implementable, but not needed: all the tracks are present
778 * at first; they just go away as they end.
781 #define PARENT(i) ((i-1)>>1)
782 #define LEFT(i) ((i<<1)+1)
783 #define RIGHT(i) ((i+1)<<1)
784 #define DTIME(i) (t[i].indirect->delta)
785 #define SWAP(i,j) do { \
786 struct track *_t = t[i].indirect; \
787 t[i].indirect = t[j].indirect; \
788 t[j].indirect = _t; \
789 } while ( /*CONSTCOND*/ 0 )
792 Heapify(struct track
*t
, int ntrks
, int node
)
799 if (rc
>= ntrks
) { /* no right child */
800 if (lc
>= ntrks
) /* node is a leaf */
802 if (DTIME(node
) > DTIME(lc
))
804 DTIME(lc
) -= DTIME(node
);
805 return; /* no rc ==> lc is a leaf */
809 if (DTIME(lc
) > DTIME(rc
))
811 if (DTIME(node
) <= DTIME(mn
)) {
812 DTIME(rc
) -= DTIME(node
);
813 DTIME(lc
) -= DTIME(node
);
818 DTIME(rc
) -= DTIME(node
);
819 DTIME(lc
) -= DTIME(node
);
820 Heapify(t
, ntrks
, mn
); /* gcc groks tail recursion */
824 BuildHeap(struct track
*t
, int ntrks
)
828 for ( node
= PARENT(ntrks
-1); node
--> 0; )
829 Heapify(t
, ntrks
, node
);
833 * Make the heap 1 item smaller by discarding the track at the root. Move the
834 * rightmost bottom-level leaf to the root and decrement ntrks. It remains to
835 * run Heapify, which the caller is expected to do. Returns the new ntrks.
838 ShrinkHeap(struct track
*t
, int ntrks
)
843 for ( ancest
= PARENT(ntrks
); ancest
> 0; ancest
= PARENT(ancest
) )
844 DTIME(ntrks
) += DTIME(ancest
);
845 t
[0].indirect
= t
[ntrks
].indirect
;