diff options
author | qwx <qwx@sciops.net> | 2023-01-21 18:12:12 +0000 |
---|---|---|
committer | qwx <qwx@sciops.net> | 2023-01-21 18:12:12 +0000 |
commit | 080a7b01bfa0fb89951cf4e30070dc7665992c90 (patch) | |
tree | 2b28b5c67b29875ec2f1aa99f006d27a758c1a24 /sys/src/games | |
parent | bb36ba0617b5aa8263ea9b5ece8c1a5249fedc86 (diff) |
games/opl3: implement real time streaming mode
this pushes all responsibility for timing to opl3, absolving
dmid(1) and other writers from constantly sending sync
events to force opl3 to synthesize audio in between events.
it reduces cpu usage and syscalls dramatically and enables
applications other than dmid(1) to modify its state in real
time, for instance to use it as a synth.
Diffstat (limited to 'sys/src/games')
-rw-r--r-- | sys/src/games/opl3/opl3m.c | 39 |
1 files changed, 35 insertions, 4 deletions
diff --git a/sys/src/games/opl3/opl3m.c b/sys/src/games/opl3/opl3m.c index 17dbae1e5..e1153a080 100644 --- a/sys/src/games/opl3/opl3m.c +++ b/sys/src/games/opl3/opl3m.c @@ -13,19 +13,22 @@ enum{ void usage(void) { - fprint(2, "usage: %s [-r rate] [file]\n", argv0); + fprint(2, "usage: %s [-s] [-r rate] [file]\n", argv0); exits("usage"); } void main(int argc, char **argv) { - int rate, n, r, v, fd, pfd[2]; - uchar sb[65536 * 4], u[5]; - double f, dt; + int rate, stream, n, r, v, fd, pfd[2]; + uchar sb[64*1024], u[5]; + double f; + vlong dt, T; Biobuf *bi; + QLock slock; fd = 0; + stream = 0; rate = OPLrate; ARGBEGIN{ case 'r': @@ -33,6 +36,9 @@ main(int argc, char **argv) if(rate <= 0 || rate > OPLrate) usage(); break; + case 's': + stream = 1; + break; default: usage(); }ARGEND; @@ -60,19 +66,44 @@ main(int argc, char **argv) } f = (double)OPLrate / rate; dt = 0; + T = nsec(); + if(stream){ + switch(rfork(RFPROC|RFMEM)){ + case -1: + sysfatal("rfork: %r"); + case 0: + for(;;){ + qlock(&slock); + n = OPLrate / 1e3; + T += n * (1e9 / OPLrate); + n *= 4; + opl3out(sb, n); + n = write(pfd[1], sb, n); + dt = (T - nsec()) / 1e6; + qunlock(&slock); + if(n <= 0) + break; + if(dt > 0) + sleep(dt); + } + } + } while((n = Bread(bi, u, sizeof u)) > 0){ r = u[1] << 8 | u[0]; v = u[2]; opl3wr(r, v); dt += (u[4] << 8 | u[3]) * f; + qlock(&slock); while((n = dt) > 0){ if(n > sizeof sb / 4) n = sizeof sb / 4; dt -= n; + T += n * (1e9 / OPLrate); n *= 4; opl3out(sb, n); write(pfd[1], sb, n); } + qunlock(&slock); } if(n < 0) sysfatal("read: %r"); |