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);
+}