diff options
| -rw-r--r-- | sys/man/1/dmid | 18 | ||||
| -rw-r--r-- | sys/src/games/dmid.c | 47 |
2 files changed, 61 insertions, 4 deletions
diff --git a/sys/man/1/dmid b/sys/man/1/dmid index df4f72dd5..c04cb6a54 100644 --- a/sys/man/1/dmid +++ b/sys/man/1/dmid @@ -4,7 +4,7 @@ dmid \- MIDI to OPL3 converter using GENMIDI-type instrument banks .SH SYNOPSIS .B dmid [ -.B -2 +.B -2s ] [ .B -i .I bank @@ -33,6 +33,13 @@ This may be overridden with the .B -i command line option. .PP +The +.B -s +flag enables streaming mode, +in which the input file is a stream of MIDI events. +The file needn't provide any timing information such as MIDI tics. +This is suitable for MIDI instruments. +.PP In .SM GENMIDI lumps, two voices are defined per instrument. @@ -55,6 +62,14 @@ file: createfile SW18_7: file already exists % games/mus /mnt/wad/d_doom | games/dmid | games/opl3 >/dev/audio .EE +.PP +Play a MIDI stream from a USB device (see +.BR usb (3)): +.IP +.EX +% games/wadfs /sys/games/lib/doom/doom2.wad >[2]/dev/null +% games/dmid -s /dev/usb/ep10.1/data | games/opl3 >/dev/audio +.EE .SH SOURCE .B /sys/src/games/dmid.c .SH "SEE ALSO" @@ -62,6 +77,7 @@ createfile SW18_7: file already exists .IR mus (1) , .IR opl3 (1) , .IR audio (3) , +.IR usb (3) , .IR wadfs (4) .SH HISTORY .I Dmid diff --git a/sys/src/games/dmid.c b/sys/src/games/dmid.c index a7da7ea0e..254d42df9 100644 --- a/sys/src/games/dmid.c +++ b/sys/src/games/dmid.c @@ -1,6 +1,7 @@ #include <u.h> #include <libc.h> #include <bio.h> +#include <thread.h> typedef struct Inst Inst; typedef struct Opl Opl; @@ -82,8 +83,9 @@ struct Trk{ Trk *tr; double freq[128]; -int mfmt, ntrk, div, tempo, opl2; +int mfmt, ntrk, div = 1, tempo, opl2, stream; uvlong T; +Channel *echan; Biobuf *ib, *ob; void * @@ -436,6 +438,29 @@ ev(Trk *x) } void +tproc(void *) +{ + vlong t, Δt; + uchar u[4]; + Trk x; + + x.e = u + sizeof u; + t = nsec(); + for(;;){ + if(nbrecv(echan, u) > 0){ + u[0] = 0; + x.p = u; + ev(&x); + } + putcmd(0, 0, 1); + t += 10000000 / (Rate / 100); + Δt = (t - nsec()) / 1000000; + if(Δt > 0) + sleep(Δt); + } +} + +void readinst(char *file) { int n; @@ -475,6 +500,8 @@ readmid(char *file) Trk *x; ib = file != nil ? bopen(file, OREAD) : bfdopen(0, OREAD); + if(stream) + return; if(get32(nil) != 0x4d546864 || get32(nil) != 6) sysfatal("invalid header"); mfmt = get16(nil); @@ -501,16 +528,17 @@ readmid(char *file) void usage(void) { - fprint(2, "usage: %s [-2] [-i inst] [mid]\n", argv0); + fprint(2, "usage: %s [-2s] [-i inst] [mid]\n", argv0); exits("usage"); } void -main(int argc, char **argv) +threadmain(int argc, char **argv) { int n, t, mint; char *i; double f; + uchar u[4]; Chan *c; Opl *o; Trk *x, *minx; @@ -519,6 +547,7 @@ main(int argc, char **argv) ARGBEGIN{ case '2': opl2 = 1; ople = opl + 9; break; case 'i': i = EARGF(usage()); break; + case 's': stream = 1; break; default: usage(); }ARGEND readinst(i); @@ -538,6 +567,18 @@ main(int argc, char **argv) tempo = 500000; putcmd(Rwse, Mwse, 0); putcmd(Rop3, 1, 0); + if(stream){ + if(proccreate(tproc, nil, mainstacksize) < 0) + sysfatal("proccreate: %r"); + if((echan = chancreate(sizeof u, 0)) == nil) + sysfatal("chancreate: %r"); + for(;;){ + if((n = Bread(ib, u, sizeof u)) != sizeof u) + break; + send(echan, u); + } + threadexitsall(n < 0 ? "read: %r" : nil); + } for(;;){ minx = nil; mint = 0; |
