dmid: add support for midi streams

tested with a usb midi keyboard and a midi->usb adaptor
This commit is contained in:
qwx 2018-08-31 18:01:21 +02:00
parent 67b24e6dac
commit 55e0fd6031
2 changed files with 61 additions and 4 deletions

View file

@ -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

View file

@ -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 *
@ -435,6 +437,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)
{
@ -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;