ref: aa05c704e7f080980bfd3ac3483d3660b7cbc29e
parent: 6544a8049f57f231de744df73403f68428bbbe1f
author: Sigrid Haflínudóttir <ftrvxmtrx@gmail.com>
date: Tue Mar 24 13:38:45 EDT 2020
waveform: faster version
--- a/waveform/waveform.c
+++ b/waveform/waveform.c
@@ -58,7 +58,101 @@
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;
+
+ 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]);
+ }
+ }
+ 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];
+
+ return p;
+}
+
static int
+wvimage128(Waveform *w, int offset, int nframes, 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)));
+ if (badrect(r))
+ return -1;
+ r.max.y += 64;
+ b = calloc(1, 128*Dy(r));
+ 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];
+ i += zoom;
+ x2 = i < nframes ? m*w->samples[(int)(i*w->nchan)+0] : x;
+ incy = x == x2 ? -999 : (x2 + x)/2;
+ y2 = y + 1;
+ do {
+ if (x >= 0)
+ b[y*2+1] |= 1ULL<<sh[64-x];
+ else
+ b[y*2+0] |= 1ULL<<sh[-x];
+ if (x < x2)
+ x++;
+ else if (x > x2)
+ x--;
+ if (x == incy)
+ y++;
+ } while (x2 != x);
+ y = y2;
+ }
+
+ y -= (y & 63);
+ y += 64;
+ p = rotate90128(b, y);
+ free(b);
+ r.max.x = y;
+ r.max.y = 128;
+ freeimage(w->image);
+ if ((w->image = allocimage(display, r, GREY1, 0, DNofill)) == nil)
+ return -1;
+
+ if (loadimage(w->image, r, (void*)p, 128*y) < 0)
+ fprint(2, "failed: %r\n");
+ free(p);
+
+ return 0;
+}
+
+static int
wvimage(Waveform *w, int offset, int nframes, Rectangle r, float zoom)
{
int i, yd, yi, bsz, xdone, ydone;
@@ -106,7 +200,10 @@
oyi = yi;
}
- return loadimage(w->image, r, b, bsz);
+ loadimage(w->image, r, b, bsz);
+ free(b);
+
+ return 0;
}
static void
@@ -117,9 +214,8 @@
r = screen->r;
r.min.y += Dy(r)/4;
r.max.y -= Dy(r)/4;
- if (wvimage(w, offset, w->nframes-offset, r, zoom) < 0)
- sysfatal("couldn't create image: %r");
-
+ wvimage128(w, offset, w->nframes-offset, r, zoom);
+ draw(screen, screen->r, display->white, nil, ZP);
draw(screen, r, w->image, nil, ZP);
flushimage(display, 1);
}
@@ -132,8 +228,10 @@
Keyboardctl *kctl;
Rune key;
float zoom;
- int offset;
+ int offset, oldo;
Mouse m;
+ int oldb;
+ Point oldp;
Alt a[] = {
{ nil, &m, CHANRCV },
{ nil, nil, CHANRCV },
@@ -163,9 +261,23 @@
zoom = 1.0f;
offset = 0;
redraw(w, offset, zoom);
+ oldb = 0;
+ oldo = 0;
+ oldp = ZP;
+
for (;;) {
switch (alt(a)) {
case 0: /* mouse */
+ if (m.buttons == 1) {
+ if (oldb == 0) {
+ oldp = m.xy;
+ oldo = offset;
+ } else if (oldb == 1) {
+ offset = MAX(0, oldo + (oldp.x - m.xy.x)*zoom);
+ redraw(w, offset, zoom);
+ }
+ }
+ oldb = m.buttons;
break;
case 1: /* resize */
@@ -186,13 +298,13 @@
redraw(w, offset, zoom);
break;
case '-':
- zoom *= 2.0f;
+ zoom *= 1.1f;
if (zoom > 32.0f)
zoom = 32.0f;
redraw(w, offset, zoom);
break;
case '+':
- zoom /= 2.0f;
+ zoom /= 1.1f;
if (zoom < 0.01f)
zoom = 0.01f;
redraw(w, offset, zoom);