ref: 92275f3b95309a13c8e1aa136bb62e7f6ea71458
parent: 088dbbe33035792dadd738982e95e607f59025fb
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Mon May 11 14:01:50 EDT 2020
piper: make kick drum work with orca
--- a/piper/kick.c
+++ b/piper/kick.c
@@ -29,12 +29,14 @@
k = aux;
switch (c->type) {
case CmdNote:
+ fprint(k->gate, "0");
+ fprint(k->volume, "%g", c->note[0].vel);
fprint(k->a.freq, "%g", c->note[0].freq);
fprint(k->a.release, "%g", c->note[0].dur);
if (c->numnotes > 1) {
fprint(k->b.freq, "%g", c->note[1].freq);
fprint(k->b.release, "%g", c->note[1].dur);
- fprint(k->b.enable, "1");
+ fprint(k->b.enable, "%g", c->note[1].vel);
} else {
fprint(k->b.enable, "0");
}
--- a/piper/piper.c
+++ b/piper/piper.c
@@ -10,6 +10,7 @@
struct Inst {
void *aux;
int data;
+ int id;
};
struct Group {
@@ -20,8 +21,12 @@
int clone;
};
+static int bpm = 120;
+static float bar = 2.0;
+static QLock grouplock;
static Group *groups;
static int numgroups;
+static int audio;
static Synth *synths[] = {
&ay_3_8910,
@@ -35,13 +40,74 @@
threadexitsall("usage");
}
+static Inst *
+getinst(Group *g, int id)
+{
+ Inst *inst;
+ void *aux;
+ char *path, tmp[8];
+ int i, n, f;
+
+ for (i = 0; i < g->numinst; i++) {
+ if (id == g->inst[i].id)
+ return &g->inst[i];
+ }
+
+ for (i = g->numinst; i <= id;) {
+ /* first see if it already exists */
+ if ((path = smprint("%s/%d", g->path, i)) == nil)
+ sysfatal("memory");
+ if ((f = open(path, OREAD)) >= 0)
+ close(f);
+ free(path);
+
+ if (f < 0) {
+ /* doesn't exist, clone */
+ seek(g->clone, 0, 0);
+ if ((n = read(g->clone, tmp, sizeof(tmp))) < 1)
+ sysfatal("clone failed");
+ tmp[n] = 0;
+ i = atoi(tmp);
+ }
+
+ if ((path = smprint("%s/%d/%s", g->path, i, g->synth->name)) == nil)
+ sysfatal("memory");
+ if ((aux = g->synth->alloc(path)) == nil)
+ sysfatal("couldn't alloc instance: %r");
+ free(path);
+
+ if ((path = smprint("%s/%d/data", g->path, i)) == nil)
+ sysfatal("memory");
+ if ((f = open(path, OREAD)) < 0)
+ sysfatal("couldn't open data: %r");
+ free(path);
+
+ if ((g->inst = realloc(g->inst, sizeof(Inst)*(g->numinst+1))) == nil)
+ sysfatal("memory");
+ inst = &g->inst[g->numinst];
+ inst->data = f;
+ inst->id = i;
+ inst->aux = aux;
+ g->numinst++;
+
+ if (i == id)
+ return inst;
+
+ if (f >= 0)
+ i++;
+ }
+
+ return nil;
+}
+
static char *
parse(char *s, Group *g)
{
Cmd c;
- char *e, *path, tmp[8];
- void *aux;
+ char *e;
+ Inst *inst;
int i, n;
+ float f;
for (i = 1; s[i] != 0 && s[i] != '\n' && s[i] != ';'; i++);
e = (s[i] == 0 || s[i] == '\n') ? nil : s + i + 1;
@@ -49,32 +115,67 @@
if (g != nil) {
s++;
- i = i36(*s);
- while (i >= g->numinst) { /* instance needs to be created */
- seek(g->clone, 0, 0);
- if ((n = read(g->clone, tmp, sizeof(tmp))) < 1)
- sysfatal("clone failed");
- tmp[n] = 0;
- if ((path = smprint("%s/%s/%s", g->path, tmp, g->synth->name)) == nil)
- sysfatal("memory");
- if ((aux = g->synth->alloc(path)) == nil)
- return e;
- if ((g->inst = realloc(g->inst, sizeof(Inst)*(g->numinst+1))) == nil)
- sysfatal("memory");
- if ((path = smprint("%s/%s/data", g->path, tmp)) == nil)
- sysfatal("memory");
- if ((g->inst[g->numinst].data = open(path, OREAD)) < 0)
- sysfatal("couldn't open data: %r");
- g->inst[g->numinst++].aux = aux;
- free(path);
+ if ((inst = getinst(g, i36(*s++))) != nil) {
+ memset(&c, 0, sizeof(c));
+ c.type = -1;
+
+ n = 0;
+nextnote:
+ f = 1.0;
+ if (*s == '!') {
+ f = -1.0;
+ s++;
+ }
+
+ if ((*s >= 'a' && *s <= 'g') || (*s >= 'A' && *s <= 'G')) {
+ if (s[1] != 0) {
+ f *= note2freq(s[0], s[1]);
+ s += 2;
+ c.type = CmdNote;
+ c.note[n].freq = f;
+ c.note[n].vel = 1.0;
+ c.note[n].dur = bar / 16.0;
+ if (*s != 0) {
+ c.note[n].vel = (float)i36(*s) / 16.0;
+ s++;
+ if (*s != 0) {
+ c.note[n].dur = bar / (float)i36(*s);
+ s++;
+ }
+ }
+ n++;
+ if (*s == ':') {
+ s++;
+ /* for the lack of better ideas, overwrite */
+ if (n >= nelem(c.note))
+ n--;
+ goto nextnote;
+ }
+ }
+ c.numnotes = n;
+ } else if (strncmp(s, "vol", 3) == 0) {
+ c.type = CmdVol;
+ c.vol = atof(s+3) / 100.0;
+ } else if (*s != 0) {
+ c.type = CmdRaw;
+ c.raw = s;
+ }
+
+ if (c.type >= 0)
+ g->synth->cmd(inst->aux, &c);
}
- memset(&c, 0, sizeof(c));
- g->synth->cmd(g->inst[i].aux, &c);
+ } else if (strncmp(s, "bpm", 3) == 0) {
+ if ((i = atoi(s+3)) > 0) {
+ bpm = i;
+ bar = 240.0 / (float)bpm;
+ }
}
return e;
}
+
+
void
threadmain(int argc, char **argv)
{
@@ -132,7 +233,9 @@
t[n] = 0;
for (s = t; s != nil && *s;) {
i = i36(s[0]);
+ qlock(&grouplock);
s = parse(s, i < numgroups ? &groups[i] : nil);
+ qunlock(&grouplock);
}
}
--- a/piper/piper.h
+++ b/piper/piper.h
@@ -13,6 +13,7 @@
struct {
float freq;
float dur;
+ float vel;
}note[3];
char *raw;
float vol;
@@ -30,5 +31,5 @@
extern Synth kick_drum;
int i36(uchar c);
-float note2freq(int octave, uchar note);
+float note2freq(uchar note, uchar octave);
int pathopen(char *path, char *fmt, ...);
--- a/piper/util.c
+++ b/piper/util.c
@@ -20,10 +20,11 @@
}
float
-note2freq(int octave, uchar note)
+note2freq(uchar note, uchar octave)
{
note -= 'A';
- if (octave < 0 || octave >= nelem(notes) || note >= nelem(notes[0]))
+ octave -= '0';
+ if (octave >= nelem(notes) || note >= nelem(notes[0]))
return 0.0;
return notes[octave][note];
}