dmid: add support for midi streams
tested with a usb midi keyboard and a midi->usb adaptor
This commit is contained in:
parent
67b24e6dac
commit
55e0fd6031
2 changed files with 61 additions and 4 deletions
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue