#include #include #include #include #include "abuf.h" #include "guic.h" enum { Sine, Saw, Square, } type; enum{ Gfreq, Gpwm, Gtype, Gexit, }; char *keywords[] = { "freq", "pwm", "type", "exit", 0, }; typedef struct Rosc Rosc; struct Rosc { double ph, inc, pww; double f, pw; int type; }; double roscnext(Rosc *osc) { double s; if(osc->ph >= 1.0 || osc->inc == 0.0){ osc->inc = osc->f / SRATE; osc->ph = fmod(osc->ph, 1); osc->pww = osc->pw; } switch(osc->type){ case Sine: s = sin(osc->ph * 2 * PI); break; case Saw: s = 2*osc->ph - 1; break; case Square: s = osc->ph > osc->pww ? 1 : -1; break; } osc->ph += osc->inc; return s; } typedef struct Blit Blit; struct Blit { int type, ptype; double p, ppw, inc, n, sum, y0; double f, pw; int reset; double (*next)(void *); }; double blitval(double t, double M) { double s; if(fmod(t, 1) < 0.000001 || fmod(t, 1) > 0.999999) s = M*cos(M*PI*t)/cos(PI*t); else s = sin(M*PI*t)/sin(PI*t); return s; } double blitnext(void *arg) { Blit *osc = arg; double y1, m, p; if(osc->p >= 1.0 || osc->inc == 0.0){ osc->inc = osc->f / SRATE; osc->n = floor(SRATE / 2 / osc->f); osc->p = fmod(osc->p, 1); osc->ppw = osc->pw; osc->ptype = osc->type; if(osc->reset){ m = 2 * osc->n + 1; osc->p = 0; osc->sum = 0; osc->reset = 0; if(osc->ptype == Saw) osc->y0 = 1 - blitval(0, m); else osc->y0 = blitval(0, m) - blitval(osc->pw, m); } } m = 2 * osc->n + 1; p = osc->p + osc->inc; if(osc->ptype == Saw) y1 = 1 - blitval(p, m); else y1 = blitval(p, m) - blitval(p + osc->pw, m); osc->sum += (osc->y0 + y1) * osc->inc / 2; osc->y0 = y1; osc->p = p; return osc->sum; } typedef struct Thir Thir; enum{ Thirbuf = 64*1024, }; struct Thir { int type, ptype; int n, d; double f, pw; int reset; double (*next)(void *); double a; double b[Thirbuf]; double y1; double itg; }; double thirnext(void *arg) { Thir *osc = arg; double d, sd, fd; int n; double x0, x1, y0; if(osc->reset){ d = SRATE / osc->f; sd = floor(d); fd = d - sd; if(fd < 0.418){ fd++; sd--; } osc->d = sd; osc->a = (1 - fd)/(1 + fd); osc->n = 0; osc->y1 = 0; memset(osc->b, 0, sizeof(osc->b)); osc->b[1] = 1; osc->reset = 0; osc->itg = 0; fprint(2, "fd=%f, sd=%f\n", fd, sd); } n = osc->n; x1 = osc->b[n % Thirbuf]; x0 = osc->b[(n + 1) % Thirbuf]; y0 = osc->a * x0 + x1 - osc->a * osc->y1; if(y0 > 1){ fprint(2, "clip+\n"); y0 = 1; }else if(y0 < -1){ fprint(2, "clip-1\n"); y0 = -1; } osc->b[(n + osc->d + 1) % Thirbuf] = -y0; osc->n = n + 1; osc->y1 = y0; osc->itg += y0; return osc->itg; } //Blit osc = { .next = blitnext }; Thir osc = { .next = thirnext }; void threadmain(int argc, char *argv[]) { Abuf ab; Event ev; double s; int t; if(argv[1] != 0 && isdigit(argv[1][0])){ osc.f = miditofreq(atoi(argv[1])); }else{ guistart(argv[1]); osc.f = miditofreq(13); } osc.reset = 1; osc.pw = 0.3; ainit(&ab, 1); for(t=0;;t++){ while(nbrecv(guichan, &ev) == 1){ switch(ev.k){ case Gtype: osc.type = ev.n; break; case Gfreq: osc.f = miditofreq(ev.n); break; case Gpwm: osc.pw = ev.n / 128.0; break; case Gexit: threadexitsall(0); } osc.reset = 1; } s = osc.next(&osc); aputd(&ab, s / 2); } }