ref: 231b9d446d132a28ef1b7f0f3dd9d2e7a9e53183
parent: 2f144ccad768088ec811f0945eb8611fbc1e0218
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Wed Mar 25 19:10:56 EDT 2020
waveform: keep the faster version and optimize it more
--- a/waveform/waveform.c
+++ b/waveform/waveform.c
@@ -17,6 +17,7 @@
float max;
int nchan;
int nframes;
+ int nvalid;
int rate;
};
@@ -53,45 +54,30 @@
}
w->samples = realloc(w->samples, n*sizeof(float));
- w->nframes = n / nchan;
+ w->nframes = w->nvalid = n / nchan;
return w;
}
-static u8int sh[65] = {
-0,
-56, 57, 58, 59, 60, 61, 62, 63,
-48, 49, 50, 51, 52, 53, 54, 55,
-40, 41, 42, 43, 44, 45, 46, 47,
-32, 33, 34, 35, 36, 37, 38, 39,
-24, 25, 26, 27, 28, 29, 30, 31,
-16, 17, 18, 19, 20, 21, 22, 23,
-8, 9, 10, 11, 12, 13, 14, 15,
-0, 1, 2, 3, 4, 5, 6, 7,
-};
-
static u64int *
rotate90128(u64int *b, int h)
{
u64int *p;
int i, j;
- u64int v;
+ u64int v, v2, i7;
p = calloc(1, 128*h/8);
for (i = 0; i < h; i++) {
- if ((v = b[i*2+1]) != 0) {
- for (j = 0; j < 64; j++) {
- if (v & (1ULL<<sh[j+1]))
- p[j*h/64 + i/64] |= 1ULL<<(63-sh[(i&63)+1]);
- }
+ i7 = 1ULL<<(i^7);
+ v = b[i*2+0];
+ v2 = b[i*2+1];
+ for (j = 1; j < 65; j++) {
+ if (v & (1ULL<<(j^56)))
+ p[(j+63)*h/64 + i/64] |= i7;
+ if (v2 & (1ULL<<(j^56)))
+ p[j*h/64 + i/64] |= i7;
}
- if ((v = b[i*2+0]) != 0) {
- for (j = 0; j < 64; j++) {
- if (v & (1ULL<<sh[j+1]))
- p[(j+64)*h/64 + i/64] |= 1ULL<<(63-sh[(i&63)+1]);
- }
- }
}
for (i = 0; i < 128*h/64; i++)
p[i] = ~p[i];
@@ -100,43 +86,45 @@
}
static int
-wvimage128(Waveform *w, int offset, int nframes, Rectangle r, float zoom)
+wvimage128(Waveform *w, int offset, Rectangle r, float zoom)
{
float m, i;
u64int *b, *p;
int x, x2, y, incy, y2;
- r = Rect(0, 0, 128, MIN(nframes-offset, Dx(r)));
+ offset = MIN(offset, w->nvalid);
+ r = Rect(0, 0, 128, Dx(r));
if (badrect(r))
return -1;
- r.max.y += 64;
- b = calloc(1, 128*Dy(r));
+ y = (Dy(r)+63) & ~63;
+ b = calloc(1, 128*y);
m = MAX(abs(w->min), abs(w->max));
m = m > 1.0f ? 63.0f/m : 63.0f;
- for (y = 0, i = offset; y < Dy(r) && i < nframes;) {
- x = m*w->samples[(int)(i*w->nchan)+0];
+ for (y = 0, i = offset; y < Dy(r) && i < w->nvalid;) {
+ x = m*w->samples[(int)i];
i += zoom;
- x2 = i < nframes ? m*w->samples[(int)(i*w->nchan)+0] : x;
- incy = x == x2 ? -999 : (x2 + x)/2;
+ x2 = i < w->nvalid ? m*w->samples[(int)i] : x;
+ incy = (x2 + x)/2;
y2 = y + 1;
do {
if (x >= 0)
- b[y*2+1] |= 1ULL<<sh[64-x];
+ b[y*2+1] |= 1ULL<<(x^7);
else
- b[y*2+0] |= 1ULL<<sh[-x];
- if (x < x2)
+ b[y*2+0] |= 1ULL<<(-x^56);
+ if (x == x2)
+ break;
+ else if (x < x2)
x++;
else if (x > x2)
x--;
- if (x == incy)
+ else if (x == incy)
y++;
- } while (x2 != x);
+ } while (1);
y = y2;
}
- y -= (y & 63);
- y += 64;
+ y = (y+63) & ~63;
p = rotate90128(b, y);
free(b);
r.max.x = y;
@@ -154,74 +142,68 @@
return 0;
}
-static int
-wvimage(Waveform *w, int offset, int nframes, Rectangle r, float zoom)
-{
- int i, yd, yi, bsz, xdone, ydone;
- float x, ox, oyi, dyi;
- u8int *b, col;
+static int offset;
+static float zoom;
- r = Rect(0, 0, Dx(r), Dy(r));
- freeimage(w->image);
- if ((w->image = allocimage(display, r, GREY8, 0, DNofill)) == nil)
- return -1;
- bsz = Dx(r)*Dy(r);
- if ((b = malloc(bsz)) == nil) {
- freeimage(w->image);
- w->image = nil;
- return -1;
- }
- memset(b, 0xff, bsz);
-
- yd = Dy(r)/2;
- if (w->max > 1.0f)
- yd /= w->max;
- yd--;
- oyi = yd;
- for (ox = x = 0, i = offset; i < offset+nframes; i++, x += 1.0f/zoom) {
- yi = yd + w->samples[i*w->nchan+0] * yd;
- if (yi >= 0 && yi < Dy(r) && x < Dx(r))
- b[(int)x + yi*Dx(r)] = 0;
- dyi = (yi < oyi ? -1.0f : 1.0f)/MAX(1.0f, zoom);
- xdone = ydone = 0;
- col = MIN(0x80, zoom*(abs(yi - oyi) + abs(x - ox)));
- while (ox < Dx(r) && (!xdone || !ydone)) {
- b[(int)ox + (int)oyi*Dx(r)] = col;
- if (ox < x)
- ox = MIN(ox + 1.0f/MAX(1.0f, zoom), x);
- else
- xdone = 1;
- if ((dyi > 0 && oyi < yi) || (dyi < 0 && oyi > yi))
- oyi = MAX(0, MIN(oyi+dyi, Dy(r)-1));
- else
- ydone = 1;
- }
- if (x >= Dx(r))
- break;
- ox = x;
- oyi = yi;
- }
-
- loadimage(w->image, r, b, bsz);
- free(b);
-
- return 0;
-}
-
static void
-redraw(Waveform *w, int offset, float zoom)
+redraw(Waveform *w)
{
Rectangle r;
+ lockdisplay(display);
r = screen->r;
r.min.y += Dy(r)/4;
r.max.y -= Dy(r)/4;
- wvimage128(w, offset, w->nframes-offset, r, zoom);
+ wvimage128(w, offset, r, zoom);
draw(screen, screen->r, display->white, nil, ZP);
draw(screen, r, w->image, nil, ZP);
flushimage(display, 1);
+ unlockdisplay(display);
}
+static Waveform *
+wvbuffer(int nsamples)
+{
+ Waveform *w;
+
+ w = calloc(1, sizeof(*w));
+ w->samples = malloc(nsamples*sizeof(float));
+ w->min = -1.0f;
+ w->max = 1.0f;
+ w->nchan = 1;
+ w->nframes = nsamples;
+ w->rate = 44100;
+ w->nvalid = 0;
+
+ return w;
+}
+
+static void
+wvproc(void *w_)
+{
+ int fi, fo, n, i;
+ Waveform *w = w_;
+ int c;
+
+ fi = 0;
+ fo = 1;
+ for (c = 0;; c++) {
+ if ((n = readn(fi, w->samples, sizeof(float)*w->nframes)) < 1)
+ break;
+ n /= sizeof(float);
+ w->nvalid = n;
+ for (i = 0; i < n; i++) {
+ w->min = MIN(-1.0f, MIN(w->min, w->samples[i]));
+ w->max = MAX(1.0f, MAX(w->max, w->samples[i]));
+ }
+ if (write(fo, w->samples, n*sizeof(float)) != n*sizeof(float))
+ break;
+ redraw(w);
+ }
+
+ threadexits(nil);
+}
+
void
threadmain(int argc, char **argv)
{
@@ -229,8 +211,7 @@
Mousectl *mctl;
Keyboardctl *kctl;
Rune key;
- float zoom;
- int offset, oldo;
+ int oldo;
Mouse m;
int oldb;
Point oldp;
@@ -243,11 +224,18 @@
USED(argc); USED(argv);
+
if ((w = wvform(0, 1, 44100)) == nil)
sysfatal("%r");
+ /*
+ if ((w = wvbuffer(1024)) == nil)
+ sysfatal("%r");
+ */
if (initdraw(nil, nil, "daw/waveform") < 0)
sysfatal("initdraw: %r");
+ display->locking = 1;
+ unlockdisplay(display);
if ((mctl = initmouse(nil, screen)) == nil)
sysfatal("initmouse: %r");
if ((kctl = initkeyboard(nil)) == nil)
@@ -257,16 +245,17 @@
a[1].c = mctl->resizec;
a[2].c = kctl->c;
- srand(time(0));
- threadsetname("daw/cfg");
+ threadsetname("daw/waveform");
zoom = 1.0f;
offset = 0;
- redraw(w, offset, zoom);
oldb = 0;
oldo = 0;
oldp = ZP;
+ //proccreate(wvproc, w, mainstacksize);
+ redraw(w);
+
for (;;) {
switch (alt(a)) {
case 0: /* mouse */
@@ -276,7 +265,7 @@
oldo = offset;
} else if (oldb == 1) {
offset = MAX(0, oldo + (oldp.x - m.xy.x)*zoom);
- redraw(w, offset, zoom);
+ redraw(w);
}
}
oldb = m.buttons;
@@ -284,7 +273,7 @@
case 1: /* resize */
getwindow(display, Refnone);
- redraw(w, offset, zoom);
+ redraw(w);
break;
case 2: /* keyboard */
@@ -293,23 +282,23 @@
goto end;
case Kleft:
offset = MAX(0, offset-MAX(8, 8*MAX(1, 1/zoom)));
- redraw(w, offset, zoom);
+ redraw(w);
break;
case Kright:
offset = MIN(w->nframes-1, offset+MAX(8, 8*MAX(1, 1/zoom)));
- redraw(w, offset, zoom);
+ redraw(w);
break;
case '-':
zoom *= 1.1f;
if (zoom > 32.0f)
zoom = 32.0f;
- redraw(w, offset, zoom);
+ redraw(w);
break;
case '+':
zoom /= 1.1f;
if (zoom < 0.01f)
zoom = 0.01f;
- redraw(w, offset, zoom);
+ redraw(w);
break;
}
break;