shithub: riscv

Download patch

ref: 55e0fd603151867eac865be660767dcc4289ed87
parent: 67b24e6dac5e9544171beb86ef657b71b87f9f5f
author: qwx <devnull@localhost>
date: Fri Aug 31 14:01:21 EDT 2018

dmid: add support for midi streams

tested with a usb midi keyboard and a midi->usb adaptor

--- a/sys/man/1/dmid
+++ b/sys/man/1/dmid
@@ -4,7 +4,7 @@
 .SH SYNOPSIS
 .B dmid
 [
-.B -2
+.B -2s
 ] [
 .B -i
 .I bank
@@ -33,6 +33,13 @@
 .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 @@
 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 @@
 .IR mus (1) ,
 .IR opl3 (1) ,
 .IR audio (3) ,
+.IR usb (3) ,
 .IR wadfs (4)
 .SH HISTORY
 .I Dmid
--- 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 @@
 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 @@
 }
 
 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 @@
 	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 @@
 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 @@
 	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 @@
 	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;