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)