shithub: neindaw

ref: 11bee08c7da60c752092e5ada1ede8a9dc916a68
dir: /piper/piano.c/

View raw version
#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,
};