stew

a monorepo of some sort
Log | Files | Refs

commit fd1313e58cce4cf2020ff9d53b130a9c9d4c4984
parent 78c02efce9ae30194bcbf675e946ba48f5500def
Author: rpa <rpa@laika>
Date:   Fri,  6 Jan 2023 23:55:30 +0000

wave: start working on instrument editor

Diffstat:
Asrc/wave/inst.c | 230+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/wave/mkfile | 2+-
Msrc/wave/piano.c | 1-
Asrc/wave/smoke.c | 23+++++++++++++++++++++++
4 files changed, 254 insertions(+), 2 deletions(-)

diff --git a/src/wave/inst.c b/src/wave/inst.c @@ -0,0 +1,230 @@ +/* + Visual instrument editor + loads/modifies/saves envelopes + allows previewing settings by playing notes +*/ + +#include <u.h> +#include <libc.h> +#include <thread.h> +#include <draw.h> +#include <mouse.h> +#include <keyboard.h> + +#include "wavetable.h" + +enum { + NameBufSize = 256, + OutBufSize = 882, +}; + +typedef struct Widget Widget; +typedef struct UI UI; + +struct UI { + Mousectl *mctl; + Mouse mv; + int rv[2]; + Keyboardctl *kctl; + Rune kv; + Widget *hot; + Widget **wp; +}; + +struct Widget { + Rectangle r; + Image **palette; + void *aux; + void (*draw)(void *); + void (*activate)(UI *, void *); +}; + +struct wavetable { + s16int *p; + char fname[NameBufSize]; +}; + +struct synth { + Inst inst; +}; + +void usage(void); +void threadsynth(void *); +void handlemouse(UI *); +void wtdraw(void *); +void wtactivate(UI *, void *); +int loadwavetable(void *, char *); +void rcalc(UI *); +Widget * findhot(UI *); + +void +threadmain(int argc, char **argv) +{ + struct synth synth; + struct wavetable wavetable; + Image *palette[8]; + UI UI; + Widget wt; + + ARGBEGIN{ + default: + usage(); + } ARGEND + if (argc != 1) usage(); + + wavetable.p = mallocz(sizeof(s16int) * WFSize * WTSize, 1); + if (loadwavetable(wavetable.p, argv[0]) != 0) { + fprint(2, "loading %s\n", argv[0]); + snprint(wavetable.fname, NameBufSize, "%s", argv[0]); + } else wavetable.fname[0] = '\0'; + + if (initdraw(nil, nil, "inst") == 0) sysfatal("%r"); + if ((UI.mctl = initmouse(nil, nil)) == nil) sysfatal("%r"); + if ((UI.kctl = initkeyboard(nil)) == nil) sysfatal("%r"); + proccreate(threadsynth, &synth, 64 * 1024); + + palette[0] = allocimage(display, Rect(0,0,1,1), XRGB32, 1, 0x7f3f00ff); + palette[1] = allocimage(display, Rect(0,0,1,1), XRGB32, 1, 0xffff00ff); + + wt.palette = palette; + wt.aux = &wavetable; + wt.draw = wtdraw; + wt.activate = wtactivate; + + Widget *wp[] = {&wt, nil}; + UI.wp = wp; + + rcalc(&UI); + + draw(screen, screen->r, display->black, nil, ZP); + wt.draw(&wt); + flushimage(display, 1); + + Alt alts[] = { + {UI.mctl->resizec, UI.rv, CHANRCV}, + {UI.mctl->c, &(UI.mv), CHANRCV}, + {UI.kctl->c, &(UI.kv), CHANRCV}, + {nil, nil, CHANEND}, + }; + + for (;;) switch (alt(alts)) { + case 0: /* resize */ + if(getwindow(display, Refnone) < 0) sysfatal("resize failed: %r"); + draw(screen, screen->r, display->black, nil, ZP); + rcalc(&UI); + wt.draw(&wt); + flushimage(display, 1); + break; + case 1: /* mouse */ + handlemouse(&UI); + break; + case 2: /* keyboard */ + break; + } +} + +void +usage(void) +{ + fprint(2, "usage: %s\n", argv0); + threadexitsall("usage"); +} + +void +threadsynth(void *arg) +{ + struct synth *synth; + int audio; + s16int *buf; + synth = (struct synth *) arg; + audio = open("/dev/audio", OWRITE); + if (audio < 0) { + fprint(2, "threadsynth: %r\n"); + return; + } + buf = mallocz(OutBufSize, 1); + while (write(audio, buf, OutBufSize) > 0) { + int i; + for (i = 0; i < OutBufSize - 1; i += 2) { + // TODO: insert synth code here + buf[i] = 0; + buf[i+1] = buf[i]; + } + } + free(buf); +} + +void +handlemouse(UI *UI) +{ + + enum { MFree, }; + static state = MFree; + switch (state) { + case MFree: + UI->hot = findhot(UI); + if ((UI->mv.buttons != 0) && (UI->hot != nil)) { + UI->hot->activate(UI, UI->hot); + UI->hot->draw(UI->hot); + flushimage(display, 1); + } + if (UI->mv.buttons == 4) threadexitsall(nil); + break; + } +} + +void +wtdraw(void *arg) +{ + Widget *w = (Widget *) arg; + struct wavetable *wt = (struct wavetable *) w->aux; + char buf[256]; + snprint(buf, NameBufSize, "wt: %s", wt->fname); + draw(screen, w->r, w->palette[0], nil, ZP); + string(screen, w->r.min, w->palette[1], ZP, font, buf); +} + +void +wtactivate(UI *UI, void *arg) +{ + Widget *w = (Widget *) arg; + struct wavetable *wt = (struct wavetable *) w->aux; + if (enter("wt:", wt->fname, NameBufSize, UI->mctl, UI->kctl, nil) != 0) { + loadwavetable(wt->p, wt->fname); + } +} + +int +loadwavetable(void *p, char *f) +{ + int fd; + long n; + fd = open(f, OREAD); + if (fd < 0) { + fprint(2, "%r\n"); + return 0; + }; + n = read(fd, p, sizeof(s16int) * WFSize * WTSize); + close(fd); + return n > 0; +} + +void +rcalc(UI *UI) +{ + Point min = screen->r.min; + Point max = screen->r.max; + Rectangle r = Rpt(min, Pt(max.x, min.y + font->height)); + UI->wp[0]->r = r; +} + +Widget * +findhot(UI *UI) +{ + Widget **w = UI->wp; + Point xy = UI->mv.xy; + for (; *w != nil; w++) { + if (ptinrect(xy, (*w)->r) != 0) return *w; + } + return nil; +} diff --git a/src/wave/mkfile b/src/wave/mkfile @@ -1,6 +1,6 @@ </$objtype/mkfile -TARG=draw loop fade piano sampler harm smoke +TARG=draw loop fade piano sampler harm smoke inst BIN=/$objtype/bin HFILES=util.h wavetable.h OFILES=wavetable.$O diff --git a/src/wave/piano.c b/src/wave/piano.c @@ -99,4 +99,3 @@ main(int argc, char **argv) } } } - diff --git a/src/wave/smoke.c b/src/wave/smoke.c @@ -0,0 +1,23 @@ +/* crashalot */ +#include <u.h> +#include <libc.h> +#include "wavetable.h" + +void +main(void) +{ + int i, n, t; + double x; + Env e; + e.n = 3; + e.val[0] = 15; + e.val[1] = 5; + e.val[2] = 0; + e.len[0] = 10; + e.len[1] = 10; + for (i = 0; i < 25; i++) { + x = envget(&e, &n, &t, 0); + print("[%d %d] %f\n", n, t, x); + t++; + } +}