shithub: pplay

Download patch

ref: e7846afe1d81e280898bb40b0966ec0a24b321b7
parent: 443ab2b67e807ff1c4f864feb80229ecd7813fe5
author: qwx <qwx@sciops.net>
date: Wed Nov 30 02:19:06 EST 2022

drawsamp: don't memcpy everything, just fetch chunk slices as intended

--- a/cmd.c
+++ b/cmd.c
@@ -256,6 +256,32 @@
 }
 
 uchar *
+getslice(Dot *d, usize n, usize *sz)
+{
+	usize Δbuf, Δloop, off;
+	Chunk *c;
+
+	if(d->pos >= totalsz){
+		*sz = 0;
+		return nil;
+	}
+	c = p2c(d->pos, &off);
+	Δloop = d->to.pos - d->pos;
+	Δbuf = c->bufsz - off;
+	if(n < Δloop && n < Δbuf){
+		*sz = n;
+		d->pos += n;
+	}else if(Δloop <= Δbuf){
+		*sz = Δloop;
+		d->pos = d->from.pos;
+	}else{
+		*sz = Δbuf;
+		d->pos += Δbuf;
+	}
+	return c->buf + off;
+}
+
+uchar *
 getbuf(Dot d, usize n, uchar *scratch, usize *boff)
 {
 	uchar *bp, *p;
--- a/draw.c
+++ b/draw.c
@@ -23,8 +23,6 @@
 static int bgscalyl, bgscalyr, bgscalf;
 static Channel *drawc;
 static usize T;
-static uchar *sbuf;
-static usize sbufsz;
 static int sampwidth = 1;
 static double zoom = 1.0;
 
@@ -67,7 +65,7 @@
 drawsamps(void*)
 {
 	int x, lmin, lmax, rmin, rmax;
-	usize n, m;
+	usize n, m, k;
 	s16int s;
 	uchar *p, *e;
 	Rectangle l, r;
@@ -77,50 +75,49 @@
 end:
 		recvul(drawc);
 again:
-		if(sbufsz < T * sampwidth){
-			sbuf = erealloc(sbuf, T * sampwidth, sbufsz);
-			sbufsz = T * sampwidth;
-		}
 		lockdisplay(display);
 		draw(viewbg, viewbg->r, col[Cbg], nil, ZP);
 		unlockdisplay(display);
+		d.from.pos = 0;
 		d.pos = views;
+		d.to.pos = totalsz;
 		m = viewe - views;
 		x = 0;
+		qlock(&lsync);
 		while(m > 0){
-			qlock(&lsync);
 			if(nbrecvul(drawc) == 1){
 				qunlock(&lsync);
 				goto again;
 			}
 			n = m < T * sampwidth ? m : T * sampwidth;
-			p = getbuf(d, n, sbuf, &n);
-			qunlock(&lsync);
-			if(p == nil){
-				if(n > 0)
-					fprint(2, "getbuf: %r\n");
-				goto end;
-			}
-			d.pos += n;
-			e = p + n;
 			lmin = lmax = 0;
 			rmin = rmax = 0;
-			while(p < e){
-				s = (s16int)(p[1] << 8 | p[0]);
-				if(s < lmin)
-					lmin = s;
-				else if(s > lmax)
-					lmax = s;
-				if(stereo){
-					s = (s16int)(p[3] << 8 | p[2]);
-					if(s < rmin)
-						rmin = s;
-					else if(s > rmax)
-						rmax = s;
+			while(n > 0){
+				p = getslice(&d, n, &k);
+				if(p == nil){
+					if(k > 0)
+						fprint(2, "getslice: %r\n");
+					goto end;
 				}
-				p += 4 * sampwidth;
+				e = p + k;
+				while(p < e){
+					s = (s16int)(p[1] << 8 | p[0]);
+					if(s < lmin)
+						lmin = s;
+					else if(s > lmax)
+						lmax = s;
+					if(stereo){
+						s = (s16int)(p[3] << 8 | p[2]);
+						if(s < rmin)
+							rmin = s;
+						else if(s > rmax)
+							rmax = s;
+					}
+					p += 4 * sampwidth;
+				}
+				n -= k;
+				m -= k;
 			}
-			m -= n;
 			l = Rect(x, bgscalyl - lmax / bgscalf,
 				x+sampwidth, bgscalyl - lmin / bgscalf);
 			r = Rect(x, bgscalyr - rmax / bgscalf,
@@ -132,6 +129,7 @@
 			unlockdisplay(display);
 			x = (d.pos - views) / T;
 		}
+		qunlock(&lsync);
 	}
 }
 
--- a/fns.h
+++ b/fns.h
@@ -14,6 +14,7 @@
 Chunk*	p2c(usize, usize*);
 void	setrange(usize, usize);
 int	setpos(usize);
+uchar*	getslice(Dot*, usize, usize*);
 uchar*	getbuf(Dot, usize, uchar*, usize*);
 int	loadin(int);
 void*	emalloc(usize);