ref: 4ae000bc715d98584e88082897ed9355e195b522
dir: /reverb.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <event.h> #include <thread.h> #define RATE 44100 int rate; double decay; int delay; Point c; void reverb(unsigned char *buf, short *tmp, int len) { short l, r; int i; int dur = delay; for(i = 0; i < len; i += 4){ l = buf[i+0] | (buf[i+1] << 8); r = buf[i+2] | (buf[i+3] << 8); l += tmp[(i/2+0+dur)%rate] * decay; r += tmp[(i/2+1+dur)%rate] * decay; tmp[(i/2+0)%rate] = l; tmp[(i/2+1)%rate] = r; buf[i+0] = l & 0xFF; buf[i+1] = (l >> 8) & 0xFF; buf[i+2] = r & 0xFF; buf[i+3] = (r >> 8) & 0xFF; } } void doproc(void *unused) { unsigned char *buf = malloc(rate * 4); short *tmp = malloc(rate * 2); int r; memset(tmp, 0, rate * 2); while((r = read(0, buf, rate * 4)) > 0){ reverb(buf, tmp, r); write(1, buf, r); } } void redraw(Image *screen) { int x = delay / 8; draw(screen, screen->r, display->white, nil, ZP); draw(screen, Rect(screen->r.min.x + x - 1, screen->r.min.y, screen->r.min.x + x + 1, screen->r.max.y - Dy(screen->r)/2), display->black, nil, ZP); x = decay * Dx(screen->r); draw(screen, Rect(screen->r.min.x + x - 1, screen->r.min.y + Dy(screen->r)/2, screen->r.min.x + x + 1, screen->r.max.y), display->black, nil, ZP); } void eresized(int new) { if(new && getwindow(display, Refnone) < 0) fprint(2,"can't reattach to window"); c = divpt(subpt(screen->r.max, screen->r.min), 2); redraw(screen); } void threadmain(int argc, char **argv) { Mouse m; Point xy; rate = RATE; delay = 0; decay = 0.0; if (argc > 1) rate = atoi(argv[1]); if(initdraw(0, 0, "reverb") < 0) sysfatal("initdraw: %r"); einit(Emouse); eresized(0); proccreate(doproc, nil, mainstacksize); for(;;m = emouse()){ if(m.buttons & 1){ xy = subpt(m.xy, screen->r.min); if (xy.y > c.y) decay = xy.x / (double)Dx(screen->r); else delay = xy.x * 8; redraw(screen); } } }