ref: f2d78c632d9384ef45c7da914321f9e30f79ff67
dir: /mid2s.c/
#include <u.h>
#include <libc.h>
#include <bio.h>
#include "midifile.h"
static int magic;
void
samp(uvlong n)
{
double Δt;
long s;
static double t0;
if(t0 == 0.0)
t0 = nsec();
t0 += n * 1000 * tempo / div;
Δt = t0 - nsec();
s = floor(Δt / 1000000);
if(s > 0)
sleep(s);
}
/* set delay to 0, and translate running status: the receiver
* only sees one track whereas running status is a property of
* each track (stream); don't send EOT for the same reason */
static void
eat(Trk *x)
{
int e, n;
uchar u[16], *p, *q;
Msg msg;
q = u + 1;
e = nextevent(x);
*q++ = e;
p = x->p;
translate(x, e, &msg);
if(msg.type == Ceot)
return;
u[0] = magic ? e >> 4 | (e & 0xf) << 4 : 0;
n = x->p - p;
if(msg.type == Csysex || n > nelem(u) - (q - u)){
write(1, u, q - u);
write(1, p, n);
}else{
memcpy(q, p, n);
write(1, u, n + (q - u));
}
}
void
usage(void)
{
fprint(2, "usage: %s [-D] [mid]\n", argv0);
exits("usage");
}
void
main(int argc, char **argv)
{
int end;
uchar eot[] = {0x00, 0xff, 0x2f, 0x00};
Trk *x;
ARGBEGIN{
case 'D': trace = 1; break;
case 'm': magic = 1; break; /* FIXME: investigate more */
default: usage();
}ARGEND
if(readmid(*argv) < 0)
sysfatal("readmid: %r");
for(;;){
end = 1;
for(x=tr; x<tr+ntrk; x++){
if(x->ended)
continue;
end = 0;
x->Δ--;
while(x->Δ <= 0){
eat(x);
if(x->ended)
break;
x->Δ = getvar(x);
}
}
if(end)
break;
samp(1);
}
write(1, eot, sizeof eot);
exits(nil);
}