shithub: pplay

Download patch

ref: d00bb9cd3cb19217b8450c9134209f7f1ec96a25
parent: 51cad53e4b70b6d9fcbbbbf6530f8d7cc3d7f7cb
author: qwx <qwx@sciops.net>
date: Sat Aug 19 20:59:50 EDT 2023

pcmmix: fix once and for all: conflicting read lengths, correct termination

now fucking usable with pplay

--- a/pcmmix.c
+++ b/pcmmix.c
@@ -1,16 +1,13 @@
 #include <u.h>
 #include <libc.h>
 
-enum{
-	Bufsz = 8192,
-};
-
 typedef struct File File;
 struct File{
 	int fd;
 	char *path;
 	int n;
-	uchar buf[Bufsz];
+	uchar *buf;
+	int bufsz;
 };
 void
 usage(void)
@@ -22,13 +19,12 @@
 void
 main(int argc, char **argv)
 {
-	int m, max, notrunc;
+	int n, last, min, k, notrunc;
 	double f;
 	File *ftab, *fp;
-	uchar u[Bufsz], *p, *q;
+	uchar u[IOUNIT], *p, *q;
 	s32int v;
 	int nf;
-	Dir *d;
 
 	notrunc = 0;
 	f = 1.0;
@@ -41,39 +37,62 @@
 	if((ftab = mallocz(nf * sizeof *ftab, 1)) == nil)
 		sysfatal("mallocz: %r");
 	fp = ftab;
-	fp->path = "/fd/0";
-	if((d = dirfstat(0)) == nil)
-		sysfatal("dirfstat: %r");
-	m = d->length;
-	free(d);
-	fp->fd = m > 0 ? 0 : -1;
+	if((n = iounit(0)) > 0){
+		fp->fd = 0;
+		fp->bufsz = n;
+		if((fp->buf = mallocz(fp->bufsz, 1)) == nil)
+			sysfatal("mallocz: %r");
+		fp->path = "/fd/0";
+	}else
+		fp->fd = -1;
 	for(fp++; *argv!=nil; fp++){
 		if((fp->fd = open(*argv, OREAD)) < 0)
 			sysfatal("open: %r");
+		fp->bufsz = iounit(fp->fd);
+		if((fp->buf = mallocz(fp->bufsz, 1)) == nil)
+			sysfatal("mallocz: %r");
 		fp->path = *argv++;
 	}
+	last = 0;
 	for(;;){
-		max = sizeof ftab[0].buf;
+		k = 0;
+		min = sizeof u;
 		for(fp=ftab; fp<ftab+nf; fp++){
 			if(fp->fd < 0)
 				continue;
-			fp->n = read(fp->fd, fp->buf, max);
+			fp->n -= last;
+			p = fp->buf;
+			n = fp->bufsz;
 			if(fp->n > 0){
-				if(fp == ftab)
-					max = fp->n;
+				memmove(fp->buf, fp->buf+last, fp->n);
+				p += fp->n;
+				n -= fp->n;
+			}
+			assert(fp->n >= 0);
+			fp->n = read(fp->fd, p, n);
+			if(fp->n == 0)
+				close(fp->fd);
+			if(fp->n >= 0)
+				fp->n += p - fp->buf;
+			if(fp->n > 0){
+				if(min > fp->n)
+					min = fp->n;
+				k++;
 				continue;
 			}
-			fp->fd = -1;
 			if(fp->n < 0)
 				fprint(2, "read %s: %r\n", fp->path);
-			if(fp == ftab && !notrunc)
+			fp->fd = -1;
+			if(!notrunc)
 				goto end;
 		}
-		memset(u, 0, max);
+		if(k == 0)
+			break;
+		memset(u, 0, min);
 		for(fp=ftab; fp<ftab+nf; fp++){
 			if(fp->fd < 0)
 				continue;
-			for(p=u, q=fp->buf; q<fp->buf+fp->n; p+=2, q+=2){
+			for(p=u, q=fp->buf; q<fp->buf+min; p+=2, q+=2){
 				v = (s16int)(q[1] << 8 | q[0]);
 				v *= f;
 				v += (s16int)(p[1] << 8 | p[0]);
@@ -85,7 +104,8 @@
 				p[1] = v >> 8;
 			}
 		}
-		write(1, u, max);
+		write(1, u, min);
+		last = min;
 	}
 end:
 	exits(nil);