shithub: neindaw

Download patch

ref: 1cc67b0d9400bcc0e751f2a631b2a1744859a5e4
parent: ba3bbfdb7c177a74fd18a7509d68950d41384ab5
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Tue May 12 18:53:41 EDT 2020

add vol command and dumb automixer

--- a/piper/README.md
+++ b/piper/README.md
@@ -8,9 +8,8 @@
 games/orca -u /fd/3 |[3] daw/piper /n/kick /n/ay
 ```
 
-Instances are created by piper automatically, but there is no
-automatic mixer connection yet, so still need to run `mixfs` and do
-manual `audio/pcmconv -i f32c1r44100` for each `data` entry.
+Instances are created by piper automatically, automatic mixing is
+enabled by default unless `-m` is passed.
 
 Piper accepts simple commands like so:
 
@@ -34,3 +33,5 @@
 it's `C2` *negative*.
 
 Commands can be separated with `;`.
+
+To change the global volume use `vol100` to set it to `1.0`.
--- a/piper/piper.c
+++ b/piper/piper.c
@@ -23,6 +23,7 @@
 
 static int bpm = 120;
 static float bar = 2.0;
+static float vol = 1.0;
 static QLock grouplock;
 static Group *groups;
 static int numgroups;
@@ -36,7 +37,7 @@
 static void
 usage(void)
 {
-	print("usage: %s DIR...\n", argv0);
+	print("usage: %s [-m] DIR...\n", argv0);
 	threadexitsall("usage");
 }
 
@@ -170,13 +171,49 @@
 			bpm = i;
 			bar = 240.0 / (float)bpm;
 		}
+	} else if (strncmp(s, "vol", 3) == 0) {
+		vol = atof(s+3) / 100.0;
 	}
 
 	return e;
 }
 
+enum {
+	Bufframes = 44100/100,
+};
 
+static void
+mixer(void *)
+{
+	int i, j, n;
+	s16int *pcm;
+	float *out, *x;
 
+	pcm = malloc(2*Bufframes*sizeof(*pcm));
+	out = malloc(Bufframes*sizeof(*out));
+	x = malloc(Bufframes*sizeof(*x));
+	for (;;) {
+		memset(out, 0, 44100/100*sizeof(*out));
+		qlock(&grouplock);
+		for (i = 0; i < numgroups; i++) {
+			for (j = 0; j < groups[i].numinst; j++) {
+				if (readn(groups[i].inst[j].data, x, Bufframes*sizeof(float)) < 1)
+					break;
+				for (n = 0; n < Bufframes; n++)
+					out[n] += x[n];
+			}
+		}
+		qunlock(&grouplock);
+		for (n = 0; n < Bufframes; n++) {
+			pcm[n*2+0] = pcm[n*2+1] = out[n] * 8192.0 * vol;
+		}
+		if (write(audio, pcm, 2*Bufframes*sizeof(*pcm)) < 0)
+			break;
+	}
+
+	threadexits(nil);
+}
+
 void
 threadmain(int argc, char **argv)
 {
@@ -183,9 +220,13 @@
 	char *s, t[256];
 	Synth *synth;
 	Biobuf *b;
-	int i, j, n;
+	int i, j, n, nomixer;
 
+	nomixer = 1;
 	ARGBEGIN{
+	case 'm':
+		nomixer = 1;
+		break;
 	default:
 		usage();
 	}ARGEND;
@@ -193,6 +234,9 @@
 	if (argc < 1)
 		usage();
 
+	if (!nomixer && (audio = open("/dev/audio", OWRITE)) < 0)
+		sysfatal("%r");
+
 	quotefmtinstall();
 
 	/* go through all groups */
@@ -227,6 +271,9 @@
 		if (synth == nil)
 			sysfatal("no name set in %s/metadata", argv[i]);
 	}
+
+	if (!nomixer)
+		proccreate(mixer, nil, 4096);
 
 	for (;;) {
 		if ((n = read(0, t, sizeof(t)-1)) < 1)