stew

a monorepo of some sort
Log | Files | Refs

commit 90ec56c54528056b5caa8b4ee98f11751063d94e
parent 5fc65fa54283cee6b1fc844c14cd22cedb23c2c3
Author: rpa <rpa@laika>
Date:   Mon,  6 Feb 2023 00:19:55 +0000

wave/track: refactor cli

Diffstat:
Msrc/wave/track.c | 406+++++++++++++++++++++++++++++++++++++------------------------------------------
1 file changed, 192 insertions(+), 214 deletions(-)

diff --git a/src/wave/track.c b/src/wave/track.c @@ -8,10 +8,11 @@ enum { Octave = 12, + MaxWT = 16, MaxPattern = 128, PatternLength = 64, SeqLength = 256, - ChanMax = 8, + ChanMax = 16, BufSize = 256, OutSize = 1024, WTBufSize = sizeof(s16int) * WTSize * WFSize, @@ -21,38 +22,49 @@ enum { NoteErr = 0xff, }; +typedef struct Track Track; +typedef struct Editor Editor; typedef struct Sequence Sequence; -typedef struct Pattern Pattern; +typedef struct SeqChan SeqChan; typedef struct Step Step; typedef struct Synthctl Synthctl; struct Step { uchar note; uchar volume; - s16int cmd[3]; + u16int cmd[3]; }; -struct Pattern { - int length; - Step *chan[ChanMax]; +struct Sequence { + int cn; + int n; + SeqChan *chan; }; -struct Sequence { - int chn; - int len; +struct SeqChan { + // options such as volume, pan int *p; }; +struct Track { + int bpm, spb, tps; + s16int *wt[MaxWT]; + Step ptrn[MaxPattern][PatternLength]; + Sequence seq; +}; + +struct Editor { + int pattern; + int channel; +}; + struct Synthctl { int play; - int pattern; int PC; Synth synth; Phasor phasor; }; -Step pattern[MaxPattern][PatternLength]; - char *notestr[Octave] = { "C-", "C#", "D-", "D#", "E-", "F-", "F#", "G-", "G#", "A-", @@ -61,34 +73,36 @@ char *notestr[Octave] = { int n; char cbuf[BufSize], *args[64]; -s16int *wt; + Synthctl sctl; -Sequence seq; +Track track; +Editor editor; -void usage(void); -void trackedit(void); -void loadwt(char *); -void patternedit(char *); -void printpattern(Step *); char * note2str(int); -void patternset(Step *, int, char **); int str2note(char *); +void repl(void); void threadsynth(void *); -void seqedit(void); +void usage(void); void threadmain(int argc, char **argv) { + track.bpm = 120; + track.spb = 4; + track.tps = 3; + track.wt[0] = sbrk(WTBufSize); + memset(track.wt[0], 0, WTBufSize); + sctl.synth.table[0] = track.wt[0]; + sctl.synth.mod.wtsel = 0; + ARGBEGIN{ default: usage(); } ARGEND; - wt = sbrk(WTBufSize); - memset(wt, 0, WTBufSize); - sctl.synth.table[0] = wt; - sctl.synth.mod.wtsel = 0; + if (argc > 1) usage(); + proccreate(threadsynth, &sctl, 64 * 1024); - trackedit(); + repl(); threadexitsall(nil); } @@ -99,127 +113,6 @@ usage(void) threadexitsall("usage"); } -void -trackedit(void) -{ - char *ps = "% "; - memset(cbuf, 0, BufSize); - print("%s", ps); - while (read(0, cbuf, BufSize) > 0) { - n = tokenize(cbuf, args, 64); - if (n != 0) switch (args[0][0]) { - case 's': - if (n != 1) goto err; - seqedit(); - break; - case 'p': - if (n != 2) goto err; - patternedit(args[1]); - break; - case 't': - if (n != 2) goto err; - else loadwt(args[1]); - break; - case 'h': - print("(h)elp, (q)uit, wave(t)able, (p)attern, (s)equence\n"); - break; - case 'q': - return; - case 'P': - sctl.PC = 0; - sctl.play = 1; - break; - case 'S': - sctl.play = 0; - sctl.PC = 0; - break; - default: - err: - print("?\n"); - } - print("%s", ps); - memset(cbuf, 0, BufSize); - } -} - -void -loadwt(char *path) -{ - int fd; - memset(wt, 0, WTBufSize); - fd = open(path, OREAD); - if (fd < 0) { - fprint(2, "%r\n"); - return; - } - read(fd, wt, WTBufSize); - close(fd); - print("ok\n"); -} - -void -patternedit(char *arg) -{ - long l; - Step *ptrn; - char *p; - char *ps = "p% "; - l = strtol(arg, &p, 16); - if (p == arg) { - print("?\n"); - return; - } - if ((l < 0) || (l >= MaxPattern)) { - print("?\n"); - return; - } - ptrn = pattern[l]; - memset(cbuf, 0, BufSize); - print("%s", ps); - while (read(0, cbuf, BufSize) > 0) { - n = tokenize(cbuf, args, 64); - if (n != 0) switch(args[0][0]) { - case 'p': - printpattern(ptrn); - break; - case 'h': - print("(p)rint, (h)elp, (q)uit\n"); - break; - case 'q': - return; - case 'P': - sctl.PC = 0; - sctl.play = 1; - break; - case 'S': - sctl.play = 0; - sctl.PC = 0; - break; - default: - if (n == 1) goto err; - patternset(ptrn, n, args); - break; - err: - print("?\n"); - } - print("%s", ps); - memset(cbuf, 0, BufSize); - } -} - -void -printpattern(Step *ptrn) -{ - int i; - for (i = 0; i < PatternLength; i++) { - print("%02uhhx: %s ", i, note2str(ptrn[i].note)); - if (ptrn[i].volume == 0) print(".. - "); - else print("%02uhhX - ", ptrn[i].volume -1); - print("%04uhX %04uhX %04uhX\n", - ptrn[i].cmd[0], ptrn[i].cmd[1], ptrn[i].cmd[2]); - } -} - char * note2str(int note) { @@ -234,53 +127,6 @@ note2str(int note) return buf; } -void -patternset(Step *ptrn, int n, char **args) -{ - long l; - int i, a, note; - char *p; - - /* Address */ - l = strtol(args[0], &p, 16); - if (p == args[0]) goto err; - if ((l < 0) || (l >= PatternLength)) goto err; - a = l; - - /* Note */ - args++, n--; - if (n <= 0) goto err; - if (strcmp(args[0], "-") != 0) { - note = str2note(args[0]); - if (note == NoteErr) goto err; - ptrn[a].note = note; - } - - /* Volume */ - args++, n--; - if (n <= 0) return; - if (strcmp(args[0], "-") != 0) { - if (strcmp(args[0], "..") == 0) l = 0; - else { - l = strtol(args[0], &p, 16) + 1; - if (p == args[0]) goto err; - } - if ((l < 0) || (l > 0x80)) goto err; - ptrn[a].volume = l; - } - for (i = 0; i < 3; i++) { - args++, n--; - if (n <= 0) return; - if (strcmp(args[0], "-") == 0) continue; - l = strtol(args[0], &p, 16); - if (p == args[0]) goto err; - ptrn[a].cmd[i] = l; - } - return; - err: - print("?\n"); -} - int str2note(char *str) { @@ -325,7 +171,7 @@ threadsynth(void *v) if (sctl->play != 0) { if (k >= 44100 / (12)) { - Step s = pattern[sctl->pattern][sctl->PC]; + Step s = track.ptrn[0][sctl->PC]; switch(s.note) { case NoteOff: sctl->synth.mod.freq = 0; @@ -349,33 +195,165 @@ threadsynth(void *v) } } +struct Dict { + char *name; + char *help; + void (*func)(int n, char **args); +}; + +void wrd_exit(int, char **); +void wrd_help(int, char **); +void wrd_play(int, char **); +void wrd_printpattern(int, char **); +void wrd_stop(int, char **); +void wrd_storestep(int, char **); +void wrd_wtload(int, char **); + +struct Dict dict[] = { + {"exit", " - leave program", wrd_exit}, + {"help", " - print help", wrd_help}, + {"play", nil, wrd_play}, + {"pp", " - print pattern", wrd_printpattern}, + {"ss", " step_n note [vol] [cmd1] [cmd2] [cmd3] - store step data", wrd_storestep}, + {"stop", nil, wrd_stop}, + {"wtload", " path - load wavetable", wrd_wtload}, + {nil, nil, nil}, +}; + void -seqedit(void) +repl(void) { - char *ps = "s% "; + int i; + char *ps = "% "; + memset(cbuf, 0, BufSize); + args[0] = cbuf; print("%s", ps); while (read(0, cbuf, BufSize) > 0) { n = tokenize(cbuf, args, 64); - if (n != 0) switch (args[0][0]) { - case 'h': - print("(h)elp, (q)uit\n"); - break; - case 'q': - return; - case 'P': - sctl.PC = 0; - sctl.play = 1; - break; - case 'S': - sctl.play = 0; - sctl.PC = 0; - break; - default: - err: - print("?\n"); + for (i = 0; dict[i].name != nil; i++) { + if (strcmp(dict[i].name, args[0]) == 0) { + dict[i].func(n, args); + break; + } } + if (dict[i].name == nil) print("?\n"); print("%s", ps); memset(cbuf, 0, BufSize); } } + +void +wrd_help(int, char **) +{ + int i; + for (i = 0; dict[i].name != nil; i++) { + print("%s", dict[i].name); + if (dict[i].help != nil) print("%s", dict[i].help); + print("\n"); + } +} + +void +wrd_exit(int, char **) +{ + threadexitsall(nil); +} + +void +wrd_printpattern(int, char **) +{ + Step *ptrn = track.ptrn[editor.pattern]; + + int i; + print("Pattern %02uhhx:\n", editor.pattern); + for (i = 0; i < PatternLength; i++) { + print("%02uhhx: %s ", i, note2str(ptrn[i].note)); + if (ptrn[i].volume == 0) print(".. - "); + else print("%02uhhX - ", ptrn[i].volume - 1); + print("%04uhX %04uhX %04uhX\n", + ptrn[i].cmd[0], ptrn[i].cmd[1], ptrn[i].cmd[2]); + } +} + +void +wrd_wtload(int n, char **args) +{ + if (n != 2) { + print("?\n"); + return; + } + char *path = args[1]; + int fd; + memset(track.wt[0], 0, WTBufSize); + fd = open(path, OREAD); + if (fd < 0) { + fprint(2, "%r\n"); + print("?\n"); + return; + } + read(fd, track.wt[0], WTBufSize); + close(fd); + print("ok\n"); +} + +void wrd_play(int, char **) +{ + sctl.play = 1; +} + +void wrd_stop(int, char **) +{ + sctl.play = 0; + sctl.PC = 0; +} + +void +wrd_storestep(int n, char **args) +{ + long l; + int i, a, note; + char *p; + Step *ptrn = track.ptrn[editor.pattern]; + + /* Address */ + args++, n--; + if (n <= 0) goto err; + l = strtol(args[0], &p, 16); + if (p == args[0]) goto err; + if ((l < 0) || (l >= PatternLength)) goto err; + a = l; + + /* Note */ + args++, n--; + if (n <= 0) goto err; + if (strcmp(args[0], "-") != 0) { + note = str2note(args[0]); + if (note == NoteErr) goto err; + ptrn[a].note = note; + } + + /* Volume */ + args++, n--; + if (n <= 0) return; + if (strcmp(args[0], "-") != 0) { + if (strcmp(args[0], "..") == 0) l = 0; + else { + l = strtol(args[0], &p, 16) + 1; + if (p == args[0]) goto err; + } + if ((l < 0) || (l > 0x80)) goto err; + ptrn[a].volume = l; + } + for (i = 0; i < 3; i++) { + args++, n--; + if (n <= 0) return; + if (strcmp(args[0], "-") == 0) continue; + l = strtol(args[0], &p, 16); + if (p == args[0]) goto err; + ptrn[a].cmd[i] = l; + } + return; + err: + print("?\n"); +}