shithub: neindaw

Download patch

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];
 }