ref: d00bb9cd3cb19217b8450c9134209f7f1ec96a25
parent: 51cad53e4b70b6d9fcbbbbf6530f8d7cc3d7f7cb
author: qwx <[email protected]>
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);