ref: d7a085bcf19f164fbd667db398ad698a9fca3ec4
dir: /waves.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <event.h> #include <thread.h> #define ROOT2 1.05946309436 #define RATE 44100; Image *back; int rate; double tones[16]; double *buf[2]; double ab = 0.0; Rectangle A; Rectangle B; void redraw(Image *screen) { Rectangle r, dot, b; int dur = rate/4; int w, h; int i; draw(screen, screen->r, back, nil, ZP); // balance r = screen->r; r.max.y = r.min.y + 30; draw(screen, insetrect(r, 3), display->white, nil, ZP); r.min.x += Dx(screen->r) * (ab + 1.0)/2.0 - 1; r.max.x = screen->r.min.x + Dx(screen->r) * (ab + 1.0)/2.0 + 1; draw(screen, r, display->black, nil, ZP); // A r = screen->r; r.min.y += 30; r.max.y -= 30; r.max.x -= Dx(screen->r)/2; A = insetrect(r, 3); w = Dx(A); h = Dy(A); draw(screen, A, display->white, nil, ZP); for(i = 0; i < dur; i++){ dot = rectaddpt(Rect((int)(((double)i/dur) * w), (int)(((buf[0][i] + 1.0)/2.0) * h), (int)(((double)(i+1)/dur) * w), (int)(((buf[0][i] + 1.0)/2.0) * h) + 1), A.min); draw(screen, dot, display->black, nil, ZP); } for(i = 0; i < 3; i++){ r = screen->r; r.min.y = r.max.y - 30; r.max.x = r.min.x + Dx(r)/6; b = insetrect(rectaddpt(r, Pt(Dx(r)*i, 0)), 3); draw(screen, b, display->white, nil, ZP); } // B r = screen->r; r.min.y += 30; r.max.y -= 30; r.min.x += Dx(screen->r)/2; B = insetrect(r, 3); w = Dx(B); h = Dy(B); draw(screen, B, display->white, nil, ZP); for(i = 0; i < dur; i++){ dot = rectaddpt(Rect((int)(((double)i/dur) * w), (int)(((buf[1][i] + 1.0)/2.0) * h), (int)(((double)(i+1)/dur) * w), (int)(((buf[1][i] + 1.0)/2.0) * h) + 1), B.min); draw(screen, dot, display->black, nil, ZP); } for(i = 0; i < 3; i++){ r = screen->r; r.min.y = r.max.y - 30; r.max.x = r.min.x + Dx(r)/6; b = insetrect(rectaddpt(r, Pt(Dx(r)*(i+3), 0)), 3); draw(screen, b, display->white, nil, ZP); } flushimage(display, 1); } void eresized(int new) { if(new && getwindow(display, Refnone) < 0) fprint(2,"can't reattach to window"); redraw(screen); } void audioproc(void *unused) { int i, j, step, dur; double tone, sum; short out; char *buffer; char str[6*16+2]; int k; int fd = open("/mnt/monome/buttons", OREAD); if (fd < 0) sysfatal("open /mnt/monome/buttons: %r"); dur = rate/4; buffer = malloc(dur * 2); for(;;){ for(j = 0; j < 16; j++){ if (readn(fd, str, 6*16+2) != (6*16+2)) sysfatal("readn /mnt/monome/buttons: %r"); k = atoi(&str[j*6]); for(step = 0; step < dur; step++){ sum = 0.0; for(i = 0; i < 16; i++){ if(k & (1<<i)){ tone = tones[16 - i - 1]; sum += buf[0][(int)(step*(tone/4)) % dur] * (ab - 1.0) * -0.5; sum += buf[1][(int)(step*(tone/4)) % dur] * (ab + 1.0) * 0.5; } } out = (short)(sum * 2047.0 * pow(0.9999, step/10.0)); buffer[step*2+0] = out & 0xFF; buffer[step*2+1] = (out >> 8) & 0xFF; } write(1, buffer, dur*2); } } free(buffer); } void threadmain(int argc, char **argv) { int i, j; int dur; Mouse m; Point xy; int dx; rate = RATE; if(argc > 1) rate = atoi(argv[1]); dur = rate/4; if(initdraw(0, 0, "waves") < 0) sysfatal("initdraw: %r"); einit(Emouse); back = allocimage(display, Rect(0,0,1,1), CMAP8, 1, 0x777777FF); if(back == nil) sysfatal("allocimage: %r"); buf[0] = malloc(dur * sizeof(double)); buf[1] = malloc(dur * sizeof(double)); for(i = 0; i < dur; i++) buf[0][i] = buf[1][i] = cos(((double)i/dur)*2*PI); for(i = 0; i < 16; i++){ tones[i] = 220.0; for(j = 0; j < i; j++) tones[i] *= ROOT2; } eresized(0); proccreate(audioproc, nil, 8192*8); for(;;m = emouse()){ if(m.buttons & 1){ xy = subpt(m.xy, screen->r.min); if (xy.y < 30) { ab = (double)xy.x / Dx(screen->r); ab -= 0.5; ab *= 2.0; } else if ((screen->r.max.y - m.xy.y) < 30){ dx = Dx(screen->r)/6; if (xy.x < dx) for(i = 0; i < dur; i++) buf[0][i] = cos(((double)i/dur)*2*PI); else if (xy.x < 2*dx) { for(i = 0; i < dur; i++) buf[0][i] = 1.0; for(i = dur/4; i < 3*dur/4; i++) buf[0][i] = -1.0; } else if (xy.x < 3*dx) { for(i = 0; i < dur/2; i++) buf[0][i] = -((double)i/(dur/2)*2.0-1.0); for(i = dur/2; i < dur; i++) buf[0][i] = -(0.75-((double)i/dur))*4.0; } else if (xy.x < 4*dx) for(i = 0; i < dur; i++) buf[1][i] = cos(((double)i/dur)*2*PI); else if (xy.x < 5*dx) { for(i = 0; i < dur; i++) buf[1][i] = 1.0; for(i = dur/4; i < 3*dur/4; i++) buf[1][i] = -1.0; } else if (xy.x < 6*dx) { for(i = 0; i < dur/2; i++) buf[1][i] = -((double)i/(dur/2)*2.0-1.0); for(i = dur/2; i < dur; i++) buf[1][i] = -(0.75-((double)i/dur))*4.0; } } else if(ptinrect(m.xy, A)) { xy = subpt(m.xy, A.min); dx = Dx(A); buf[0][(int)(((double)xy.x/dx)*dur)] = (((double)xy.y/Dy(A))-0.5)*2.0; } else if(ptinrect(m.xy, B)) { xy = subpt(m.xy, B.min); dx = Dx(B); buf[1][(int)(((double)xy.x/dx)*dur)] = (((double)xy.y/Dy(B))-0.5)*2.0; } redraw(screen); } } }