ref: 1330d1fff8e87caf7a85e4d32c17feb965484bae
dir: /piper/piano.c/
#include <u.h>
#include <libc.h>
#include <thread.h>
#include "piper.h"
#include "util.h"
typedef struct Piano Piano;
struct Piano {
int freq;
int gain;
int gate;
Channel *offc;
char path[1];
};
static void
gateoff(void *aux)
{
uvlong t, n;
Piano *p;
threadsetname("piper/gateoff");
p = aux;
for (;;) {
if (recv(p->offc, &t) != 1)
break;
next:
while (1) {
n = nanosec();
if (n >= t)
break;
n = t - n;
if (n > 750000000LL)
sleep(70);
else if (n > 25000000LL)
sleep(20);
else if (n > 10000000LL)
sleep(1);
}
if (nbrecv(p->offc, &t) != 0)
goto next;
fprint(p->gate, "0");
}
threadexits(nil);
}
static int
cmd(void *aux, Cmd *c)
{
Piano *p;
uvlong off;
p = aux;
switch (c->type) {
case CmdNote:
off = nanosec() + 1000000000ULL*c->note[0].dur;
send(p->offc, &off);
fprint(p->gain, "%g", c->note[0].vel);
fprint(p->freq, "%g", c->note[0].freq);
fprint(p->gate, "1");
break;
case CmdRaw:
break;
}
return 0;
}
static void *
alloc(char *path)
{
Piano *p;
if ((p = calloc(1, sizeof(*p) + strlen(path) + 1)) != nil) {
p->freq = pathopen(path, "Basic/Freq/ctl");
p->gain = pathopen(path, "Basic/Gain/ctl");
p->gate = pathopen(path, "Basic/Gate/ctl");
p->offc = chancreate(sizeof(uvlong), 10);
strcpy(p->path, path);
proccreate(gateoff, p, 4096);
}
return p;
}
Synth piano = {
.name = "Piano",
.cmd = cmd,
.alloc = alloc,
};