shithub: syro

Download patch

ref: cca5d94e30aec54182ae28141b2ca1915de9e278
parent: 1aeb17d34e45ce3d1fa4a640e399d7030d68c207
author: qwx <[email protected]>
date: Wed Oct 25 22:14:34 EDT 2023

add syroenc: write or erase individual samples

--- /dev/null
+++ b/mkfile
@@ -1,0 +1,22 @@
+</$objtype/mkfile
+BIN=/$objtype/bin/audio
+TARG=syroenc
+
+OFILES=\
+	korg_syro_comp.$O\
+	korg_syro_func.$O\
+	korg_syro_volcasample.$O\
+	volcasample_pattern.$O\
+	syro.$O\
+
+HFILES=\
+	korg_syro_comp.h\
+	korg_syro_func.h\
+	korg_syro_type.h\
+	korg_syro_volcasample.h\
+	volcasample_pattern.h\
+
+</sys/src/cmd/mkone
+
+CFLAGS=$CFLAGS -p -D__plan9__ -D__${objtype}__ -I/sys/include/npe \
+	 -D_POSIX_SOURCE
--- /dev/null
+++ b/syro.c
@@ -1,0 +1,118 @@
+#include <u.h>
+#include <libc.h>
+#include <bio.h>
+#include "korg_syro_volcasample.h"
+
+int
+parsepath(char *spec, char **path, int *id)
+{
+	int n;
+	char *p, *q;
+
+	if((p = strchr(spec, ':')) != nil && p != spec){
+		if((n = strtol(spec, &q, 10)) == 0 || q != p++)
+			goto error;
+		if(n < 0 || n >= VOLCASAMPLE_NUM_OF_SAMPLE)
+			goto error;
+		*id = n;
+	}else
+		p = spec;
+	if(*p == 0)
+		goto error;
+	*path = p;
+	return 0;
+error:
+	werrstr("invalid format");
+	return -1;
+}
+
+void
+usage(void)
+{
+	fprint(2, "usage: %s [-e] [ID:]FILE [[ID:]FILE..]\n", argv0);
+	exits("usage");
+}
+
+/* audio/wavdec < in.wav > in.pcm
+ * audio/syro *.pcm >/dev/audio → sync in
+ */
+void
+threadmain(int argc, char **argv)
+{
+	int pfd[2], type, id;
+	char *path;
+	uchar s[4], *buf;
+	s16int l, r;
+	u32int nf;
+	vlong n, off, nbuf;
+	SyroHandle sh;
+	SyroData dat[VOLCASAMPLE_NUM_OF_SAMPLE], *dp;
+	Biobuf *bf;
+
+	type = DataType_Sample_Compress;
+	ARGBEGIN{
+	case 'e': type = DataType_Sample_Erase; break;
+	case 'l': type = DataType_Sample_Liner; break;	/* uncompressed? */
+	default: usage();
+	}ARGEND
+	if(*argv == nil)
+		usage();
+	for(dp=dat; *argv!=nil && dp<dat+nelem(dat); dp++, argv++){
+		id = dp - dat;
+		if(parsepath(*argv, &path, &id) < 0)
+			sysfatal("parsepath: %r");
+		if(pipe(pfd) < 0)
+			sysfatal("pipe: %r");
+		if(rfork(RFPROC|RFFDG) == 0){
+			close(pfd[1]);
+			close(0);
+			if(open(path, OREAD) < 0)
+				sysfatal("open: %r");
+			dup(pfd[0], 1);
+			close(pfd[0]);
+			execl("/bin/audio/pcmconv", "pcmconv", "-i", "r44100c2s16",
+				"-o", "r31250c1s16", nil);
+			sysfatal("execl: %r");
+		}
+		close(pfd[0]);
+		off = 0;
+		nbuf = IOUNIT * 4;
+		if((buf = malloc(nbuf)) == nil)
+			sysfatal("malloc: %r");
+		while((n = readn(pfd[1], buf+off, nbuf-off)) > 0){
+			off += n;
+			if((buf = realloc(buf, nbuf*2)) == nil)
+				sysfatal("realloc: %r");
+			nbuf *= 2;
+		}
+		if(n < 0)
+			sysfatal("read: %r");
+		close(pfd[1]);
+		if((buf = realloc(buf, off)) == nil)
+			sysfatal("realloc: %r");
+		dp->Size = off;
+		dp->pData = buf;
+		dp->DataType = type;
+		dp->Number = id;
+		dp->Quality = 16;
+		dp->Fs = 31250;
+		dp->SampleEndian = LittleEndian;
+		fprint(2, "[%zd] %s size %lld → sample %d\n", dp-dat, path, off, id);
+	}
+	if((n = SyroVolcaSample_Start(&sh, dat, dp - dat, 0, &nf)) != Status_Success)
+		sysfatal("SyroVolcaSample_Start %lld", n);
+	fprint(2, "%ud total samples, %ud total size\n", nf, nf*4);
+	if((bf = Bfdopen(1, OWRITE)) == nil)
+		sysfatal("Bfdopen: %r");
+	while(nf-- > 0){
+		SyroVolcaSample_GetSample(sh, &l, &r);
+		s[0] = l;
+		s[1] = l >> 8;
+		s[2] = r;
+		s[3] = r >> 8;
+		Bwrite(bf, s, sizeof s);
+	}
+	Bterm(bf);
+	SyroVolcaSample_End(sh);
+	exits(nil);
+}