shithub: neindaw

Download patch

ref: aa05c704e7f080980bfd3ac3483d3660b7cbc29e
parent: 6544a8049f57f231de744df73403f68428bbbe1f
author: Sigrid Haflínudóttir <[email protected]>
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);