stew

a monorepo of some sort
Log | Files | Refs

commit 34b341144e9e63e1ad92d5937c32cd45669d9471
parent 9cd0007204972fc84ee36857ae82e1c4eed72749
Author: rpa <rpa@laika>
Date:   Mon, 12 Dec 2022 01:28:00 +0000

mu: trk improvements

Diffstat:
Msrc/mu/mubox.c | 7+++++--
Msrc/mu/tplay | 2+-
Msrc/mu/trk.c | 200++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
3 files changed, 158 insertions(+), 51 deletions(-)

diff --git a/src/mu/mubox.c b/src/mu/mubox.c @@ -1,7 +1,10 @@ -/* simplistic audio synth, +/* + Primitive audio synth + - 6-voice polyphony, 1 noise channel, 1 kick channel - only triangle osc, only freq, vol and decay ctls - - controlled via stdin */ + - controlled via stdin +*/ #include <u.h> #include <libc.h> diff --git a/src/mu/tplay b/src/mu/tplay @@ -1,3 +1,3 @@ #!/bin/rc rfork e -6.trk | 6.mubox -r > /dev/audio +6.trk $* | 6.mubox -r > /dev/audio diff --git a/src/mu/trk.c b/src/mu/trk.c @@ -1,72 +1,176 @@ -/* read lines from stdin and print them at specified rate */ +/* + Primitive sequencer / music-tracker + + reads lines from stdin and prints them at controllable rate +*/ #include <u.h> #include <libc.h> #include <bio.h> typedef struct List List; + struct List { void *v; List *next; }; -List start; +List *list; +char *file; +vlong t, dt; long bpm = 120, steps = 1; -vlong dt; -int -cmd(char *s) +List * loadlist(char *); +void clearlist(List *); + +void pause(void); + +#define CMD(X) void X(List **, int , char **) +CMD(cmdbpm); +CMD(cmdpause); +CMD(cmdjump); +CMD(cmdret); +CMD(cmdreload); + +struct Cmds { + char *name; + void (*func)(List **, int, char **); +} cmds[] = { + { "#", nil }, /* comment */ + { ".bpm", cmdbpm }, /* update bpm to new value */ + { "----", cmdpause }, + { ".rld", cmdreload }, /* reload file and start from the beginning */ +}; + +void +cmdbpm(List **, int n, char **args) { - if (s[0] == '.') { - int argc; char *argv[32]; - argc = tokenize(s, argv, 32); - if (strcmp(argv[0], ".") == 0) { - int i; - for (i = 0; i < argc; i++) print("%s ", argv[i]); - print("\n"); - return 1; - } - if (strcmp(argv[0], ".bpm") == 0) { - long x = 0; - if (argc > 1) x = strtol(argv[1], nil, 10); - if (x != 0) bpm = x; - if (argc > 2) x = strtol(argv[2], nil, 10); - if (x != 0) steps = x; - dt = 60000000000 / (bpm * steps); - return 0; - } - if (strcmp(argv[0], ".end") == 0) { - - } - } else if (s[0] == ':') return 0; - print("%s\n", s); - return 0; + switch(n){ + case 0: /* what */ + case 1: + fprint(2, ".bpm: not enough arguments\n"); + break; + default: + fprint(2, ".bpm: too much arguments\n"); + case 2: + case 3: + bpm = strtol(args[1], nil, 10); + if (n == 3) steps = strtol(args[2], nil, 10); + } + if (bpm <= 0) { + fprint(2, "bpm is nonsence (%ld), restoring to 120\n", bpm); + bpm = 120; + } + if (steps <= 0) { + fprint(2, "steps is nonsence (%ld), restoring to 1\n", steps); + steps = 1; + } + dt = 60000000000 / (bpm * steps); } void -main(void) +cmdpause(List **, int, char **) { - Biobuf *in = Bfdopen(0, OREAD); - vlong t = nsec(); - List *lp = &start; + pause(); +} + +void +cmdreload(List **lp, int, char **) +{ + clearlist(list); + list = loadlist(file); + *lp = list; +} + +List * +loadlist(char *file) +{ + List start, *lp; char *s; - dt = 60000000000 / (bpm * steps); - while ((s = Brdstr(in, '\n', 1)) != nil) { - while((s[0] == ' ') || (s[0] == '\t')) s++; - if ((s[0] == '\0') || (s[0] == '#')) { - free(s); - } else { - lp->v = s; - lp->next = sbrk(sizeof(List)); - lp = lp->next; - lp->next = nil, lp->v = nil; - } + Biobuf *in = Bopen(file, OREAD); + if (in == nil) sysfatal("%r"); + lp = &start; + while((s = Brdstr(in, '\n', 1)) != nil) { + lp->next = mallocz(sizeof(List), 1); + lp = lp->next; + lp->v = s; } - for (lp = &start, s = lp->v; s!= nil; lp = lp->next, s = lp->v) { - if (cmd(s) != 0) { - t += dt; - sleep((t - nsec()) / 1000000); + Bterm(in); + return start.next; +} + +void +clearlist(List *lp) +{ + while (lp != nil) { + free(lp->v); + List *next = lp->next; + free(lp); + lp = next; + } +} + +void +pause(void) +{ + t += dt; + sleep((t - nsec()) / 1000000); +} + +void +trkstep(List **lp) +{ + char *s = (char *)(*lp)->v; + *lp = (*lp)->next; + int i; + for (i = 0; i < sizeof(cmds) / sizeof(struct Cmds); i++) { + if (strlen(s) == 0) return; + if (strncmp(s, cmds[i].name, strlen(cmds[i].name)) == 0) { + if (cmds[i].func != nil) { + char *dup = strdup(s); + char *args[64]; + int n = tokenize(dup, args, 64); + cmds[i].func(lp, n, args); + free(dup); + } + return; } } + if (i >= sizeof(cmds) / sizeof(struct Cmds)) { + print("%s\n", s); + pause(); + } +} + +void +trkexec(List *start) +{ + List *lp = start; + while (lp != nil) trkstep(&lp); +} + +void +usage(void) +{ + fprint(2, "usage: %s file\n", argv0); + exits("usage"); +} + +void +main(int argc, char **argv) +{ + ARGBEGIN { + default: + usage(); + } ARGEND; + if (argc != 1) usage(); + file = argv[0]; + list = loadlist(file); + + t = nsec(); + dt = 60000000000 / (bpm * steps); + + trkexec(list); + clearlist(list); }