shithub: pplay

Download patch

ref: f87b680a865536dafad94ed9e08e62970519450b
parent: c923daa68daae862ccdd638cbb9e255c609b09de
author: qwx <qwx@sciops.net>
date: Wed Jul 26 00:24:26 EDT 2023

pcmmix: truncate to shortest buffer; heuristic for stdin

bleh
necessary for easy single track editing in pplay

--- a/pcmmix.c
+++ b/pcmmix.c
@@ -1,17 +1,22 @@
 #include <u.h>
 #include <libc.h>
 
+enum{
+	Bufsz = 8192,
+};
+
 typedef struct File File;
 struct File{
 	int fd;
 	char *path;
 	int n;
-	uchar buf[8192];
+	int Δ;
+	uchar buf[Bufsz];
 };
 void
 usage(void)
 {
-	fprint(2, "usage: %s [-f factor] [FILE..]\n", argv0);
+	fprint(2, "usage: %s [-t] [-f factor] [FILE..]\n", argv0);
 	exits("usage");
 }
 
@@ -18,17 +23,19 @@
 void
 main(int argc, char **argv)
 {
-	int n;
+	int n, m, notrunc, gotem;
 	double f;
-	uchar u[8192], *p, *q;
+	File *ftab, *fp;
+	uchar u[Bufsz], *p, *q;
 	s32int v;
 	int nf;
-	File *ftab, *fp;
 	Dir *d;
 
+	notrunc = 0;
 	f = 1.0;
 	ARGBEGIN{
 	case 'f': f = strtod(EARGF(usage()), nil); break;
+	case 't': notrunc = 1; break;
 	default: usage();
 	}ARGEND
 	nf = argc + 1;
@@ -35,34 +42,56 @@
 	if((ftab = mallocz(nf * sizeof *ftab, 1)) == nil)
 		sysfatal("mallocz: %r");
 	fp = ftab;
-	fp->path = "stdin";
-	if(nf > 1){
-		if((d = dirfstat(0)) == nil)
-			sysfatal("dirfstat: %r");
-		fp->fd = d->length > 0 ? 0 : -1;
-		free(d);
-	}
-	fp++;
+	(fp++)->path = "stdin";
 	while(*argv != nil){
 		if((fp->fd = open(*argv, OREAD)) < 0)
 			sysfatal("open: %r");
-		fp->path = *argv++;
-		fp++;
+		(fp++)->path = *argv++;
 	}
+	gotem = 0;
 	for(;;){
 		n = 0;
 		for(fp=ftab; fp<ftab+nf; fp++){
 			if(fp->fd < 0)
 				continue;
-			if((fp->n = read(fp->fd, fp->buf, sizeof fp->buf)) > 0)
+			if(fp == ftab){
+				if((d = dirfstat(0)) == nil)
+					sysfatal("dirfstat: %r");
+				m = d->length;
+				free(d);
+				if(m > 0)
+					gotem = 1;
+				else if(gotem){
+					if(!notrunc)
+						exits(nil);
+					fp->fd = -1;
+					continue;
+				}
+			}
+			m = sizeof fp->buf - fp->Δ;
+			if(m < 0)
+				m = sizeof fp->buf;
+			if(n > 0 && n < m)
+				m = n;
+			fp->n = read(fp->fd, fp->buf+fp->Δ, m);
+			if(n == 0 || notrunc && n < fp->n || !notrunc && n > fp->n)
+				n = fp->n;
+			fprint(2, "%zd n %d fp->n %d Δ %d\n", fp-ftab, n, fp->n, fp->Δ);
+			if(fp->n > 0)
 				continue;
 			fp->fd = -1;
+			if(!notrunc)
+				exits(nil);
 			if(fp->n < 0)
 				fprint(2, "file %s: read: %r\n", fp->path);
 		}
-		memset(u, 0, sizeof u);
+		if(n <= 0)
+			break;
+		memset(u, 0, n);
 		for(fp=ftab; fp<ftab+nf; fp++){
-			for(p=u, q=fp->buf; q<fp->buf+fp->n; p+=2, q+=2){
+			if(fp->fd < 0)
+				continue;
+			for(p=u, q=fp->buf; q<fp->buf+n; p+=2, q+=2){
 				v = (s16int)(q[1] << 8 | q[0]);
 				v *= f;
 				v += (s16int)(p[1] << 8 | p[0]);
@@ -73,11 +102,8 @@
 				p[0] = v;
 				p[1] = v >> 8;
 			}
-			if(fp->n > n)
-				n = fp->n;
+			fp->Δ = n < fp->n ? fp->n - n : 0;
 		}
-		if(n == 0)
-			break;
 		write(1, u, n);
 	}
 	exits(nil);