shithub: neindaw

Download patch

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;